/** * Fetches information about the applications * @param apps Record * @returns an object including the apps' name, emoji, and blobs ids */ async function fetch_info(apps) { let result = {}; // For each app for (let [key, value] of Object.entries(apps)) { // Get it's blob and parse it let blob = await ssb.blobGet(value); blob = blob ? utf8Decode(blob) : '{}'; // Add it to the result object result[key] = JSON.parse(blob); } return result; } async function fetch_shared_apps() { let messages = {}; await ssb.sqlAsync( ` SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature FROM messages_fts('"application/tildefriends"') JOIN messages ON messages.rowid = messages_fts.rowid ORDER BY messages.timestamp `, [], function (row) { 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, }; } } } ); let result = {}; for (let app of Object.values(messages).sort( (x, y) => y.message.timestamp - x.message.timestamp )) { 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; } } return result; } async function main() { 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; margin: 8px; } .iconbox { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); } .iconbox::after { content: ""; flex: auto; } .app { height: 96px; width: 64px; display: flex; flex-direction: column; align-items: center; justify-content: center; white-space: nowrap; } .app > a { text-decoration: none; max-width: 64px; text-overflow: ellipsis ellipsis; overflow: hidden; color: whitesmoke; } `; const body = `

Welcome to Tilde Friends

Your Apps

Shared Apps

Core Apps

`; 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 inline = document.createElement('div'); inline.style.display = 'inline-block'; inline.classList.add('w3-button'); list.appendChild(inline); let div = document.createElement('div'); inline.appendChild(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); } } 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 = ` ${body} `; // Send it to the browser app.setDocument(document); } main();