plugins: added entryIcon frontend-event
Massimo Melina committed
May 20, 2023 at 15:15 UTC
0b436c63505634bac1c49b54808b598280e245af
4 files changed
+19
-6
dev-plugins.md
+5
@@ -196,6 +196,10 @@ This is a list of available frontend-events, with respective object parameter an
196
- you receive each entry of the list, and optionally produce HTML code that will be added after the name of the entry.
197
- parameter `{ entry: Entry }` (refer above for Entry object)
198
- output `Html`
199
+- `entryIcon`
200
+ - you receive an entry of the list and optionally produce HTML that will be used in place of the standard icon.
201
+ - parameter `{ entry: Entry }` (refer above for Entry object)
202
+ - output `Html`
203
- `beforeHeader` & `afterHeader`
204
- use this to produce content that should go right before/after the `header` part
205
- output `Html`
@@ -253,6 +257,7 @@ HFS will scan through them in inverted alphabetical order searching for a compat
257
- HFS.apiCall, reloadList, logout, h, React, state, t, _, dialogLib
258
- second parameter of onEvent is now deprecated
259
- renamed: additionalEntryProps > additionalEntryDetails & entry-props > entry-details
260
+ - entryIcon event
261
- 8 (v0.43.0)
262
- entry.name & .uri
263
- tools.dialogLib
frontend/src/BrowseFiles.ts
+5
-1
@@ -235,7 +235,11 @@ const Entry = memo(({ entry, midnight, separator }: EntryProps) => {
235
})
236
237
export function getEntryIcon(entry: DirEntry) {
238
- return hIcon(entry.isFolder ? 'folder' : 'file')
238
+ return h(CustomCode, {
239
+ name: 'entryIcon',
240
+ props: { entry },
241
+ ifEmpty: () => hIcon(entry.isFolder ? 'folder' : 'file')
242
+ })
243
}
244
245
const EntryDetails = memo(({ entry, midnight }: { entry: DirEntry, midnight: Date }) => {
frontend/src/components.ts
+6
-4
@@ -4,6 +4,7 @@ import { getHFS, hfsEvent, hIcon } from './misc'
4
import {
5
ChangeEvent,
6
createElement as h,
7
+ FC,
8
Fragment,
9
HTMLAttributes,
10
InputHTMLAttributes,
@@ -59,15 +60,15 @@ export function Select({ onChange, value, options, ...props }:SelectProps) {
60
}, options.map(({ value, label }) => h('option', { key:value, value }, label)))
61
}
62
62
-export function Html({ code, ...rest }:{ code:string } & HTMLAttributes<any>) {
63
+export function Html({ code, ...rest }: { code:string } & HTMLAttributes<any>) {
64
return !code ? null : h('span', { ...rest, ref(x) {
65
if (x)
66
x.append(document.createRange().createContextualFragment(code))
67
} })
68
}
69
69
-export function CustomCode({ name, props }: any) {
70
- return h(Fragment, {}, useMemo(() => {
70
+export function CustomCode({ name, props, ifEmpty }: { name: string, props?: any, ifEmpty?: FC }) {
71
+ const children = useMemo(() => {
72
const ret = hfsEvent(name, props)
73
.filter(x => x === 0 || x)
74
.map((x, key) => isValidElement(x) ? h(Fragment, { key }, x)
@@ -77,5 +78,6 @@ export function CustomCode({ name, props }: any) {
78
if (html?.trim?.())
79
ret.push(h(Html, { key: 'x', code: html }))
80
return ret
80
- }, props ? Object.values(props) : []))
81
+ }, props ? Object.values(props) : [])
82
+ return children.length || !ifEmpty ? h(Fragment, {}, children) : h(ifEmpty)
83
}
\ No newline at end of file
frontend/src/index.scss
+3
-1
@@ -68,12 +68,13 @@ input[type=checkbox] {
68
label input[type=checkbox] {
69
margin-right: .8em;
70
}
71
-select { text-align: center; } /* it is surely cooler on the options dialog */
71
+select { text-align: center; } // it is surely cooler on the options dialog
72
73
.hidden { display: none !important }
74
75
.icon {
76
font-size: 1.2em;
77
+ height: 1.18em; min-width: 1.4em; // give similar size to <img> icons
78
}
79
.emoji-icon {
80
display: inline-block;
@@ -247,6 +248,7 @@ ul.dir {
248
}
249
& .icon {
250
margin-right: .3em;
251
+ vertical-align: text-bottom; // give similar aligning to <img> icons
252
}
253
&:hover {
254
text-decoration: underline;