mirror of
https://github.com/misode/misode.github.io.git
synced 2026-04-24 15:47:08 +00:00
🔥 Nuke all mcschema related code
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
import { DataModel } from '@mcschema/core'
|
||||
import { useState } from 'preact/hooks'
|
||||
import { Analytics } from '../../Analytics.js'
|
||||
import { useLocale, useProject } from '../../contexts/index.js'
|
||||
import type { FileModel } from '../../services/index.js'
|
||||
import { Btn } from '../Btn.js'
|
||||
import { TextInput } from '../forms/index.js'
|
||||
import { Modal } from '../Modal.js'
|
||||
|
||||
interface Props {
|
||||
model: DataModel,
|
||||
model: FileModel,
|
||||
id: string,
|
||||
method: string,
|
||||
onClose: () => void,
|
||||
@@ -29,7 +29,7 @@ export function FileCreation({ model, id, method, onClose }: Props) {
|
||||
return
|
||||
}
|
||||
Analytics.saveProjectFile(id, projects.length, project.files.length, method as any)
|
||||
updateFile(id, undefined, { type: id, id: fileId, data: DataModel.unwrapLists(model.data) })
|
||||
updateFile(id, undefined, { type: id, id: fileId, data: model.data })
|
||||
onClose()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,69 +1,59 @@
|
||||
import type { DataModel } from '@mcschema/core'
|
||||
import { Path } from '@mcschema/core'
|
||||
import { useState } from 'preact/hooks'
|
||||
import { useModel } from '../../hooks/index.js'
|
||||
import type { VersionId } from '../../services/index.js'
|
||||
import { useVersion } from '../../contexts/Version.jsx'
|
||||
import type { FileModel } from '../../services/index.js'
|
||||
import { checkVersion } from '../../services/index.js'
|
||||
import { BiomeSourcePreview, BlockStatePreview, DecoratorPreview, DensityFunctionPreview, LootTablePreview, ModelPreview, NoisePreview, NoiseSettingsPreview, RecipePreview, StructureSetPreview } from '../previews/index.js'
|
||||
|
||||
export const HasPreview = ['loot_table', 'recipe', 'dimension', 'worldgen/density_function', 'worldgen/noise', 'worldgen/noise_settings', 'worldgen/configured_feature', 'worldgen/placed_feature', 'worldgen/structure_set', 'block_definition', 'model']
|
||||
|
||||
type PreviewPanelProps = {
|
||||
model: DataModel | undefined,
|
||||
version: VersionId,
|
||||
model: FileModel | undefined,
|
||||
id: string,
|
||||
shown: boolean,
|
||||
onError: (message: string) => unknown,
|
||||
}
|
||||
export function PreviewPanel({ model, version, id, shown }: PreviewPanelProps) {
|
||||
const [, setCount] = useState(0)
|
||||
|
||||
useModel(model, () => {
|
||||
setCount(count => count + 1)
|
||||
})
|
||||
export function PreviewPanel({ model, id, shown }: PreviewPanelProps) {
|
||||
const { version } = useVersion()
|
||||
|
||||
if (!model) return <></>
|
||||
const data = model.get(new Path([]))
|
||||
if (!data) return <></>
|
||||
|
||||
if (id === 'loot_table') {
|
||||
return <LootTablePreview {...{ model, version, shown, data }} />
|
||||
return <LootTablePreview {...{ model, shown }} />
|
||||
}
|
||||
|
||||
if (id === 'recipe') {
|
||||
return <RecipePreview {...{ model, version, shown, data }} />
|
||||
return <RecipePreview {...{ model, shown }} />
|
||||
}
|
||||
|
||||
if (id === 'dimension' && model.get(new Path(['generator', 'type']))?.endsWith('noise')) {
|
||||
return <BiomeSourcePreview {...{ model, version, shown, data }} />
|
||||
if (id === 'dimension' && model.data.generator?.type?.endsWith('noise')) {
|
||||
return <BiomeSourcePreview {...{ model, shown }} />
|
||||
}
|
||||
|
||||
if (id === 'worldgen/density_function') {
|
||||
return <DensityFunctionPreview {...{ model, version, shown, data }} />
|
||||
return <DensityFunctionPreview {...{ model, shown }} />
|
||||
}
|
||||
|
||||
if (id === 'worldgen/noise') {
|
||||
return <NoisePreview {...{ model, version, shown, data }} />
|
||||
return <NoisePreview {...{ model, shown }} />
|
||||
}
|
||||
|
||||
if (id === 'worldgen/noise_settings' && checkVersion(version, '1.18')) {
|
||||
return <NoiseSettingsPreview {...{ model, version, shown, data }} />
|
||||
return <NoiseSettingsPreview {...{ model, shown }} />
|
||||
}
|
||||
|
||||
if ((id === 'worldgen/placed_feature' || (id === 'worldgen/configured_feature' && checkVersion(version, '1.16', '1.17')))) {
|
||||
return <DecoratorPreview {...{ model, version, shown, data }} />
|
||||
return <DecoratorPreview {...{ model, shown }} />
|
||||
}
|
||||
|
||||
if (id === 'worldgen/structure_set' && checkVersion(version, '1.19')) {
|
||||
return <StructureSetPreview {...{ model, version, shown, data }} />
|
||||
return <StructureSetPreview {...{ model, shown }} />
|
||||
}
|
||||
|
||||
if (id === 'block_definition') {
|
||||
return <BlockStatePreview {...{ model, version, shown, data }} />
|
||||
return <BlockStatePreview {...{ model, shown }} />
|
||||
}
|
||||
|
||||
if (id === 'model') {
|
||||
return <ModelPreview {...{ model, version, shown, data }} />
|
||||
return <ModelPreview {...{ model, shown }} />
|
||||
}
|
||||
|
||||
return <></>
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { DataModel } from '@mcschema/core'
|
||||
import { useCallback, useMemo, useRef, useState } from 'preact/hooks'
|
||||
import { Analytics } from '../../Analytics.js'
|
||||
import config from '../../Config.js'
|
||||
import { disectFilePath, DRAFT_PROJECT, getFilePath, useLocale, useProject, useVersion } from '../../contexts/index.js'
|
||||
import { useFocus } from '../../hooks/useFocus.js'
|
||||
import type { VersionId } from '../../services/index.js'
|
||||
import { stringifySource } from '../../services/index.js'
|
||||
import { Store } from '../../Store.js'
|
||||
import { writeZip } from '../../Utils.js'
|
||||
@@ -15,9 +13,6 @@ import type { TreeViewGroupRenderer, TreeViewLeafRenderer } from '../TreeView.js
|
||||
import { TreeView } from '../TreeView.js'
|
||||
|
||||
interface Props {
|
||||
model: DataModel | undefined,
|
||||
version: VersionId,
|
||||
id: string,
|
||||
onError: (message: string) => unknown,
|
||||
onRename: (file: { type: string, id: string }) => unknown,
|
||||
onCreate: () => unknown,
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { DataModel, Path } from '@mcschema/core'
|
||||
import { route } from 'preact-router'
|
||||
import { useCallback, useEffect, useErrorBoundary, useMemo, useRef, useState } from 'preact/hooks'
|
||||
import { useCallback, useEffect, useErrorBoundary, useMemo, useState } from 'preact/hooks'
|
||||
import { Analytics } from '../../Analytics.js'
|
||||
import type { ConfigGenerator } from '../../Config.js'
|
||||
import config from '../../Config.js'
|
||||
import { DRAFT_PROJECT, useLocale, useProject, useVersion } from '../../contexts/index.js'
|
||||
import { AsyncCancel, useActiveTimeout, useAsync, useModel, useSearchParam } from '../../hooks/index.js'
|
||||
import { getOutput } from '../../schema/transformOutput.js'
|
||||
import type { VersionId } from '../../services/index.js'
|
||||
import { checkVersion, fetchPreset, getBlockStates, getCollections, getModel, getSnippet, shareSnippet } from '../../services/index.js'
|
||||
import { AsyncCancel, useActiveTimeout, useAsync, useSearchParam } from '../../hooks/index.js'
|
||||
import type { FileModel, VersionId } from '../../services/index.js'
|
||||
import { checkVersion, createMockFileModel, fetchPreset, fetchRegistries, getSnippet, shareSnippet } from '../../services/index.js'
|
||||
import { Store } from '../../Store.js'
|
||||
import { cleanUrl, deepEqual, genPath } from '../../Utils.js'
|
||||
import { Ad, Btn, BtnMenu, ErrorPanel, FileCreation, FileRenaming, Footer, HasPreview, Octicon, PreviewPanel, ProjectCreation, ProjectDeletion, ProjectPanel, SearchList, SourcePanel, TextInput, Tree, VersionSwitcher } from '../index.js'
|
||||
@@ -22,7 +20,7 @@ interface Props {
|
||||
export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
const { locale } = useLocale()
|
||||
const { version, changeVersion, changeTargetVersion } = useVersion()
|
||||
const { projects, project, file, updateProject, updateFile, closeFile } = useProject()
|
||||
const { projects, project, file, updateProject, closeFile } = useProject()
|
||||
const [error, setError] = useState<Error | string | null>(null)
|
||||
const [errorBoundary, errorRetry] = useErrorBoundary()
|
||||
if (errorBoundary) {
|
||||
@@ -34,16 +32,15 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
|
||||
const [currentPreset, setCurrentPreset] = useSearchParam('preset')
|
||||
const [sharedSnippetId, setSharedSnippetId] = useSearchParam(SHARE_KEY)
|
||||
const ignoreChange = useRef(false)
|
||||
const backup = useMemo(() => Store.getBackup(gen.id), [gen.id])
|
||||
|
||||
const loadBackup = () => {
|
||||
if (backup !== undefined) {
|
||||
model?.reset(DataModel.wrapLists(backup), false)
|
||||
// TODO: implement
|
||||
}
|
||||
}
|
||||
|
||||
const { value } = useAsync(async () => {
|
||||
const {} = useAsync(async () => {
|
||||
let data: unknown = undefined
|
||||
if (currentPreset && sharedSnippetId) {
|
||||
setSharedSnippetId(undefined)
|
||||
@@ -81,81 +78,65 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
}
|
||||
data = file.data
|
||||
}
|
||||
const [model, blockStates] = await Promise.all([
|
||||
getModel(version, gen.id),
|
||||
getBlockStates(version),
|
||||
])
|
||||
if (data) {
|
||||
ignoreChange.current = true
|
||||
model.reset(DataModel.wrapLists(data), false)
|
||||
// TODO: set file contents to data
|
||||
}
|
||||
Analytics.setGenerator(gen.id)
|
||||
return { model, blockStates }
|
||||
return {}
|
||||
}, [gen.id, version, sharedSnippetId, currentPreset, project.name, file?.id])
|
||||
|
||||
const model = value?.model
|
||||
const blockStates = value?.blockStates
|
||||
const model: FileModel = createMockFileModel()
|
||||
|
||||
useModel(model, model => {
|
||||
if (!ignoreChange.current) {
|
||||
setCurrentPreset(undefined, true)
|
||||
setSharedSnippetId(undefined, true)
|
||||
}
|
||||
if (file && model && blockStates) {
|
||||
const data = getOutput(model, blockStates)
|
||||
updateFile(gen.id, file.id, { id: file.id, data })
|
||||
}
|
||||
ignoreChange.current = false
|
||||
Store.setBackup(gen.id, DataModel.unwrapLists(model.data))
|
||||
setError(null)
|
||||
}, [gen.id, setCurrentPreset, setSharedSnippetId, blockStates, file?.id])
|
||||
// TODO: when contents of file change:
|
||||
// - remove preset and share id from url
|
||||
// - update project
|
||||
// - store backup
|
||||
|
||||
const reset = () => {
|
||||
Analytics.resetGenerator(gen.id, model?.historyIndex ?? 1, 'menu')
|
||||
model?.reset(DataModel.wrapLists(model.schema.default()), true)
|
||||
Analytics.resetGenerator(gen.id, 1, 'menu')
|
||||
// TODO
|
||||
}
|
||||
const undo = (e: MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
Analytics.undoGenerator(gen.id, model?.historyIndex ?? 1, 'menu')
|
||||
model?.undo()
|
||||
Analytics.undoGenerator(gen.id, 1, 'menu')
|
||||
// TODO
|
||||
}
|
||||
const redo = (e: MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
Analytics.redoGenerator(gen.id, model?.historyIndex ?? 1, 'menu')
|
||||
model?.redo()
|
||||
Analytics.redoGenerator(gen.id, 1, 'menu')
|
||||
// TODO
|
||||
}
|
||||
|
||||
const onKeyUp = (e: KeyboardEvent) => {
|
||||
if (e.ctrlKey && e.key === 'z') {
|
||||
Analytics.undoGenerator(gen.id, model?.historyIndex ?? 1, 'hotkey')
|
||||
model?.undo()
|
||||
} else if (e.ctrlKey && e.key === 'y') {
|
||||
Analytics.redoGenerator(gen.id, model?.historyIndex ?? 1, 'hotkey')
|
||||
model?.redo()
|
||||
}
|
||||
}
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.ctrlKey && e.key === 's') {
|
||||
setFileSaving('hotkey')
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
const onKeyUp = (e: KeyboardEvent) => {
|
||||
if (e.ctrlKey && e.key === 'z') {
|
||||
Analytics.undoGenerator(gen.id, 1, 'hotkey')
|
||||
// TODO
|
||||
} else if (e.ctrlKey && e.key === 'y') {
|
||||
Analytics.redoGenerator(gen.id, 1, 'hotkey')
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.ctrlKey && e.key === 's') {
|
||||
setFileSaving('hotkey')
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('keyup', onKeyUp)
|
||||
document.addEventListener('keydown', onKeyDown)
|
||||
return () => {
|
||||
document.removeEventListener('keyup', onKeyUp)
|
||||
document.removeEventListener('keydown', onKeyDown)
|
||||
}
|
||||
}, [model, blockStates, file])
|
||||
}, [gen.id])
|
||||
|
||||
const [presets, setPresets] = useState<string[]>([])
|
||||
useEffect(() => {
|
||||
getCollections(version).then(collections => {
|
||||
setPresets(collections.get(gen.id).map(p => p.startsWith('minecraft:') ? p.slice(10) : p))
|
||||
})
|
||||
.catch(e => { console.error(e); setError(e) })
|
||||
const { value: presets } = useAsync(async () => {
|
||||
const registries = await fetchRegistries(version)
|
||||
const entries = registries.get(gen.id) ?? []
|
||||
return entries.map(e => e.startsWith('minecraft:') ? e.slice(10) : e)
|
||||
}, [version, gen.id])
|
||||
|
||||
const selectPreset = (id: string) => {
|
||||
@@ -168,13 +149,7 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
const loadPreset = async (id: string) => {
|
||||
try {
|
||||
const preset = await fetchPreset(version, genPath(gen, version), id)
|
||||
const seed = model?.get(new Path(['generator', 'seed']))
|
||||
if (preset?.generator?.seed !== undefined && seed !== undefined) {
|
||||
preset.generator.seed = seed
|
||||
if (preset.generator.biome_source?.seed !== undefined) {
|
||||
preset.generator.biome_source.seed = seed
|
||||
}
|
||||
}
|
||||
// TODO: sync random seed
|
||||
return preset
|
||||
} catch (e) {
|
||||
setError(`Cannot load preset ${id} in ${version}`)
|
||||
@@ -203,14 +178,14 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
setShareUrl(`${location.origin}/${gen.url}/?version=${version}&preset=${currentPreset}`)
|
||||
setShareShown(true)
|
||||
copySharedId()
|
||||
} else if (model && blockStates) {
|
||||
const output = getOutput(model, blockStates)
|
||||
if (deepEqual(output, model.schema.default())) {
|
||||
} else {
|
||||
// TODO: get contents from file, and compare to default of type
|
||||
if (deepEqual(model.data, {})) {
|
||||
setShareUrl(`${location.origin}/${gen.url}/?version=${version}`)
|
||||
setShareShown(true)
|
||||
} else {
|
||||
setShareLoading(true)
|
||||
shareSnippet(gen.id, version, output, previewShown)
|
||||
shareSnippet(gen.id, version, model.data, previewShown)
|
||||
.then(({ id, length, compressed, rate }) => {
|
||||
Analytics.createSnippet(gen.id, id, version, length, compressed, rate)
|
||||
const url = `${location.origin}/${gen.url}/?${SHARE_KEY}=${id}`
|
||||
@@ -298,21 +273,12 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
const [projectDeleting, setprojectDeleting] = useState(false)
|
||||
const [fileSaving, setFileSaving] = useState<string | undefined>(undefined)
|
||||
const [fileRenaming, setFileRenaming] = useState<{ type: string, id: string } | undefined>(undefined)
|
||||
const [newFileQueued, setNewFileQueued] = useState(false)
|
||||
|
||||
const onNewFile = useCallback(() => {
|
||||
closeFile()
|
||||
// Need to queue reset because otherwise the useModel hook will update the old file
|
||||
setNewFileQueued(true)
|
||||
// TODO: create new file with default contents
|
||||
}, [closeFile])
|
||||
|
||||
useEffect(() => {
|
||||
if (file === undefined && newFileQueued) {
|
||||
model?.reset(DataModel.wrapLists(model.schema.default()), true)
|
||||
setNewFileQueued(false)
|
||||
}
|
||||
}, [model, newFileQueued, file])
|
||||
|
||||
return <>
|
||||
<main class={`generator${previewShown ? ' has-preview' : ''}${projectShown ? ' has-project' : ''}`}>
|
||||
{!gen.tags?.includes('partners') && <Ad id="data-pack-generator" type="text" />}
|
||||
@@ -335,7 +301,7 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
</BtnMenu>
|
||||
</div>
|
||||
{error && <ErrorPanel error={error} onDismiss={() => setError(null)} />}
|
||||
<Tree {...{model, version, blockStates}} onError={setError} />
|
||||
<Tree model={model} onError={setError} />
|
||||
<Footer donate={!gen.tags?.includes('partners')} />
|
||||
</main>
|
||||
<div class="popup-actions right-actions" style={`--offset: -${8 + actionsShown * 50}px;`}>
|
||||
@@ -356,10 +322,10 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
</div>
|
||||
</div>
|
||||
<div class={`popup-preview${previewShown ? ' shown' : ''}`}>
|
||||
<PreviewPanel {...{model, version, id: gen.id}} shown={previewShown} onError={setError} />
|
||||
<PreviewPanel model={model} id={gen.id} shown={previewShown} onError={setError} />
|
||||
</div>
|
||||
<div class={`popup-source${sourceShown ? ' shown' : ''}`}>
|
||||
<SourcePanel {...{model, blockStates, doCopy, doDownload, doImport}} name={gen.schema ?? 'data'} copySuccess={copySuccess} onError={setError} />
|
||||
<SourcePanel {...{model, doCopy, doDownload, doImport}} name={gen.schema ?? 'data'} copySuccess={copySuccess} onError={setError} />
|
||||
</div>
|
||||
<div class={`popup-share${shareShown ? ' shown' : ''}`}>
|
||||
<TextInput value={shareUrl} readonly />
|
||||
@@ -371,7 +337,7 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
|
||||
</div>
|
||||
</div>
|
||||
<div class={`popup-project${projectShown ? ' shown' : ''}`}>
|
||||
<ProjectPanel {...{model, version, id: gen.id}} onError={setError} onDeleteProject={() => setprojectDeleting(true)} onRename={setFileRenaming} onCreate={() => setProjectCreating(true)} />
|
||||
<ProjectPanel onError={setError} onDeleteProject={() => setprojectDeleting(true)} onRename={setFileRenaming} onCreate={() => setProjectCreating(true)} />
|
||||
</div>
|
||||
{projectCreating && <ProjectCreation onClose={() => setProjectCreating(false)} />}
|
||||
{projectDeleting && <ProjectDeletion onClose={() => setprojectDeleting(false)} />}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { DataModel } from '@mcschema/core'
|
||||
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
|
||||
import { useLocale } from '../../contexts/index.js'
|
||||
import { useLocalStorage, useModel } from '../../hooks/index.js'
|
||||
import { getOutput } from '../../schema/transformOutput.js'
|
||||
import type { BlockStateRegistry } from '../../services/index.js'
|
||||
import { useLocalStorage } from '../../hooks/index.js'
|
||||
import type { FileModel } from '../../services/index.js'
|
||||
import { getSourceFormats, getSourceIndent, getSourceIndents, parseSource, sortData, stringifySource } from '../../services/index.js'
|
||||
import { Store } from '../../Store.js'
|
||||
import { message } from '../../Utils.js'
|
||||
@@ -18,15 +16,14 @@ interface Editor {
|
||||
|
||||
type SourcePanelProps = {
|
||||
name: string,
|
||||
model: DataModel | undefined,
|
||||
blockStates: BlockStateRegistry | undefined,
|
||||
model: FileModel | undefined,
|
||||
doCopy?: number,
|
||||
doDownload?: number,
|
||||
doImport?: number,
|
||||
copySuccess: () => unknown,
|
||||
onError: (message: string | Error) => unknown,
|
||||
}
|
||||
export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doImport, copySuccess, onError }: SourcePanelProps) {
|
||||
export function SourcePanel({ name, model, doCopy, doDownload, doImport, copySuccess, onError }: SourcePanelProps) {
|
||||
const { locale } = useLocale()
|
||||
const [indent, setIndent] = useState(Store.getIndent())
|
||||
const [format, setFormat] = useState(Store.getFormat())
|
||||
@@ -40,8 +37,8 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm
|
||||
const textarea = useRef<HTMLTextAreaElement>(null)
|
||||
const editor = useRef<Editor>()
|
||||
|
||||
const getSerializedOutput = useCallback((model: DataModel, blockStates: BlockStateRegistry) => {
|
||||
let data = getOutput(model, blockStates)
|
||||
const getSerializedOutput = useCallback((model: FileModel) => {
|
||||
let data = model.data
|
||||
if (sort === 'alphabetically') {
|
||||
data = sortData(data)
|
||||
}
|
||||
@@ -51,9 +48,9 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm
|
||||
useEffect(() => {
|
||||
retransform.current = () => {
|
||||
if (!editor.current) return
|
||||
if (!model || !blockStates) return
|
||||
if (!model) return
|
||||
try {
|
||||
const output = getSerializedOutput(model, blockStates)
|
||||
const output = getSerializedOutput(model)
|
||||
editor.current.setValue(output)
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
@@ -72,8 +69,8 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm
|
||||
const value = editor.current.getValue()
|
||||
if (value.length === 0) return
|
||||
try {
|
||||
const data = await parseSource(value, format)
|
||||
model?.reset(DataModel.wrapLists(data), false)
|
||||
await parseSource(value, format)
|
||||
// TODO: import
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
e.message = `Error importing: ${e.message}`
|
||||
@@ -84,7 +81,7 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
}, [model, blockStates, indent, format, sort, highlighting])
|
||||
}, [model, indent, format, sort, highlighting])
|
||||
|
||||
useEffect(() => {
|
||||
if (highlighting) {
|
||||
@@ -145,10 +142,7 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm
|
||||
}
|
||||
}, [highlighting])
|
||||
|
||||
useModel(model, () => {
|
||||
if (!retransform.current) return
|
||||
retransform.current()
|
||||
})
|
||||
// TODO: when file contents change, retransform
|
||||
useEffect(() => {
|
||||
if (!retransform.current) return
|
||||
if (model) retransform.current()
|
||||
@@ -163,16 +157,16 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm
|
||||
}, [indent, format, sort, highlighting, braceLoaded])
|
||||
|
||||
useEffect(() => {
|
||||
if (doCopy && model && blockStates) {
|
||||
navigator.clipboard.writeText(getSerializedOutput(model, blockStates)).then(() => {
|
||||
if (doCopy && model) {
|
||||
navigator.clipboard.writeText(getSerializedOutput(model)).then(() => {
|
||||
copySuccess()
|
||||
})
|
||||
}
|
||||
}, [doCopy])
|
||||
|
||||
useEffect(() => {
|
||||
if (doDownload && model && blockStates && download.current) {
|
||||
const content = encodeURIComponent(getSerializedOutput(model, blockStates))
|
||||
if (doDownload && model && download.current) {
|
||||
const content = encodeURIComponent(getSerializedOutput(model))
|
||||
download.current.setAttribute('href', `data:text/json;charset=utf-8,${content}`)
|
||||
const fileName = name === 'pack_mcmeta' ? 'pack.mcmeta' : `${name}.${format}`
|
||||
download.current.setAttribute('download', fileName)
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
import type { DataModel } from '@mcschema/core'
|
||||
import { useErrorBoundary, useState } from 'preact/hooks'
|
||||
import { useErrorBoundary } from 'preact/hooks'
|
||||
import { useLocale } from '../../contexts/index.js'
|
||||
import { useModel } from '../../hooks/index.js'
|
||||
import { FullNode } from '../../schema/renderHtml.js'
|
||||
import type { BlockStateRegistry, VersionId } from '../../services/index.js'
|
||||
import type { FileModel } from '../../services/index.js'
|
||||
|
||||
type TreePanelProps = {
|
||||
version: VersionId,
|
||||
model: DataModel | undefined,
|
||||
blockStates: BlockStateRegistry | undefined,
|
||||
model: FileModel | undefined,
|
||||
onError: (message: string) => unknown,
|
||||
}
|
||||
export function Tree({ version, model, blockStates, onError }: TreePanelProps) {
|
||||
export function Tree({ model, onError }: TreePanelProps) {
|
||||
const { lang } = useLocale()
|
||||
if (!model || !blockStates || lang === 'none') return <></>
|
||||
if (!model || lang === 'none') return <></>
|
||||
|
||||
const [error] = useErrorBoundary(e => {
|
||||
onError(`Error rendering the tree: ${e.message}`)
|
||||
@@ -21,12 +16,7 @@ export function Tree({ version, model, blockStates, onError }: TreePanelProps) {
|
||||
})
|
||||
if (error) return <></>
|
||||
|
||||
const [, setState] = useState(0)
|
||||
useModel(model, () => {
|
||||
setState(state => state + 1)
|
||||
})
|
||||
|
||||
return <div class="tree" data-cy="tree">
|
||||
<FullNode {...{model, lang, version, blockStates}}/>
|
||||
{/* TODO: render tree */}
|
||||
</div>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user