feat: search in command panel (#576)
This commit is contained in:
parent
d585d4eeb7
commit
a775203bdc
3 changed files with 181 additions and 64 deletions
|
@ -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++
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue