Refactor spyglass service and context

This commit is contained in:
Misode
2024-10-23 05:44:20 +02:00
parent c358c871da
commit a0f3e71000
6 changed files with 157 additions and 120 deletions

View File

@@ -18,18 +18,23 @@ type ErrorPanelProps = {
}
export function ErrorPanel({ error, prefix, reportable, onDismiss, body: body_, children }: ErrorPanelProps) {
const { version } = useVersion()
const { spyglass } = useSpyglass()
const { service } = useSpyglass()
const [stackVisible, setStackVisible] = useState(false)
const [stack, setStack] = useState<string | undefined>(undefined)
const name = (prefix ?? '') + (error instanceof Error ? error.message : error)
const gen = getGenerator(getCurrentUrl())
const { value: source } = useAsync(async () => {
if (gen) {
return await spyglass?.readFile(spyglass.getUnsavedFileUri(version, gen))
if (!service || !gen) {
return undefined
}
return undefined
}, [spyglass, version, gen])
// TODO: read project file if open
const uri = service.getUnsavedFileUri(gen)
if (!uri) {
return undefined
}
return await service.readFile(uri)
}, [service, version, gen])
useEffect(() => {
if (error instanceof Error) {

View File

@@ -21,7 +21,7 @@ interface Props {
export function SchemaGenerator({ gen, allowedVersions }: Props) {
const { locale } = useLocale()
const { version, changeVersion, changeTargetVersion } = useVersion()
const { spyglass } = useSpyglass()
const { service } = useSpyglass()
const { projects, project, file, updateProject, updateFile, closeFile } = useProject()
const [error, setError] = useState<Error | string | null>(null)
const [errorBoundary, errorRetry] = useErrorBoundary()
@@ -34,8 +34,8 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
const uri = useMemo(() => {
// TODO: return different uri when project file is open
return spyglass?.getUnsavedFileUri(version, gen)
}, [spyglass, version, gen])
return service?.getUnsavedFileUri(gen)
}, [service, version, gen])
const [currentPreset, setCurrentPreset] = useSearchParam('preset')
const [sharedSnippetId, setSharedSnippetId] = useSearchParam(SHARE_KEY)
@@ -82,14 +82,17 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
ignoreChange.current = true
data = file.data
}
if (!service || !uri) {
return AsyncCancel
}
if (data) {
await spyglass.writeFile(version, uri, JSON.stringify(data))
await service.writeFile(uri, JSON.stringify(data))
}
// TODO: if data is undefined, set to generator's default
const docAndNode = await spyglass.getFile(version, uri, () => '{}')
const docAndNode = await service.getFile(uri, () => '{}')
Analytics.setGenerator(gen.id)
return docAndNode
}, [gen.id, version, sharedSnippetId, currentPreset, project.name, file?.id, spyglass])
}, [gen.id, version, sharedSnippetId, currentPreset, project.name, file?.id, service])
const { doc } = docAndNode ?? {}
@@ -112,23 +115,32 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
}
const undo = async (e: MouseEvent) => {
e.stopPropagation()
if (!service || !uri) {
return
}
Analytics.undoGenerator(gen.id, 1, 'menu')
await spyglass.undoEdits(version, uri)
await service.undoEdits(uri)
}
const redo = async (e: MouseEvent) => {
e.stopPropagation()
if (!service || !uri) {
return
}
Analytics.redoGenerator(gen.id, 1, 'menu')
await spyglass.redoEdits(version, uri)
await service?.redoEdits(uri)
}
useEffect(() => {
const onKeyUp = async (e: KeyboardEvent) => {
if (!service || !uri) {
return
}
if (e.ctrlKey && e.key === 'z') {
Analytics.undoGenerator(gen.id, 1, 'hotkey')
await spyglass.undoEdits(version, uri)
await service.undoEdits(uri)
} else if (e.ctrlKey && e.key === 'y') {
Analytics.redoGenerator(gen.id, 1, 'hotkey')
await spyglass.redoEdits(version, uri)
await service.redoEdits(uri)
}
}
const onKeyDown = (e: KeyboardEvent) => {
@@ -145,7 +157,7 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
document.removeEventListener('keyup', onKeyUp)
document.removeEventListener('keydown', onKeyDown)
}
}, [gen.id, spyglass, version, uri])
}, [gen.id, service, uri])
const { value: presets } = useAsync(async () => {
const registries = await fetchRegistries(version)
@@ -338,7 +350,7 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
<PreviewPanel docAndNode={docAndNode} id={gen.id} shown={previewShown} onError={setError} />
</div>
<div class={`popup-source${sourceShown ? ' shown' : ''}`}>
<SourcePanel spyglass={spyglass} docAndNode={docAndNode} {...{doCopy, doDownload, doImport}} copySuccess={copySuccess} onError={setError} />
<SourcePanel docAndNode={docAndNode} {...{doCopy, doDownload, doImport}} copySuccess={copySuccess} onError={setError} />
</div>
<div class={`popup-share${shareShown ? ' shown' : ''}`}>
<TextInput value={shareUrl} readonly />

View File

@@ -1,11 +1,10 @@
import type { DocAndNode } from '@spyglassmc/core'
import { fileUtil } from '@spyglassmc/core'
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
import { useLocale, useVersion } from '../../contexts/index.js'
import { useDocAndNode } from '../../contexts/Spyglass.jsx'
import { useLocale } from '../../contexts/index.js'
import { useDocAndNode, useSpyglass } from '../../contexts/Spyglass.jsx'
import { useLocalStorage } from '../../hooks/index.js'
import { getSourceFormats, getSourceIndent, getSourceIndents, parseSource, sortData, stringifySource } from '../../services/index.js'
import type { Spyglass } from '../../services/Spyglass.js'
import { Store } from '../../Store.js'
import { message } from '../../Utils.js'
import { Btn, BtnMenu } from '../index.js'
@@ -18,7 +17,6 @@ interface Editor {
}
type SourcePanelProps = {
spyglass: Spyglass | undefined,
docAndNode: DocAndNode | undefined,
doCopy?: number,
doDownload?: number,
@@ -26,9 +24,9 @@ type SourcePanelProps = {
copySuccess: () => unknown,
onError: (message: string | Error) => unknown,
}
export function SourcePanel({ spyglass, docAndNode, doCopy, doDownload, doImport, copySuccess, onError }: SourcePanelProps) {
export function SourcePanel({ docAndNode, doCopy, doDownload, doImport, copySuccess, onError }: SourcePanelProps) {
const { locale } = useLocale()
const { version } = useVersion()
const { service } = useSpyglass()
const [indent, setIndent] = useState(Store.getIndent())
const [format, setFormat] = useState(Store.getFormat())
const [sort, setSort] = useLocalStorage('misode_output_sort', 'schema')
@@ -75,10 +73,10 @@ export function SourcePanel({ spyglass, docAndNode, doCopy, doDownload, doImport
if (!editor.current) return
const value = editor.current.getValue()
if (value.length === 0) return
if (!spyglass || !docAndNode) return
if (!service || !docAndNode) return
try {
const data = await parseSource(value, format)
await spyglass.writeFile(version, docAndNode.doc.uri, JSON.stringify(data))
await service.writeFile(docAndNode.doc.uri, JSON.stringify(data))
} catch (e) {
if (e instanceof Error) {
e.message = `Error importing: ${e.message}`
@@ -89,7 +87,7 @@ export function SourcePanel({ spyglass, docAndNode, doCopy, doDownload, doImport
console.error(e)
}
}
}, [spyglass, version, docAndNode, text, indent, format, sort, highlighting])
}, [service, docAndNode, text, indent, format, sort, highlighting])
useEffect(() => {
if (highlighting) {

View File

@@ -1,7 +1,7 @@
import type { DocAndNode } from '@spyglassmc/core'
import { JsonFileNode } from '@spyglassmc/json'
import { useCallback, useErrorBoundary } from 'preact/hooks'
import { useLocale, useVersion } from '../../contexts/index.js'
import { useLocale } from '../../contexts/index.js'
import { useDocAndNode, useSpyglass } from '../../contexts/Spyglass.jsx'
import type { Edit } from '../../services/Spyglass.js'
import { McdocRoot } from './McdocRenderer.jsx'
@@ -12,8 +12,7 @@ type TreePanelProps = {
}
export function Tree({ docAndNode, onError }: TreePanelProps) {
const { lang } = useLocale()
const { version } = useVersion()
const { spyglass } = useSpyglass()
const { service } = useSpyglass()
if (lang === 'none') return <></>
@@ -29,8 +28,11 @@ export function Tree({ docAndNode, onError }: TreePanelProps) {
if (error) return <></>
const makeEdits = useCallback((edits: Edit[]) => {
spyglass.applyEdits(version, docAndNode.doc.uri, edits)
}, [spyglass, version, docAndNode])
if (!service) {
return
}
service.applyEdits(docAndNode.doc.uri, edits)
}, [service, docAndNode])
return <div class="tree node-root" data-cy="tree">
<McdocRoot node={fileChild.children[0]} makeEdits={makeEdits} />