main
ts 71 lines 3.1 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 { createElement as h, Fragment, MouseEvent, ReactElement } from 'react'
4 import { Link } from 'wouter'
5 import { getPrefixUrl, hIcon } from './misc'
6 import { DirEntry, state, useSnapState } from './state'
7 import { usePath, reloadList } from './useFetchList'
8 import { openFileMenu } from './fileMenu'
9 import { createFolder } from './upload'
10 import { dragFilesDestination } from './dragFiles'
11 import i18n from './i18n'
12 const { useI18N } = i18n
13
14 export function Breadcrumbs() {
15 const base = getPrefixUrl() + '/'
16 const currentPath = usePath().slice(base.length,-1)
17 const parent = base + currentPath.slice(0, currentPath.lastIndexOf('/') + 1)
18 let prev = base
19 const breadcrumbs = currentPath ? currentPath.split('/').map(x => [prev += x + '/', decodeURIComponent(x)]) : []
20 const {t} = useI18N()
21 return h(Fragment, {},
22 h(Breadcrumb, { id: 'breadcrumb-parent', path: parent, label: hIcon('parent', { alt: t`parent folder` }) }),
23 h(Breadcrumb, { id: 'breadcrumb-home', path: base, ...currentLabel(!currentPath, hIcon('home', { alt: t`home` })) }),
24 breadcrumbs.map(([path,label], i) =>
25 h(Breadcrumb, { key: path, path, ...currentLabel(i === breadcrumbs.length - 1, label) }) )
26 )
27
28 function currentLabel(isCurrent: boolean, label: string | ReactElement) {
29 return !isCurrent ? { label } : {
30 current: true,
31 label: h(Fragment, {}, label, hIcon('menu', { style: { position: 'relative', top: 1 } }))
32 }
33 }
34 }
35
36 function Breadcrumb({ path, label, current, id }: { id?: string, current?: boolean, path: string, label?: string | ReactElement }) {
37 const PAD = '\u00A0\u00A0' // make small elements easier to tap. Don't use min-width 'cause it requires display-inline that breaks word-wrapping
38 if (typeof label === 'string' && label.length < 3)
39 label = PAD + label + PAD
40 const {t} = useI18N()
41 const { props } = useSnapState()
42 const p = props?.can_archive ? '' : 'a'
43 return h(Link, {
44 className: 'breadcrumb',
45 href: path || '/',
46 ...!current && dragFilesDestination, // we don't really know if this folder allows upload, but in the worst case the user will get an error
47 id,
48 onClick(ev: MouseEvent) {
49 if (!current) return
50 ev.preventDefault()
51 void openFileMenu(new DirEntry(decodeURIComponent(path), { p, comment: props?.comment }), ev, [
52 props?.can_upload && {
53 id: 'create-folder',
54 label: t`Create folder`,
55 icon: 'folder',
56 onClick: createFolder,
57 },
58 {
59 id: 'reload',
60 label: t`Reload`,
61 icon: 'reload',
62 onClick() {
63 state.remoteSearch = undefined
64 state.stopSearch?.()
65 reloadList()
66 }
67 }
68 ])
69 }
70 }, label)
71 }