@samitouri / QOSami-HFS / commits / 69bbf3df

plugins: api.events.stop

Massimo Melina committed Jun 5, 2024 at 10:38 UTC 69bbf3df20ed9e095c7db84e294c04ea0a56fb37
6 files changed +22 -23
dev-plugins.md
+1 -1
@@ -383,7 +383,7 @@ api.events.on('deleting', async () => your-code-here)
383
384 ### Stop, the way you prevent default behavior
385
386 -Some events allow you to stop their default behavior, by returning `false`.
386 +Some events allow you to stop their default behavior, by returning `api.events.stop`.
387 This is reported in the list below with the word "stoppable".
388
389 ```js
frontend/src/fileMenu.ts
+13 -13
@@ -99,25 +99,25 @@ export function openFileMenu(entry: DirEntry, ev: MouseEvent, addToMenu: (FileMe
99 ),
100 entry.cantOpen && h(Fragment, {}, hIcon('password', { style: { marginRight: '.5em' } }), t(MISSING_PERM)),
101 h('div', { className: 'file-menu' },
102 - dontBotherWithKeys(menu.map((e: FileMenuEntry, i) => // render menu entries
103 - isValidElement(e) ? e
104 - : e?.label && h('a', {
102 + dontBotherWithKeys(menu.map((entry: FileMenuEntry, i) => // render menu entries
103 + isValidElement(entry) ? entry
104 + : entry?.label && h('a', {
105 key: i,
106 href: '#',
107 - ..._.omit(e, ['label', 'icon', 'toggled']),
108 - id: e.id && `menu-entry-${e.id}`,
109 - className: e.toggled ? 'toggled' : undefined,
110 - async onClick(event: MouseEvent) {
111 - if (!e.href)
112 - event.preventDefault()
113 - if (false !== await e.onClick?.(event))
107 + ..._.omit(entry, ['label', 'icon', 'toggled']),
108 + id: entry.id && `menu-entry-${entry.id}`,
109 + className: entry.toggled ? 'toggled' : undefined,
110 + async onClick(ev: MouseEvent) {
111 + if (!entry.href)
112 + ev.preventDefault()
113 + if (false !== await entry.onClick?.(ev))
114 close()
115 }
116 },
117 - hIcon(e.icon || 'file'),
117 + hIcon(entry.icon || 'file'),
118 h('label', { style: { display: 'flex', flexDirection: 'column' } },
119 - h('div', {}, e.label),
120 - h('small', {}, e.subLabel) )
119 + h('div', {}, entry.label),
120 + h('small', {}, entry.subLabel) )
121 )
122 ))
123 )
frontend/src/upload.ts
+3 -3
@@ -64,10 +64,10 @@ setInterval(() => {
64 uploadState.eta = uploadState.speed && Math.round(left / uploadState.speed)
65 }, 5_000)
66
67 -window.onbeforeunload = e => {
67 +window.onbeforeunload = ev => {
68 if (!uploadState.qs.length) return
69 - e.preventDefault()
70 - return e.returnValue = t("Uploading") // modern browsers ignore this message
69 + ev.preventDefault()
70 + return ev.returnValue = t("Uploading") // modern browsers ignore this message
71 }
72
73 let reloadOnClose = false
src/events.ts
+3 -4
@@ -6,6 +6,7 @@ const LISTENERS_SUFFIX = '\0listeners'
6
7 export class BetterEventEmitter {
8 protected listeners = new Map<string, Listeners>()
9 + stop = Symbol()
10 on(event: string | string[], listener: Listener, { warnAfter=10 }={}) {
11 if (typeof event === 'string')
12 event = [event]
@@ -56,15 +57,13 @@ export class BetterEventEmitter {
57 ret.push(res)
58 }
59 return Object.assign(ret, {
59 - preventDefault: () => ret.some(r => r === false)
60 + isDefaultPrevented: () => ret.some(r => r === this.stop),
61 })
62 }
63 emitAsync(event: string, ...args: any[]) {
64 const ret = Promise.all(this.emit(event, ...args) || [])
65 return Object.assign(ret, {
65 - async preventDefault() {
66 - return (await ret).some((x: any) => x === false)
67 - }
66 + isDefaultPrevented: async () => (await ret).some((r: any) => r === this.stop)
67 })
68 }
69 }
src/misc.ts
+1 -1
@@ -132,7 +132,7 @@ export async function deleteNode(ctx: Koa.Context, node: VfsNode, uri: string) {
132 if (statusCodeForMissingPerm(node, 'can_delete', ctx))
133 return ctx.status
134 try {
135 - if (await events.emitAsync('deleting', { node, ctx }).preventDefault())
135 + if (await events.emitAsync('deleting', { node, ctx }).isDefaultPrevented())
136 return null // stop
137 ctx.logExtra(null, { target: decodeURI(uri) })
138 await rm(source, { recursive: true })
src/upload.ts
+1 -1
@@ -116,7 +116,7 @@ export function uploadWriter(base: VfsNode, path: string, ctx: Koa.Context) {
116 // allow plugins to mess with the write-stream, because the read-stream can be complicated in case of multipart
117 const obj = { ctx, writeStream }
118 const resEvent = events.emit('uploadStart', obj)
119 - if (resEvent?.preventDefault()) return
119 + if (resEvent?.isDefaultPrevented()) return
120
121 const fileStream = resuming ? fs.createWriteStream(resumable, { flags: 'r+', start: resume })
122 : fs.createWriteStream(tempName)