expose entry.uri to plugins

Massimo Melina committed Apr 2, 2023 at 13:01 UTC d63021ff7a983a86b675952ea5ef0366cbc14448
4 files changed +34 -24
dev-plugins.md
+6 -1
@@ -175,7 +175,9 @@ This is a list of available frontend-events, with respective object parameter an
175 - parameter `{ entry: Entry }`
176
177 The `Entry` type is an object with the following properties:
178 - - `n: string` name of the entry, including relative path in some cases.
178 + - `name: string` name of the entry.
179 + - `n: string` name of the entry, including relative path when searched in sub-folders.
180 + - `uri: string` relative url of the entry.
181 - `s?: number` size of the entry, in bytes. It may be missing, for example for folders.
182 - `t?: Date` generic timestamp, combination of creation-time and modified-time.
183 - `c?: Date` creation-time.
@@ -222,6 +224,9 @@ HFS will scan through them in inverted alphabetical order searching for a compat
224
225 ## API version history
226
227 +- 8 (v0.43.0)
228 + - entry.name & .uri
229 + - tools.dialogLib
230 - 7 (v0.42.0)
231 - event.fileMenu
232 - HFS.SPECIAL_URI, PLUGINS_PUB_URI, FRONTEND_URI,
frontend/src/BrowseFiles.ts
+13 -20
@@ -16,7 +16,7 @@ import { Checkbox, CustomCode, Spinner } from './components'
16 import { Head } from './Head'
17 import { state, useSnapState } from './state'
18 import { alertDialog } from './dialog'
19 -import useFetchList, { usePath } from './useFetchList'
19 +import useFetchList, { pathDecode, usePath } from './useFetchList'
20 import { useAuthorized } from './login'
21 import { acceptDropFiles, enqueue } from './upload'
22 import _ from 'lodash'
@@ -24,7 +24,7 @@ import { t, useI18N } from './i18n'
24 import { deleteFiles } from './menu'
25
26 export interface DirEntry { n:string, s?:number, m?:string, c?:string,
27 - ext:string, isFolder:boolean, t?:Date } // we memoize these value for speed
27 + name: string, uri: string, ext:string, isFolder:boolean, t?:Date } // we memoize these value for speed
28 export type DirList = DirEntry[]
29
30 export function BrowseFiles() {
@@ -177,12 +177,10 @@ function useMidnight() {
177 const PAGE_SEPARATOR_CLASS = 'page-separator'
178
179 const Entry = memo((entry: DirEntry & { midnight: Date, separator?: string }) => {
180 - let { n: relativePath, isFolder, separator } = entry
180 + const { name, uri, isFolder, separator } = entry
181 const base = usePath()
182 const { showFilter, selected, can_delete } = useSnapState()
183 - const href = fixUrl(relativePath)
184 - const containerDir = isFolder ? '' : relativePath.substring(0, relativePath.lastIndexOf('/')+1)
185 - const name = relativePath.substring(containerDir.length)
183 + const containerDir = isFolder ? '' : uri.substring(0, uri.lastIndexOf('/')+1)
184 let className = isFolder ? 'folder' : 'file'
185 if (separator)
186 className += ' ' + PAGE_SEPARATOR_CLASS
@@ -190,18 +188,18 @@ const Entry = memo((entry: DirEntry & { midnight: Date, separator?: string }) =>
188 const menuOnLink = getHFS().fileMenuOnLink
189 return h('li', { className, label: separator },
190 showFilter && h(Checkbox, {
193 - value: selected[relativePath],
191 + value: selected[uri],
192 onChange(v){
193 if (v)
196 - return state.selected[relativePath] = true
197 - delete state.selected[relativePath]
194 + return state.selected[uri] = true
195 + delete state.selected[uri]
196 },
197 }),
200 - isFolder ? h(Link, { to: base + href }, ico, relativePath.slice(0,-1))
198 + isFolder ? h(Link, { to: base + uri }, ico, entry.n.slice(0,-1))
199 : h(Fragment, {},
202 - containerDir && h(Link, { to: base+fixUrl(containerDir), className:'container-folder' }, ico, containerDir ),
200 + containerDir && h(Link, { to: base + containerDir, className:'container-folder' }, ico, pathDecode(containerDir) ),
201 h('a', {
204 - href,
202 + href: uri,
203 onClick(ev: MouseEvent) {
204 if (menuOnLink)
205 openFileMenu(ev)
@@ -220,9 +218,9 @@ const Entry = memo((entry: DirEntry & { midnight: Date, separator?: string }) =>
218 if (ev.altKey || ev.ctrlKey || ev.metaKey) return
219 ev.preventDefault()
220 const menu = [
223 - menuOnLink && { label: t('file_open', "Open"), href, target: '_blank', icon: 'play' },
224 - { label: t`Download`, href: href + '?dl', icon: 'download' },
225 - can_delete && { label: t`Delete`, icon: 'trash', onClick: () => deleteFiles([href], base) }
221 + menuOnLink && { label: t('file_open', "Open"), href: uri, target: '_blank', icon: 'play' },
222 + { label: t`Download`, href: uri + '?dl', icon: 'download' },
223 + can_delete && { label: t`Delete`, icon: 'trash', onClick: () => deleteFiles([uri], base) }
224 ]
225 const res = hfsEvent('fileMenu', { entry })
226 if (res)
@@ -255,11 +253,6 @@ const Entry = memo((entry: DirEntry & { midnight: Date, separator?: string }) =>
253 }
254 })
255
258 -function fixUrl(s:string) {
259 - return s.replace(/[#%]/g, encodeURIComponent)
260 -}
261 -
262 -
256 const EntryProps = memo((entry: DirEntry & { midnight: Date }) => {
257 const { t: time, s } = entry
258 const today = time && time > entry.midnight
frontend/src/useFetchList.ts
+14 -2
@@ -18,6 +18,14 @@ export function usePath() {
18 return useLocation().pathname
19 }
20
21 +export function pathEncode(s: string) {
22 + return encodeURI(s).replace(/#/g, encodeURIComponent)
23 +}
24 +
25 +export function pathDecode(s: string) {
26 + return decodeURI(s).replace(/%23/g, '#')
27 +}
28 +
29 export default function useFetchList() {
30 const snap = useSnapState()
31 const desiredPath = usePath()
@@ -103,8 +111,12 @@ export default function useFetchList() {
111 }
112 state.can_upload ??= false
113 state.can_delete ??= false
106 - if (entry.add)
107 - buffer.push(entry.add)
114 + const { add } = entry
115 + if (add) {
116 + add.uri = pathEncode(add.n)
117 + add.name = add.n.slice(add.n.lastIndexOf('/')+1)
118 + buffer.push(add)
119 + }
120 }
121 if (src?.readyState === src?.CLOSED)
122 return state.stopSearch?.()
src/const.ts
+1 -1
@@ -17,7 +17,7 @@ export const VERSION = pkg.version
17 export const DAY = 86_400_000
18 export const SESSION_DURATION = DAY
19
20 -export const API_VERSION = 7 // fileMenu event
20 +export const API_VERSION = 8 // entry.uri
21 export const COMPATIBLE_API_VERSION = 1 // while changes in the api are not breaking, this number stays the same, otherwise is made equal to API_VERSION
22
23 export const SPECIAL_URI = '/~/'