gif picker
This commit is contained in:
parent
174fde846a
commit
3952937581
7 changed files with 206 additions and 9 deletions
1
src/webpage/icons/gif.svg
Normal file
1
src/webpage/icons/gif.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="512" height="512" xmlns="http://www.w3.org/2000/svg"><path d="m400 159-26 1 1 49h25zM112 340V177a85 85 0 0 0-35 58c-8 43 8 89 35 105zM293 209v94h10v-94zM222 277a24 16 90 0 1 2 18l-2 8h31v-94h-44v45a20 20 0 0 1 14 19 20 20 0 0 1-1 4z" style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:red;stroke-linecap:round;stroke-linejoin:round;enable-background:accumulate;stop-color:#000;stop-opacity:1"/><path d="M112 112v13c15-5 31-6 47 1l21 12a24 16 90 0 1 6 34 24 16 90 0 1-22 9l-14-8c-13-5-26-4-38 4v163l7 4c28 11 58-11 70-50l-48 2a20 20 0 0 1-21-19 20 20 0 0 1 19-21l63-2a20 20 0 0 1 7 0v-45h44v-70a20 20 0 0 1 20-20 20 20 0 0 1 20 20v70h10v94h-10l-1 67a20 20 0 0 1-20 20 20 20 0 0 1-20-20l1-67h-31c-16 66-64 105-110 89v8h288V249h-25l1 122a20 20 0 0 1-20 20 20 20 0 0 1-20-20l-2-230a20 20 0 0 1 20-20 20 20 0 0 1 1 0 20 20 0 0 1 3-1l42-1v-7z" style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:red;stroke-linecap:round;stroke-linejoin:round;enable-background:accumulate;stop-color:#000;stop-opacity:1"/><path d="M112 16a96 96 0 0 0-96 96v288a96 96 0 0 0 96 96h288a96 96 0 0 0 96-96V112a96 96 0 0 0-96-96Zm0 96h288v7l45-1a20 20 0 0 1 21 20 20 20 0 0 1-20 20l-46 1v50h52a20 20 0 0 1 20 20 20 20 0 0 1-20 20h-52v151H112v-8l-2-1c-49-20-78-97-65-169 9-49 36-85 67-97Z" style="baseline-shift:baseline;display:inline;overflow:visible;vector-effect:none;fill:red;stroke-linecap:round;stroke-linejoin:round;enable-background:accumulate;stop-color:#000;stop-opacity:1"/></svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -96,6 +96,7 @@
|
|||
<div class="outerTypeBox">
|
||||
<span class="svg-upload svgicon" id="upload"></span>
|
||||
<div id="typebox" contenteditable="true"></div>
|
||||
<span class="svgicon svg-gif" id="gifTB"></span>
|
||||
<span class="svgicon svg-emoji" id="emojiTB"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -275,4 +275,12 @@ import {I18n} from "./i18n.js";
|
|||
thisUser.TBEmojiMenu(emojiTB.getBoundingClientRect());
|
||||
};
|
||||
emojiTB.onclick = (e) => e.stopImmediatePropagation();
|
||||
|
||||
const gifTB = document.getElementById("gifTB") as HTMLElement;
|
||||
gifTB.onmousedown = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
thisUser.makeGifBox(gifTB.getBoundingClientRect());
|
||||
};
|
||||
gifTB.onclick = (e) => e.stopImmediatePropagation();
|
||||
})();
|
||||
|
|
|
@ -31,6 +31,7 @@ import {Message} from "./message.js";
|
|||
import {badgeArr} from "./Dbadges.js";
|
||||
import {Rights} from "./rights.js";
|
||||
import {Contextmenu} from "./contextmenu.js";
|
||||
import {Search} from "./search.js";
|
||||
|
||||
const wsCodesRetry = new Set([4000, 4001, 4002, 4003, 4005, 4007, 4008, 4009]);
|
||||
interface CustomHTMLDivElement extends HTMLDivElement {
|
||||
|
@ -2238,12 +2239,122 @@ class Localuser {
|
|||
this.search(document.getElementById("searchOptions") as HTMLDivElement, typeMd, str, pre);
|
||||
};
|
||||
}
|
||||
async makeGifBox(rect: DOMRect) {
|
||||
interface fullgif {
|
||||
id: string;
|
||||
title: string;
|
||||
url: string;
|
||||
src: string;
|
||||
gif_src: string;
|
||||
width: number;
|
||||
height: number;
|
||||
preview: string;
|
||||
}
|
||||
const menu = document.createElement("div");
|
||||
menu.classList.add("flexttb", "gifmenu");
|
||||
menu.style.bottom = window.innerHeight - rect.top + 15 + "px";
|
||||
menu.style.right = window.innerWidth - rect.right + "px";
|
||||
document.body.append(menu);
|
||||
Contextmenu.keepOnScreen(menu);
|
||||
if (Contextmenu.currentmenu !== "") {
|
||||
Contextmenu.currentmenu.remove();
|
||||
}
|
||||
Contextmenu.currentmenu = menu;
|
||||
const trending = (await (
|
||||
await fetch(
|
||||
this.info.api + "/gifs/trending?" + new URLSearchParams([["locale", I18n.lang]]),
|
||||
{headers: this.headers},
|
||||
)
|
||||
).json()) as {
|
||||
categories: {
|
||||
name: string;
|
||||
src: string;
|
||||
}[];
|
||||
gifs: [fullgif];
|
||||
};
|
||||
const gifbox = document.createElement("div");
|
||||
gifbox.classList.add("gifbox");
|
||||
const search = document.createElement("input");
|
||||
let gifs = gifbox;
|
||||
const searchBox = async () => {
|
||||
gifs.remove();
|
||||
if (search.value === "") {
|
||||
menu.append(gifbox);
|
||||
gifs = gifbox;
|
||||
return;
|
||||
}
|
||||
gifs = document.createElement("div");
|
||||
gifs.classList.add("gifbox");
|
||||
menu.append(gifs);
|
||||
const sValue = search.value;
|
||||
const gifReturns = (await (
|
||||
await fetch(
|
||||
this.info.api +
|
||||
"/gifs/search?" +
|
||||
new URLSearchParams([
|
||||
["locale", I18n.lang],
|
||||
["q", sValue],
|
||||
["limit", "500"],
|
||||
]),
|
||||
{headers: this.headers},
|
||||
)
|
||||
).json()) as fullgif[];
|
||||
if (sValue !== search.value) {
|
||||
return;
|
||||
}
|
||||
for (const gif of gifReturns) {
|
||||
const div = document.createElement("div");
|
||||
div.classList.add("gifBox");
|
||||
const img = document.createElement("img");
|
||||
img.src = gif.gif_src;
|
||||
img.alt = gif.title;
|
||||
const scale = gif.width / 196;
|
||||
|
||||
img.width = gif.width / scale;
|
||||
img.height = gif.height / scale;
|
||||
div.append(img);
|
||||
gifs.append(div);
|
||||
div.onclick = () => {
|
||||
if (this.channelfocus) {
|
||||
this.channelfocus.sendMessage(gif.url, {embeds: [], attachments: [], replyingto: null});
|
||||
menu.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
let last = "";
|
||||
search.onkeyup = () => {
|
||||
if (last === search.value) {
|
||||
return;
|
||||
}
|
||||
last = search.value;
|
||||
searchBox();
|
||||
};
|
||||
search.classList.add("searchGifBar");
|
||||
search.placeholder = I18n.searchGifs();
|
||||
for (const category of trending.categories) {
|
||||
const div = document.createElement("div");
|
||||
div.classList.add("gifPreviewBox");
|
||||
const img = document.createElement("img");
|
||||
img.src = category.src;
|
||||
const title = document.createElement("span");
|
||||
title.textContent = category.name;
|
||||
div.append(img, title);
|
||||
gifbox.append(div);
|
||||
div.onclick = (e) => {
|
||||
e.stopImmediatePropagation();
|
||||
search.value = category.name;
|
||||
searchBox();
|
||||
};
|
||||
}
|
||||
menu.append(search, gifbox);
|
||||
search.focus();
|
||||
}
|
||||
async TBEmojiMenu(rect: DOMRect) {
|
||||
const typebox = document.getElementById("typebox") as CustomHTMLDivElement;
|
||||
const p = saveCaretPosition(typebox);
|
||||
if (!p) return;
|
||||
const original = MarkDown.getText();
|
||||
console.log(original);
|
||||
|
||||
const emoji = await Emoji.emojiPicker(
|
||||
-0 + rect.right - window.innerWidth,
|
||||
|
|
|
@ -663,8 +663,10 @@ class Message extends SnowFlake {
|
|||
} else {
|
||||
this.content.onUpdate = () => {};
|
||||
const messaged = this.content.makeHTML();
|
||||
messagedwrap.classList.add("flexttb");
|
||||
messagedwrap.appendChild(messaged);
|
||||
if (!this.embeds.find((_) => _.json.url === messaged.textContent)) {
|
||||
messagedwrap.classList.add("flexttb");
|
||||
messagedwrap.appendChild(messaged);
|
||||
}
|
||||
}
|
||||
text.appendChild(messagedwrap);
|
||||
build.appendChild(text);
|
||||
|
|
|
@ -355,6 +355,9 @@ textarea {
|
|||
.svg-emoji {
|
||||
mask: url(/icons/emoji.svg);
|
||||
}
|
||||
.svg-gif {
|
||||
mask: url(/icons/gif.svg);
|
||||
}
|
||||
.svg-edit {
|
||||
mask: url(/icons/edit.svg);
|
||||
}
|
||||
|
@ -433,11 +436,19 @@ textarea {
|
|||
aspect-ratio: 1/1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
#emojiTB{
|
||||
width:.2in;
|
||||
height:.2in;
|
||||
#emojiTB {
|
||||
width: 0.2in;
|
||||
height: 0.2in;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
margin-left: 6px;
|
||||
}
|
||||
#gifTB {
|
||||
width: 0.2in;
|
||||
height: 0.2in;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
mask-size: 0.2in 0.2in;
|
||||
}
|
||||
.selectarrow {
|
||||
position: absolute;
|
||||
|
@ -1158,7 +1169,7 @@ span.instanceStatus {
|
|||
flex-shrink: 1;
|
||||
text-wrap: auto;
|
||||
overflow-y: auto;
|
||||
margin-right: .03in;
|
||||
margin-right: 0.03in;
|
||||
}
|
||||
.outerTypeBox {
|
||||
max-height: 50svh;
|
||||
|
@ -2395,7 +2406,8 @@ fieldset input[type="radio"] {
|
|||
background: var(--primary-bg);
|
||||
transition: left 0.3s;
|
||||
}
|
||||
#sideContainDiv, #sideContainDiv.searchDiv {
|
||||
#sideContainDiv,
|
||||
#sideContainDiv.searchDiv {
|
||||
display: block;
|
||||
right: -100svw;
|
||||
width: 100svw;
|
||||
|
@ -2424,7 +2436,8 @@ fieldset input[type="radio"] {
|
|||
#page:has(#maintoggle:checked) #mainarea {
|
||||
left: 0;
|
||||
}
|
||||
#page:has(#memberlisttoggle:checked) #sideContainDiv, #sideContainDiv.searchDiv {
|
||||
#page:has(#memberlisttoggle:checked) #sideContainDiv,
|
||||
#sideContainDiv.searchDiv {
|
||||
right: 0;
|
||||
}
|
||||
#page:has(#maintoggle:checked) #maintoggleicon {
|
||||
|
@ -2631,3 +2644,63 @@ fieldset input[type="radio"] {
|
|||
right: 0.2in;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.gifmenu {
|
||||
position: absolute;
|
||||
width: 4.5in;
|
||||
height: 5in;
|
||||
background: var(--secondary-bg);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.gifPreviewBox {
|
||||
position: relative;
|
||||
width: 2in;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 7px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 2in;
|
||||
height: 1in;
|
||||
object-fit: cover;
|
||||
}
|
||||
span {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #00000099;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.gifbox {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
overflow-y: auto;
|
||||
margin: 0.1in;
|
||||
align-items: center;
|
||||
}
|
||||
.searchGifBar {
|
||||
height: 0.3in;
|
||||
margin: 0.15in 0.15in 0 0.15in;
|
||||
flex-shrink: 0;
|
||||
background: var(--black);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 0.2in;
|
||||
padding: 0 0.1in;
|
||||
}
|
||||
.gifBox {
|
||||
img {
|
||||
max-width: 196px;
|
||||
}
|
||||
cursor: pointer;
|
||||
cursor: p;
|
||||
}
|
||||
|
|
|
@ -149,6 +149,7 @@
|
|||
"name": "Accessibility",
|
||||
"roleColors": "Disable role colors"
|
||||
},
|
||||
"searchGifs": "Search Tenor",
|
||||
"channel": {
|
||||
"creating": "Creating channel",
|
||||
"name": "Channel",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue