plugins: api.notifyClient + HFS.getNotifications
Massimo Melina committed
Jun 4, 2024 at 12:40 UTC
0be2f0e8407fb3fb6f03a21d028ef740f07b2f21
7 files changed
+42
-10
dev-plugins.md
+30
-1
@@ -203,6 +203,8 @@ The `api` object you get as parameter of the `init` contains the following:
203
The specified file name will be stored in the "storage" folder of the plugin, by default.
204
Refer to [dedicated documentation](https://www.npmjs.com/package/@rejetto/kvstorage) for details.
205
206
+- `notifyClient(channel: string, eventName: string, data?: any)` send a message to those frontends that are on the same channel.
207
+
208
## Front-end specific
209
210
The following information applies to the default front-end, and may not apply to a custom one.
@@ -235,6 +237,8 @@ The HFS objects contains many properties:
237
- `Icon: ReactComponent` Properties:
238
- `name: string` refer to file `icons.ts` for names, but you can also enter an emoji instead.
239
- `useBatch: (worker, job) => any`
240
+- `getNotifications(channel: string, cb: (eventName: string, data:any) => void)`
241
+ receive messages when the backend uses `notifyClient` on the same channel.
242
243
The following properties are accessible only immediately at top-level; don't call it later in a callback.
244
- `getPluginConfig()` returns object of all config keys that are declared frontend-accessible by this plugin.
@@ -421,6 +425,30 @@ This section is still partially documented, and you may need to have a look at t
425
- `publicIpsChanged`
426
- parameters: { IPs, IP4, IP6, IPX }
427
428
+# Notifications (backend-to-frontend events)
429
+
430
+You can send messages from the backend (plugin.js) using `api.notifyClient`, and receive on the frontend
431
+using `HFS.getNotifications`. Find details in the reference above.
432
+
433
+Example:
434
+
435
+`plugin.js`
436
+```js
437
+exports.init = api => {
438
+ const t = setInterval(() => api.notifyClient('test', 'message', 'hello'), 5000)
439
+ return {
440
+ frontend_js: 'main.js',
441
+ unload() {
442
+ clearInterval(t)
443
+ }
444
+ }
445
+}
446
+```
447
+`public/main.js`
448
+```js
449
+HFS.getNotifications('test', console.log)
450
+```
451
+
452
# The `ctx` object
453
454
HFS is currently based on [Koa](https://koajs.com), so you'll see some things related to it in the backend API.
@@ -546,13 +574,14 @@ If you want to override a text regardless of the language, use the special langu
574
575
## API version history
576
549
-- 8.82 (v0.53.0)
577
+- 8.84 (v0.53.0)
578
- api.openDb
579
- frontend event: menuZip
580
- config.type:username
581
- api.events class has changed
582
- frontend event "fileMenu": changed props format
583
- api.getConfig() without parameters
584
+ - api.notifyClient + HFS.getNotifications
585
- 8.72 (v0.52.0)
586
- HFS.toast
587
- HFS.misc functions
frontend/src/misc.ts
+2
-1
@@ -6,7 +6,7 @@ import { newDialog, toast } from './dialog'
6
import { Icon } from './icons'
7
import { Dict, getHFS, HTTP_MESSAGES, useBatch } from '@hfs/shared'
8
import * as misc from '../../src/cross'
9
-import { apiCall, useApi } from '@hfs/shared/api'
9
+import { apiCall, getNotifications, useApi } from '@hfs/shared/api'
10
import { state } from './state'
11
import { t } from './i18n'
12
import * as dialogLib from './dialog'
@@ -66,6 +66,7 @@ const tools = {
66
Object.assign(getHFS(), {
67
...tools,
68
emit: hfsEvent,
69
+ getNotifications,
70
onEvent(name: string, cb: (params:any, tools: any, output:any) => any) {
71
const key = 'hfs.' + name
72
document.addEventListener(key, wrapper)
frontend/src/upload.ts
+2
-2
@@ -11,7 +11,7 @@ import _ from 'lodash'
11
import { INTERNAL_Snapshot, proxy, ref, snapshot, subscribe, useSnapshot } from 'valtio'
12
import { alertDialog, confirmDialog, promptDialog, toast } from './dialog'
13
import { reloadList } from './useFetchList'
14
-import { apiCall, getNotification } from '@hfs/shared/api'
14
+import { apiCall, getNotifications } from '@hfs/shared/api'
15
import { state, useSnapState } from './state'
16
import { Link } from 'react-router-dom'
17
import { t } from './i18n'
@@ -345,7 +345,7 @@ async function startUpload(toUpload: ToUpload, to: string, resume=0) {
345
async function subscribeNotifications() {
346
if (notificationChannel) return
347
notificationChannel = 'upload-' + randomId()
348
- notificationSource = await getNotification(notificationChannel, async (name, data) => {
348
+ notificationSource = await getNotifications(notificationChannel, async (name, data) => {
349
const {uploading} = uploadState
350
if (!uploading) return
351
if (name === 'upload.resumable') {
shared/api.ts
+1
-1
@@ -172,7 +172,7 @@ export function useApiEvents<T=any>(cmd: string, params: Dict={}) {
172
return { data, loading, error }
173
}
174
175
-export async function getNotification(channel: string, cb: (name: string, data:any) => void): Promise<EventSource> {
175
+export async function getNotifications(channel: string, cb: (name: string, data:any) => void): Promise<EventSource> {
176
return new Promise(resolve => {
177
const ret = apiEvents('get_notifications', { channel }, (type, entries) => {
178
if (type === 'connected')
src/const.ts
+1
-1
@@ -7,7 +7,7 @@ import { mkdirSync } from 'fs'
7
import { basename, dirname, join } from 'path'
8
export * from './cross-const'
9
10
-export const API_VERSION = 8.83
10
+export const API_VERSION = 8.84
11
export const COMPATIBLE_API_VERSION = 1 // while changes in the api are not breaking, this number stays the same, otherwise it is made equal to API_VERSION
12
export const HFS_REPO = 'rejetto/hfs'
13
src/frontEndApis.ts
+4
-4
@@ -149,10 +149,10 @@ export const frontEndApis: ApiHandlers = {
149
},
150
}
151
152
-export function notifyClient(ctx: Koa.Context, name: string, data: any) {
153
- const {notificationChannel} = ctx.query
154
- if (notificationChannel)
155
- events.emit(NOTIFICATION_PREFIX + notificationChannel, name, data)
152
+export function notifyClient(channel: string | Koa.Context, name: string, data: any) {
153
+ if (typeof channel !== 'string')
154
+ channel = String(channel.query.notificationChannel)
155
+ events.emit(NOTIFICATION_PREFIX + channel, name, data)
156
}
157
158
const NOTIFICATION_PREFIX = 'notificationChannel:'
src/plugins.ts
+2
@@ -23,6 +23,7 @@ import { dirname, join, resolve } from 'path'
23
import { watchLoadCustomHtml } from './customHtml'
24
import { KvStorage, KvStorageOptions } from '@rejetto/kvstorage'
25
import { onProcessExit } from './first'
26
+import { notifyClient } from './frontEndApis'
27
28
export const PATH = 'plugins'
29
export const DISABLING_SUFFIX = '-disabled'
@@ -110,6 +111,7 @@ async function initPlugin<T>(pl: any, morePassedToInit?: T) {
111
log: console.log,
112
getHfsConfig: getConfig,
113
customApiCall,
114
+ notifyClient,
115
...morePassedToInit
116
}))
117
}