/** * 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; font-family: sans-serif; margin: 16px; } .container { display: grid; grid-template-columns: repeat(auto-fill, 64px); gap: 1em; justify-content: space-around; background-color: #ffffff10; border: 2px solid #073642; border-radius: 8px; } .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 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); } } 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();