mirror of https://codeberg.org/pzp/zooboard.git
pretty good use of gc, conductor, invites, hubs
This commit is contained in:
parent
bb79bb05a1
commit
d4e1cc8481
116
main.js
116
main.js
|
@ -1,8 +1,9 @@
|
|||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
const { app, BrowserWindow, ipcMain, shell } = require('electron')
|
||||
const Path = require('node:path')
|
||||
const URL = require('node:url')
|
||||
const p = require('node:util').promisify
|
||||
const Keypair = require('ppppp-keypair')
|
||||
const awaitable = require('pull-awaitable')
|
||||
|
||||
// WARNING monkey patch! --------------------------------------
|
||||
const na = require('sodium-native')
|
||||
|
@ -98,14 +99,33 @@ async function loadAccount() {
|
|||
if (globalAccountID !== null) {
|
||||
return { id: globalAccountID, name: globalAccountName }
|
||||
}
|
||||
|
||||
// Kickstart
|
||||
await peer.db.loaded()
|
||||
const id = await p(peer.db.account.findOrCreate)({ subdomain: 'account' })
|
||||
const id = await p(peer.db.account.findOrCreate)({ subdomain: 'person' })
|
||||
globalAccountID = id
|
||||
await p(peer.set.load)(id)
|
||||
await p(peer.dict.load)(id)
|
||||
peer.conductor.start(
|
||||
id,
|
||||
[
|
||||
['profile@dict', 'zooboardElements@newest-100', 'hubs@set'],
|
||||
['profile@dict', 'zooboardElements@newest-100'],
|
||||
],
|
||||
64_000_000
|
||||
)
|
||||
|
||||
// Read hubs
|
||||
const multiaddrs = peer.set.values('hubs')
|
||||
for (const multiaddr of multiaddrs) {
|
||||
scheduleWithHub(multiaddr)
|
||||
}
|
||||
|
||||
// Read profile
|
||||
const profile = peer.dict.read(id, 'profile')
|
||||
const name = profile?.name ?? ''
|
||||
globalAccountName = name
|
||||
|
||||
return { id, name }
|
||||
}
|
||||
|
||||
|
@ -115,6 +135,7 @@ async function setProfileName(ev, name) {
|
|||
}
|
||||
|
||||
async function writeElements(ev, actions) {
|
||||
await loadAccount() // FIXME: ideally the frontend shouldn't do this
|
||||
if (globalAccountID === null) throw new Error('account not loaded')
|
||||
for (const action of actions) {
|
||||
await p(peer.db.feed.publish)({
|
||||
|
@ -147,18 +168,105 @@ function subscribeToReadElements() {
|
|||
})
|
||||
}
|
||||
|
||||
async function scheduleWithHub(multiaddr) {
|
||||
const hubRPC = await p(peer.net.connect)(multiaddr)
|
||||
|
||||
// FIXME: this should be in the ppppp-net scheduler
|
||||
for await (const attendants of awaitable(hubRPC.hub.attendants())) {
|
||||
for (const attendant of attendants) {
|
||||
if (attendant !== peer.pubkey) {
|
||||
const tunnelMultiaddr = `/tunnel/${hubRPC.shse.pubkey}.${attendant}/shse/${attendant}`
|
||||
peer.net.connect(tunnelMultiaddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handlePPPPPUri(uri) {
|
||||
if (!uri.startsWith('ppppp://')) return
|
||||
console.log('handlePPPPPUri', uri)
|
||||
const commands = peer.invite.parse(uri)
|
||||
for (const command of commands) {
|
||||
console.log(command)
|
||||
switch (command.type) {
|
||||
case 'join': {
|
||||
try {
|
||||
await p(peer.hubClient.addHub)(command.multiaddr)
|
||||
scheduleWithHub(command.multiaddr)
|
||||
} catch (err) {
|
||||
console.error('Failed to properly join hub', err)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'follow': {
|
||||
await p(peer.set.add)('follows', command.id)
|
||||
break
|
||||
}
|
||||
case 'promise.follow': {
|
||||
const [issuerType, issuerPubkey] = command.issuer
|
||||
if (issuerType !== 'pubkey') {
|
||||
throw new Error(
|
||||
'dont know how to claim promise issued by ' + issuerType
|
||||
)
|
||||
}
|
||||
// eslint-disable-next-line no-loop-func
|
||||
peer.addListener('rpc:connect', function onConnect(rpc) {
|
||||
if (rpc.shse.pubkey === issuerPubkey) {
|
||||
rpc.promise.follow(command.token, globalAccountID, (err) => {
|
||||
if (err)
|
||||
return console.error('Failed to claim follow promise', err)
|
||||
peer.removeListener('rpc:connect', onConnect)
|
||||
})
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
default:
|
||||
console.log('Unknown command type', command.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('ppppp', process.execPath, [
|
||||
Path.resolve(process.argv[1]),
|
||||
])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('ppppp')
|
||||
}
|
||||
|
||||
const hasLock = app.requestSingleInstanceLock()
|
||||
|
||||
if (!hasLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (ev, argv, cwd, extraData) => {
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) mainWindow.restore()
|
||||
mainWindow.focus()
|
||||
if (argv.length > 1) {
|
||||
handlePPPPPUri(argv[argv.length - 1])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
app.whenReady().then(() => {
|
||||
ipcMain.handle('loadAccount', loadAccount)
|
||||
ipcMain.handle('setProfileName', setProfileName)
|
||||
ipcMain.handle('writeElements', writeElements)
|
||||
ipcMain.handle('subscribeToReadElements', subscribeToReadElements)
|
||||
createWindow()
|
||||
if (process.argv.length > 1) {
|
||||
handlePPPPPUri(process.argv[process.argv.length - 1])
|
||||
}
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -31,11 +31,12 @@
|
|||
"ppppp-promise": "github:staltz/ppppp-promise",
|
||||
"ppppp-set": "github:staltz/ppppp-set",
|
||||
"ppppp-sync": "github:staltz/ppppp-sync",
|
||||
"pull-awaitable": "1.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-scripts": "5.0.1",
|
||||
"secret-handshake-ext": "0.0.11",
|
||||
"secret-stack": "8.0.0",
|
||||
"secret-stack": "8.1.0",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
Loading…
Reference in New Issue