pretty good use of gc, conductor, invites, hubs

This commit is contained in:
Andre Staltz 2024-01-18 16:59:26 +02:00
parent bb79bb05a1
commit d4e1cc8481
No known key found for this signature in database
GPG Key ID: 9EDE23EA7E8A4890
2 changed files with 124 additions and 15 deletions

116
main.js
View File

@ -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()
}) })
})
}

View File

@ -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": {