forked from forktown/watch-party
add unicode emoji autocomplete
This commit is contained in:
parent
c7efd725b3
commit
65212087e3
4 changed files with 41 additions and 24 deletions
|
@ -5,20 +5,18 @@ import {
|
||||||
} from "./watch-session.mjs?v=1e57e6";
|
} from "./watch-session.mjs?v=1e57e6";
|
||||||
import { emojify, emojis } from "./emojis.mjs?v=1e57e6";
|
import { emojify, emojis } from "./emojis.mjs?v=1e57e6";
|
||||||
|
|
||||||
function insertAtCursor(input, textToInsert) {
|
function setCaretPosition(elem, caretPos) {
|
||||||
const isSuccess = document.execCommand("insertText", false, textToInsert);
|
if(elem.createTextRange) {
|
||||||
|
var range = elem.createTextRange();
|
||||||
// Firefox (non-standard method)
|
range.move('character', caretPos);
|
||||||
if (!isSuccess && typeof input.setRangeText === "function") {
|
range.select();
|
||||||
const start = input.selectionStart;
|
} else {
|
||||||
input.setRangeText(textToInsert);
|
if(elem.selectionStart) {
|
||||||
// update cursor to be at the end of insertion
|
elem.focus();
|
||||||
input.selectionStart = input.selectionEnd = start + textToInsert.length;
|
elem.setSelectionRange(caretPos, caretPos);
|
||||||
|
}
|
||||||
// Notify any possible listeners of the change
|
else
|
||||||
const e = document.createEvent("UIEvent");
|
elem.focus();
|
||||||
e.initEvent("input", true, false);
|
|
||||||
input.dispatchEvent(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,22 +51,27 @@ const setupChatboxEvents = (socket) => {
|
||||||
};
|
};
|
||||||
emojiAutocomplete.append(
|
emojiAutocomplete.append(
|
||||||
...(await emojis)
|
...(await emojis)
|
||||||
.filter((e) => e.toLowerCase().startsWith(search.toLowerCase()))
|
.filter(([name]) => name.toLowerCase().startsWith(search.toLowerCase()))
|
||||||
.map((name, i) => {
|
.map(([name, replaceWith], i) => {
|
||||||
const button = Object.assign(document.createElement("button"), {
|
const button = Object.assign(document.createElement("button"), {
|
||||||
className: "emoji-option" + (i === 0 ? " selected" : ""),
|
className: "emoji-option" + (i === 0 ? " selected" : ""),
|
||||||
onmousedown: (e) => e.preventDefault(),
|
onmousedown: (e) => e.preventDefault(),
|
||||||
onclick: () =>
|
onclick: () => {
|
||||||
insertAtCursor(button, name.slice(match[2].length) + ": "),
|
messageInput.value=prefix+replaceWith+" "+suffix;
|
||||||
|
setCaretPosition(messageInput, (prefix+" "+replaceWith).length)
|
||||||
|
},
|
||||||
onmouseover: () => select(button),
|
onmouseover: () => select(button),
|
||||||
onfocus: () => select(button),
|
onfocus: () => select(button),
|
||||||
});
|
});
|
||||||
button.append(
|
button.append(
|
||||||
Object.assign(new Image(), {
|
(replaceWith[0]!==":"?Object.assign(document.createElement("span"), {
|
||||||
|
textContent: replaceWith,
|
||||||
|
className: "emoji",
|
||||||
|
}):Object.assign(new Image(), {
|
||||||
loading: "lazy",
|
loading: "lazy",
|
||||||
src: `/emojis/${name}.png`,
|
src: `/emojis/${name}.png`,
|
||||||
className: "emoji",
|
className: "emoji",
|
||||||
}),
|
})),
|
||||||
Object.assign(document.createElement("span"), { textContent: name })
|
Object.assign(document.createElement("span"), { textContent: name })
|
||||||
);
|
);
|
||||||
return button;
|
return button;
|
||||||
|
|
|
@ -21,6 +21,10 @@ export async function emojify(text) {
|
||||||
if (last < text.length) nodes.push(document.createTextNode(text.slice(last)));
|
if (last < text.length) nodes.push(document.createTextNode(text.slice(last)));
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
export const emojis = fetch("/emojis")
|
export const emojis = Promise.all([
|
||||||
|
fetch("/emojis")
|
||||||
.then((e) => e.json())
|
.then((e) => e.json())
|
||||||
.then((e) => e.map((e) => e.slice(0, -4)));
|
.then((e) => e.map((e) => [e.slice(0, -4), ":"+e.slice(0, -4)+":"])),
|
||||||
|
fetch('/emojis/unicode.json')
|
||||||
|
.then((e) => e.json())
|
||||||
|
]).then(e=>e.flat(1));
|
|
@ -287,6 +287,10 @@ button.small-button {
|
||||||
width: 1.25rem;
|
width: 1.25rem;
|
||||||
height: 1.25rem;
|
height: 1.25rem;
|
||||||
margin: 0 0.5rem 0 0;
|
margin: 0 0.5rem 0 0;
|
||||||
|
font-size: 2.25ch;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emoji-option.selected {
|
.emoji-option.selected {
|
||||||
|
|
6
scripts/get_unicode_emojis.sh
Executable file
6
scripts/get_unicode_emojis.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Get emoji folder
|
||||||
|
emojiFolder="$(readlink -f "$(dirname $0)/../frontend/emojis/")"
|
||||||
|
|
||||||
|
curl 'https://raw.githubusercontent.com/iamcal/emoji-data/master/emoji.json' | jq '. | map(. as $emoji | .short_names | map([., ($emoji.unified | split("-") | map(. | split("") | map(. as $nibble | (["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"] | index($nibble))) | reduce .[] as $item (0; (. * 16) + $item)) | map(if (. < 65536) then (.) else [55296 - 64 + (. / 1024 | floor), 56320 + (((. / 1024) - (. / 1024 | floor)) * 1024)] end) | flatten(1) | map(("\\u" + ("0000" + ({"str": "", "num": .} | until(.num < 1; {"str": (["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"][((.num / 16) - (.num / 16 | floor)) * 16] + .str), "num": (.num / 16) | floor})).str)[-4:])) | join("") | "\"" + . + "\"" | fromjson)])) | flatten(1)' --raw-output >"$emojiFolder/unicode.json"
|
Loading…
Reference in a new issue