From 68e8c010b772e7912eec807a8e63a445e98c4bc5 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Thu, 4 Apr 2024 02:12:43 +0100 Subject: [PATCH] Show recently used emojis in the emoji picker. #16 --- apps/ssb.json | 2 +- apps/ssb/emojis.js | 230 +++++++++++++++++++++++++---------------- apps/ssb/tf-message.js | 2 +- 3 files changed, 141 insertions(+), 93 deletions(-) diff --git a/apps/ssb.json b/apps/ssb.json index 272212ad..f36b6863 100644 --- a/apps/ssb.json +++ b/apps/ssb.json @@ -1,5 +1,5 @@ { "type": "tildefriends-app", "emoji": "🐌", - "previous": "&uSuRSjzMShdQllrt3gVYhWlixI6o6n0c1c/+pEhJCCI=.sha256" + "previous": "&W6OyIT7eLYsiAZ6BHEAsvF+OJXlVgFs1MH1eLf+EhkQ=.sha256" } diff --git a/apps/ssb/emojis.js b/apps/ssb/emojis.js index b87f165b..1e4202b1 100644 --- a/apps/ssb/emojis.js +++ b/apps/ssb/emojis.js @@ -1,3 +1,5 @@ +import * as tfrpc from '/static/tfrpc.js'; + let g_emojis; function get_emojis() { @@ -10,105 +12,151 @@ function get_emojis() { }); } -export function picker(callback, anchor) { - get_emojis().then(function (json) { - let div = document.createElement('div'); - div.id = 'emoji_picker'; - div.style.color = '#000'; - div.style.background = '#fff'; - div.style.border = '1px solid #000'; - div.style.display = 'block'; - div.style.position = 'absolute'; - div.style.minWidth = 'min(16em, 90vw)'; - div.style.width = 'min(16em, 90vw)'; - div.style.maxWidth = 'min(16em, 90vw)'; - div.style.maxHeight = '16em'; - div.style.overflow = 'scroll'; - div.style.fontWeight = 'bold'; - div.style.fontSize = 'xx-large'; - let input = document.createElement('input'); - input.type = 'text'; - input.style.display = 'block'; - input.style.boxSizing = 'border-box'; - input.style.width = '100%'; - input.style.margin = '0'; - input.style.position = 'relative'; - div.appendChild(input); - let list = document.createElement('div'); - div.appendChild(list); - div.addEventListener('mousedown', function (event) { - event.stopPropagation(); - }); +async function get_recent(author) { + let recent = await tfrpc.rpc.query(` + SELECT DISTINCT content ->> '$.vote.expression' AS value + FROM messages + WHERE author = ? AND + content ->> '$.type' = 'vote' + ORDER BY timestamp DESC LIMIT 10 + `, [author]); + return recent.map(x => x.value); +} - function cleanup() { - console.log('emoji cleanup'); - div.parentElement.removeChild(div); - window.removeEventListener('keydown', key_down); - console.log('removing click'); - document.body.removeEventListener('mousedown', cleanup); - } +export async function picker(callback, anchor, author) { + let json = await get_emojis(); + let recent = await get_recent(author); - function key_down(event) { - if (event.key == 'Escape') { - cleanup(); - } - } + let div = document.createElement('div'); + div.id = 'emoji_picker'; + div.style.color = '#000'; + div.style.background = '#fff'; + div.style.border = '1px solid #000'; + div.style.display = 'block'; + div.style.position = 'absolute'; + div.style.minWidth = 'min(16em, 90vw)'; + div.style.width = 'min(16em, 90vw)'; + div.style.maxWidth = 'min(16em, 90vw)'; + div.style.maxHeight = '16em'; + div.style.overflow = 'scroll'; + div.style.fontWeight = 'bold'; + div.style.fontSize = 'xx-large'; + let input = document.createElement('input'); + input.type = 'text'; + input.style.display = 'block'; + input.style.boxSizing = 'border-box'; + input.style.width = '100%'; + input.style.margin = '0'; + input.style.position = 'relative'; + div.appendChild(input); + let list = document.createElement('div'); + div.appendChild(list); + div.addEventListener('mousedown', function (event) { + event.stopPropagation(); + }); - function chosen(event) { - console.log(event.srcElement.innerText); - callback(event.srcElement.innerText); + function cleanup() { + console.log('emoji cleanup'); + div.parentElement.removeChild(div); + window.removeEventListener('keydown', key_down); + console.log('removing click'); + document.body.removeEventListener('mousedown', cleanup); + } + + function key_down(event) { + if (event.key == 'Escape') { cleanup(); } + } - function refresh() { - while (list.firstChild) { - list.removeChild(list.firstChild); - } - let search = input.value.toLowerCase(); - let any_at_all = false; - for (let row of Object.entries(json)) { - let header = document.createElement('div'); - header.appendChild(document.createTextNode(row[0])); - list.appendChild(header); - let any = false; - for (let entry of Object.entries(row[1])) { - if ( - search && - search.length && - entry[0].toLowerCase().indexOf(search) == -1 - ) { - continue; - } - let emoji = document.createElement('span'); - const k_size = '1.25em'; - emoji.style.display = 'inline-block'; - emoji.style.overflow = 'hidden'; - emoji.style.cursor = 'pointer'; - emoji.onclick = chosen; - emoji.title = entry[0]; - emoji.appendChild(document.createTextNode(entry[1])); - list.appendChild(emoji); - any = true; - any_at_all = true; - } - if (!any) { - list.removeChild(header); + function chosen(event) { + console.log(event.srcElement.innerText); + callback(event.srcElement.innerText); + cleanup(); + } + + function refresh() { + while (list.firstChild) { + list.removeChild(list.firstChild); + } + let search = input.value.toLowerCase(); + let any_at_all = false; + if (recent) { + let emoji_to_name = {}; + for (let row of Object.values(json)) { + for (let entry of Object.entries(row)) { + emoji_to_name[entry[1]] = entry[0]; } } - if (!any_at_all) { - list.appendChild(document.createTextNode('No matches found.')); + let header = document.createElement('div'); + header.appendChild(document.createTextNode('Recent')); + list.appendChild(header); + let any = false; + for (let entry of recent) { + if ( + search && + search.length && + (emoji_to_name[entry] || '').toLowerCase().indexOf(search) == -1 + ) { + continue; + } + let emoji = document.createElement('span'); + const k_size = '1.25em'; + emoji.style.display = 'inline-block'; + emoji.style.overflow = 'hidden'; + emoji.style.cursor = 'pointer'; + emoji.onclick = chosen; + emoji.title = emoji_to_name[entry] || entry; + emoji.appendChild(document.createTextNode(entry)); + list.appendChild(emoji); + any = true; + } + if (!any) { + list.removeChild(header); } } - refresh(); - input.oninput = refresh; - document.body.appendChild(div); - div.style.position = 'fixed'; - div.style.top = '50%'; - div.style.left = '50%'; - div.style.transform = 'translate(-50%, -50%)'; - input.focus(); - console.log('adding click'); - document.body.addEventListener('mousedown', cleanup); - window.addEventListener('keydown', key_down); - }); + for (let row of Object.entries(json)) { + let header = document.createElement('div'); + header.appendChild(document.createTextNode(row[0])); + list.appendChild(header); + let any = false; + for (let entry of Object.entries(row[1])) { + if ( + search && + search.length && + entry[0].toLowerCase().indexOf(search) == -1 + ) { + continue; + } + let emoji = document.createElement('span'); + const k_size = '1.25em'; + emoji.style.display = 'inline-block'; + emoji.style.overflow = 'hidden'; + emoji.style.cursor = 'pointer'; + emoji.onclick = chosen; + emoji.title = entry[0]; + emoji.appendChild(document.createTextNode(entry[1])); + list.appendChild(emoji); + any = true; + any_at_all = true; + } + if (!any) { + list.removeChild(header); + } + } + if (!any_at_all) { + list.appendChild(document.createTextNode('No matches found.')); + } + } + refresh(); + input.oninput = refresh; + document.body.appendChild(div); + div.style.position = 'fixed'; + div.style.top = '50%'; + div.style.left = '50%'; + div.style.transform = 'translate(-50%, -50%)'; + input.focus(); + console.log('adding click'); + document.body.addEventListener('mousedown', cleanup); + window.addEventListener('keydown', key_down); } diff --git a/apps/ssb/tf-message.js b/apps/ssb/tf-message.js index 84ff3c07..4be9ec85 100644 --- a/apps/ssb/tf-message.js +++ b/apps/ssb/tf-message.js @@ -125,7 +125,7 @@ class TfMessageElement extends LitElement { } react(event) { - emojis.picker((x) => this.vote(x)); + emojis.picker((x) => this.vote(x), null, this.whoami); } show_image(link) {