add image spoilers

This commit is contained in:
MathMan05 2025-04-02 10:49:06 -05:00
parent 54416197de
commit ea7769ce85
6 changed files with 131 additions and 6 deletions

View file

@ -2,6 +2,7 @@ import {Message} from "./message.js";
import {filejson} from "./jsontypes.js";
import {ImagesDisplay} from "./disimg.js";
import {makePlayBox, MediaPlayer} from "./media.js";
import {I18n} from "./i18n.js";
class File {
owner: Message | null;
id: string;
@ -24,7 +25,17 @@ class File {
this.content_type = fileJSON.content_type;
this.size = fileJSON.size;
}
getHTML(temp: boolean = false, fullScreen = false): HTMLElement {
getHTML(temp: boolean = false, fullScreen = false, OSpoiler = false): HTMLElement {
function makeSpoilerHTML(): HTMLElement {
const spoil = document.createElement("div");
spoil.classList.add("fSpoil");
const stext = document.createElement("span");
stext.textContent = I18n.spoiler();
spoil.append(stext);
spoil.onclick = () => spoil.remove();
return spoil;
}
OSpoiler ||= this.filename.startsWith("SPOILER_");
const src = this.proxy_url || this.url;
if (this.width && this.height) {
let scale = 1;
@ -60,6 +71,9 @@ class File {
div.style.height = this.height + "px";
}
if (!fullScreen) {
if (OSpoiler) {
div.append(makeSpoilerHTML());
}
return div;
} else {
return img;
@ -75,11 +89,25 @@ class File {
video.width = this.width;
video.height = this.height;
}
if (OSpoiler) {
const div = document.createElement("div");
div.style.setProperty("position", "relative");
div.append(video, makeSpoilerHTML());
return div;
}
return video;
} else if (this.content_type.startsWith("audio/")) {
return this.getAudioHTML();
const a = this.getAudioHTML();
if (OSpoiler) {
a.append(makeSpoilerHTML());
}
return a;
} else {
return this.createunknown();
const uk = this.createunknown();
if (OSpoiler) {
uk.append(makeSpoilerHTML());
}
return uk;
}
}
private getAudioHTML() {
@ -88,10 +116,12 @@ class File {
}
upHTML(files: Blob[], file: globalThis.File): HTMLElement {
const div = document.createElement("div");
const contained = this.getHTML(true);
let contained = this.getHTML(true, false, file.name.startsWith("SPOILER_"));
div.classList.add("containedFile");
div.append(contained);
const controls = document.createElement("div");
controls.classList.add("controls");
const garbage = document.createElement("button");
const icon = document.createElement("span");
icon.classList.add("svgicon", "svg-delete");
@ -100,9 +130,37 @@ class File {
div.remove();
files.splice(files.indexOf(file), 1);
};
controls.classList.add("controls");
const spoiler = document.createElement("button");
const sicon = document.createElement("span");
sicon.classList.add(
"svgicon",
file.name.startsWith("SPOILER_") ? "svg-unspoiler" : "svg-spoiler",
);
spoiler.append(sicon);
spoiler.onclick = (_) => {
if (file.name.startsWith("SPOILER_")) {
const name = file.name.split("SPOILER_");
name.shift();
file = files[files.indexOf(file)] = new globalThis.File([file], name.join("SPOILER_"), {
type: file.type,
});
sicon.classList.add("svg-spoiler");
sicon.classList.remove("svg-unspoiler");
} else {
file = files[files.indexOf(file)] = new globalThis.File([file], "SPOILER_" + file.name, {
type: file.type,
});
sicon.classList.add("svg-unspoiler");
sicon.classList.remove("svg-spoiler");
}
contained.remove();
contained = this.getHTML(true, false, file.name.startsWith("SPOILER_"));
div.append(contained);
};
div.append(controls);
controls.append(garbage);
controls.append(spoiler, garbage);
return div;
}
static initFromBlob(file: globalThis.File) {

View file

@ -317,6 +317,34 @@ class Guild extends SnowFlake {
genDiv();
emoji.addHTMLArea(containdiv);
}
(async () => {
const widgetMenu = settings.addButton(I18n.widget());
const cur = (await (
await fetch(this.info.api + "/guilds/" + this.id + "/widget", {
headers: this.headers,
})
).json()) as {
enabled: boolean;
channel_id?: null | string;
};
const form = widgetMenu.addForm("", () => {}, {
traditionalSubmit: true,
fetchURL: this.info.api + "/guilds/" + this.id + "/widget",
headers: this.headers,
method: "PATCH",
});
form.addCheckboxInput(I18n.widgetEnabled(), "enabled", {initState: cur.enabled});
const channels = this.channels.filter((_) => _.type !== 4);
form.addSelect(
I18n.channel.name(),
"channel_id",
channels.map((_) => _.name),
{
defaultIndex: channels.findIndex((_) => _.id == cur.channel_id),
},
channels.map((_) => _.id),
);
})();
const webhooks = settings.addButton(I18n.webhooks.base());
webhookMenu(this, this.info.api + `/guilds/${this.id}/webhooks`, webhooks);
settings.show();

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g stroke="red" stroke-linecap="round" stroke-linejoin="round"><path fill="none" stroke-width="72.7" d="M45 247c71-72 143-145 213-145 71 0 140 73 209 145m1 9c-72 73-144 144-214 144-71 0-140-71-208-144"/><circle cx="256.5" cy="251" r="33" fill="red" stroke-width="80"/></g></svg>

After

Width:  |  Height:  |  Size: 340 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g fill="red" stroke="red" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="m94 356 52-51c-18-16-36-34-54-54 28-28 56-54 82-74 33-25 62-38 84-38 13 0 29 4 45 13l54-53c-30-19-63-33-99-33-48 0-89 23-128 53-39 29-75 66-111 102a36 36 0 0 0-10 32 36 36 0 0 0 10 28c24 26 49 52 75 75zm327-207-53 51 53 52c-29 28-57 55-83 74-32 25-61 38-84 38-12 0-27-4-42-11l-54 53c29 18 61 31 96 31 47 0 89-23 128-53 39-29 76-66 112-103a36 36 0 0 0 9-32 36 36 0 0 0-10-27l-72-73z" overflow="visible"/><path stroke="none" d="m329 239-86 84 14 1a74 74 0 0 0 72-85zm-144 28 89-87-17-2a74 74 0 0 0-72 89z" overflow="visible"/><path stroke-width="34.9" d="M450 64 63 442v0"/></g></svg>

After

Width:  |  Height:  |  Size: 741 B

View file

@ -36,6 +36,7 @@ body {
flex-grow: 0;
flex-shrink: 0;
height: 52px;
position: relative;
* {
margin: 2px;
@ -333,6 +334,12 @@ textarea {
display: block;
mask-size: cover !important;
}
.svg-spoiler {
mask: url(/icons/spoiler.svg);
}
.svg-unspoiler {
mask: url(/icons/unspoiler.svg);
}
.svg-soundMore {
mask: url(/icons/soundMore.svg);
}
@ -1094,6 +1101,7 @@ span.instanceStatus {
}
.messageimgdiv {
height: 100%;
position: relative;
}
.messageimg {
height: 100%;
@ -1223,6 +1231,29 @@ span.instanceStatus {
.messagediv:hover {
background: var(--primary-hover);
}
.fSpoil {
position: absolute;
top: 0;
width: 100%;
height: 100%;
backdrop-filter: blur(20px);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
transition: backdrop-filter 0.4s;
span {
background: var(--spoiler-bg);
padding: 3px 6px;
border-radius: 6px;
}
}
.fSpoil:hover {
backdrop-filter: blur(15px);
span {
background: var(--spoiler-hover);
}
}
.messageButtons,
.controls {
position: absolute;
@ -1262,6 +1293,7 @@ span.instanceStatus {
top: 6px;
right: 6px;
box-shadow: 0 0 1.5px var(--primary-text-soft);
z-index: 1;
}
.message {
padding-right: 28px;
@ -1603,6 +1635,7 @@ img.bigembedimg {
padding: 4px;
background: var(--secondary-bg);
border-radius: 4px;
position: relative;
}
.acceptinvbutton {
width: calc(100% - 24px);

View file

@ -144,7 +144,9 @@
"typing": "$2 {{PLURAL:$1|is|are}} typing",
"noMessages": "No messages appear to be here, be the first to say something!",
"blankMessage": "Blank Message",
"spoiler": "Spoiler",
"channel": {
"name": "Channel",
"copyId": "Copy channel id",
"markRead": "Mark as read",
"settings": "Settings",
@ -509,6 +511,8 @@
"name:": "Name:",
"confirmDel": "Are you sure you want to delete this emoji?"
},
"widget": "Guild Widget",
"widgetEnabled": "Widget enabled",
"incorrectURLS": "## This instance has likely sent the incorrect URLs.\n### If you're the instance owner please see [here](https://docs.spacebar.chat/setup/server/) under *Connecting from remote machines* to correct the issue.\n Would you like Jank Client to automatically try to fix this error to let you connect to the instance?",
"jankInfo": "Client Information",
"clientDesc": "Client version: $1\n\n[Join the official Jank Client guild]($2/invite/USgYJo?instance=https%3A%2F%2Fspacebar.chat)\n\n[Help translate Jank Client](https://translatewiki.net/wiki/Translating:JankClient#sortable:3=desc) \n\n[Help create Jank client](https://github.com/MathMan05/JankClient)\n\n[Help maintain the server jank client relies on](https://github.com/spacebarchat/server)\n\nCalculated rights: $3",