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 Path = require('node:path')
|
||||||
const URL = require('node:url')
|
const URL = require('node:url')
|
||||||
const p = require('node:util').promisify
|
const p = require('node:util').promisify
|
||||||
const Keypair = require('ppppp-keypair')
|
const Keypair = require('ppppp-keypair')
|
||||||
|
const awaitable = require('pull-awaitable')
|
||||||
|
|
||||||
// WARNING monkey patch! --------------------------------------
|
// WARNING monkey patch! --------------------------------------
|
||||||
const na = require('sodium-native')
|
const na = require('sodium-native')
|
||||||
|
@ -98,14 +99,33 @@ async function loadAccount() {
|
||||||
if (globalAccountID !== null) {
|
if (globalAccountID !== null) {
|
||||||
return { id: globalAccountID, name: globalAccountName }
|
return { id: globalAccountID, name: globalAccountName }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kickstart
|
||||||
await peer.db.loaded()
|
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
|
globalAccountID = id
|
||||||
await p(peer.set.load)(id)
|
await p(peer.set.load)(id)
|
||||||
await p(peer.dict.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 profile = peer.dict.read(id, 'profile')
|
||||||
const name = profile?.name ?? ''
|
const name = profile?.name ?? ''
|
||||||
globalAccountName = name
|
globalAccountName = name
|
||||||
|
|
||||||
return { id, name }
|
return { id, name }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +135,7 @@ async function setProfileName(ev, name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writeElements(ev, actions) {
|
async function writeElements(ev, actions) {
|
||||||
|
await loadAccount() // FIXME: ideally the frontend shouldn't do this
|
||||||
if (globalAccountID === null) throw new Error('account not loaded')
|
if (globalAccountID === null) throw new Error('account not loaded')
|
||||||
for (const action of actions) {
|
for (const action of actions) {
|
||||||
await p(peer.db.feed.publish)({
|
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(() => {
|
app.whenReady().then(() => {
|
||||||
ipcMain.handle('loadAccount', loadAccount)
|
ipcMain.handle('loadAccount', loadAccount)
|
||||||
ipcMain.handle('setProfileName', setProfileName)
|
ipcMain.handle('setProfileName', setProfileName)
|
||||||
ipcMain.handle('writeElements', writeElements)
|
ipcMain.handle('writeElements', writeElements)
|
||||||
ipcMain.handle('subscribeToReadElements', subscribeToReadElements)
|
ipcMain.handle('subscribeToReadElements', subscribeToReadElements)
|
||||||
createWindow()
|
createWindow()
|
||||||
|
if (process.argv.length > 1) {
|
||||||
|
handlePPPPPUri(process.argv[process.argv.length - 1])
|
||||||
|
}
|
||||||
|
|
||||||
app.on('activate', function () {
|
app.on('activate', function () {
|
||||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
app.on('window-all-closed', function () {
|
app.on('window-all-closed', function () {
|
||||||
if (process.platform !== 'darwin') app.quit()
|
if (process.platform !== 'darwin') app.quit()
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -31,11 +31,12 @@
|
||||||
"ppppp-promise": "github:staltz/ppppp-promise",
|
"ppppp-promise": "github:staltz/ppppp-promise",
|
||||||
"ppppp-set": "github:staltz/ppppp-set",
|
"ppppp-set": "github:staltz/ppppp-set",
|
||||||
"ppppp-sync": "github:staltz/ppppp-sync",
|
"ppppp-sync": "github:staltz/ppppp-sync",
|
||||||
|
"pull-awaitable": "1.0.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"secret-handshake-ext": "0.0.11",
|
"secret-handshake-ext": "0.0.11",
|
||||||
"secret-stack": "8.0.0",
|
"secret-stack": "8.1.0",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
Loading…
Reference in New Issue