Repository navigation
Expand file tree
/
Copy pathpreload.js
More file actions
75 lines (62 loc) · 3.41 KB
/
Copy pathpreload.js
File metadata and controls
75 lines (62 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
const { contextBridge, ipcRenderer } = require('electron')
// Build a CRUD surface bound to a given IPC channel prefix. `data` binds to
// the scoped `~/.general-app/` handlers; `fs` binds to the unscoped handlers
// that accept absolute or `~/` paths. Markdown parsing runs in the main
// process — preload is sandboxed and can't require `js-yaml`.
function makeApi(prefix) {
return {
read: (name) => ipcRenderer.invoke(`${prefix}-read`, name),
write: (name, text) => ipcRenderer.invoke(`${prefix}-write`, name, text),
readBytes: (name) => ipcRenderer.invoke(`${prefix}-read-bytes`, name),
writeBytes: (name, bytes) => ipcRenderer.invoke(`${prefix}-write-bytes`, name, bytes),
readJSON: async (name) => {
const r = await ipcRenderer.invoke(`${prefix}-read`, name)
if (!r.ok) return r
try { return { ok: true, data: JSON.parse(r.data) } }
catch (err) { return { ok: false, error: err.message } }
},
writeJSON: (name, obj) => ipcRenderer.invoke(`${prefix}-write`, name, JSON.stringify(obj, null, 2)),
readBlob: async (name, type) => {
const r = await ipcRenderer.invoke(`${prefix}-read-bytes`, name)
if (!r.ok) return r
return { ok: true, data: new Blob([r.data], type ? { type } : undefined) }
},
writeBlob: async (name, blob) => {
const buf = await blob.arrayBuffer()
return ipcRenderer.invoke(`${prefix}-write-bytes`, name, buf)
},
readMarkdown: (name) => ipcRenderer.invoke(`${prefix}-read-markdown`, name),
writeMarkdown: (name, doc) => ipcRenderer.invoke(`${prefix}-write-markdown`, name, doc),
delete: (name) => ipcRenderer.invoke(`${prefix}-delete`, name),
exists: (name) => ipcRenderer.invoke(`${prefix}-exists`, name),
list: (subpath) => ipcRenderer.invoke(`${prefix}-list`, subpath || (prefix === 'data' ? '' : '~')),
}
}
const data = makeApi('data')
const fs = makeApi('fs')
contextBridge.exposeInMainWorld('app', {
getSettings: () => ipcRenderer.invoke('get-settings'),
saveSettings: (s) => ipcRenderer.invoke('save-settings', s),
onShowSettings: (cb) => { ipcRenderer.removeAllListeners('show-settings'); ipcRenderer.on('show-settings', cb) },
onSourceChanged: (cb) => { ipcRenderer.removeAllListeners('source-changed'); ipcRenderer.on('source-changed', cb) },
onToast: (cb) => { ipcRenderer.removeAllListeners('show-toast'); ipcRenderer.on('show-toast', (_e, msg) => cb(msg)) },
reloadUI: () => ipcRenderer.invoke('reload-ui'),
getUpdateStatus: () => ipcRenderer.invoke('get-update-status'),
prepareUpdate: () => ipcRenderer.invoke('prepare-update'),
finalizeUpdate: () => ipcRenderer.invoke('finalize-update'),
openPath: (p) => ipcRenderer.invoke('open-path', p),
resetUI: () => ipcRenderer.invoke('reset-ui'),
getUIPaths: () => ipcRenderer.invoke('get-ui-paths'),
checkForAppUpdate: () => ipcRenderer.invoke('check-for-app-update'),
downloadAppUpdate: () => ipcRenderer.invoke('download-app-update'),
installAppUpdate: () => ipcRenderer.invoke('install-app-update'),
getAppUpdateState: () => ipcRenderer.invoke('get-app-update-state'),
onAppUpdateState: (cb) => {
ipcRenderer.removeAllListeners('app-update-state')
ipcRenderer.on('app-update-state', (_e, s) => cb(s))
},
getAppVersion: () => ipcRenderer.invoke('get-app-version'),
isDevMode: () => ipcRenderer.invoke('is-dev-mode'),
data,
fs,
})