support for sending and seeing stickers
This commit is contained in:
parent
956016a9a0
commit
5c58b50a25
9 changed files with 344 additions and 7 deletions
|
@ -26,6 +26,7 @@ import {I18n} from "./i18n.js";
|
||||||
import {mobile} from "./utils/utils.js";
|
import {mobile} from "./utils/utils.js";
|
||||||
import {webhookMenu} from "./webhooks.js";
|
import {webhookMenu} from "./webhooks.js";
|
||||||
import {File} from "./file.js";
|
import {File} from "./file.js";
|
||||||
|
import {Sticker} from "./sticker.js";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface NotificationOptions {
|
interface NotificationOptions {
|
||||||
|
@ -1569,7 +1570,12 @@ class Channel extends SnowFlake {
|
||||||
this.fakeMessageMap.delete(id);
|
this.fakeMessageMap.delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
makeFakeMessage(content: string, files: filejson[] = [], reply = undefined) {
|
makeFakeMessage(
|
||||||
|
content: string,
|
||||||
|
files: filejson[] = [],
|
||||||
|
reply = undefined,
|
||||||
|
sticker_ids: string[],
|
||||||
|
) {
|
||||||
const m = new Message(
|
const m = new Message(
|
||||||
{
|
{
|
||||||
author: this.localuser.user.tojson(),
|
author: this.localuser.user.tojson(),
|
||||||
|
@ -1590,6 +1596,11 @@ class Channel extends SnowFlake {
|
||||||
type: 0,
|
type: 0,
|
||||||
pinned: false,
|
pinned: false,
|
||||||
message_reference: reply,
|
message_reference: reply,
|
||||||
|
sticker_items: sticker_ids
|
||||||
|
.map((_) => {
|
||||||
|
return Sticker.getFromId(_, this.localuser);
|
||||||
|
})
|
||||||
|
.filter((_) => _ !== undefined),
|
||||||
},
|
},
|
||||||
this,
|
this,
|
||||||
true,
|
true,
|
||||||
|
@ -1654,9 +1665,20 @@ class Channel extends SnowFlake {
|
||||||
attachments = [],
|
attachments = [],
|
||||||
replyingto = null,
|
replyingto = null,
|
||||||
embeds = [],
|
embeds = [],
|
||||||
}: {attachments: Blob[]; embeds: embedjson[]; replyingto: Message | null},
|
sticker_ids = [],
|
||||||
|
}: {
|
||||||
|
attachments: Blob[];
|
||||||
|
embeds: embedjson[];
|
||||||
|
replyingto: Message | null;
|
||||||
|
sticker_ids: string[];
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
if (content.trim() === "" && attachments.length === 0 && embeds.length == 0) {
|
if (
|
||||||
|
content.trim() === "" &&
|
||||||
|
attachments.length === 0 &&
|
||||||
|
embeds.length == 0 &&
|
||||||
|
sticker_ids.length === 0
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let replyjson: any;
|
let replyjson: any;
|
||||||
|
@ -1702,6 +1724,7 @@ class Channel extends SnowFlake {
|
||||||
content,
|
content,
|
||||||
nonce: Math.floor(Math.random() * 1000000000),
|
nonce: Math.floor(Math.random() * 1000000000),
|
||||||
message_reference: undefined,
|
message_reference: undefined,
|
||||||
|
sticker_ids,
|
||||||
};
|
};
|
||||||
if (replyjson) {
|
if (replyjson) {
|
||||||
body.message_reference = replyjson;
|
body.message_reference = replyjson;
|
||||||
|
@ -1714,7 +1737,7 @@ class Channel extends SnowFlake {
|
||||||
res.open("POST", this.info.api + "/channels/" + this.id + "/messages");
|
res.open("POST", this.info.api + "/channels/" + this.id + "/messages");
|
||||||
res.setRequestHeader("Content-type", (ctype = this.headers["Content-type"]));
|
res.setRequestHeader("Content-type", (ctype = this.headers["Content-type"]));
|
||||||
res.setRequestHeader("Authorization", this.headers.Authorization);
|
res.setRequestHeader("Authorization", this.headers.Authorization);
|
||||||
funcs = this.makeFakeMessage(content, [], body.message_reference);
|
funcs = this.makeFakeMessage(content, [], body.message_reference, sticker_ids);
|
||||||
res.send((rbody = JSON.stringify(body)));
|
res.send((rbody = JSON.stringify(body)));
|
||||||
/*
|
/*
|
||||||
res = fetch(this.info.api + "/channels/" + this.id + "/messages", {
|
res = fetch(this.info.api + "/channels/" + this.id + "/messages", {
|
||||||
|
@ -1729,6 +1752,7 @@ class Channel extends SnowFlake {
|
||||||
content,
|
content,
|
||||||
nonce: Math.floor(Math.random() * 1000000000),
|
nonce: Math.floor(Math.random() * 1000000000),
|
||||||
message_reference: undefined,
|
message_reference: undefined,
|
||||||
|
sticker_ids,
|
||||||
};
|
};
|
||||||
if (replyjson) {
|
if (replyjson) {
|
||||||
body.message_reference = replyjson;
|
body.message_reference = replyjson;
|
||||||
|
@ -1756,6 +1780,7 @@ class Channel extends SnowFlake {
|
||||||
url: URL.createObjectURL(_),
|
url: URL.createObjectURL(_),
|
||||||
})),
|
})),
|
||||||
body.message_reference,
|
body.message_reference,
|
||||||
|
sticker_ids,
|
||||||
);
|
);
|
||||||
res.send((rbody = formData));
|
res.send((rbody = formData));
|
||||||
/*
|
/*
|
||||||
|
|
1
src/webpage/icons/sticker.svg
Normal file
1
src/webpage/icons/sticker.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg width="512" height="512" xmlns="http://www.w3.org/2000/svg"><g style="opacity:1"><path d="M76 0C34 0 0 34 0 76v319c0 42 34 75 76 75h174V326c0-42 34-76 76-76h143V76c0-42-33-76-75-76Z" style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:#fe0000;stroke-linecap:round;stroke-linejoin:round;enable-background:accumulate;stop-color:#000;stop-opacity:1" transform="translate(22 22)"/></g><path style="fill:red;stroke:#fe0000;stroke-width:151.239;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none" d="M375 371h46l-46 47z"/></svg>
|
After Width: | Height: | Size: 576 B |
|
@ -104,6 +104,7 @@
|
||||||
<span class="svg-upload svgicon" id="upload"></span>
|
<span class="svg-upload svgicon" id="upload"></span>
|
||||||
<div id="typebox" contenteditable="true"></div>
|
<div id="typebox" contenteditable="true"></div>
|
||||||
<span class="svgicon svg-gif" id="gifTB"></span>
|
<span class="svgicon svg-gif" id="gifTB"></span>
|
||||||
|
<span class="svgicon svg-sticker" id="stickerTB"></span>
|
||||||
<span class="svgicon svg-emoji" id="emojiTB"></span>
|
<span class="svgicon svg-emoji" id="emojiTB"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -309,4 +309,12 @@ import {I18n} from "./i18n.js";
|
||||||
thisUser.makeGifBox(gifTB.getBoundingClientRect());
|
thisUser.makeGifBox(gifTB.getBoundingClientRect());
|
||||||
};
|
};
|
||||||
gifTB.onclick = (e) => e.stopImmediatePropagation();
|
gifTB.onclick = (e) => e.stopImmediatePropagation();
|
||||||
|
|
||||||
|
const stickerTB = document.getElementById("stickerTB") as HTMLElement;
|
||||||
|
stickerTB.onmousedown = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
thisUser.makeStickerBox(stickerTB.getBoundingClientRect());
|
||||||
|
};
|
||||||
|
stickerTB.onclick = (e) => e.stopImmediatePropagation();
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -250,6 +250,7 @@ interface stickerJson {
|
||||||
type: number;
|
type: number;
|
||||||
format_type: number;
|
format_type: number;
|
||||||
description?: string;
|
description?: string;
|
||||||
|
guild_id?: string;
|
||||||
}
|
}
|
||||||
type extendedProperties = guildjson["properties"] & {
|
type extendedProperties = guildjson["properties"] & {
|
||||||
emojis: emojipjson[];
|
emojis: emojipjson[];
|
||||||
|
@ -358,6 +359,7 @@ type messagejson = {
|
||||||
pinned: boolean;
|
pinned: boolean;
|
||||||
type: number;
|
type: number;
|
||||||
webhook?: webhookInfo;
|
webhook?: webhookInfo;
|
||||||
|
sticker_items: stickerJson[];
|
||||||
message_reference?: string;
|
message_reference?: string;
|
||||||
};
|
};
|
||||||
type filejson = {
|
type filejson = {
|
||||||
|
|
|
@ -2279,6 +2279,23 @@ class Localuser {
|
||||||
if (!this.channelfocus) return;
|
if (!this.channelfocus) return;
|
||||||
await this.channelfocus.pinnedClick(rect);
|
await this.channelfocus.pinnedClick(rect);
|
||||||
}
|
}
|
||||||
|
async makeStickerBox(rect: DOMRect) {
|
||||||
|
const sticker = await Sticker.stickerPicker(
|
||||||
|
-0 + rect.right - window.innerWidth,
|
||||||
|
-20 + rect.top - window.innerHeight,
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
console.log(sticker);
|
||||||
|
if (this.channelfocus) {
|
||||||
|
this.channelfocus.sendMessage("", {
|
||||||
|
embeds: [],
|
||||||
|
attachments: [],
|
||||||
|
sticker_ids: [sticker.id],
|
||||||
|
replyingto: this.channelfocus.replyingto,
|
||||||
|
});
|
||||||
|
this.channelfocus.replyingto = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
async makeGifBox(rect: DOMRect) {
|
async makeGifBox(rect: DOMRect) {
|
||||||
interface fullgif {
|
interface fullgif {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -2373,6 +2390,7 @@ class Localuser {
|
||||||
this.channelfocus.sendMessage(gif.url, {
|
this.channelfocus.sendMessage(gif.url, {
|
||||||
embeds: [],
|
embeds: [],
|
||||||
attachments: [],
|
attachments: [],
|
||||||
|
sticker_ids: [],
|
||||||
replyingto: this.channelfocus.replyingto,
|
replyingto: this.channelfocus.replyingto,
|
||||||
});
|
});
|
||||||
menu.remove();
|
menu.remove();
|
||||||
|
|
|
@ -14,9 +14,11 @@ import {mobile} from "./utils/utils.js";
|
||||||
import {I18n} from "./i18n.js";
|
import {I18n} from "./i18n.js";
|
||||||
import {Hover} from "./hover.js";
|
import {Hover} from "./hover.js";
|
||||||
import {Dialog} from "./settings.js";
|
import {Dialog} from "./settings.js";
|
||||||
|
import {Sticker} from "./sticker.js";
|
||||||
|
|
||||||
class Message extends SnowFlake {
|
class Message extends SnowFlake {
|
||||||
static contextmenu = new Contextmenu<Message, void>("message menu");
|
static contextmenu = new Contextmenu<Message, void>("message menu");
|
||||||
|
stickers: Sticker[];
|
||||||
owner: Channel;
|
owner: Channel;
|
||||||
headers: Localuser["headers"];
|
headers: Localuser["headers"];
|
||||||
embeds!: Embed[];
|
embeds!: Embed[];
|
||||||
|
@ -249,6 +251,11 @@ class Message extends SnowFlake {
|
||||||
continue;
|
continue;
|
||||||
} else if (thing === "author") {
|
} else if (thing === "author") {
|
||||||
continue;
|
continue;
|
||||||
|
} else if (thing === "sticker_items") {
|
||||||
|
this.stickers = messagejson.sticker_items.map((_) => {
|
||||||
|
const guild = this.localuser.guildids.get(_.guild_id as string);
|
||||||
|
return new Sticker(_, guild || this.localuser);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
(this as any)[thing] = (messagejson as any)[thing];
|
(this as any)[thing] = (messagejson as any)[thing];
|
||||||
}
|
}
|
||||||
|
@ -791,6 +798,12 @@ class Message extends SnowFlake {
|
||||||
text.append(time);
|
text.append(time);
|
||||||
div.classList.add("topMessage");
|
div.classList.add("topMessage");
|
||||||
}
|
}
|
||||||
|
const stickerArea = document.createElement("div");
|
||||||
|
stickerArea.classList.add("flexltr", "stickerMArea");
|
||||||
|
for (const sticker of this.stickers) {
|
||||||
|
stickerArea.append(sticker.getHTML());
|
||||||
|
}
|
||||||
|
div.append(stickerArea);
|
||||||
if (!dupe) {
|
if (!dupe) {
|
||||||
const reactions = document.createElement("div");
|
const reactions = document.createElement("div");
|
||||||
reactions.classList.add("flexltr", "reactiondiv");
|
reactions.classList.add("flexltr", "reactiondiv");
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
import {Contextmenu} from "./contextmenu.js";
|
||||||
import {Guild} from "./guild.js";
|
import {Guild} from "./guild.js";
|
||||||
|
import {Hover} from "./hover.js";
|
||||||
import {stickerJson} from "./jsontypes.js";
|
import {stickerJson} from "./jsontypes.js";
|
||||||
|
import {Localuser} from "./localuser.js";
|
||||||
import {SnowFlake} from "./snowflake.js";
|
import {SnowFlake} from "./snowflake.js";
|
||||||
import {createImg} from "./utils/utils.js";
|
import {createImg} from "./utils/utils.js";
|
||||||
|
|
||||||
|
@ -7,16 +10,19 @@ class Sticker extends SnowFlake {
|
||||||
name: string;
|
name: string;
|
||||||
type: number;
|
type: number;
|
||||||
format_type: number;
|
format_type: number;
|
||||||
owner: Guild;
|
owner: Guild | Localuser;
|
||||||
description: string;
|
description: string;
|
||||||
tags: string;
|
tags: string;
|
||||||
get guild() {
|
get guild() {
|
||||||
return this.owner;
|
return this.owner;
|
||||||
}
|
}
|
||||||
get localuser() {
|
get localuser() {
|
||||||
|
if (this.owner instanceof Localuser) {
|
||||||
|
return this.owner;
|
||||||
|
}
|
||||||
return this.owner.localuser;
|
return this.owner.localuser;
|
||||||
}
|
}
|
||||||
constructor(json: stickerJson, owner: Guild) {
|
constructor(json: stickerJson, owner: Guild | Localuser) {
|
||||||
super(json.id);
|
super(json.id);
|
||||||
this.name = json.name;
|
this.name = json.name;
|
||||||
this.type = json.type;
|
this.type = json.type;
|
||||||
|
@ -30,7 +36,207 @@ class Sticker extends SnowFlake {
|
||||||
this.owner.info.cdn + "/stickers/" + this.id + ".webp?size=160&quality=lossless",
|
this.owner.info.cdn + "/stickers/" + this.id + ".webp?size=160&quality=lossless",
|
||||||
);
|
);
|
||||||
img.classList.add("sticker");
|
img.classList.add("sticker");
|
||||||
|
const hover = new Hover(this.name);
|
||||||
|
hover.addEvent(img);
|
||||||
|
img.alt = this.description;
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
static searchStickers(search: string, localuser: Localuser, results = 50): [Sticker, number][] {
|
||||||
|
//NOTE this function is used for searching in the emoji picker for reactions, and the emoji auto-fill
|
||||||
|
const ranked: [Sticker, number][] = [];
|
||||||
|
function similar(json: Sticker) {
|
||||||
|
if (json.name.includes(search)) {
|
||||||
|
ranked.push([json, search.length / json.name.length]);
|
||||||
|
return true;
|
||||||
|
} else if (json.name.toLowerCase().includes(search.toLowerCase())) {
|
||||||
|
ranked.push([json, search.length / json.name.length / 1.4]);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const weakGuild = new WeakMap<Sticker, Guild>();
|
||||||
|
for (const guild of localuser.guilds) {
|
||||||
|
if (guild.id !== "@me" && guild.stickers.length !== 0) {
|
||||||
|
for (const sticker of guild.stickers) {
|
||||||
|
if (similar(sticker)) {
|
||||||
|
weakGuild.set(sticker, guild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ranked.sort((a, b) => b[1] - a[1]);
|
||||||
|
return ranked.splice(0, results).map((a) => {
|
||||||
|
return a;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
static getFromId(id: string, localuser: Localuser) {
|
||||||
|
for (const guild of localuser.guilds) {
|
||||||
|
const stick = guild.stickers.find((_) => _.id === id);
|
||||||
|
if (stick) {
|
||||||
|
return stick;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
static async stickerPicker(x: number, y: number, localuser: Localuser): Promise<Sticker> {
|
||||||
|
let res: (r: Sticker) => void;
|
||||||
|
this;
|
||||||
|
const promise: Promise<Sticker> = new Promise((r) => {
|
||||||
|
res = r;
|
||||||
|
});
|
||||||
|
const menu = document.createElement("div");
|
||||||
|
menu.classList.add("flexttb", "stickerPicker");
|
||||||
|
if (y > 0) {
|
||||||
|
menu.style.top = y + "px";
|
||||||
|
} else {
|
||||||
|
menu.style.bottom = y * -1 + "px";
|
||||||
|
}
|
||||||
|
if (x > 0) {
|
||||||
|
menu.style.left = x + "px";
|
||||||
|
} else {
|
||||||
|
menu.style.right = x * -1 + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
const topBar = document.createElement("div");
|
||||||
|
topBar.classList.add("flexltr", "emojiHeading");
|
||||||
|
const guilds = [
|
||||||
|
localuser.lookingguild,
|
||||||
|
...localuser.guilds
|
||||||
|
.filter((guild) => guild.id != "@me" && guild.stickers.length > 0)
|
||||||
|
.filter((guild) => guild !== localuser.lookingguild),
|
||||||
|
].filter((guild) => guild !== undefined);
|
||||||
|
|
||||||
|
const title = document.createElement("h2");
|
||||||
|
title.textContent = guilds[0].properties.name;
|
||||||
|
title.classList.add("emojiTitle");
|
||||||
|
topBar.append(title);
|
||||||
|
|
||||||
|
const search = document.createElement("input");
|
||||||
|
search.type = "text";
|
||||||
|
topBar.append(search);
|
||||||
|
|
||||||
|
let html: HTMLElement | undefined = undefined;
|
||||||
|
let topSticker: undefined | Sticker = undefined;
|
||||||
|
const updateSearch = () => {
|
||||||
|
if (search.value === "") {
|
||||||
|
if (html) html.click();
|
||||||
|
search.style.removeProperty("width");
|
||||||
|
topSticker = undefined;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
search.style.setProperty("width", "3in");
|
||||||
|
title.innerText = "";
|
||||||
|
body.innerHTML = "";
|
||||||
|
const searchResults = Sticker.searchStickers(search.value, localuser, 200);
|
||||||
|
if (searchResults[0]) {
|
||||||
|
topSticker = searchResults[0][0];
|
||||||
|
}
|
||||||
|
for (const [sticker] of searchResults) {
|
||||||
|
const emojiElem = document.createElement("div");
|
||||||
|
emojiElem.classList.add("stickerSelect");
|
||||||
|
|
||||||
|
emojiElem.append(sticker.getHTML());
|
||||||
|
body.append(emojiElem);
|
||||||
|
|
||||||
|
emojiElem.addEventListener("click", () => {
|
||||||
|
res(sticker);
|
||||||
|
if (Contextmenu.currentmenu !== "") {
|
||||||
|
Contextmenu.currentmenu.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
search.addEventListener("input", () => {
|
||||||
|
updateSearch.call(this);
|
||||||
|
});
|
||||||
|
search.addEventListener("keyup", (e) => {
|
||||||
|
if (e.key === "Enter" && topSticker) {
|
||||||
|
res(topSticker);
|
||||||
|
if (Contextmenu.currentmenu !== "") {
|
||||||
|
Contextmenu.currentmenu.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.append(topBar);
|
||||||
|
|
||||||
|
const selection = document.createElement("div");
|
||||||
|
selection.classList.add("flexltr", "emojirow");
|
||||||
|
const body = document.createElement("div");
|
||||||
|
body.classList.add("stickerBody");
|
||||||
|
|
||||||
|
let isFirst = true;
|
||||||
|
let i = 0;
|
||||||
|
guilds.forEach((guild) => {
|
||||||
|
const select = document.createElement("div");
|
||||||
|
if (i === 0) {
|
||||||
|
html = select;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
select.classList.add("emojiSelect");
|
||||||
|
|
||||||
|
if (guild.properties.icon) {
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.classList.add("pfp", "servericon", "emoji-server");
|
||||||
|
img.crossOrigin = "anonymous";
|
||||||
|
img.src =
|
||||||
|
localuser.info.cdn +
|
||||||
|
"/icons/" +
|
||||||
|
guild.properties.id +
|
||||||
|
"/" +
|
||||||
|
guild.properties.icon +
|
||||||
|
".png?size=48";
|
||||||
|
img.alt = "Server: " + guild.properties.name;
|
||||||
|
select.appendChild(img);
|
||||||
|
} else {
|
||||||
|
const div = document.createElement("span");
|
||||||
|
div.textContent = guild.properties.name
|
||||||
|
.replace(/'s /g, " ")
|
||||||
|
.replace(/\w+/g, (word) => word[0])
|
||||||
|
.replace(/\s/g, "");
|
||||||
|
select.append(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
selection.append(select);
|
||||||
|
|
||||||
|
const clickEvent = () => {
|
||||||
|
search.value = "";
|
||||||
|
updateSearch.call(this);
|
||||||
|
title.textContent = guild.properties.name;
|
||||||
|
body.innerHTML = "";
|
||||||
|
for (const sticker of guild.stickers) {
|
||||||
|
const stickerElem = document.createElement("div");
|
||||||
|
stickerElem.classList.add("stickerSelect");
|
||||||
|
stickerElem.append(sticker.getHTML());
|
||||||
|
body.append(stickerElem);
|
||||||
|
stickerElem.addEventListener("click", () => {
|
||||||
|
res(sticker);
|
||||||
|
if (Contextmenu.currentmenu !== "") {
|
||||||
|
Contextmenu.currentmenu.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
select.addEventListener("click", clickEvent);
|
||||||
|
if (isFirst) {
|
||||||
|
clickEvent();
|
||||||
|
isFirst = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Contextmenu.currentmenu !== "") {
|
||||||
|
Contextmenu.currentmenu.remove();
|
||||||
|
}
|
||||||
|
document.body.append(menu);
|
||||||
|
Contextmenu.currentmenu = menu;
|
||||||
|
Contextmenu.keepOnScreen(menu);
|
||||||
|
menu.append(selection);
|
||||||
|
menu.append(body);
|
||||||
|
search.focus();
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export {Sticker};
|
export {Sticker};
|
||||||
|
|
|
@ -393,6 +393,10 @@ textarea {
|
||||||
mask: url(/icons/plainx.svg);
|
mask: url(/icons/plainx.svg);
|
||||||
mask-size: contain !important;
|
mask-size: contain !important;
|
||||||
}
|
}
|
||||||
|
.svg-sticker {
|
||||||
|
mask: url(/icons/sticker.svg);
|
||||||
|
mask-size: contain !important;
|
||||||
|
}
|
||||||
.svg-search {
|
.svg-search {
|
||||||
mask: url(/icons/search.svg);
|
mask: url(/icons/search.svg);
|
||||||
mask-size: contain !important;
|
mask-size: contain !important;
|
||||||
|
@ -535,6 +539,13 @@ textarea {
|
||||||
bottom: -5px;
|
bottom: -5px;
|
||||||
border-radius: 1in;
|
border-radius: 1in;
|
||||||
}
|
}
|
||||||
|
#stickerTB {
|
||||||
|
width: 0.2in;
|
||||||
|
height: 0.2in;
|
||||||
|
cursor: pointer;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
#emojiTB {
|
#emojiTB {
|
||||||
width: 0.2in;
|
width: 0.2in;
|
||||||
height: 0.2in;
|
height: 0.2in;
|
||||||
|
@ -568,6 +579,7 @@ textarea {
|
||||||
animation-name: fade-in;
|
animation-name: fade-in;
|
||||||
|
|
||||||
border: solid 0.03in var(--black);
|
border: solid 0.03in var(--black);
|
||||||
|
z-index: 4;
|
||||||
}
|
}
|
||||||
@keyframes fade-in {
|
@keyframes fade-in {
|
||||||
from {
|
from {
|
||||||
|
@ -2057,6 +2069,44 @@ img.bigembedimg {
|
||||||
background: var(--card-bg);
|
background: var(--card-bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.stickerSelect {
|
||||||
|
width: 1in;
|
||||||
|
height: 1in;
|
||||||
|
margin-right: 6px;
|
||||||
|
padding: 8px;
|
||||||
|
background: var(--secondary-bg);
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.stickerPicker {
|
||||||
|
position: absolute;
|
||||||
|
height: 440px;
|
||||||
|
width: 390px;
|
||||||
|
max-height: 100svh;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 8px var(--shadow);
|
||||||
|
gap: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
user-select: none;
|
||||||
|
background: var(--secondary-bg);
|
||||||
|
z-index: 4;
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 1in;
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
top: 2px;
|
||||||
|
transition: width 0.2s;
|
||||||
|
background: var(--card-bg);
|
||||||
|
}
|
||||||
|
.sticker {
|
||||||
|
max-width: 1in;
|
||||||
|
max-height: 1in;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
.emojiHeading {
|
.emojiHeading {
|
||||||
height: 0.25in;
|
height: 0.25in;
|
||||||
}
|
}
|
||||||
|
@ -2067,6 +2117,7 @@ img.bigembedimg {
|
||||||
flex: none;
|
flex: none;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
flex-grow: 0;
|
||||||
}
|
}
|
||||||
.emojiSelect {
|
.emojiSelect {
|
||||||
flex: none;
|
flex: none;
|
||||||
|
@ -2101,7 +2152,16 @@ img.bigembedimg {
|
||||||
grid-auto-rows: min-content;
|
grid-auto-rows: min-content;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
.stickerBody {
|
||||||
|
flex: 1;
|
||||||
|
padding: 8px;
|
||||||
|
background: var(--card-bg);
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
overflow-y: auto;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
/* Fullscreen and Modal (TEMP) */
|
/* Fullscreen and Modal (TEMP) */
|
||||||
.background {
|
.background {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -2888,3 +2948,6 @@ fieldset input[type="radio"] {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border-radius: 2in;
|
border-radius: 2in;
|
||||||
}
|
}
|
||||||
|
.stickerMArea {
|
||||||
|
padding-left: 48px;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue