forked from cory/tildefriends
		
	Show recently used emojis in the emoji picker. #16
This commit is contained in:
		@@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
	"type": "tildefriends-app",
 | 
			
		||||
	"emoji": "🐌",
 | 
			
		||||
	"previous": "&uSuRSjzMShdQllrt3gVYhWlixI6o6n0c1c/+pEhJCCI=.sha256"
 | 
			
		||||
	"previous": "&W6OyIT7eLYsiAZ6BHEAsvF+OJXlVgFs1MH1eLf+EhkQ=.sha256"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user