| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Fetches information about the applications | 
					
						
							|  |  |  |  * @param apps Record<appName, blobId> | 
					
						
							|  |  |  |  * @returns an object including the apps' name, emoji, and blobs ids | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2023-03-21 23:08:04 +00:00
										 |  |  | async function fetch_info(apps) { | 
					
						
							|  |  |  | 	let result = {}; | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// For each app
 | 
					
						
							| 
									
										
										
										
											2023-03-21 23:08:04 +00:00
										 |  |  | 	for (let [key, value] of Object.entries(apps)) { | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 		// Get it's blob and parse it
 | 
					
						
							| 
									
										
										
										
											2023-03-21 23:08:04 +00:00
										 |  |  | 		let blob = await ssb.blobGet(value); | 
					
						
							|  |  |  | 		blob = blob ? utf8Decode(blob) : '{}'; | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Add it to the result object
 | 
					
						
							| 
									
										
										
										
											2023-03-21 23:08:04 +00:00
										 |  |  | 		result[key] = JSON.parse(blob); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-21 23:08:04 +00:00
										 |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | /** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2024-01-17 22:43:32 +00:00
										 |  |  | async function fetch_shared_apps() { | 
					
						
							|  |  |  | 	let messages = {}; | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 	await ssb.sqlAsync( | 
					
						
							|  |  |  | 		`
 | 
					
						
							| 
									
										
										
										
											2024-02-29 19:26:56 -05:00
										 |  |  | 				SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature | 
					
						
							| 
									
										
										
										
											2024-01-17 22:43:32 +00:00
										 |  |  | 				FROM messages_fts('"application/tildefriends"') | 
					
						
							|  |  |  | 				JOIN messages ON messages.rowid = messages_fts.rowid | 
					
						
							| 
									
										
										
										
											2024-02-29 19:26:56 -05:00
										 |  |  | 				ORDER BY messages.timestamp | 
					
						
							| 
									
										
										
										
											2024-01-17 22:43:32 +00:00
										 |  |  | 		`,
 | 
					
						
							|  |  |  | 		[], | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 		function (row) { | 
					
						
							| 
									
										
										
										
											2024-01-17 22:43:32 +00:00
										 |  |  | 			let content = JSON.parse(row.content); | 
					
						
							|  |  |  | 			for (let mention of content.mentions) { | 
					
						
							|  |  |  | 				if (mention?.type === 'application/tildefriends') { | 
					
						
							|  |  |  | 					messages[JSON.stringify([row.author, mention.name])] = { | 
					
						
							|  |  |  | 						message: row, | 
					
						
							|  |  |  | 						blob: mention.link, | 
					
						
							|  |  |  | 						name: mention.name, | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-17 22:43:32 +00:00
										 |  |  | 	let result = {}; | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 	for (let app of Object.values(messages).sort( | 
					
						
							|  |  |  | 		(x, y) => y.message.timestamp - x.message.timestamp | 
					
						
							|  |  |  | 	)) { | 
					
						
							| 
									
										
										
										
											2024-01-19 02:17:09 +00:00
										 |  |  | 		let app_object = JSON.parse(utf8Decode(await ssb.blobGet(app.blob))); | 
					
						
							|  |  |  | 		if (app_object) { | 
					
						
							|  |  |  | 			app_object.blob_id = app.blob; | 
					
						
							|  |  |  | 			result[app.name] = app_object; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-01-17 22:43:32 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 17:48:21 +00:00
										 |  |  | async function main() { | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 	const apps = await fetch_info(await core.apps()); | 
					
						
							|  |  |  | 	const core_apps = await fetch_info(await core.apps('core')); | 
					
						
							|  |  |  | 	const shared_apps = await fetch_shared_apps(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const stylesheet = `
 | 
					
						
							|  |  |  | 		body { | 
					
						
							|  |  |  | 			color: whitesmoke; | 
					
						
							|  |  |  | 			font-family: sans-serif; | 
					
						
							|  |  |  | 			margin: 16px; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-03-21 16:54:06 +00:00
										 |  |  | 		.container { | 
					
						
							|  |  |  | 			display: grid; | 
					
						
							| 
									
										
										
										
											2023-03-21 23:08:04 +00:00
										 |  |  | 			grid-template-columns: repeat(auto-fill, 64px); | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 			gap: 1em; | 
					
						
							| 
									
										
										
										
											2023-03-21 16:54:06 +00:00
										 |  |  | 			justify-content: space-around; | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 			background-color: #ffffff10; | 
					
						
							|  |  |  | 			border: 2px solid #073642; | 
					
						
							|  |  |  | 			border-radius: 8px; | 
					
						
							| 
									
										
										
										
											2023-03-21 16:54:06 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-21 16:54:06 +00:00
										 |  |  | 		.app { | 
					
						
							| 
									
										
										
										
											2023-03-21 23:08:04 +00:00
										 |  |  | 			height: 96px; | 
					
						
							|  |  |  | 			width: 64px; | 
					
						
							| 
									
										
										
										
											2023-03-21 16:54:06 +00:00
										 |  |  | 			display: flex; | 
					
						
							|  |  |  | 			flex-direction: column; | 
					
						
							|  |  |  | 			align-items: center; | 
					
						
							|  |  |  | 			justify-content: center; | 
					
						
							|  |  |  | 			white-space: nowrap; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		.app > a { | 
					
						
							|  |  |  | 			text-decoration: none; | 
					
						
							| 
									
										
										
										
											2023-03-21 23:08:04 +00:00
										 |  |  | 			max-width: 64px; | 
					
						
							| 
									
										
										
										
											2023-03-21 16:54:06 +00:00
										 |  |  | 			text-overflow: ellipsis ellipsis; | 
					
						
							|  |  |  | 			overflow: hidden; | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 			color: whitesmoke; | 
					
						
							| 
									
										
										
										
											2023-03-21 16:54:06 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 	`;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const body = `
 | 
					
						
							|  |  |  | 		<h1 style="text-shadow: #808080 0 0 10px;">Welcome to Tilde Friends.</h1> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		<h2>your apps</h2> | 
					
						
							|  |  |  | 		<div id="apps" class="container"></div> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		<h2>shared apps</h2> | 
					
						
							|  |  |  | 		<div id="shared_apps" class="container"></div> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		<h2>core apps</h2> | 
					
						
							|  |  |  | 		<div id="core_apps" class="container"></div> | 
					
						
							|  |  |  | 	`;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const script = `
 | 
					
						
							|  |  |  | 		/* | 
					
						
							|  |  |  | 		 * Creates a list of apps | 
					
						
							|  |  |  | 		 * @param id the id of the element to populate | 
					
						
							|  |  |  | 		 * @param name (a username, 'core' or undefined) | 
					
						
							|  |  |  | 		 * @param apps Object, a list of apps | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		function populate_apps(id, name, apps) { | 
					
						
							|  |  |  | 			// Our target
 | 
					
						
							|  |  |  | 			var list = document.getElementById(id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// For each app in the provided list
 | 
					
						
							|  |  |  | 			for (let app of Object.keys(apps).sort()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Create the item
 | 
					
						
							|  |  |  | 				let div = list.appendChild(document.createElement('div')); | 
					
						
							|  |  |  | 				div.classList.add('app'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// The app's icon
 | 
					
						
							|  |  |  | 				let href = name ? '/~' + name + '/' + app + '/' : ('/' + apps[app].blob_id + '/'); | 
					
						
							|  |  |  | 				let icon_a = document.createElement('a'); | 
					
						
							|  |  |  | 				let icon = document.createElement('div'); | 
					
						
							|  |  |  | 				icon.appendChild(document.createTextNode(apps[app].emoji || '📦')); | 
					
						
							|  |  |  | 				icon.style.fontSize = 'xxx-large'; | 
					
						
							|  |  |  | 				icon_a.appendChild(icon); | 
					
						
							|  |  |  | 				icon_a.href = href; | 
					
						
							|  |  |  | 				icon_a.target = '_top'; | 
					
						
							|  |  |  | 				div.appendChild(icon_a); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// The app's name
 | 
					
						
							|  |  |  | 				let a = document.createElement('a'); | 
					
						
							|  |  |  | 				a.appendChild(document.createTextNode(app)); | 
					
						
							|  |  |  | 				a.href = href; | 
					
						
							|  |  |  | 				a.target = '_top'; | 
					
						
							|  |  |  | 				div.appendChild(a); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-01-26 02:49:45 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-02-16 00:13:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		populate_apps('apps', '${core.user.credentials?.session?.name}', ${JSON.stringify(apps)}); | 
					
						
							|  |  |  | 		populate_apps('core_apps', 'core', ${JSON.stringify(core_apps)}); | 
					
						
							|  |  |  | 		populate_apps('shared_apps', undefined, ${JSON.stringify(shared_apps)}); | 
					
						
							|  |  |  | 	`;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Build the document
 | 
					
						
							|  |  |  | 	const document = `
 | 
					
						
							|  |  |  | 	<!DOCTYPE html> | 
					
						
							|  |  |  | 	<html> | 
					
						
							|  |  |  | 		<head> | 
					
						
							|  |  |  | 			<style> | 
					
						
							|  |  |  | 				${stylesheet} | 
					
						
							|  |  |  | 			</style> | 
					
						
							|  |  |  | 		</head> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		<body> | 
					
						
							|  |  |  | 			${body} | 
					
						
							|  |  |  | 		</body> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		<script> | 
					
						
							|  |  |  | 			${script} | 
					
						
							|  |  |  | 		</script> | 
					
						
							|  |  |  | 	</html>`; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Send it to the browser
 | 
					
						
							|  |  |  | 	app.setDocument(document); | 
					
						
							| 
									
										
										
										
											2021-12-28 17:48:21 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-21 23:08:04 +00:00
										 |  |  | main(); |