diff --git a/apps/cory/docs.json b/apps/cory/docs.json index 2216bbd7..975704f2 100644 --- a/apps/cory/docs.json +++ b/apps/cory/docs.json @@ -1 +1 @@ -{"type":"tildefriends-app","files":{"app.js":"&5rHyeAQKxrbvIm32W3rKrh+LVRxlqLkN2cStJf5tCSM=.sha256","index.md":"&5EeOHUkDadC+lJsDsKXbfrVDQdePyOHZ7KwaJtR5mrs=.sha256","todo.md":"&U6hrQ6cfJ6+Uvg+wA7ahpCQaM2XiYXKjZUOz2iZDSGM=.sha256","structure.md":"&T+CBfT9XP6ooKFvD1ZCI9hsutqsNIamfBxtAho0HtlU=.sha256","guide.md":"&SgnGL0+rjetY2o9A2+lVRbNvHIkqKwMnZr9gXWneIlc=.sha256","id_refactor.md":"&8yoYd14gX2Z3ppktVrPYf4qR78fuwAlvrtsWkSCkWUA=.sha256"}} \ No newline at end of file +{"type":"tildefriends-app","files":{"app.js":"&5rHyeAQKxrbvIm32W3rKrh+LVRxlqLkN2cStJf5tCSM=.sha256","index.md":"&5EeOHUkDadC+lJsDsKXbfrVDQdePyOHZ7KwaJtR5mrs=.sha256","todo.md":"&uQuym9MPT7fIym79K8e/gdi5yOJrMoetZcutcsWYhQY=.sha256","structure.md":"&T+CBfT9XP6ooKFvD1ZCI9hsutqsNIamfBxtAho0HtlU=.sha256","guide.md":"&SgnGL0+rjetY2o9A2+lVRbNvHIkqKwMnZr9gXWneIlc=.sha256","id_refactor.md":"&8yoYd14gX2Z3ppktVrPYf4qR78fuwAlvrtsWkSCkWUA=.sha256"}} \ No newline at end of file diff --git a/apps/cory/docs/todo.md b/apps/cory/docs/todo.md index d5c3be8c..226cb9dc 100644 --- a/apps/cory/docs/todo.md +++ b/apps/cory/docs/todo.md @@ -2,11 +2,16 @@ [Back to index](#index) ## MVP2 +- multiple identities per user, in database +- make a cool independent app +- indicate when workspace differs from installed +- / => Something good. +- confirm posting all new messages +- administrators config - update README - update docs - audit + document API exposed to apps - emoji reaction picker -- logging to browser - fix weird HTTP warnings - ssb from child process? - channels @@ -15,7 +20,6 @@ - placeholder/missing images - connections 2.0 - no denial of service -- multiple identities per user, in database - expose loads of stats - package standalone executable - build for windows @@ -23,12 +27,7 @@ - tf account timeout why - attribute blob wants to messages - installable apps (bring back an app message?) -- make a cool independent app - editor without app iframe -- indicate when workspace differs from installed -- / => Something good. -- administrators config -- confirm posting all new messages ## Maybe Done - auto-populate data on initial launch @@ -38,4 +37,5 @@ - keep working on good error feedback ## Done -- update LICENSE \ No newline at end of file +- update LICENSE +- logging to browser \ No newline at end of file diff --git a/apps/cory/index.json b/apps/cory/index.json index 67ef1584..d00972d1 100644 --- a/apps/cory/index.json +++ b/apps/cory/index.json @@ -1 +1 @@ -{"type":"tildefriends-app","files":{"app.js":"&iqkvaTLEbxeintzHb07jiFncdg3N1aS8h8ZNUzy7MZI=.sha256","index.html":"&2LRN4tFXkx5lGQkoWDuBolODntJI95PBWoFzwB1tg/Q=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256","tf-user.js":"&DdJwZYEo7AqFyutYMvEjykoVXxdHVog0UXye6Sbo0TU=.sha256","tf-message.js":"&kIpc5B2dt4oefsTgNASz2cVte3WRO0k2NCYJYRzu/MA=.sha256","tf.js":"&wbm9maPsAXoS3c6jfLAHMkCPOi8gL00bH+OmJys9t60=.sha256","commonmark.min.js":"&EP0OeR9zyLwZannz+0ga4s9AGES2RLvvIIQYHqqV6+k=.sha256","vue.js":"&g1wvA+yHl1sVC+eufTsg9If7ZeVyMTBU+h0tks7ZNzE=.sha256","vue-material-theme-default-dark.css":"&RP2nr+2CR18BpHHw5ST9a5GJUCOG9n0G2kuGkcQioWE=.sha256","vue-material.min.css":"&kGbUM2QgFSyHZRzqQb0b+0S3EVIlZ0AXpdiAVjIhou8=.sha256","roboto.css":"&jJv43Om673mQO5JK0jj7714s5E+5Yrf82H6LcDx7wUs=.sha256","material-icons.css":"&a28PdcVvgq/DxyIvJAx/e+ZOEtOuHnr3kjLWKyzH11M=.sha256","tf-shared.js":"&+qPP3g4CAUlkt8K4iBCZ+F5Fy6N7fu6MggvSVss2juE=.sha256"}} \ No newline at end of file +{"type":"tildefriends-app","files":{"app.js":"&iSr0GObnkNKOpDGUkCikfwI7XI4mg6E3YNazCHSza2A=.sha256","index.html":"&xCI4SATYvlJkVX5EdlRROoDSMWlajF+wDFrWSUYZqd8=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256","tf-user.js":"&DdJwZYEo7AqFyutYMvEjykoVXxdHVog0UXye6Sbo0TU=.sha256","tf-message.js":"&kIpc5B2dt4oefsTgNASz2cVte3WRO0k2NCYJYRzu/MA=.sha256","tf.js":"&WvteLAg4G92YOUO3/B36kmar5lqFq8Pil4rsy7uFNDY=.sha256","commonmark.min.js":"&EP0OeR9zyLwZannz+0ga4s9AGES2RLvvIIQYHqqV6+k=.sha256","vue.js":"&g1wvA+yHl1sVC+eufTsg9If7ZeVyMTBU+h0tks7ZNzE=.sha256","vue-material-theme-default-dark.css":"&RP2nr+2CR18BpHHw5ST9a5GJUCOG9n0G2kuGkcQioWE=.sha256","vue-material.min.css":"&kGbUM2QgFSyHZRzqQb0b+0S3EVIlZ0AXpdiAVjIhou8=.sha256","roboto.css":"&jJv43Om673mQO5JK0jj7714s5E+5Yrf82H6LcDx7wUs=.sha256","material-icons.css":"&a28PdcVvgq/DxyIvJAx/e+ZOEtOuHnr3kjLWKyzH11M=.sha256","tf-shared.js":"&+qPP3g4CAUlkt8K4iBCZ+F5Fy6N7fu6MggvSVss2juE=.sha256"}} \ No newline at end of file diff --git a/apps/cory/index/app.js b/apps/cory/index/app.js index 45f49338..59df9cb6 100644 --- a/apps/cory/index/app.js +++ b/apps/cory/index/app.js @@ -6,9 +6,9 @@ const k_votes_max = 20; var g_ready = false; var g_selected = null; +var g_blocking_cache = {}; var g_following_cache = {}; var g_following_deep_cache = {}; -var g_stats = {}; var g_sequence = {}; async function following(db, id) { @@ -41,9 +41,11 @@ async function following(db, id) { } else { f.users.delete(row.contact); } - f.sequence = row.sequence; - g_sequence[id] = row.sequence; + if (row.sequence) { + f.sequence = row.sequence; + } }); + g_sequence[id] = f.sequence; var as_set = f.users; f.users = Array.from(f.users).sort(); var j = JSON.stringify(f); @@ -55,30 +57,81 @@ async function following(db, id) { return f.users; } -async function followingDeep(db, seed_ids, depth) { +async function followingDeep(db, seed_ids, depth, blocked) { if (depth <= 0) { return seed_ids; } - var key = JSON.stringify([seed_ids, depth]); + var key = JSON.stringify([seed_ids, depth, blocked]); if (g_following_deep_cache[key]) { return g_following_deep_cache[key]; } var f = await Promise.all(seed_ids.map(x => following(db, x).then(x => [...x]))); var ids = [].concat(...f); - var x = await followingDeep(db, [...new Set(ids)].sort(), depth - 1); + if (blocked) { + ids = ids.filter(x => !blocked.has(x)); + } + var x = await followingDeep(db, [...new Set(ids)].sort(), depth - 1, blocked); x = [...new Set([].concat(...x, ...seed_ids))].sort(); g_following_deep_cache[key] = x; return x; } +async function blocking(db, id) { + if (g_blocking_cache[id]) { + return g_blocking_cache[id]; + } + var o = await db.get(id + ":blocking"); + const k_version = 5; + var f = o ? JSON.parse(o) : o; + if (!f || f.version != k_version) { + f = {users: [], sequence: 0, version: k_version}; + } + f.users = new Set(f.users); + if (!g_sequence[id] || g_sequence[id] > f.sequence) { + await ssb.sqlStream( + "SELECT "+ + " sequence, "+ + " json_extract(content, '$.contact') AS contact, "+ + " json_extract(content, '$.blocking') AS blocking "+ + "FROM messages "+ + "WHERE "+ + " author = ?1 AND "+ + " sequence > ?2 AND "+ + " json_extract(content, '$.type') = 'contact' "+ + "UNION SELECT MAX(sequence) AS sequence, NULL, NULL FROM messages WHERE author = ?1 "+ + "ORDER BY sequence", + [id, f.sequence], + function(row) { + if (row.blocking) { + f.users.add(row.contact); + } else { + f.users.delete(row.contact); + } + if (row.sequence) { + f.sequence = row.sequence; + } + }); + g_sequence[id] = f.sequence; + } + var as_set = f.users; + f.users = Array.from(f.users).sort(); + var j = JSON.stringify(f); + if (o != j) { + await db.set(id + ":blocking", j); + } + f.users = as_set; + g_blocking_cache[id] = f.users; + return f.users; +} + async function getAbout(db, id) { var o = await db.get(id + ":about"); - const k_version = 4; + const k_version = 5; var f = o ? JSON.parse(o) : o; if (!f || f.version != k_version) { f = {about: {}, sequence: 0, version: k_version}; } - if (g_sequence[id] > f.sequence) { + if (g_sequence[id] === undefined || g_sequence[id] > f.sequence) { await ssb.sqlStream( "SELECT "+ " sequence, "+ @@ -93,8 +146,6 @@ async function getAbout(db, id) { "ORDER BY sequence", [id, f.sequence], function(row) { - g_stats.rows_read = (g_stats.rows_read || 0) + 1; - f.sequence = row.sequence; if (row.content) { var about = {}; try { @@ -105,12 +156,15 @@ async function getAbout(db, id) { delete about.type; f.about = Object.assign(f.about, about); } + if (row.sequence) { + f.sequence = Math.max(f.sequence, row.sequence); + } }); - } - var j = JSON.stringify(f); - if (o != j) { - g_stats.rows_written = (g_stats.rows_written || 0) + 1; - await db.set(id + ":about", j); + g_sequence[id] = f.sequence; + var j = JSON.stringify(f); + if (o != j) { + await db.set(id + ":about", j); + } } return f.about; } @@ -152,7 +206,7 @@ async function getRecentPostIds(db, id, ids, limit) { return await getRecentPostsSingleId(db, ids[0], limit); } const k_version = 11; - const k_batch_max = 16; + const k_batch_max = 32; var o = await db.get(id + ':recent_posts'); var recent = []; var f = o ? JSON.parse(o) : o; @@ -251,12 +305,12 @@ async function getRelatedPostIds(db, message, ids, limit) { async function getVotes(db, id) { var o = await db.get(id + ":votes"); const k_version = 7; - var votes = []; var f = o ? JSON.parse(o) : o; if (!f || f.version != k_version) { f = {votes: [], sequence: 0, version: k_version}; } - if (!g_sequence[id] || g_sequence[id] > f.sequence) { + if (g_sequence[id] === undefined || g_sequence[id] > f.sequence) { + var votes = []; await ssb.sqlStream( "SELECT "+ " author, "+ @@ -269,20 +323,24 @@ async function getVotes(db, id) { " author = ? AND "+ " sequence > ? AND "+ " json_extract(content, '$.type') = 'vote' "+ - "UNION SELECT NULL, NULL, MAX(sequence), NULL, NULL FROM messages WHERE author = ? "+ + "UNION SELECT NULL, NULL, MAX(sequence) AS sequence, NULL, NULL FROM messages WHERE author = ? "+ "ORDER BY sequence DESC LIMIT ?", [id, f.sequence, id, k_votes_max], function(row) { if (row.id) { votes.push(row); } - f.sequence = Math.max(f.sequence, row.sequence); + if (row.sequence) { + f.sequence = Math.max(f.sequence, row.sequence); + } }); - } - f.votes = [].concat(votes, f.votes).slice(0, k_votes_max); - var j = JSON.stringify(f); - if (o != j) { - await db.set(id + ":votes", j); + g_sequence[id] = f.sequence; + f.votes = [].concat(votes, f.votes).slice(0, k_votes_max); + var j = JSON.stringify(f); + if (o != j) { + print('set', id + ':votes'); + await db.set(id + ":votes", j); + } } return f.votes; } @@ -322,7 +380,9 @@ async function refresh(selected) { var whoami = await ssb.whoami(); var db = await database("ssb"); timing.push({name: 'init', time: new Date()}); - var all_followed = await followingDeep(db, [whoami], 2); + var blocked = await blocking(db, whoami); + timing.push({name: 'blocked', time: new Date()}); + var all_followed = await followingDeep(db, [whoami], 2, blocked); timing.push({name: 'all_followed', time: new Date()}); if (selected) { g_selected = selected; @@ -376,13 +436,13 @@ async function refresh(selected) { ) ); timing.push({name: 'following', time: new Date()}); - - print(JSON.stringify(g_stats)); + await app.postMessage({blocking: {id: whoami, users: [...(g_blocking_cache[whoami] || [])]}}); + timing.push({name: 'send_blocking', time: new Date()}); var times = {}; var previous = null; for (let t of timing) { - times[t.name] = t.time - (previous || t).time; + times[t.name] = (t.time - (previous || t).time) / 1000.0 + ' s'; previous = t; } diff --git a/apps/cory/index/index.html b/apps/cory/index/index.html index d5780a43..0404e3be 100644 --- a/apps/cory/index/index.html +++ b/apps/cory/index/index.html @@ -52,7 +52,7 @@ Loaded in {{load_time}} seconds. -
{{key}}: {{times[key] / 1000.0}} s
+
{{key}}: {{times[key]}}
@@ -137,6 +137,10 @@ +