add better reaction popup
This commit is contained in:
parent
ae33a8a61b
commit
ecf7e3b4ce
14 changed files with 31442 additions and 14 deletions
BIN
android/app/src/main/assets/public/NotoColorEmoji-Regular.ttf
Normal file
BIN
android/app/src/main/assets/public/NotoColorEmoji-Regular.ttf
Normal file
Binary file not shown.
|
|
@ -124,6 +124,7 @@
|
||||||
"messages.decrypt.failed": "failed to decrypt meow :c",
|
"messages.decrypt.failed": "failed to decrypt meow :c",
|
||||||
"title.reply.message": "meow back",
|
"title.reply.message": "meow back",
|
||||||
"title.react.message": "purr",
|
"title.react.message": "purr",
|
||||||
|
"title.text.react": "text purr",
|
||||||
"title.delete.message": "hiss away",
|
"title.delete.message": "hiss away",
|
||||||
"title.replied.to": "meowed back to",
|
"title.replied.to": "meowed back to",
|
||||||
"title.replying.to": "meowing back to",
|
"title.replying.to": "meowing back to",
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@
|
||||||
"messages.decrypt.failed": "Failed to decrypt message",
|
"messages.decrypt.failed": "Failed to decrypt message",
|
||||||
"title.reply.message": "Reply",
|
"title.reply.message": "Reply",
|
||||||
"title.react.message": "React",
|
"title.react.message": "React",
|
||||||
|
"title.text.react": "Text React",
|
||||||
"title.delete.message": "Delete",
|
"title.delete.message": "Delete",
|
||||||
"title.replied.to": "Replied to",
|
"title.replied.to": "Replied to",
|
||||||
"title.replying.to": "Replying to",
|
"title.replying.to": "Replying to",
|
||||||
|
|
|
||||||
15644
android/app/src/main/assets/public/emotes.json
Normal file
15644
android/app/src/main/assets/public/emotes.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1057,8 +1057,10 @@ async function ensureUserKeys() {
|
||||||
|
|
||||||
async function mainJS() {
|
async function mainJS() {
|
||||||
await initBlahs();
|
await initBlahs();
|
||||||
|
await loadEmotes();
|
||||||
|
|
||||||
passwordHash = await hashSHA3_512(password);
|
passwordHash = await hashSHA3_512(password);
|
||||||
|
|
||||||
if (localStorage.getItem('lang') != null) {
|
if (localStorage.getItem('lang') != null) {
|
||||||
lang = localStorage.getItem('lang');
|
lang = localStorage.getItem('lang');
|
||||||
}
|
}
|
||||||
|
|
@ -2503,13 +2505,76 @@ async function replyMessage(msgId) {
|
||||||
input.focus();
|
input.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var reactionPickerMenuHtml = "";
|
||||||
|
var loadedEmotes = [];
|
||||||
|
|
||||||
|
async function loadEmotes() {
|
||||||
|
try {
|
||||||
|
let res = await fetch("emotes.json");
|
||||||
|
let emotesObj = await res.json();
|
||||||
|
let skinTones = ['\u{1F3FB}', '\u{1F3FC}', '\u{1F3FD}', '\u{1F3FE}', '\u{1F3FF}'];
|
||||||
|
loadedEmotes = Object.keys(emotesObj).flatMap(char => {
|
||||||
|
let baseEmote = { char: char, name: emotesObj[char].name, slug: emotesObj[char].slug };
|
||||||
|
if (emotesObj[char].skin_tone_support) {
|
||||||
|
let variants = skinTones.map(tone => ({
|
||||||
|
char: char + tone,
|
||||||
|
name: emotesObj[char].name + " skin tone",
|
||||||
|
slug: emotesObj[char].slug
|
||||||
|
}));
|
||||||
|
return [baseEmote, ...variants];
|
||||||
|
}
|
||||||
|
return [baseEmote];
|
||||||
|
});
|
||||||
|
|
||||||
|
reactionPickerMenuHtml = `
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 0.4rem; padding: 0.2rem; min-width: 14rem;">
|
||||||
|
<input type="text" id="reaction-picker-search" placeholder="Type text / emoji..." oninput="filterReactions(this.value)" onkeydown="if(event.key === 'Enter') { if(this.value.trim() !== '') reactMessagePrompt(currentContextMenuMsgId, encodeURIComponent(this.value)); }" style="width: 100%; box-sizing: border-box; padding: 0.5rem 0.6rem; border-radius: 0.65rem; border: var(--border-width) solid var(--light-border-color); background: transparent; color: var(--text-color); font-family: inherit;">
|
||||||
|
<div id="reaction-picker-grid" style="display: grid; grid-template-columns: repeat(5, 1fr); gap: 0.2rem; max-height: 12rem; overflow-y: auto; overflow-x: hidden;">
|
||||||
|
${loadedEmotes.map(emoji => `<button onclick="reactMessagePrompt(currentContextMenuMsgId, encodeURIComponent('${emoji.char}'))" data-name="${emoji.name}" style="min-width: unset; width: 100%; aspect-ratio: 1; display: flex; justify-content: center; align-items: center; padding: 0; font-size: 1.2rem; border-radius: 0.65rem;" class="reaction-emoji-btn">${emoji.char}</button>`).join('')}
|
||||||
|
</div>
|
||||||
|
<button onclick="reactMessagePrompt(currentContextMenuMsgId, encodeURIComponent(document.getElementById('reaction-picker-search').value))" style="margin: 0; padding: 0.5rem; justify-content: center; border-radius: 0.65rem; width: 100%;">
|
||||||
|
<span class="blah">title.text.react</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to load emotes", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterReactions(query) {
|
||||||
|
let grid = document.getElementById("reaction-picker-grid");
|
||||||
|
if (!grid) return;
|
||||||
|
let buttons = grid.querySelectorAll(".reaction-emoji-btn");
|
||||||
|
let lowerQuery = query.toLowerCase();
|
||||||
|
buttons.forEach(btn => {
|
||||||
|
let name = btn.getAttribute("data-name");
|
||||||
|
if (name && name.toLowerCase().indexOf(lowerQuery) > -1) {
|
||||||
|
btn.style.display = "flex";
|
||||||
|
} else {
|
||||||
|
btn.style.display = "none";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function openReactionPicker(e) {
|
||||||
|
if (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
if (!reactionPickerMenuHtml) return;
|
||||||
|
let rect = fixedContextMenu.getBoundingClientRect();
|
||||||
|
showFixedContextMenu({top: rect.top, right: rect.left, bottom: rect.top, left: rect.left}, reactionPickerMenuHtml);
|
||||||
|
let searchInput = document.getElementById('reaction-picker-search');
|
||||||
|
if (searchInput) searchInput.focus();
|
||||||
|
}
|
||||||
|
|
||||||
async function reactMessagePrompt(msgId, quickReaction = null) {
|
async function reactMessagePrompt(msgId, quickReaction = null) {
|
||||||
if (fixedContextMenu) fixedContextMenu.classList.remove("show");
|
if (fixedContextMenu) fixedContextMenu.classList.remove("show");
|
||||||
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
||||||
let reaction = quickReaction;
|
let reaction = quickReaction;
|
||||||
if (!reaction) {
|
if (!reaction) {
|
||||||
reaction = prompt("Enter reaction (emoji or text):");
|
return;
|
||||||
if (!reaction) return;
|
|
||||||
} else {
|
} else {
|
||||||
reaction = decodeURIComponent(reaction);
|
reaction = decodeURIComponent(reaction);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -225,15 +225,13 @@ var addSpaceMenu = `
|
||||||
<button onclick="gotoCreateSpace()">
|
<button onclick="gotoCreateSpace()">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M80-120v-720h400v160h400v320h-80v-240H480v80h80v80h-80v80h80v80h-80v80h160v80H80Zm80-80h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm160 480h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80ZM800-40v-80h-80v-80h80v-80h80v80h80v80h-80v80h-80ZM640-440v-80h80v80h-80Zm0 160v-80h80v80h-80Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M80-120v-720h400v160h400v320h-80v-240H480v80h80v80h-80v80h80v80h-80v80h160v80H80Zm80-80h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm160 480h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80ZM800-40v-80h-80v-80h80v-80h80v80h80v80h-80v80h-80ZM640-440v-80h80v80h-80Zm0 160v-80h80v80h-80Z"/></svg>
|
||||||
<span class="blah">title.create.space</span>
|
<span class="blah">title.create.space</span>
|
||||||
</button>
|
</button>`
|
||||||
`;
|
|
||||||
|
|
||||||
var messageContextMenu = `
|
var messageContextMenu = `
|
||||||
<button onclick="replyMessage(currentContextMenuMsgId)">
|
<button onclick="replyMessage(currentContextMenuMsgId)">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M760-200v-160q0-50-35-85t-85-35H273l144 144-57 56-240-240 240-240 57 56-144 144h367q83 0 141.5 58.5T840-360v160h-80Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M760-200v-160q0-50-35-85t-85-35H273l144 144-57 56-240-240 240-240 57 56-144 144h367q83 0 141.5 58.5T840-360v160h-80Z"/></svg>
|
||||||
<span class="blah">title.reply.message</span>
|
<span class="blah">title.reply.message</span>
|
||||||
</button>
|
</button>
|
||||||
<button onclick="reactMessagePrompt(currentContextMenuMsgId)">
|
<button onclick="openReactionPicker(event)">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M480-260q70 0 126.5-40.5T682-400H278q19 59 75.5 99.5T480-260Zm-160-220q25 0 42.5-17.5T380-540q0-25-17.5-42.5T320-600q-25 0-42.5 17.5T260-540q0 25 17.5 42.5T320-480Zm320 0q25 0 42.5-17.5T700-540q0-25-17.5-42.5T640-600q-25 0-42.5 17.5T580-540q0 25 17.5 42.5T640-480ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M480-260q70 0 126.5-40.5T682-400H278q19 59 75.5 99.5T480-260Zm-160-220q25 0 42.5-17.5T380-540q0-25-17.5-42.5T320-600q-25 0-42.5 17.5T260-540q0 25 17.5 42.5T320-480Zm320 0q25 0 42.5-17.5T700-540q0-25-17.5-42.5T640-600q-25 0-42.5 17.5T580-540q0 25 17.5 42.5T640-480ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
||||||
<span class="blah">title.react.message</span>
|
<span class="blah">title.react.message</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -246,3 +244,4 @@ var messageContextMenu = `
|
||||||
//elements
|
//elements
|
||||||
var detailsBtn = `<button class="mobile-nav-btn right" onclick="mobileNavDetails()"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z"/></svg></button>`;
|
var detailsBtn = `<button class="mobile-nav-btn right" onclick="mobileNavDetails()"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z"/></svg></button>`;
|
||||||
var backBtnHtml = `<button class="mobile-nav-btn" onclick="mobileNavBack()"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="m313-440 224 224-57 56-320-320 320-320 57 56-224 224h487v80H313Z"/></svg></button>`;
|
var backBtnHtml = `<button class="mobile-nav-btn" onclick="mobileNavBack()"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="m313-440 224 224-57 56-320-320 320-320 57 56-224 224h487v80H313Z"/></svg></button>`;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,10 @@
|
||||||
font-family: 'Nunito';
|
font-family: 'Nunito';
|
||||||
src: URL('Nunito-Regular.ttf') format('truetype');
|
src: URL('Nunito-Regular.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'NotoColorEmoji';
|
||||||
|
src: URL('NotoColorEmoji-Regular.ttf') format('truetype');
|
||||||
|
}
|
||||||
:root {
|
:root {
|
||||||
--main-bg-color: rgb(20, 20, 20);
|
--main-bg-color: rgb(20, 20, 20);
|
||||||
--text-color: rgb(240, 240, 245);
|
--text-color: rgb(240, 240, 245);
|
||||||
|
|
@ -66,7 +70,7 @@ loading {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
font-family: "Nunito", sans-serif;
|
font-family: "Nunito", "NotoColorEmoji", sans-serif;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
user-select: none !important;
|
user-select: none !important;
|
||||||
-webkit-user-drag: none !important;
|
-webkit-user-drag: none !important;
|
||||||
|
|
|
||||||
BIN
webroot/NotoColorEmoji-Regular.ttf
Normal file
BIN
webroot/NotoColorEmoji-Regular.ttf
Normal file
Binary file not shown.
|
|
@ -124,6 +124,7 @@
|
||||||
"messages.decrypt.failed": "failed to decrypt meow :c",
|
"messages.decrypt.failed": "failed to decrypt meow :c",
|
||||||
"title.reply.message": "meow back",
|
"title.reply.message": "meow back",
|
||||||
"title.react.message": "purr",
|
"title.react.message": "purr",
|
||||||
|
"title.text.react": "text purr",
|
||||||
"title.delete.message": "hiss away",
|
"title.delete.message": "hiss away",
|
||||||
"title.replied.to": "meowed back to",
|
"title.replied.to": "meowed back to",
|
||||||
"title.replying.to": "meowing back to",
|
"title.replying.to": "meowing back to",
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@
|
||||||
"messages.decrypt.failed": "Failed to decrypt message",
|
"messages.decrypt.failed": "Failed to decrypt message",
|
||||||
"title.reply.message": "Reply",
|
"title.reply.message": "Reply",
|
||||||
"title.react.message": "React",
|
"title.react.message": "React",
|
||||||
|
"title.text.react": "Text React",
|
||||||
"title.delete.message": "Delete",
|
"title.delete.message": "Delete",
|
||||||
"title.replied.to": "Replied to",
|
"title.replied.to": "Replied to",
|
||||||
"title.replying.to": "Replying to",
|
"title.replying.to": "Replying to",
|
||||||
|
|
|
||||||
15644
webroot/emotes.json
Normal file
15644
webroot/emotes.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1057,8 +1057,10 @@ async function ensureUserKeys() {
|
||||||
|
|
||||||
async function mainJS() {
|
async function mainJS() {
|
||||||
await initBlahs();
|
await initBlahs();
|
||||||
|
await loadEmotes();
|
||||||
|
|
||||||
passwordHash = await hashSHA3_512(password);
|
passwordHash = await hashSHA3_512(password);
|
||||||
|
|
||||||
if (localStorage.getItem('lang') != null) {
|
if (localStorage.getItem('lang') != null) {
|
||||||
lang = localStorage.getItem('lang');
|
lang = localStorage.getItem('lang');
|
||||||
}
|
}
|
||||||
|
|
@ -2503,13 +2505,76 @@ async function replyMessage(msgId) {
|
||||||
input.focus();
|
input.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var reactionPickerMenuHtml = "";
|
||||||
|
var loadedEmotes = [];
|
||||||
|
|
||||||
|
async function loadEmotes() {
|
||||||
|
try {
|
||||||
|
let res = await fetch("emotes.json");
|
||||||
|
let emotesObj = await res.json();
|
||||||
|
let skinTones = ['\u{1F3FB}', '\u{1F3FC}', '\u{1F3FD}', '\u{1F3FE}', '\u{1F3FF}'];
|
||||||
|
loadedEmotes = Object.keys(emotesObj).flatMap(char => {
|
||||||
|
let baseEmote = { char: char, name: emotesObj[char].name, slug: emotesObj[char].slug };
|
||||||
|
if (emotesObj[char].skin_tone_support) {
|
||||||
|
let variants = skinTones.map(tone => ({
|
||||||
|
char: char + tone,
|
||||||
|
name: emotesObj[char].name + " skin tone",
|
||||||
|
slug: emotesObj[char].slug
|
||||||
|
}));
|
||||||
|
return [baseEmote, ...variants];
|
||||||
|
}
|
||||||
|
return [baseEmote];
|
||||||
|
});
|
||||||
|
|
||||||
|
reactionPickerMenuHtml = `
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 0.4rem; padding: 0.2rem; min-width: 14rem;">
|
||||||
|
<input type="text" id="reaction-picker-search" placeholder="Type text / emoji..." oninput="filterReactions(this.value)" onkeydown="if(event.key === 'Enter') { if(this.value.trim() !== '') reactMessagePrompt(currentContextMenuMsgId, encodeURIComponent(this.value)); }" style="width: 100%; box-sizing: border-box; padding: 0.5rem 0.6rem; border-radius: 0.65rem; border: var(--border-width) solid var(--light-border-color); background: transparent; color: var(--text-color); font-family: inherit;">
|
||||||
|
<div id="reaction-picker-grid" style="display: grid; grid-template-columns: repeat(5, 1fr); gap: 0.2rem; max-height: 12rem; overflow-y: auto; overflow-x: hidden;">
|
||||||
|
${loadedEmotes.map(emoji => `<button onclick="reactMessagePrompt(currentContextMenuMsgId, encodeURIComponent('${emoji.char}'))" data-name="${emoji.name}" style="min-width: unset; width: 100%; aspect-ratio: 1; display: flex; justify-content: center; align-items: center; padding: 0; font-size: 1.2rem; border-radius: 0.65rem;" class="reaction-emoji-btn">${emoji.char}</button>`).join('')}
|
||||||
|
</div>
|
||||||
|
<button onclick="reactMessagePrompt(currentContextMenuMsgId, encodeURIComponent(document.getElementById('reaction-picker-search').value))" style="margin: 0; padding: 0.5rem; justify-content: center; border-radius: 0.65rem; width: 100%;">
|
||||||
|
<span class="blah">title.text.react</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Failed to load emotes", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterReactions(query) {
|
||||||
|
let grid = document.getElementById("reaction-picker-grid");
|
||||||
|
if (!grid) return;
|
||||||
|
let buttons = grid.querySelectorAll(".reaction-emoji-btn");
|
||||||
|
let lowerQuery = query.toLowerCase();
|
||||||
|
buttons.forEach(btn => {
|
||||||
|
let name = btn.getAttribute("data-name");
|
||||||
|
if (name && name.toLowerCase().indexOf(lowerQuery) > -1) {
|
||||||
|
btn.style.display = "flex";
|
||||||
|
} else {
|
||||||
|
btn.style.display = "none";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function openReactionPicker(e) {
|
||||||
|
if (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
if (!reactionPickerMenuHtml) return;
|
||||||
|
let rect = fixedContextMenu.getBoundingClientRect();
|
||||||
|
showFixedContextMenu({top: rect.top, right: rect.left, bottom: rect.top, left: rect.left}, reactionPickerMenuHtml);
|
||||||
|
let searchInput = document.getElementById('reaction-picker-search');
|
||||||
|
if (searchInput) searchInput.focus();
|
||||||
|
}
|
||||||
|
|
||||||
async function reactMessagePrompt(msgId, quickReaction = null) {
|
async function reactMessagePrompt(msgId, quickReaction = null) {
|
||||||
if (fixedContextMenu) fixedContextMenu.classList.remove("show");
|
if (fixedContextMenu) fixedContextMenu.classList.remove("show");
|
||||||
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
if (typeof clearContextMenuStyles === "function") clearContextMenuStyles();
|
||||||
let reaction = quickReaction;
|
let reaction = quickReaction;
|
||||||
if (!reaction) {
|
if (!reaction) {
|
||||||
reaction = prompt("Enter reaction (emoji or text):");
|
return;
|
||||||
if (!reaction) return;
|
|
||||||
} else {
|
} else {
|
||||||
reaction = decodeURIComponent(reaction);
|
reaction = decodeURIComponent(reaction);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -225,15 +225,13 @@ var addSpaceMenu = `
|
||||||
<button onclick="gotoCreateSpace()">
|
<button onclick="gotoCreateSpace()">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M80-120v-720h400v160h400v320h-80v-240H480v80h80v80h-80v80h80v80h-80v80h160v80H80Zm80-80h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm160 480h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80ZM800-40v-80h-80v-80h80v-80h80v80h80v80h-80v80h-80ZM640-440v-80h80v80h-80Zm0 160v-80h80v80h-80Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M80-120v-720h400v160h400v320h-80v-240H480v80h80v80h-80v80h80v80h-80v80h160v80H80Zm80-80h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm160 480h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80Zm0-160h80v-80h-80v80ZM800-40v-80h-80v-80h80v-80h80v80h80v80h-80v80h-80ZM640-440v-80h80v80h-80Zm0 160v-80h80v80h-80Z"/></svg>
|
||||||
<span class="blah">title.create.space</span>
|
<span class="blah">title.create.space</span>
|
||||||
</button>
|
</button>`
|
||||||
`;
|
|
||||||
|
|
||||||
var messageContextMenu = `
|
var messageContextMenu = `
|
||||||
<button onclick="replyMessage(currentContextMenuMsgId)">
|
<button onclick="replyMessage(currentContextMenuMsgId)">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M760-200v-160q0-50-35-85t-85-35H273l144 144-57 56-240-240 240-240 57 56-144 144h367q83 0 141.5 58.5T840-360v160h-80Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M760-200v-160q0-50-35-85t-85-35H273l144 144-57 56-240-240 240-240 57 56-144 144h367q83 0 141.5 58.5T840-360v160h-80Z"/></svg>
|
||||||
<span class="blah">title.reply.message</span>
|
<span class="blah">title.reply.message</span>
|
||||||
</button>
|
</button>
|
||||||
<button onclick="reactMessagePrompt(currentContextMenuMsgId)">
|
<button onclick="openReactionPicker(event)">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M480-260q70 0 126.5-40.5T682-400H278q19 59 75.5 99.5T480-260Zm-160-220q25 0 42.5-17.5T380-540q0-25-17.5-42.5T320-600q-25 0-42.5 17.5T260-540q0 25 17.5 42.5T320-480Zm320 0q25 0 42.5-17.5T700-540q0-25-17.5-42.5T640-600q-25 0-42.5 17.5T580-540q0 25 17.5 42.5T640-480ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="1.4rem" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M480-260q70 0 126.5-40.5T682-400H278q19 59 75.5 99.5T480-260Zm-160-220q25 0 42.5-17.5T380-540q0-25-17.5-42.5T320-600q-25 0-42.5 17.5T260-540q0 25 17.5 42.5T320-480Zm320 0q25 0 42.5-17.5T700-540q0-25-17.5-42.5T640-600q-25 0-42.5 17.5T580-540q0 25 17.5 42.5T640-480ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
|
||||||
<span class="blah">title.react.message</span>
|
<span class="blah">title.react.message</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -246,3 +244,4 @@ var messageContextMenu = `
|
||||||
//elements
|
//elements
|
||||||
var detailsBtn = `<button class="mobile-nav-btn right" onclick="mobileNavDetails()"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z"/></svg></button>`;
|
var detailsBtn = `<button class="mobile-nav-btn right" onclick="mobileNavDetails()"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z"/></svg></button>`;
|
||||||
var backBtnHtml = `<button class="mobile-nav-btn" onclick="mobileNavBack()"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="m313-440 224 224-57 56-320-320 320-320 57 56-224 224h487v80H313Z"/></svg></button>`;
|
var backBtnHtml = `<button class="mobile-nav-btn" onclick="mobileNavBack()"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="var(--text-color)"><path d="m313-440 224 224-57 56-320-320 320-320 57 56-224 224h487v80H313Z"/></svg></button>`;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,10 @@
|
||||||
font-family: 'Nunito';
|
font-family: 'Nunito';
|
||||||
src: URL('Nunito-Regular.ttf') format('truetype');
|
src: URL('Nunito-Regular.ttf') format('truetype');
|
||||||
}
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'NotoColorEmoji';
|
||||||
|
src: URL('NotoColorEmoji-Regular.ttf') format('truetype');
|
||||||
|
}
|
||||||
:root {
|
:root {
|
||||||
--main-bg-color: rgb(20, 20, 20);
|
--main-bg-color: rgb(20, 20, 20);
|
||||||
--text-color: rgb(240, 240, 245);
|
--text-color: rgb(240, 240, 245);
|
||||||
|
|
@ -66,7 +70,7 @@ loading {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
font-family: "Nunito", sans-serif;
|
font-family: "Nunito", "NotoColorEmoji", sans-serif;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
user-select: none !important;
|
user-select: none !important;
|
||||||
-webkit-user-drag: none !important;
|
-webkit-user-drag: none !important;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue