Trying to make the SSB client webapp tolerable. Middling success. Let me set some 'about' information. Tweak what information is shown where as I experiment. Mess with the feed logic.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3714 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2021-12-28 20:21:23 +00:00
parent 12ab2f4b85
commit 0f7472fa22
5 changed files with 63 additions and 30 deletions

View File

@ -1 +1 @@
{"type":"tildefriends-app","files":{"app.js":"&sZTfWDIl4CjCU0ZxbkkwvpR+xlBtrgf6meH5+Vx7AHo=.sha256","index.html":"&V0OKwISmSZZH/9QbJyp9rdCgscD5bO9yw4dpzS5pFCw=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256","tf-user.js":"&V9Ol799hM6i1PZDbAS91CMhgx7aENDTJnT+KrwK4Lh4=.sha256","tf-message.js":"&VNC8ptzGXWAVl9LBBZfrk3YmweA8PQ02d7/wZxWXoAA=.sha256","tf.js":"&kQT5zbrevsHUlxIoHw0gBaIhT4dwuCUSazORCwZOiS4=.sha256","commonmark.min.js":"&5x6ek3tFrKTZX6hXNNyFsjmhvrjmWpUkwuuaiyVV1Us=.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"}} {"type":"tildefriends-app","files":{"app.js":"&CuC9hpnUkbbSAgR4E30aVNWMXySrbHDhoIXI/pxU1g8=.sha256","index.html":"&mv6A+VsR0hIDWLtczTB1SlexmT1FTpU/IjfL46Je6Y4=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256","tf-user.js":"&xkxw1x8obGvv2Tly3M8xDGCIiI/EYMgjZWWji2wUUe4=.sha256","tf-message.js":"&VNC8ptzGXWAVl9LBBZfrk3YmweA8PQ02d7/wZxWXoAA=.sha256","tf.js":"&swCMB9K4dkPCPC2tYS5aTUZSGUmaezlW6FNeLM9QNXI=.sha256","commonmark.min.js":"&5x6ek3tFrKTZX6hXNNyFsjmhvrjmWpUkwuuaiyVV1Us=.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"}}

View File

@ -150,7 +150,7 @@ function fnv32a(value)
} }
async function getRecentPostIds(db, id, ids, limit) { async function getRecentPostIds(db, id, ids, limit) {
const k_version = 7; const k_version = 9;
var o = await db.get(id + ':recent_posts'); var o = await db.get(id + ':recent_posts');
var recent = []; var recent = [];
var f = o ? JSON.parse(o) : o; var f = o ? JSON.parse(o) : o;
@ -161,14 +161,15 @@ async function getRecentPostIds(db, id, ids, limit) {
await ssb.sqlStream( await ssb.sqlStream(
"SELECT "+ "SELECT "+
" rowid, "+ " rowid, "+
" id "+ " id, "+
" timestamp "+
"FROM messages "+ "FROM messages "+
"WHERE "+ "WHERE "+
" rowid > ? AND "+ " rowid > ? AND "+
" author IN (" + ids.map(x => '?').join(", ") + ") AND "+ " author IN (" + ids.map(x => '?').join(", ") + ") AND "+
" json_extract(content, '$.type') IN ('post', 'tildefriends-app') "+ " json_extract(content, '$.type') IN ('post', 'tildefriends-app') "+
"UNION SELECT MAX(rowid) as rowid, NULL FROM messages "+ "UNION SELECT MAX(rowid) as rowid, NULL, NULL FROM messages "+
"ORDER BY rowid DESC LIMIT ?", "ORDER BY timestamp DESC LIMIT ?",
[].concat([f.rowid], ids, [limit + 1]), [].concat([f.rowid], ids, [limit + 1]),
function(row) { function(row) {
if (row.id) { if (row.id) {
@ -240,7 +241,7 @@ async function ready() {
return refresh(); return refresh();
} }
core.register('onBroadcastsChanged', async function() { ssb.addEventListener('broadcasts', async function() {
await app.postMessage({broadcasts: await ssb.getBroadcasts()}); await app.postMessage({broadcasts: await ssb.getBroadcasts()});
}); });
@ -270,8 +271,8 @@ async function refresh() {
} }
}); });
roots = roots.filter(function(root) { roots = roots.filter(function(root) {
return root && posts.every(post => post.id != root); return root && posts.every(post => post.id != root);
}); });
return [].concat(posts, await getPosts(db, roots)); return [].concat(posts, await getPosts(db, roots));
}).then(function(posts) { }).then(function(posts) {
return Promise.all(posts.map(x => app.postMessage({message: x}))); return Promise.all(posts.map(x => app.postMessage({message: x})));
@ -321,6 +322,8 @@ core.register('message', async function(m) {
} else if (m.message.refresh) { } else if (m.message.refresh) {
await refresh(); await refresh();
} }
} else if (m.event == 'focus' || m.event == 'blur') {
/* Shh. */
} else { } else {
print(JSON.stringify(m)); print(JSON.stringify(m));
} }

View File

@ -29,18 +29,17 @@
</md-dialog> </md-dialog>
<md-app style="position: absolute; height: 100%; width: 100%"> <md-app style="position: absolute; height: 100%; width: 100%">
<md-app-toolbar class="md-primary"> <md-app-toolbar class="md-primary">
<md-button class="md-icon-button" @click="showUsers = !showUsers">
<md-icon>menu</md-icon>
</md-button>
<span class="md-title">Tilde Friends Secure Scuttlebutt Test</span> <span class="md-title">Tilde Friends Secure Scuttlebutt Test</span>
</md-app-toolbar> </md-app-toolbar>
<md-app-drawer :md-active.sync="showUsers" md-persistent="full"> <md-app-drawer md-permanent="full">
<md-list> <md-list>
<md-subheader>Network</md-subheader> <md-subheader>Broadcasts</md-subheader>
<md-list-item v-for="broadcast in broadcasts" v-bind:key="JSON.stringify(broadcast)" @click="ssb_connect(broadcast)">{{broadcast.address}}:{{broadcast.port}} <tf-user :id="broadcast.pubkey"></tf-user></md-list-item> <md-list-item v-for="broadcast in broadcasts" v-bind:key="JSON.stringify(broadcast)" @click="ssb_connect(broadcast)">{{broadcast.address}}:{{broadcast.port}} <tf-user :id="broadcast.pubkey"></tf-user></md-list-item>
<md-subheader>Connections</md-subheader> <md-subheader>Connections</md-subheader>
<md-list-item v-for="connection in connections" v-bind:key="'connection-' + JSON.stringify(connection)"><tf-user :id="connection"></tf-user></md-list-item> <md-list-item v-for="connection in connections" v-bind:key="'connection-' + JSON.stringify(connection)"><tf-user :id="connection"></tf-user></md-list-item>
<md-list-item @click="show_connect_dialog = true">Connect</md-list-item> <md-list-item @click="show_connect_dialog = true">Connect</md-list-item>
<md-subheader>Users</md-subheader>
<md-list-item v-for="user in Object.keys(users)" v-bind:key="'user-' + user"><tf-user v-bind:id="user"/></md-list-item>
</md-list> </md-list>
</md-app-drawer> </md-app-drawer>
<md-app-content> <md-app-content>

View File

@ -1,5 +1,11 @@
Vue.component('tf-user', { Vue.component('tf-user', {
data: function() { return {users: g_data.users, show_user_dialog: false, show_follow_dialog: false} }, data: function() { return {
users: g_data.users,
show_user_dialog: false,
show_follow_dialog: false,
edit_profile_name: null,
edit_profile_description: null,
} },
props: ['id'], props: ['id'],
mounted: function() { mounted: function() {
window.parent.postMessage({user: this.id}, '*'); window.parent.postMessage({user: this.id}, '*');
@ -22,29 +28,54 @@ Vue.component('tf-user', {
} }
}, },
}, },
whoami: { get: function() { return g_data.whoami; } },
},
methods: {
save_profile: function() {
var message = {appendMessage: {
type: 'about',
about: this.id,
name: this.edit_profile_name,
description: this.edit_profile_description,
}};
window.parent.postMessage(message, '*');
},
}, },
template: `<span @click="show_user_dialog = true"> template: `<span @click="show_user_dialog = true">
{{users[id] && users[id].name ? users[id].name : id}} {{users[id] && users[id].name ? users[id].name : id}}
<md-tooltip v-if="users[id] && users[id].name">{{id}}</md-tooltip> <md-tooltip v-if="users[id] && users[id].name">{{id}}</md-tooltip>
<md-dialog :md-active.sync="show_user_dialog"> <md-dialog :md-active.sync="show_user_dialog">
<md-dialog-title>{{users[id] && users[id].name ? users[id].name : id}}</md-dialog-title> <md-dialog-title>{{users[id] && users[id].name ? users[id].name : id}}</md-dialog-title>
<md-dialog-content v-if="users[id]"> <md-dialog-content>
<div v-if="users[id].image"><img :src="'/' + users[id].image + '/view'"></div> <div v-if="id == whoami">
<div v-if="users[id].name">{{id}}</div> <md-field>
<div>{{users[id].description}}</div> <label>Name</label>
<div><md-switch v-model="following">Following</md-switch></div> <md-input v-model="edit_profile_name"></md-input>
<md-list> </md-field>
<md-subheader>Followers</md-subheader> <md-field>
<md-list-item v-for="follower in (users[id] || []).followers" v-bind:key="'follower-' + follower"> <label>Description</label>
<tf-user :id="follower"></tf-user> <md-textarea v-model="edit_profile_description"></md-textarea>
</md-list-item> </md-field>
<md-subheader>Following</md-subheader> </div>
<md-list-item v-for="user in (users[id] || []).following" v-bind:key="'following-' + user"> <template v-if="users[id]">
<tf-user :id="user"></tf-user> <div v-if="users[id].image"><img :src="'/' + users[id].image + '/view'"></div>
</md-list-item> <div v-if="users[id].name">{{id}}</div>
</md-list> <div>{{users[id].description}}</div>
<div><md-switch v-model="following">Following</md-switch></div>
<md-list>
<md-subheader>Followers</md-subheader>
<md-list-item v-for="follower in (users[id] || []).followers" v-bind:key="'follower-' + follower">
<tf-user :id="follower"></tf-user>
</md-list-item>
<md-subheader>Following</md-subheader>
<md-list-item v-for="user in (users[id] || []).following" v-bind:key="'following-' + user">
<tf-user :id="user"></tf-user>
</md-list-item>
</md-list>
</template>
</md-dialog-content> </md-dialog-content>
<md-dialog-actions> <md-dialog-actions>
<md-button @click="save_profile">Save Profile</md-button>
<md-button @click="show_user_dialog = false">Close</md-button> <md-button @click="show_user_dialog = false">Close</md-button>
</md-dialog-actions> </md-dialog-actions>
</md-dialog> </md-dialog>

View File

@ -5,7 +5,6 @@ var g_data = {
messages: [], messages: [],
users: {}, users: {},
broadcasts: [], broadcasts: [],
showUsers: false,
show_connect_dialog: false, show_connect_dialog: false,
show_user_dialog: null, show_user_dialog: null,
connect: null, connect: null,
@ -21,6 +20,7 @@ window.addEventListener('message', function(event) {
if (key == 'message') { if (key == 'message') {
g_data.messages.push(event.data[key]); g_data.messages.push(event.data[key]);
g_data.messages.sort((x, y) => y.timestamp - x.timestamp); g_data.messages.sort((x, y) => y.timestamp - x.timestamp);
g_data.messages.splice(100);
} else if (key + 's' in g_data && Array.isArray(g_data[key + 's'])) { } else if (key + 's' in g_data && Array.isArray(g_data[key + 's'])) {
g_data[key + 's'].push(event.data[key]); g_data[key + 's'].push(event.data[key]);
} else if (key == 'user') { } else if (key == 'user') {