main
ts 76 lines 2.92 KB
Raw
1 // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3 import { useLocation } from 'wouter'
4 import { createElement as h } from 'react'
5 import { BrowseFiles } from "./BrowseFiles"
6 import { alertDialog, Dialogs } from './dialog'
7 import useTheme from "./useTheme"
8 import { state, useSnapState } from './state'
9 import { acceptDropFiles } from './upload'
10 import { enqueueUpload, getFilePath, uploadState } from './uploadQueue'
11 import { proxy, ref, useSnapshot } from "valtio"
12 import { Spinner } from "./components"
13 import { enforceStarting, getHFS, getPrefixUrl, loadScript } from '@hfs/shared'
14 import { Toasts } from './toasts'
15 import i18n from './i18n'
16 const { t } = i18n
17
18 const { i18nWrapperProps } = i18n
19
20 export default function App() {
21 useTheme()
22 const go = useLocation()[1] // expose navigate function for programmatic usage
23 getHFS().navigate = (uri: string) => go(getPrefixUrl() + enforceStarting('/', uri))
24
25 const { ready } = useSnapshot(pageState) // wait for all plugins to be loaded
26 const { messageOnly } = useSnapState()
27 if (messageOnly)
28 return h('h1', { style: { textAlign: 'center'} }, messageOnly)
29 if (!ready)
30 return h(Spinner, { style: { margin: 'auto' } })
31 installScript() // do this only after React has started working
32 return h('div', {
33 ...i18nWrapperProps(),
34 ...acceptDropFiles((files, to) => {
35 if (uploadState.uploadDialogIsOpen) // in this case the upload is not started until confirmed
36 uploadState.adding.push(...files.map(f => ({ file: ref(f), path: getFilePath(f), to })))
37 else
38 state.props?.can_upload ? enqueueUpload(files.map(file => ({ file, path: getFilePath(file) })), location.pathname + to)
39 : alertDialog(t("Upload not available"), 'warning')
40 })
41 },
42 h(Toasts),
43 h(Dialogs, {},
44 h(BrowseFiles)
45 ),
46 )
47 }
48
49 let scriptAdded = false
50 function installScript() {
51 if (scriptAdded) return // only once
52 scriptAdded = true
53 const s = getHFS().customHtml?.script // we don't need frontend-event-generated code, i guess
54 if (!s) return
55 const el = document.createElement('script')
56 el.type = 'text/javascript'
57 el.text = s
58 el.setAttribute('plugin', el.id = '?customHtmlScript')
59 document.head.appendChild(el)
60 }
61
62 export function navigate(uri: string) {
63 return getHFS().navigate(uri)
64 }
65
66 const pageState = proxy({ ready: document.readyState === 'complete' })
67 document.addEventListener('readystatechange', () => {
68 pageState.ready = document.readyState === 'complete'
69 })
70
71 // load plugins' now, as vite-legacy delayed app's loading
72 ;(async () => { // without this wrapper I see a longer delay
73 for (const [plugin, files] of Object.entries(getHFS().loadScripts))
74 if (Array.isArray(files)) for (const f of files)
75 await loadScript(f, { plugin })
76 })()