From 4cedc54d2dddfc553f08b3daab1b812005d370fd Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Fri, 3 Nov 2023 00:45:30 +0000 Subject: [PATCH] Reworked some following math. git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4601 ed5197a5-7fde-0310-b194-c3ffbd925b24 --- apps/ssb.json | 2 +- apps/ssb/tf-app.js | 13 ++++++- apps/ssb/tf-profile.js | 41 ++++++++++++++++----- src/ssb.db.c | 84 ++++++++++++++++++++++++++++++++++++------ src/ssb.db.h | 13 ++++++- src/ssb.js.c | 23 +++++++----- 6 files changed, 143 insertions(+), 33 deletions(-) diff --git a/apps/ssb.json b/apps/ssb.json index b528aa10..bfeacb7a 100644 --- a/apps/ssb.json +++ b/apps/ssb.json @@ -1,5 +1,5 @@ { "type": "tildefriends-app", "emoji": "🐌", - "previous": "&fDu52QJE1dYO2lB/HBpQqoGnGR1b0j38JkGrqt2wHQA=.sha256" + "previous": "&JKRKYoQgzxByd80DTQQVWoDfoEd27h2jhaUrNXAGK7k=.sha256" } \ No newline at end of file diff --git a/apps/ssb/tf-app.js b/apps/ssb/tf-app.js index a018ad37..95621567 100644 --- a/apps/ssb/tf-app.js +++ b/apps/ssb/tf-app.js @@ -212,9 +212,18 @@ class TfElement extends LitElement { let whoami = this.whoami; let tags = this.load_recent_tags(); let following = await tfrpc.rpc.following([whoami], 2); + console.log(following); let users = {}; - users = await this.fetch_about(following.sort(), users); - this.following = following; + for (let [id, v] of Object.entries(following)) { + users[id] = { + following: v.of, + blocking: v.ob, + followed: v.if, + blocked: v.ib, + }; + } + users = await this.fetch_about(Object.keys(following).sort(), users); + this.following = Object.keys(following); this.users = users; await tags; console.log(`load finished ${whoami} => ${this.whoami}`); diff --git a/apps/ssb/tf-profile.js b/apps/ssb/tf-profile.js index 5085686a..21817df7 100644 --- a/apps/ssb/tf-profile.js +++ b/apps/ssb/tf-profile.js @@ -12,6 +12,8 @@ class TfProfileElement extends LitElement { users: {type: Object}, size: {type: Number}, server_follows_me: {type: Boolean}, + following: {type: Boolean}, + blocking: {type: Boolean}, }; } @@ -28,11 +30,31 @@ class TfProfileElement extends LitElement { this.server_follows_me = undefined; } + async load() { + if (this.whoami !== this._follow_whoami) { + this._follow_whoami = this.whoami; + this.following = undefined; + this.blocking = undefined; + + let result = await tfrpc.rpc.query(` + SELECT json_extract(content, '$.following') AS following + FROM messages WHERE author = ? AND + json_extract(content, '$.type') = 'contact' AND + json_extract(content, '$.contact') = ? + ORDER BY sequence DESC LIMIT 1 + `, [this.whoami, this.id]); + console.log(result); + this.following = result?.[0]?.following ?? false; + console.log('FOLLOWING', this.whoami, this.id, this.following); + } + } + async initial_load() { this.server_follows_me = undefined; let server_id = await tfrpc.rpc.getServerIdentity(); let followed = await tfrpc.rpc.query(` - SELECT json_extract(content, '$.following') AS following FROM messages + SELECT json_extract(content, '$.following') AS following + FROM messages WHERE author = ? AND json_extract(content, '$.type') = 'contact' AND json_extract(content, '$.contact') = ? ORDER BY sequence DESC LIMIT 1 @@ -138,6 +160,7 @@ class TfProfileElement extends LitElement { if (this.id == this.whoami && this.editing && this.server_follows_me === undefined) { this.initial_load(); } + this.load(); let self = this; let profile = this.users[this.id] || {}; tfrpc.rpc.query( @@ -166,16 +189,16 @@ class TfProfileElement extends LitElement { } } if (this.id !== this.whoami && - this.users[this.whoami]?.following) { + this.following !== undefined) { follow = - this.users[this.whoami].following[this.id] ? + this.following ? html`` : html``; } if (this.id !== this.whoami && - this.users[this.whoami]?.blocking) { + this.blocking !== undefined) { block = - this.users[this.whoami].blocking[this.id] ? + this.blocking ? html`` : html``; } @@ -208,10 +231,10 @@ class TfProfileElement extends LitElement {
- Following ${Object.keys(profile.following || {}).length} identities. - Followed by ${Object.values(self.users).filter(x => (x.following || {})[self.id]).length} identities. - Blocking ${Object.keys(profile.blocking || {}).length} identities. - Blocked by ${Object.values(self.users).filter(x => (x.blocking || {})[self.id]).length} identities. + Following ${profile.following} identities. + Followed by ${profile.followed} identities. + Blocking ${profile.blocking} identities. + Blocked by ${profile.blocked} identities.
${edit} diff --git a/src/ssb.db.c b/src/ssb.db.c index 396bc0c0..4d576bb3 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -1300,6 +1300,7 @@ typedef struct _following_t int blocking_count; int depth; int ref_count; + int block_ref_count; } following_t; static int _following_compare(const void* a, const void* b) @@ -1309,7 +1310,7 @@ static int _following_compare(const void* a, const void* b) return strcmp(ida, (*followingb)->id); } -static void _add_following_entry(following_t*** list, int* count, following_t* add) +static bool _add_following_entry(following_t*** list, int* count, following_t* add) { int index = tf_util_insert_index(add->id, *list, *count, sizeof(following_t*), _following_compare); if (index >= *count || strcmp(add->id, (*list)[index]->id) != 0) @@ -1321,10 +1322,12 @@ static void _add_following_entry(following_t*** list, int* count, following_t* a } (*list)[index] = add; (*count)++; + return true; } + return false; } -static void _remove_following_entry(following_t*** list, int* count, following_t* remove) +static bool _remove_following_entry(following_t*** list, int* count, following_t* remove) { int index = tf_util_insert_index(remove->id, *list, *count, sizeof(following_t*), _following_compare); if (index < *count && strcmp(remove->id, (*list)[index]->id) == 0) @@ -1335,7 +1338,9 @@ static void _remove_following_entry(following_t*** list, int* count, following_t } *list = tf_resize_vec(*list, sizeof(**list) * (*count - 1)); (*count)--; + return true; } + return false; } static following_t* _get_following(tf_ssb_t* ssb, const char* id, following_t*** following, int* following_count, int depth, int max_depth) @@ -1384,26 +1389,36 @@ static following_t* _get_following(tf_ssb_t* ssb, const char* id, following_t*** following_t* next = _get_following(ssb, contact, following, following_count, depth + 1, max_depth); if (is_following) { - _add_following_entry(&entry->following, &entry->following_count, next); - next->ref_count++; + if (_add_following_entry(&entry->following, &entry->following_count, next)) + { + next->ref_count++; + } } else { - _remove_following_entry(&entry->following, &entry->following_count, next); - next->ref_count--; + if (_remove_following_entry(&entry->following, &entry->following_count, next)) + { + next->ref_count--; + } } } if (sqlite3_column_type(statement, 2) != SQLITE_NULL) { - bool is_blocking = sqlite3_column_int(statement, 2 != 0); + bool is_blocking = sqlite3_column_int(statement, 2) != 0; following_t* next = _get_following(ssb, contact, following, following_count, depth + 1, 0 /* don't dig deeper into blocked users */); if (is_blocking) { - _add_following_entry(&entry->blocking, &entry->blocking_count, next); + if (_add_following_entry(&entry->blocking, &entry->blocking_count, next)) + { + next->block_ref_count++; + } } else { - _remove_following_entry(&entry->blocking, &entry->blocking_count, next); + if (_remove_following_entry(&entry->blocking, &entry->blocking_count, next)) + { + next->block_ref_count--; + } } } } @@ -1415,7 +1430,54 @@ static following_t* _get_following(tf_ssb_t* ssb, const char* id, following_t*** return entry; } -const char** tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, int count, int depth) +tf_ssb_following_t* tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, int count, int depth) +{ + following_t** following = NULL; + int following_count = 0; + for (int i = 0; i < count; i++) + { + following_t* entry = _get_following(ssb, ids[i], &following, &following_count, 0, depth); + entry->ref_count++; + } + + int actual_following_count = 0; + for (int i = 0; i < following_count; i++) + { + if (following[i]->ref_count > 0) + { + actual_following_count++; + } + } + + tf_ssb_following_t* result = tf_malloc(sizeof(tf_ssb_following_t) * (actual_following_count + 1)); + memset(result, 0, sizeof(tf_ssb_following_t) * (actual_following_count + 1)); + + int write_index = 0; + for (int i = 0; i < following_count; i++) + { + if (following[i]->ref_count > 0) + { + snprintf(result[write_index].id, sizeof(result[write_index].id), "%s", following[i]->id); + result[write_index].following_count = following[i]->following_count; + result[write_index].blocking_count = following[i]->blocking_count; + result[write_index].followed_by_count = following[i]->ref_count; + result[write_index].blocked_by_count = following[i]->block_ref_count; + write_index++; + } + } + + for (int i = 0; i < following_count; i++) + { + tf_free(following[i]->following); + tf_free(following[i]->blocking); + tf_free(following[i]); + } + tf_free(following); + + return result; +} + +const char** tf_ssb_db_following_deep_ids(tf_ssb_t* ssb, const char** ids, int count, int depth) { following_t** following = NULL; int following_count = 0; @@ -1479,7 +1541,7 @@ const char** tf_ssb_db_get_all_visible_identities(tf_ssb_t* ssb, int depth) { identities_t identities = { 0 }; tf_ssb_db_identity_visit_all(ssb, _add_identity, &identities); - const char** following = tf_ssb_db_following_deep(ssb, identities.ids, identities.count, depth); + const char** following = tf_ssb_db_following_deep_ids(ssb, identities.ids, identities.count, depth); for (int i = 0; i < identities.count; i++) { tf_free((void*)identities.ids[i]); diff --git a/src/ssb.db.h b/src/ssb.db.h index c58f819e..a0b7ccdf 100644 --- a/src/ssb.db.h +++ b/src/ssb.db.h @@ -46,7 +46,18 @@ JSValue tf_ssb_format_message( const char* content, const char* signature, bool sequence_before_author); -const char** tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, int count, int depth); + +typedef struct _tf_ssb_following_t +{ + char id[k_id_base64_len]; + int following_count; + int blocking_count; + int followed_by_count; + int blocked_by_count; +} tf_ssb_following_t; + +const char** tf_ssb_db_following_deep_ids(tf_ssb_t* ssb, const char** ids, int count, int depth); +tf_ssb_following_t* tf_ssb_db_following_deep(tf_ssb_t* ssb, const char** ids, int count, int depth); const char** tf_ssb_db_get_all_visible_identities(tf_ssb_t* ssb, int depth); typedef struct _tf_ssb_db_stored_connection_t diff --git a/src/ssb.js.c b/src/ssb.js.c index 01a41e1a..417fe72c 100644 --- a/src/ssb.js.c +++ b/src/ssb.js.c @@ -105,7 +105,7 @@ static JSValue _tf_ssb_set_server_following_me(JSContext* context, JSValueConst else { const char* server_id_ptr = server_id; - const char** current_following = tf_ssb_db_following_deep(ssb, &server_id_ptr, 1, 1); + const char** current_following = tf_ssb_db_following_deep_ids(ssb, &server_id_ptr, 1, 1); bool is_following = false; for (const char** it = current_following; *it; it++) { @@ -1519,7 +1519,7 @@ typedef struct _following_t JSContext* context; JSValue promise[2]; - const char** out_ids; + tf_ssb_following_t* out_following; int depth; int ids_count; @@ -1529,7 +1529,7 @@ typedef struct _following_t static void _tf_ssb_following_work(uv_work_t* work) { following_t* following = work->data; - following->out_ids = tf_ssb_db_following_deep(following->ssb, following->ids, following->ids_count, following->depth); + following->out_following = tf_ssb_db_following_deep(following->ssb, following->ids, following->ids_count, following->depth); } static void _tf_ssb_following_after_work(uv_work_t* work, int status) @@ -1538,13 +1538,18 @@ static void _tf_ssb_following_after_work(uv_work_t* work, int status) JSContext* context = following->context; if (status == 0) { - JSValue array = JS_NewArray(context); - for (int i = 0; following->out_ids[i]; i++) + JSValue object = JS_NewObject(context); + for (int i = 0; *following->out_following[i].id; i++) { - JS_SetPropertyUint32(context, array, i, JS_NewString(context, following->out_ids[i])); + JSValue entry = JS_NewObject(context); + JS_SetPropertyStr(context, entry, "of", JS_NewInt32(context, following->out_following[i].following_count)); + JS_SetPropertyStr(context, entry, "ob", JS_NewInt32(context, following->out_following[i].blocking_count)); + JS_SetPropertyStr(context, entry, "if", JS_NewInt32(context, following->out_following[i].followed_by_count)); + JS_SetPropertyStr(context, entry, "ib", JS_NewInt32(context, following->out_following[i].blocked_by_count)); + JS_SetPropertyStr(context, object, following->out_following[i].id, entry); } - JS_Call(context, following->promise[0], JS_UNDEFINED, 1, &array); - JS_FreeValue(context, array); + JS_Call(context, following->promise[0], JS_UNDEFINED, 1, &object); + JS_FreeValue(context, object); } else { @@ -1559,7 +1564,7 @@ static void _tf_ssb_following_after_work(uv_work_t* work, int status) { tf_free((void*)following->ids[i]); } - tf_free(following->out_ids); + tf_free(following->out_following); tf_free(following); }