forked from cory/tildefriends
		
	ssb: A first pass at showing private messages next to channels. #84
This commit is contained in:
		| @@ -1,5 +1,5 @@ | ||||
| { | ||||
| 	"type": "tildefriends-app", | ||||
| 	"emoji": "🐌", | ||||
| 	"previous": "&pySy2RopLJGGrJRpoyzKM7zDzQUCxRXLuE62kS4C5s4=.sha256" | ||||
| 	"previous": "&0gBRfD+3EaZD2S82zAnXT3hgGuNTnUncOh5vGwZwbSw=.sha256" | ||||
| } | ||||
|   | ||||
| @@ -267,6 +267,34 @@ class TfElement extends LitElement { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	async get_latest_private(following) { | ||||
| 		let latest = (await tfrpc.rpc.query('SELECT MAX(rowid) AS latest FROM messages'))[0].latest; | ||||
| 		const k_chunk_count = 256; | ||||
| 		while (latest - k_chunk_count >= 0) { | ||||
| 			let messages = await tfrpc.rpc.query(` | ||||
| 					SELECT messages.rowid, messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature | ||||
| 						FROM messages | ||||
| 						JOIN json_each(?1) AS following ON messages.author = following.value | ||||
| 						WHERE | ||||
| 							messages.rowid > ?2 AND | ||||
| 							messages.rowid <= ?3 AND | ||||
| 							json(messages.content) LIKE '"%' | ||||
| 						ORDER BY sequence DESC | ||||
| 					`, | ||||
| 					[ | ||||
| 						JSON.stringify(following), | ||||
| 						latest - k_chunk_count, | ||||
| 						latest, | ||||
| 					]); | ||||
| 			messages = (await this.decrypt(messages)).filter(x => x.decrypted); | ||||
| 			if (messages.length) { | ||||
| 				return Math.max(...messages.map(x => x.rowid)); | ||||
| 			} | ||||
| 			latest -= k_chunk_count; | ||||
| 		}; | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	async load() { | ||||
| 		let whoami = this.whoami; | ||||
| 		let following = await tfrpc.rpc.following([whoami], 2); | ||||
| @@ -302,6 +330,7 @@ class TfElement extends LitElement { | ||||
| 				'"' + this.whoami.replace('"', '""') + '"', | ||||
| 			] | ||||
| 		); | ||||
| 		let latest_private = this.get_latest_private(Object.keys(following)); | ||||
| 		this.channels_unread = JSON.parse( | ||||
| 			(await tfrpc.rpc.databaseGet('unread')) ?? '{}' | ||||
| 		); | ||||
| @@ -320,6 +349,11 @@ class TfElement extends LitElement { | ||||
| 		this.channels_latest = Object.fromEntries( | ||||
| 			channels.map((x) => [x.channel, x.rowid]) | ||||
| 		); | ||||
| 		let self = this; | ||||
| 		latest_private.then(function(latest) { | ||||
| 			self.channels_latest = Object.assign({}, self.channels_latest, {'🔐': latest}); | ||||
| 			console.log('private took', (new Date() - start_time) / 1000.0); | ||||
| 		}); | ||||
| 		this.following = Object.keys(following); | ||||
| 		this.users = users; | ||||
| 		console.log(`load finished ${whoami} => ${this.whoami}`); | ||||
| @@ -333,6 +367,30 @@ class TfElement extends LitElement { | ||||
| 		tfrpc.rpc.databaseSet('unread', JSON.stringify(this.channels_unread)); | ||||
| 	} | ||||
|  | ||||
| 	async decrypt(messages) { | ||||
| 		let whoami = this.whoami; | ||||
| 		return Promise.all(messages.map(async function (message) { | ||||
| 			let content; | ||||
| 			try { | ||||
| 				content = JSON.parse(message?.content); | ||||
| 			} catch {} | ||||
| 			if (typeof content === 'string') { | ||||
| 				let decrypted; | ||||
| 				try { | ||||
| 					decrypted = await tfrpc.rpc.try_decrypt(whoami, content); | ||||
| 				} catch {} | ||||
| 				if (decrypted) { | ||||
| 					try { | ||||
| 						message.decrypted = JSON.parse(decrypted); | ||||
| 					} catch { | ||||
| 						message.decrypted = decrypted; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			return message; | ||||
| 		})); | ||||
| 	} | ||||
|  | ||||
| 	render_tab() { | ||||
| 		let following = this.following; | ||||
| 		let users = this.users; | ||||
|   | ||||
| @@ -151,6 +151,21 @@ class TfTabNewsFeedElement extends LitElement { | ||||
| 				); | ||||
| 			} | ||||
| 			result = [].concat(...(await Promise.all(promises))); | ||||
| 		} else if (this.hash == '#🔐') { | ||||
| 			result = await tfrpc.rpc.query( | ||||
| 				` | ||||
| 					SELECT messages.rowid, messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature | ||||
| 						FROM messages | ||||
| 						JOIN json_each(?1) AS following ON messages.author = following.value | ||||
| 						WHERE | ||||
| 							messages.timestamp >= ?2 AND | ||||
| 							messages.timestamp < ?3 AND | ||||
| 							json(messages.content) LIKE '"%' | ||||
| 						ORDER BY sequence DESC | ||||
| 				`, | ||||
| 				[JSON.stringify(this.following), start_time, end_time] | ||||
| 			); | ||||
| 			result = (await this.decrypt(result)).filter(x => x.decrypted); | ||||
| 		} else { | ||||
| 			let promises = []; | ||||
| 			const k_following_limit = 256; | ||||
|   | ||||
| @@ -210,6 +210,12 @@ class TfTabNewsElement extends LitElement { | ||||
| 					style=${this.hash == '#@' ? 'font-weight: bold' : undefined} | ||||
| 					>@mentions ${this.unread_status('@')}</a | ||||
| 				> | ||||
| 				<a | ||||
| 					href="#🔐" | ||||
| 					class="w3-bar-item w3-button" | ||||
| 					style=${this.hash == '#🔐' ? 'font-weight: bold' : undefined} | ||||
| 					>🔐private ${this.unread_status('🔐')}</a | ||||
| 				> | ||||
| 				${this.channels.map( | ||||
| 					(x) => html` | ||||
| 						<a | ||||
|   | ||||
		Reference in New Issue
	
	Block a user