From ac588d93868ae08045e9696c0a8795db7349b105 Mon Sep 17 00:00:00 2001 From: bobbydigitales Date: Sun, 1 Jun 2025 00:00:17 -0700 Subject: [PATCH] Small tweaks --- src/App.ts | 154 ++++++++++++++++++++++++++++++++++++--------- src/PeerManager.ts | 8 +-- static/index.html | 2 +- static/main.css | 3 + 4 files changed, 132 insertions(+), 35 deletions(-) diff --git a/src/App.ts b/src/App.ts index d89fc6b..7f066a2 100644 --- a/src/App.ts +++ b/src/App.ts @@ -8,6 +8,8 @@ import { log, logID, renderLog, setLogVisibility } from "log" declare let marked: any; declare let QRCode: any; +type PeerID = string; + class Post { post_timestamp: Date; post_id: string; @@ -54,6 +56,63 @@ interface SyncItem { } +class StatusBar { + peerStatus = new Map(); + headless = false; + + setMessageHTML(html:string) { + let statusBarElement = document.getElementById('status_bar'); + + if (!statusBarElement) { + return; + } + + statusBarElement.innerHTML = html; + + } + + setHeadless(headless:boolean) { + this.headless = headless; + } + updatePeerMessage(peerID: string, message: string) { + this.peerStatus.set(peerID, {message, data:this.peerStatus.get(peerID)?.data}); + this.render(); + } + + updatePeerData(peerID:PeerID, data:any) { + this.peerStatus.set(peerID, {message:this.peerStatus.get(peerID)?.message, data:data}); + } + + updatePeerStatus(peerID:PeerID, message:string="", data={}) { + this.peerStatus.set(peerID, {message, data}); + this.render(); + } + + getPeerData(peerID:PeerID) { + let status = this.peerStatus.get(peerID); + if (status) { + return status.data; + } + + return null; + } + + render() { + if (this.headless) { + // TODO:Make a nice htop-like display for headless at some point + return; + } + + let newStatus = ""; + for (let [peerID, status] of this.peerStatus.entries()) { + let statusBarItem = `(${logID(peerID)} | ${status.message}) `; + newStatus += statusBarItem; + } + + this.setMessageHTML(newStatus); + } +} + export class App { username: string = ''; peername: string = ''; @@ -74,43 +133,43 @@ export class App { firstRun = false; peerManager: PeerManager | null = null; sync: Sync = new Sync(); - renderTimer: ReturnType|null = null; + renderTimer: ReturnType | null = null; syncQueues: Map = new Map(); syncing: Set = new Set(); - statusBar = ""; + statusBar = new StatusBar(); - updateStatusBar() { + // updateStatusBar() { - let statusBarElement = document.getElementById('status_bar'); + // let statusBarElement = document.getElementById('status_bar'); - if (!statusBarElement) { - return; - } + // if (!statusBarElement) { + // return; + // } - let newStatusBar = ""; + // let newStatusBar = ""; - for (let [userID, syncItems] of this.syncQueues.entries()) { - for (let item of syncItems) { - let {peerID, postIDs} = item; - let statusBarItem = ` checking ${postIDs.length} for user [${logID(userID)}] from peer [${logID(peerID)}]`; - newStatusBar+= statusBarItem; - } + // for (let [userID, syncItems] of this.syncQueues.entries()) { + // for (let item of syncItems) { + // let {peerID, postIDs} = item; + // // let statusBarItem = ` 🤔(${postIDs.length})✉️ [${this.getUserFunkyName(userID)}]${logID(userID)} from [${this.getPeerFunkyName(peerID)}]${logID(peerID)} `; + // // let statusBarItem = ` 🤔(${postIDs.length})✉️ [${this.getUserFunkyName(userID)}] from [${this.getPeerFunkyName(peerID)}] `; + // let statusBarItem = ` (${this.getUserFunkyName(userID)}+${this.getPeerFunkyName(peerID)})🧐 `; + // newStatusBar+= statusBarItem; + // } - } + // } - this.statusBar += newStatusBar; - statusBarElement.innerHTML = this.statusBar; - } + // this.statusBar += newStatusBar; + // statusBarElement.innerHTML = this.statusBar; + // } async processSyncQueue(userID: string) { if (this.syncing.has(userID)) { - return; + return } - // this.updateStatusBar(); - let syncQueue = this.syncQueues.get(userID) as SyncItem[]; while (syncQueue.length !== 0) { @@ -127,12 +186,15 @@ export class App { if (neededPostIDs.length > 0) { console.log.apply(null, log(`[app] Need (${neededPostIDs.length}) posts for user ${logID(userID)} from peer ${logID(peerID)}`)); - let neededPosts = await this.peerManager?.rpc.getPostsForUser(peerID, this.peerID, userID, neededPostIDs); - // console.log(neededPosts); + let neededPostCount = neededPostIDs.length; + this.statusBar.updatePeerStatus(peerID, `need(${logID(userID)} | ${neededPostCount})`, {havePostCount:0, neededPostCount:neededPostCount}); + let neededPosts = await this.peerManager?.rpc.getPostsForUser(peerID, this.peerID, userID, neededPostIDs); } else { console.log.apply(null, log(`[app] Don't need any posts for user ${logID(userID)} from peer ${logID(peerID)}`)); + this.statusBar.updatePeerStatus(peerID, `synced(${logID(userID)})`); + } } @@ -169,18 +231,22 @@ export class App { console.log.apply(null, log(`[app] got announceUsers from ${logID(sendingPeerID)}`, userIDs)); + this.statusBar.updatePeerStatus(sendingPeerID, `announcePeers(${userIDs.length})⬇️`); + for (let userID of userIDs) { // console.log.apply(null, log(`[app] announceUsers, got user:${userID} from peer ${sendingPeerID}`)); this.sync.addUserPeer(userID, sendingPeerID); if (!(this.sync.shouldSyncUserID(userID) || (this.router.route === App.Route.USER && userID === this.router.userID))) { console.log.apply(null, log(`[app] announceUser_rpc_response skipping user[${logID(userID)}] from[${logID(sendingPeerID)}]`)); - continue; } console.log.apply(null, log(`[app] calling getPostIDsForUser for user [${logID(userID)}] on peer [${logID(sendingPeerID)}]`)); let postIDs = await this.peerManager?.rpc.getPostIDsForUser(sendingPeerID, userID); + + this.statusBar.updatePeerStatus(sendingPeerID, `syncing(${logID(userID)} ${postIDs.length})`); + console.log.apply(null, log(`[app] Got (${postIDs.length}) post IDs for user [${logID(userID)}] from peer [${logID(sendingPeerID)}]`)); this.addPostIDsToSyncQueue(userID, sendingPeerID, postIDs); } @@ -243,10 +309,12 @@ export class App { this.peerManager.registerRPC('getPostsForUser', async (requestingPeerID: string, userID: string, postIDs: string[]) => { let posts = await this.sync.getPostsForUser(userID, postIDs); - + let i=0; for (let post of posts) { console.log.apply(null, log(`[app] sendPostForUser sending post [${logID(post.post_id)}] to [${logID(requestingPeerID)}]`, userID, post.author, post.text)); + i++; + this.statusBar.updatePeerStatus(this.peerID, `⬆️${logID(requestingPeerID)} ${i}/${posts.length}`); await this.peerManager?.rpc.sendPostForUser(requestingPeerID, this.peerID, userID, post); } @@ -261,9 +329,19 @@ export class App { // if (post.text === "image...") { // debugger; // } + + let peerData = this.statusBar.getPeerData(sendingPeerID); + if (peerData) { + this.statusBar.updatePeerMessage(sendingPeerID, `⬇️${logID(userID)} ${peerData.havePostCount}/${peerData.neededPostCount}}`); + } await this.sync.writePostForUser(userID, post); // if (userID === this.userID) { + if (peerData) { + peerData.havePostCount++ + this.statusBar.updatePeerMessage(sendingPeerID, `⬇️${logID(userID)} ${peerData.havePostCount}/${peerData.neededPostCount}}`); + } + if (this.renderTimer) { clearTimeout(this.renderTimer); } @@ -275,8 +353,11 @@ export class App { }); + this.statusBar.setMessageHTML("Connecting to ddln network...") await this.peerManager.connect(); console.log.apply(null, log("*************** after peerManager.connect"));; + this.statusBar.setMessageHTML("Connected to ddln network...") + if (this.isBootstrapPeer) { @@ -699,6 +780,16 @@ export class App { return { first, second } } + getUserFunkyName(userID: string) { + let { first: adjective, second: animal } = this.funkyName(userID, this.adjectives, this.animals); + return `${adjective}_${animal}` + } + + getPeerFunkyName(peerID: string) { + let { first: adjective, second: snake } = this.funkyName(peerID, this.adjectives, this.snakes); + return `${adjective}_${snake}` + } + getUsername() { let username = localStorage.getItem("dandelion_username"); @@ -706,16 +797,15 @@ export class App { return username; } - let { first: adjective, second: animal } = this.funkyName(this.userID, this.adjectives, this.animals); - username = `${adjective}_${animal}` + username = this.getUserFunkyName(this.userID); + localStorage.setItem("dandelion_username", username); return username; } getPeername() { - let { first: adjective, second: snake } = this.funkyName(this.peerID, this.adjectives, this.snakes); - let peername = `${adjective}_${snake}` + let peername = this.getPeerFunkyName(this.peerID); return peername; } @@ -1107,12 +1197,16 @@ export class App { console.log(`[headless]${this.isHeadless} [archive] ${this.isArchivePeer} [bootstrap] ${this.isBootstrapPeer}`); + + this.statusBar.setHeadless(this.isHeadless); + + let limitPostsParam = urlParams.get('limitPosts'); if (limitPostsParam) { this.limitPosts = parseInt(limitPostsParam); } - + this.getRoute(); if (this.router.route === App.Route.CONNECT) { diff --git a/src/PeerManager.ts b/src/PeerManager.ts index 78dd64c..9b8978c 100644 --- a/src/PeerManager.ts +++ b/src/PeerManager.ts @@ -520,10 +520,10 @@ class PeerConnection { { urls: "stun:ddln.app" }, { urls: "turn:ddln.app", username: "a", credential: "b" }, { urls: "stun:stun.l.google.com" }, // keeping this for now as my STUN server is not returning ipv6 - // { urls: "stun:stun1.l.google.com" }, - // { urls: "stun:stun2.l.google.com" }, - // { urls: "stun:stun3.l.google.com" }, - // { urls: "stun:stun4.l.google.com" }, + { urls: "stun:stun1.l.google.com" }, + { urls: "stun:stun2.l.google.com" }, + { urls: "stun:stun3.l.google.com" }, + { urls: "stun:stun4.l.google.com" }, ], }; // longMessageQueue: string[] = []; diff --git a/static/index.html b/static/index.html index 582d039..fdba9bd 100644 --- a/static/index.html +++ b/static/index.html @@ -42,7 +42,7 @@ -
+
Connecting...
diff --git a/static/main.css b/static/main.css index 7571c3c..f5c28a4 100644 --- a/static/main.css +++ b/static/main.css @@ -364,6 +364,9 @@ iframe { .status-bar { align-content: center; + padding-left: 55px; + font-size: 12px; + height:12px; } .spinner {