import { useCallback, useMemo, useState } from 'preact/hooks' import config from '../../Config.js' import { useLocale, useProject } from '../../contexts/index.js' import { useModal } from '../../contexts/Modal.jsx' import { useSpyglass } from '../../contexts/Spyglass.jsx' import type { VersionId } from '../../services/index.js' import { DEFAULT_VERSION } from '../../services/index.js' import { PROJECTS_URI } from '../../services/Spyglass.js' import { hexId, message, readZip } from '../../Utils.js' import { Btn, BtnMenu, FileUpload, Octicon, TextInput } from '../index.js' import { Modal } from '../Modal.js' export function ProjectCreation() { const { locale } = useLocale() const { hideModal } = useModal() const { projects, createProject, changeProject } = useProject() const { client } = useSpyglass() const [name, setName] = useState('') const [namespace, setNamespace] = useState('') const [version, setVersion] = useState(DEFAULT_VERSION) const [file, setFile] = useState(undefined) const [creating, setCreating] = useState(false) const onUpload = (file: File) => { if (file.type.match(/^application\/(x-)?zip(-compressed)?$/)) { if (name.length === 0) { setName(file.name .replace(/\.zip$/, '') .replaceAll(/[ _-]+/g, ' ')) } setFile(file) } } const onCreate = useCallback(async () => { setCreating(true) const rootUri = `${PROJECTS_URI}${hexId()}/` await client.fs.mkdir(rootUri) createProject({ name, namespace, version, storage: { type: 'indexeddb', rootUri } }) changeProject(name) if (file) { readZip(file).then(async (entries) => { await Promise.all(entries.map((entry) => { const path = entry[0].startsWith('/') ? entry[0].slice(1) : entry[0] return client.fs.writeFile(rootUri + path, entry[1]) })) hideModal() }).catch((e) => { // TODO: handle errors console.warn(`Error importing data pack: ${message(e)}`) hideModal() }) } else { hideModal() } }, [createProject, changeProject, client, version, name, namespace, file]) const invalidName = useMemo(() => { return projects.map(p => p.name.trim().toLowerCase()).includes(name.trim().toLowerCase()) }, [projects, name]) const invalidNamespace = useMemo(() => { return !(namespace.length === 0 || namespace.match(/^(?:[a-z0-9._-]+:)?[a-z0-9/._-]+$/)) }, [namespace]) const versions = config.versions.map(v => v.id as VersionId).reverse() return

{locale('project.create')}

{!creating && invalidName &&
{Octicon.issue_opened}
}
{!creating && invalidNamespace &&
{Octicon.issue_opened}
}
{versions.map(v => setVersion(v)} /> )}
}