feat: server auto complete

zio/stable
Anthony Fu 2022-12-24 01:40:51 +01:00
parent 52a8ae47fe
commit b30e8a2b03
1 changed files with 48 additions and 1 deletions

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import Fuse from 'fuse.js'
import { DEFAULT_SERVER } from '~/constants' import { DEFAULT_SERVER } from '~/constants'
const input = $ref<HTMLInputElement>() const input = $ref<HTMLInputElement>()
@ -6,6 +7,8 @@ let server = $ref<string>('')
let busy = $ref<boolean>(false) let busy = $ref<boolean>(false)
let error = $ref<boolean>(false) let error = $ref<boolean>(false)
let displayError = $ref<boolean>(false) let displayError = $ref<boolean>(false)
let knownServers = $ref<string[]>([])
let acIndex = $ref(0)
async function oauth() { async function oauth() {
if (busy) if (busy)
@ -44,8 +47,32 @@ async function handleInput() {
displayError = false displayError = false
} }
onMounted(() => { let fuse = $shallowRef(new Fuse([] as string[]))
const filteredServers = $computed(() => {
if (!server)
return []
const results = fuse.search(server, { limit: 6 }).map(result => result.item)
if (results.length === 1 && results[0] === server)
return []
return results
})
function move(delta: number) {
acIndex = ((acIndex + delta) + filteredServers.length) % filteredServers.length
}
function onEnter() {
if (filteredServers[acIndex])
server = filteredServers[acIndex]
}
onMounted(async () => {
input?.focus() input?.focus()
knownServers = await $fetch('/api/list-servers')
fuse = new Fuse(knownServers, { shouldSort: true })
}) })
</script> </script>
@ -65,15 +92,35 @@ onMounted(() => {
flex bg-gray:10 px4 py2 mxa rounded flex bg-gray:10 px4 py2 mxa rounded
border="~ base" items-center font-mono border="~ base" items-center font-mono
focus:outline-none focus:ring="2 primary inset" focus:outline-none focus:ring="2 primary inset"
relative
:class="displayError ? 'border-red-600 dark:border-red-400' : null" :class="displayError ? 'border-red-600 dark:border-red-400' : null"
> >
<span text-secondary-light mr1>https://</span> <span text-secondary-light mr1>https://</span>
<input <input
ref="input" ref="input"
v-model="server" v-model="server"
outline-none bg-transparent w-full max-w-50 outline-none bg-transparent w-full max-w-50
@input="handleInput" @input="handleInput"
@keydown.down="move(-1)"
@keydown.up="move(1)"
@keydown.enter="onEnter"
> >
<div
absolute left-6em right-0 top="100%"
bg-base rounded border="~ base"
text-left
>
<div
v-for="server, idx in filteredServers"
:key="server"
:value="server"
px-2 py1 font-mono
:class="acIndex === idx ? 'text-primary font-bold' : null"
>
{{ server }}
</div>
</div>
</div> </div>
<div min-h-4> <div min-h-4>
<Transition css enter-active-class="animate animate-fade-in"> <Transition css enter-active-class="animate animate-fade-in">