use-command-registry-source.tsx 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import { useCallback, useMemo } from 'react'
  2. import MiniSearch from 'minisearch'
  3. import { CommandPaletteSearchResult, CommandPaletteSource } from '../types'
  4. import {
  5. Command,
  6. useCommandRegistry,
  7. } from '@/features/ide-react/context/command-registry-context'
  8. const ENABLED_COMMANDS: string[] = [
  9. 'new_file',
  10. 'new_folder',
  11. 'upload_file',
  12. 'open-settings',
  13. 'show_version_history',
  14. 'word_count',
  15. 'view-pdf-presentation-mode',
  16. 'comment',
  17. 'compile',
  18. 'stop-compile',
  19. 'recompile-from-scratch',
  20. ]
  21. const useCommandRegistrySource = (): CommandPaletteSource => {
  22. const { registry } = useCommandRegistry()
  23. const commands = useMemo(() => {
  24. const enabled = new Set(ENABLED_COMMANDS)
  25. return [...registry.values()].filter(
  26. c => enabled.has(c.id) && !c.disabled && c.handler
  27. )
  28. }, [registry])
  29. const defaults = useCallback((): CommandPaletteSearchResult[] => {
  30. return commands.map(command => ({
  31. title: command.label,
  32. onSelect: () => command.handler!({ location: 'command-palette' }),
  33. score: 1,
  34. }))
  35. }, [commands])
  36. const index = useMemo(() => {
  37. const miniSearch = new MiniSearch<Command>({
  38. fields: ['label'],
  39. storeFields: ['id'],
  40. idField: 'id',
  41. })
  42. miniSearch.addAll(commands)
  43. return miniSearch
  44. }, [commands])
  45. return useMemo<CommandPaletteSource>(
  46. () => ({
  47. id: 'command-registry',
  48. search(query) {
  49. const results = index.search(query, {
  50. prefix: true,
  51. fuzzy: term => (term.length > 3 ? 0.2 : false),
  52. })
  53. return results.flatMap(({ id, score }) => {
  54. const command = registry.get(id)
  55. if (!command?.handler) return []
  56. return [
  57. {
  58. title: command.label,
  59. onSelect: () => command.handler!({ location: 'command-palette' }),
  60. score,
  61. },
  62. ]
  63. })
  64. },
  65. defaults,
  66. }),
  67. [index, registry, defaults]
  68. )
  69. }
  70. export default useCommandRegistrySource