forked from cory/tildefriends
		
	
		
			
				
	
	
		
			101 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			101 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
let g_hash;
 | 
						|
 | 
						|
async function query(sql, params) {
 | 
						|
	let results = [];
 | 
						|
	await ssb.sqlAsync(sql, params, function (row) {
 | 
						|
		results.push(row);
 | 
						|
	});
 | 
						|
	return results;
 | 
						|
}
 | 
						|
 | 
						|
async function resolve(id) {
 | 
						|
	try {
 | 
						|
		let blob = await ssb.blobGet(id);
 | 
						|
		if (blob) {
 | 
						|
			let json;
 | 
						|
			try {
 | 
						|
				json = JSON.parse(utf8Decode(blob));
 | 
						|
			} catch {
 | 
						|
				return {id: utf8Decode(blob)};
 | 
						|
			}
 | 
						|
			if (json?.links) {
 | 
						|
				for (let [key, value] of Object.entries(json.links)) {
 | 
						|
					json.links[key] = await resolve(value);
 | 
						|
				}
 | 
						|
				return json;
 | 
						|
			} else {
 | 
						|
				return 'huh?' + json;
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			return `missing<${id}>`;
 | 
						|
		}
 | 
						|
	} catch (e) {
 | 
						|
		return id + ': ' + e.message;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
async function get_names(identities) {
 | 
						|
	return Object.fromEntries(
 | 
						|
		(
 | 
						|
			await query(
 | 
						|
				`
 | 
						|
		SELECT author, name FROM (
 | 
						|
			SELECT
 | 
						|
				messages.author,
 | 
						|
				RANK() OVER (PARTITION BY messages.author ORDER BY messages.sequence DESC) AS author_rank,
 | 
						|
				messages.content ->> 'name' AS name
 | 
						|
			FROM messages
 | 
						|
			JOIN json_each(?) AS identities ON identities.value = messages.author
 | 
						|
			WHERE
 | 
						|
				json_extract(messages.content, '$.type') = 'about' AND
 | 
						|
				content ->> 'about' = messages.author AND name IS NOT NULL)
 | 
						|
		WHERE author_rank = 1
 | 
						|
	`,
 | 
						|
				[JSON.stringify(identities)]
 | 
						|
			)
 | 
						|
		).map((x) => [x.author, x.name])
 | 
						|
	);
 | 
						|
}
 | 
						|
 | 
						|
async function render(hash) {
 | 
						|
	g_hash = hash;
 | 
						|
	if (!hash) {
 | 
						|
		let sites = await query(
 | 
						|
			`
 | 
						|
			SELECT site.author, site.id
 | 
						|
			FROM messages site
 | 
						|
			WHERE site.content ->> 'type' = 'web-init'
 | 
						|
		`,
 | 
						|
			[]
 | 
						|
		);
 | 
						|
		let names = await get_names(sites.map((x) => x.author));
 | 
						|
		if (hash === g_hash) {
 | 
						|
			await app.setDocument(
 | 
						|
				`<ul style="background-color: #ddd">${sites.map((x) => `<li><a target="_top" href="#${encodeURIComponent(x.id)}">${names[x.author] ?? x.author} - ${x.id}</a></li>`).join('\n')}</ul>`
 | 
						|
			);
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		let site_id =
 | 
						|
			hash.charAt(0) == '#'
 | 
						|
				? decodeURIComponent(hash.substring(1))
 | 
						|
				: decodeURIComponent(hash);
 | 
						|
		await app.setDocument(`<html style="margin: 0; padding: 0; width: 100vw; height: 100vh; margin: 0; padding: 0">
 | 
						|
			<body style="display: flex; flex-direction: column; width: 100vw; height: 100vh">
 | 
						|
				<iframe src="${encodeURIComponent(site_id)}/index.html" style="flex: 1 1; border: 0; background-color: #fff"></iframe>
 | 
						|
			</body>
 | 
						|
		</html>`);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
core.register('message', async function message_handler(message) {
 | 
						|
	if (message.event == 'hashChange') {
 | 
						|
		await render(message.hash);
 | 
						|
	}
 | 
						|
});
 | 
						|
 | 
						|
async function main() {
 | 
						|
	render(null);
 | 
						|
}
 | 
						|
 | 
						|
main();
 |