Merge pull request 'Use newly released pzp deps' (#7) from fix-replication into master

Reviewed-on: https://codeberg.org/pzp/zooboard/pulls/7
This commit is contained in:
Powersource 2024-05-15 17:38:00 +00:00
commit f91ea507dd
8 changed files with 12400 additions and 20721 deletions

View File

@ -1,5 +1,7 @@
# Zooboard # Zooboard
## Running
To run it yourself: To run it yourself:
1. `npm install` 1. `npm install`
@ -18,4 +20,10 @@ To use:
4. Draw together and be happy! 4. Draw together and be happy!
5. [Discuss bugs here](https://codeberg.org/pzp/pzp-hub/issues) or pzp in general on the #pzp hashtag on your preferred social network. 5. [Discuss bugs here](https://codeberg.org/pzp/pzp-hub/issues) or pzp in general on the #pzp hashtag on your preferred social network.
## Known bugs
* Most of the time the things you try to draw (boxes, lines) just turn into dots ¯\\\_(ツ)\_/¯
* Moving an item doesn't replicate to peers. Resizing an item also doesn't but might also make it disappear.
* Probably other stuff that you can find in [the issue tracker](https://codeberg.org/pzp/pzp-hub/issues)
[pzp-hub]: https://codeberg.org/pzp/pzp-hub [pzp-hub]: https://codeberg.org/pzp/pzp-hub

58
main.js
View File

@ -2,7 +2,7 @@ const { app, BrowserWindow, ipcMain, shell, clipboard } = 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('pzp-keypair')
const awaitable = require('pull-awaitable') const awaitable = require('pull-awaitable')
// WARNING monkey patch! ------------------------------------------------------- // WARNING monkey patch! -------------------------------------------------------
@ -20,7 +20,8 @@ na.sodium_free = function sodium_free_monkey_patched() {}
process.env.ZOOBOARD_DATA ??= Path.join(app.getPath('appData'), 'zooboard') process.env.ZOOBOARD_DATA ??= Path.join(app.getPath('appData'), 'zooboard')
app.setPath('userData', process.env.ZOOBOARD_DATA) app.setPath('userData', process.env.ZOOBOARD_DATA)
const path = process.env.PZP_DIR ?? Path.resolve(app.getPath('userData'), 'ppppp') const path = Path.resolve(app.getPath('userData'), 'pzp')
console.log("Appdata path:", process.env.ZOOBOARD_DATA)
const keypairPath = Path.join(path, 'keypair.json') const keypairPath = Path.join(path, 'keypair.json')
const keypair = Keypair.loadOrCreateSync(keypairPath) const keypair = Keypair.loadOrCreateSync(keypairPath)
@ -31,20 +32,20 @@ let globalAccountName = null
const peer = require('secret-stack/bare')() const peer = require('secret-stack/bare')()
.use(require('secret-stack/plugins/net')) .use(require('secret-stack/plugins/net'))
.use(require('secret-handshake-ext/secret-stack')) .use(require('secret-handshake-ext/secret-stack'))
.use(require('ppppp-net')) .use(require('pzp-net'))
.use(require('ppppp-db')) .use(require('pzp-db'))
.use(require('ppppp-set')) .use(require('pzp-set'))
.use(require('ppppp-dict')) .use(require('pzp-dict'))
.use(require('ppppp-goals')) .use(require('pzp-goals'))
.use(require('ppppp-sync')) .use(require('pzp-sync'))
.use(require('ppppp-gc')) .use(require('pzp-gc'))
.use(require('ppppp-conductor')) .use(require('pzp-conductor'))
.use(require('ppppp-hub-client')) .use(require('pzp-hub-client'))
.use(require('ppppp-promise')) .use(require('pzp-promise'))
.use(require('ppppp-invite')) .use(require('pzp-invite'))
.call(null, { .call(null, {
shse: { shse: {
caps: require('ppppp-caps'), caps: require('pzp-caps'),
}, },
global: { global: {
keypair, keypair,
@ -108,11 +109,11 @@ async function loadAccount() {
await p(peer.dict.load)(id) await p(peer.dict.load)(id)
// Read profile // Read profile
const profile = peer.dict.read(id, 'profile') const profile = await p(peer.dict.read)(id, 'profile')
const name = profile?.name ?? '' const name = profile?.name ?? ''
globalAccountName = name globalAccountName = name
peer.net.start() await peer.net.start()
return { id, name } return { id, name }
} }
@ -149,14 +150,14 @@ function copyToClipboard(ev, text) {
} }
let hasSubscribedToReadElements = false let hasSubscribedToReadElements = false
function subscribeToReadElements() { async function subscribeToReadElements() {
if (hasSubscribedToReadElements) return if (hasSubscribedToReadElements) return
hasSubscribedToReadElements = true hasSubscribedToReadElements = true
// Load initial elements and inform renderer // Load initial elements and inform renderer
const elementsByID = new Map() const elementsByID = new Map()
const msgIDToElemID = new Map() const msgIDToElemID = new Map()
for (const { id: msgID, msg } of peer.db.records()) { for await (const { id: msgID, msg } of peer.db.records()) {
if (msg.data && msg.metadata.domain === 'zooboardElements') { if (msg.data && msg.metadata.domain === 'zooboardElements') {
const { id: elemID, isDeleted } = msg.data const { id: elemID, isDeleted } = msg.data
if (isDeleted) { if (isDeleted) {
@ -210,7 +211,10 @@ function subscribeToReadElements() {
['profile@dict', 'zooboardElements@newest-100', 'hubs@set'], ['profile@dict', 'zooboardElements@newest-100', 'hubs@set'],
['profile@dict', 'zooboardElements@newest-100'], ['profile@dict', 'zooboardElements@newest-100'],
], ],
64_000 64_000,
(err) => {
if (err) console.error('Starting conductor failed:', err)
}
) )
}, 32) }, 32)
} }
@ -225,15 +229,15 @@ async function subscribeToConnections() {
} }
} }
async function handlePPPPPUri(ev, uri) { async function handlePZPUri(ev, uri) {
if (!globalAccountID) { if (!globalAccountID) {
setTimeout(handlePPPPPUri, 100, null, uri) setTimeout(handlePZPUri, 100, null, uri)
return return
} }
if (uri.startsWith("http:") || uri.startsWith("https://")) { if (uri.startsWith("http:") || uri.startsWith("https://")) {
uri = decodeURIComponent(uri.split('/invite#')[1]) uri = decodeURIComponent(uri.split('/invite#')[1])
} }
if (!uri.startsWith('ppppp://')) return console.log('Not a ppppp invite URI', uri) if (!uri.startsWith('pzp://')) return console.log('Not a pzp invite URI', uri)
const commands = peer.invite.parse(uri) const commands = peer.invite.parse(uri)
for (const command of commands) { for (const command of commands) {
console.log('Executing command', JSON.stringify(command)) console.log('Executing command', JSON.stringify(command))
@ -274,12 +278,12 @@ async function handlePPPPPUri(ev, uri) {
if (process.defaultApp) { if (process.defaultApp) {
if (process.argv.length >= 2) { if (process.argv.length >= 2) {
app.setAsDefaultProtocolClient('ppppp', process.execPath, [ app.setAsDefaultProtocolClient('pzp', process.execPath, [
Path.resolve(process.argv[1]), Path.resolve(process.argv[1]),
]) ])
} }
} else { } else {
app.setAsDefaultProtocolClient('ppppp') app.setAsDefaultProtocolClient('pzp')
} }
//const hasLock = app.requestSingleInstanceLock() //const hasLock = app.requestSingleInstanceLock()
@ -292,7 +296,7 @@ if (process.defaultApp) {
// if (mainWindow.isMinimized()) mainWindow.restore() // if (mainWindow.isMinimized()) mainWindow.restore()
// mainWindow.focus() // mainWindow.focus()
// if (argv.length > 1) { // if (argv.length > 1) {
// handlePPPPPUri(null, argv[argv.length - 1]) // handlePZPUri(null, argv[argv.length - 1])
// } // }
// } // }
// }) // })
@ -303,12 +307,12 @@ if (process.defaultApp) {
ipcMain.handle('createInvite', createInvite) ipcMain.handle('createInvite', createInvite)
ipcMain.handle('copyToClipboard', copyToClipboard) ipcMain.handle('copyToClipboard', copyToClipboard)
ipcMain.handle('writeElements', writeElements) ipcMain.handle('writeElements', writeElements)
ipcMain.handle('consumeInvite', handlePPPPPUri) ipcMain.handle('consumeInvite', handlePZPUri)
ipcMain.handle('subscribeToReadElements', subscribeToReadElements) ipcMain.handle('subscribeToReadElements', subscribeToReadElements)
ipcMain.handle('subscribeToConnections', subscribeToConnections) ipcMain.handle('subscribeToConnections', subscribeToConnections)
createWindow() createWindow()
if (process.argv.length > 1) { if (process.argv.length > 1) {
handlePPPPPUri(null, process.argv[process.argv.length - 1]) handlePZPUri(null, process.argv[process.argv.length - 1])
} }
app.on('activate', function () { app.on('activate', function () {

20673
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,12 +6,12 @@
"homepage": "./", "homepage": "./",
"scripts": { "scripts": {
"start": "PORT=3001 BROWSER=none react-scripts start", "start": "PORT=3001 BROWSER=none react-scripts start",
"start2": "PZP_DIR=/tmp/zooboard-test PORT=3002 BROWSER=none react-scripts start", "start2": "ZOOBOARD_DATA=/tmp/zooboard-test PORT=3002 BROWSER=none react-scripts start",
"build": "react-scripts build", "build": "react-scripts build",
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject", "eject": "react-scripts eject",
"electron": "ELECTRON_START_URL=http://localhost:3001 DEBUG=*,-shse,-pull-secretstream electron .", "electron": "ELECTRON_START_URL=http://localhost:3001 DEBUG=*,-shse,-pull-secretstream electron .",
"electron2": "PZP_DIR=/tmp/zooboard-test ELECTRON_START_URL=http://localhost:3002 DEBUG=*,-shse,-pull-secretstream electron .", "electron2": "ZOOBOARD_DATA=/tmp/zooboard-test ELECTRON_START_URL=http://localhost:3002 DEBUG=*,-shse,-pull-secretstream electron .",
"start-all": "concurrently --kill-others \"npm start\" \"./scripts/wait.sh 3001 && npm run electron\" \"npm run start2\" \"./scripts/wait.sh 3002 && npm run electron2\"" "start-all": "concurrently --kill-others \"npm start\" \"./scripts/wait.sh 3001 && npm run electron\" \"npm run start2\" \"./scripts/wait.sh 3002 && npm run electron2\""
}, },
"dependencies": { "dependencies": {
@ -21,19 +21,19 @@
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"concurrently": "^8.2.2", "concurrently": "^8.2.2",
"debounce": "2.0", "debounce": "2.0",
"ppppp-caps": "github:staltz/ppppp-caps#93fa810b9a40b78aef4872d4c2a8412cccb52929", "pzp-caps": "^1.0.0",
"ppppp-db": "github:staltz/ppppp-db#cf1532965ea1d16929ed2291a9b737a4ce74caac", "pzp-db": "^1.0.1",
"ppppp-dict": "github:staltz/ppppp-dict#c40d51be6cb96982b4fe691a292b3c12b6f49a36", "pzp-dict": "^1.0.0",
"ppppp-gc": "github:staltz/ppppp-gc#9075f983d8fa9a13c18a63451a78bed5912e78d0", "pzp-gc": "^1.0.0",
"ppppp-goals": "github:staltz/ppppp-goals#46a8d8889c668cf291607963fd7301f21aa634b5", "pzp-goals": "^1.0.0",
"ppppp-keypair": "github:staltz/ppppp-keypair#c33980c580e33f9a35cb0c672b916ec9fe8b4c6d", "pzp-keypair": "^1.0.0",
"ppppp-set": "github:staltz/ppppp-set#07c3e295b2d09d2d6c3ac6b5b93ad2ea80698452", "pzp-set": "^1.0.0",
"ppppp-sync": "github:staltz/ppppp-sync#93f00dbd04267f472fbf2f3ae63495092d3a921e", "pzp-sync": "^1.0.0",
"ppppp-conductor": "github:staltz/ppppp-conductor#8ebeb0fb12de766fac21f8292121307cf7d1bd1e", "pzp-conductor": "^1.0.0",
"ppppp-hub-client": "github:staltz/ppppp-hub-client#6dec9c25291155151051e28b048560038c47ea3f", "pzp-hub-client": "^1.0.0",
"ppppp-invite": "github:staltz/ppppp-invite#745eea3de0b98a4896face25cb31288c9b0c9ed2", "pzp-invite": "^1.0.0",
"ppppp-net": "github:staltz/ppppp-net#5b79b9566bb425e27169f90544bc54b8b418b87c", "pzp-net": "^1.0.1",
"ppppp-promise": "github:staltz/ppppp-promise#e4f559178c35b71fb96ed0029d3d9b839c7d64ff", "pzp-promise": "^1.0.0",
"pull-awaitable": "1.0.0", "pull-awaitable": "1.0.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
@ -41,6 +41,7 @@
"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.1.0", "secret-stack": "8.1.0",
"sodium-native": "4.1.1",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"devDependencies": { "devDependencies": {

12336
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,9 @@ contextBridge.exposeInMainWorld('electronAPI', {
setProfileName: (name) => ipcRenderer.invoke('setProfileName', name), setProfileName: (name) => ipcRenderer.invoke('setProfileName', name),
writeElements: (actions) => ipcRenderer.invoke('writeElements', actions), writeElements: (actions) => ipcRenderer.invoke('writeElements', actions),
onReadElements: (callback) => { onReadElements: (callback) => {
ipcRenderer.invoke('subscribeToReadElements') ipcRenderer.invoke('subscribeToReadElements').then(() => {
ipcRenderer.on('readElements', (_event, value) => callback(value)) ipcRenderer.on('readElements', (_event, value) => callback(value))
})
}, },
onConnections: (callback) => { onConnections: (callback) => {
ipcRenderer.invoke('subscribeToConnections') ipcRenderer.invoke('subscribeToConnections')

View File

@ -22,14 +22,16 @@ function Connections() {
{connections.map(([multiaddr, info]) => ( {connections.map(([multiaddr, info]) => (
<div <div
key={multiaddr} key={multiaddr}
className="flex flex-row items-center mt-1 text-xs text-gray-500 font-mono overflow-x-hidden overflow-ellipsis" className="flex flex-row items-center mt-1 text-xs text-gray-500 font-mono"
> >
{info.state === 'connected' ? ( {info.state === 'connected' ? (
<div className="shrink-0 w-2 h-2 mb-0.5 bg-green-500 rounded-full mr-1" /> <div className="shrink-0 w-2 h-2 mb-0.5 bg-green-500 rounded-full mr-1" />
) : ( ) : (
<div className="shrink-0 w-2 h-2 mb-0.5 bg-yellow-500 rounded-full mr-1" /> <div className="shrink-0 w-2 h-2 mb-0.5 bg-yellow-500 rounded-full mr-1" />
)} )}
{tinyMultiaddr(multiaddr)} <div className="break-all">
{tinyMultiaddr(multiaddr)}
</div>
</div> </div>
))} ))}
</> </>

View File

@ -16,10 +16,10 @@ function JoinModal({ isOpen, onClose }) {
return ( return (
<Modal isOpen={isOpen} onClose={onClose}> <Modal isOpen={isOpen} onClose={onClose}>
Insert here the ppppp:// or http(s):// invite code you received from your friend. Insert here the pzp:// or http(s):// invite code you received from your friend.
<textarea <textarea
key="input" key="input"
placeholder={'ppppp://... or http(s)://...'} placeholder={'pzp://... or http(s)://...'}
className="border font-mono border-gray-400 resize-none rounded px-1 text-wrap break-all outline-offset-3 outline-2 outline-green-500 my-4 h-64" className="border font-mono border-gray-400 resize-none rounded px-1 text-wrap break-all outline-offset-3 outline-2 outline-green-500 my-4 h-64"
onChange={updateCode} onChange={updateCode}
/> />