feat: search in command panel (#576)

This commit is contained in:
Ayaka Rizumu 2022-12-29 00:29:07 +08:00 committed by GitHub
parent d585d4eeb7
commit a775203bdc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 181 additions and 64 deletions

View file

@ -2,6 +2,7 @@ import type { ComputedRef } from 'vue'
import { defineStore } from 'pinia'
import Fuse from 'fuse.js'
import type { LocaleObject } from '#i18n'
import type { SearchResult } from '@/components/search/types'
// @unocss-include
@ -15,6 +16,8 @@ const scopes = [
'Languages',
'Switch account',
'Settings',
'Hashtags',
'Users',
] as const
export type CommandScopeNames = typeof scopes[number]
@ -42,16 +45,37 @@ export interface CommandProvider {
onComplete?: () => CommandScope
}
export type ResolvedCommand =
Exclude<CommandProvider, 'icon' | 'name' | 'description' | 'bindings'> & {
icon: string
name: string
description: string | undefined
bindings: string[] | undefined
}
export type ResolvedCommand = Exclude<CommandProvider, 'icon' | 'name' | 'description' | 'bindings'> & {
icon: string
name: string
description: string | undefined
bindings: string[] | undefined
}
export type QueryIndexedCommand = ResolvedCommand & {
export interface BaseQueryResultItem {
index: number
type: string
scope?: CommandScopeNames
onActivate?: () => void
onComplete?: () => CommandScope
}
export interface SearchQueryResultItem extends BaseQueryResultItem {
type: 'search'
search: SearchResult
}
export interface CommandQueryResultItem extends BaseQueryResultItem {
type: 'command'
cmd: ResolvedCommand
}
export type QueryResultItem = SearchQueryResultItem | CommandQueryResultItem
export interface QueryResult {
length: number
items: QueryResultItem[]
grouped: Map<CommandScopeNames, QueryResultItem[]>
}
const r = <T extends Object | undefined>(i: T | (() => T)): T =>
@ -86,7 +110,7 @@ export const useCommandRegistry = defineStore('command', () => {
providers.delete(provider)
},
query: (scope: string, query: string) => {
query: (scope: string, query: string): QueryResult => {
const cmds = commands.value
.filter(cmd => (cmd.parent ?? '') === scope)
@ -105,7 +129,7 @@ export const useCommandRegistry = defineStore('command', () => {
.map(({ item }) => ({ ...item }))
// group by scope
const grouped = new Map<CommandScopeNames, QueryIndexedCommand[]>()
const grouped = new Map<CommandScopeNames, CommandQueryResultItem[]>()
for (const cmd of res) {
const scope = cmd.scope ?? ''
if (!grouped.has(scope))
@ -113,13 +137,17 @@ export const useCommandRegistry = defineStore('command', () => {
grouped
.get(scope)!
.push({
...cmd,
index: 0,
type: 'command',
scope,
cmd,
onActivate: cmd.onActivate,
onComplete: cmd.onComplete,
})
}
let index = 0
const indexed: QueryIndexedCommand[] = []
const indexed: CommandQueryResultItem[] = []
for (const items of grouped.values()) {
for (const cmd of items) {
cmd.index = index++
@ -137,21 +165,28 @@ export const useCommandRegistry = defineStore('command', () => {
else {
const indexed = cmds.map((cmd, index) => ({ ...cmd, index }))
const grouped = new Map<CommandScopeNames, QueryIndexedCommand[]>(
const grouped = new Map<CommandScopeNames, CommandQueryResultItem[]>(
scopes.map(scope => [scope, []]))
for (const cmd of indexed) {
const scope = cmd.scope ?? ''
grouped.get(scope)!.push(cmd)
grouped.get(scope)!.push({
index: cmd.index,
type: 'command',
scope,
cmd,
onActivate: cmd.onActivate,
onComplete: cmd.onComplete,
})
}
let index = 0
const sorted: QueryIndexedCommand[] = []
const sorted: CommandQueryResultItem[] = []
for (const [scope, items] of grouped) {
if (items.length === 0) {
grouped.delete(scope)
}
else {
const o = (cmd: QueryIndexedCommand) => (cmd.order ?? 0) * 100 + cmd.index
const o = (item: CommandQueryResultItem) => (item.cmd.order ?? 0) * 100 + item.index
items.sort((a, b) => o(a) - o(b))
for (const cmd of items) {
cmd.index = index++