make gifs animate on hover
This commit is contained in:
parent
25817fdaba
commit
4a9a17814e
10 changed files with 127 additions and 47 deletions
|
@ -102,7 +102,7 @@ class Direct extends Guild {
|
|||
const div = document.createElement("div");
|
||||
div.classList.add("flexltr", "liststyle");
|
||||
user.bind(div);
|
||||
div.append(user.buildpfp());
|
||||
div.append(user.buildpfp(undefined, div));
|
||||
|
||||
const userinfos = document.createElement("div");
|
||||
userinfos.classList.add("flexttb");
|
||||
|
@ -417,7 +417,7 @@ class Group extends Channel {
|
|||
const myhtml = document.createElement("span");
|
||||
myhtml.classList.add("ellipsis");
|
||||
myhtml.textContent = this.name;
|
||||
div.appendChild(this.user.buildpfp());
|
||||
div.appendChild(this.user.buildpfp(undefined, div));
|
||||
div.appendChild(myhtml);
|
||||
(div as any).myinfo = this;
|
||||
div.onclick = (_) => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {Message} from "./message.js";
|
||||
import {MarkDown} from "./markdown.js";
|
||||
import {embedjson, invitejson} from "./jsontypes.js";
|
||||
import {getapiurls, getBulkUsers, getInstances, Specialuser} from "./utils/utils.js";
|
||||
import {createImg, getapiurls, getBulkUsers, getInstances, Specialuser} from "./utils/utils.js";
|
||||
import {Guild} from "./guild.js";
|
||||
import {I18n} from "./i18n.js";
|
||||
import {ImagesDisplay} from "./disimg.js";
|
||||
|
@ -171,7 +171,7 @@ class Embed {
|
|||
return div;
|
||||
}
|
||||
generateImage() {
|
||||
const img = document.createElement("img");
|
||||
const img = createImg(this.json.thumbnail.proxy_url);
|
||||
img.classList.add("messageimg");
|
||||
img.onclick = function () {
|
||||
const full = new ImagesDisplay([
|
||||
|
@ -179,7 +179,6 @@ class Embed {
|
|||
]);
|
||||
full.show();
|
||||
};
|
||||
img.src = this.json.thumbnail.proxy_url;
|
||||
if (this.json.thumbnail.width) {
|
||||
let scale = 1;
|
||||
const max = 96 * 3;
|
||||
|
|
|
@ -3,6 +3,7 @@ import {filejson} from "./jsontypes.js";
|
|||
import {ImagesDisplay} from "./disimg.js";
|
||||
import {makePlayBox, MediaPlayer} from "./media.js";
|
||||
import {I18n} from "./i18n.js";
|
||||
import {createImg} from "./utils/utils.js";
|
||||
class File {
|
||||
owner: Message | null;
|
||||
id: string;
|
||||
|
@ -47,9 +48,10 @@ class File {
|
|||
this.width /= scale;
|
||||
this.height /= scale;
|
||||
}
|
||||
|
||||
if (this.content_type.startsWith("image/")) {
|
||||
const div = document.createElement("div");
|
||||
const img = document.createElement("img");
|
||||
const img = createImg(src);
|
||||
if (!fullScreen) {
|
||||
img.classList.add("messageimg");
|
||||
div.classList.add("messageimgdiv");
|
||||
|
@ -66,7 +68,6 @@ class File {
|
|||
full.show();
|
||||
}
|
||||
};
|
||||
img.src = src;
|
||||
div.append(img);
|
||||
if (this.width && !fullScreen) {
|
||||
div.style.maxWidth = this.width + "px";
|
||||
|
|
|
@ -19,6 +19,7 @@ import {User} from "./user.js";
|
|||
import {I18n} from "./i18n.js";
|
||||
import {Emoji} from "./emoji.js";
|
||||
import {webhookMenu} from "./webhooks.js";
|
||||
import {createImg} from "./utils/utils.js";
|
||||
|
||||
class Guild extends SnowFlake {
|
||||
owner!: Localuser;
|
||||
|
@ -745,9 +746,8 @@ class Guild extends SnowFlake {
|
|||
icon = guild.icon;
|
||||
}
|
||||
if (icon !== null) {
|
||||
const img = document.createElement("img");
|
||||
const img = createImg(guild.info.cdn + "/icons/" + guild.id + "/" + icon + ".png");
|
||||
img.classList.add("pfp", "servericon");
|
||||
img.src = guild.info.cdn + "/icons/" + guild.id + "/" + icon + ".png";
|
||||
divy.appendChild(img);
|
||||
if (guild instanceof Guild) {
|
||||
img.onclick = () => {
|
||||
|
|
|
@ -3,7 +3,7 @@ import {Channel} from "./channel.js";
|
|||
import {Direct} from "./direct.js";
|
||||
import {AVoice} from "./audio/voice.js";
|
||||
import {User} from "./user.js";
|
||||
import {getapiurls, getBulkUsers, SW} from "./utils/utils.js";
|
||||
import {createImg, getapiurls, getBulkUsers, SW} from "./utils/utils.js";
|
||||
import {getBulkInfo, setTheme, Specialuser} from "./utils/utils.js";
|
||||
import {
|
||||
channeljson,
|
||||
|
@ -88,8 +88,7 @@ class Localuser {
|
|||
const userInfo = document.createElement("div");
|
||||
userInfo.classList.add("flexltr", "switchtable");
|
||||
|
||||
const pfp = document.createElement("img");
|
||||
pfp.src = specialUser.pfpsrc;
|
||||
const pfp = createImg(specialUser.pfpsrc);
|
||||
pfp.classList.add("pfp");
|
||||
userInfo.append(pfp);
|
||||
|
||||
|
@ -1244,24 +1243,26 @@ class Localuser {
|
|||
content.classList.add("discovery-guild");
|
||||
|
||||
if (guild.banner) {
|
||||
const banner = document.createElement("img");
|
||||
const banner = createImg(
|
||||
this.info.cdn + "/icons/" + guild.id + "/" + guild.banner + ".png?size=256",
|
||||
);
|
||||
banner.classList.add("banner");
|
||||
banner.crossOrigin = "anonymous";
|
||||
banner.src = this.info.cdn + "/icons/" + guild.id + "/" + guild.banner + ".png?size=256";
|
||||
banner.alt = "";
|
||||
content.appendChild(banner);
|
||||
}
|
||||
|
||||
const nameContainer = document.createElement("div");
|
||||
nameContainer.classList.add("flex");
|
||||
const img = document.createElement("img");
|
||||
const img = createImg(
|
||||
this.info.cdn +
|
||||
(guild.icon
|
||||
? "/icons/" + guild.id + "/" + guild.icon + ".png?size=48"
|
||||
: "/embed/avatars/3.png"),
|
||||
);
|
||||
img.classList.add("icon");
|
||||
img.crossOrigin = "anonymous";
|
||||
img.src =
|
||||
this.info.cdn +
|
||||
(guild.icon
|
||||
? "/icons/" + guild.id + "/" + guild.icon + ".png?size=48"
|
||||
: "/embed/avatars/3.png");
|
||||
|
||||
img.alt = "";
|
||||
nameContainer.appendChild(img);
|
||||
|
||||
|
@ -1797,6 +1798,20 @@ class Localuser {
|
|||
initState: !this.perminfo.user.disableColors,
|
||||
},
|
||||
);
|
||||
const gifSettings = ["hover", "always", "never"] as const;
|
||||
accessibility.addSelect(
|
||||
I18n.accessibility.playGif(),
|
||||
(i) => {
|
||||
localStorage.setItem("gifSetting", gifSettings[i]);
|
||||
},
|
||||
gifSettings.map((_) => I18n.accessibility.gifSettings[_]()),
|
||||
{
|
||||
defaultIndex:
|
||||
((gifSettings as readonly string[]).indexOf(
|
||||
localStorage.getItem("gifSetting") as string,
|
||||
) + 1 || 1) - 1,
|
||||
},
|
||||
);
|
||||
}
|
||||
{
|
||||
const connections = settings.addButton(I18n.getTranslation("localuser.connections"));
|
||||
|
@ -1891,15 +1906,14 @@ class Localuser {
|
|||
const container = document.createElement("div");
|
||||
|
||||
if (application.cover_image || application.icon) {
|
||||
const cover = document.createElement("img");
|
||||
cover.crossOrigin = "anonymous";
|
||||
cover.src =
|
||||
const cover = createImg(
|
||||
this.info.cdn +
|
||||
"/app-icons/" +
|
||||
application.id +
|
||||
"/" +
|
||||
(application.cover_image || application.icon) +
|
||||
".png?size=256";
|
||||
"/app-icons/" +
|
||||
application.id +
|
||||
"/" +
|
||||
(application.cover_image || application.icon) +
|
||||
".png?size=256",
|
||||
);
|
||||
cover.alt = "";
|
||||
cover.loading = "lazy";
|
||||
container.appendChild(cover);
|
||||
|
|
|
@ -574,7 +574,7 @@ class Message extends SnowFlake {
|
|||
this.message_reference ||
|
||||
!messageTypes.has(premessage.type);
|
||||
if (combine) {
|
||||
const pfp = this.author.buildpfp();
|
||||
const pfp = this.author.buildpfp(undefined, div);
|
||||
this.author.bind(pfp, this.guild, false);
|
||||
pfpRow.appendChild(pfp);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import {I18n} from "./i18n.js";
|
|||
import {Direct} from "./direct.js";
|
||||
import {Hover} from "./hover.js";
|
||||
import {Dialog} from "./settings.js";
|
||||
import {createImg} from "./utils/utils.js";
|
||||
|
||||
class User extends SnowFlake {
|
||||
owner: Localuser;
|
||||
|
@ -456,10 +457,9 @@ class User extends SnowFlake {
|
|||
}
|
||||
}
|
||||
|
||||
buildpfp(guild: Guild | void | Member | null): HTMLImageElement {
|
||||
const pfp = document.createElement("img");
|
||||
buildpfp(guild: Guild | void | Member | null, hoverElm: void | HTMLElement): HTMLImageElement {
|
||||
const pfp = createImg(this.getpfpsrc(), undefined, hoverElm);
|
||||
pfp.loading = "lazy";
|
||||
pfp.src = this.getpfpsrc();
|
||||
pfp.classList.add("pfp");
|
||||
pfp.classList.add("userid:" + this.id);
|
||||
if (guild) {
|
||||
|
@ -467,9 +467,9 @@ class User extends SnowFlake {
|
|||
if (guild instanceof Guild) {
|
||||
const memb = await Member.resolveMember(this, guild);
|
||||
if (!memb) return;
|
||||
pfp.src = memb.getpfpsrc();
|
||||
pfp.setSrcs(memb.getpfpsrc());
|
||||
} else {
|
||||
pfp.src = guild.getpfpsrc();
|
||||
pfp.setSrcs(guild.getpfpsrc());
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
@ -479,7 +479,7 @@ class User extends SnowFlake {
|
|||
async buildstatuspfp(guild: Guild | void | Member | null): Promise<HTMLDivElement> {
|
||||
const div = document.createElement("div");
|
||||
div.classList.add("pfpDiv");
|
||||
const pfp = this.buildpfp(guild);
|
||||
const pfp = this.buildpfp(guild, div);
|
||||
div.append(pfp);
|
||||
const status = document.createElement("div");
|
||||
status.classList.add("statusDiv");
|
||||
|
@ -560,9 +560,10 @@ class User extends SnowFlake {
|
|||
changepfp(update: string | null): void {
|
||||
this.avatar = update;
|
||||
this.hypotheticalpfp = false;
|
||||
const src = this.getpfpsrc();
|
||||
Array.from(document.getElementsByClassName("userid:" + this.id)).forEach((element) => {
|
||||
(element as HTMLImageElement).src = src;
|
||||
//const src = this.getpfpsrc();
|
||||
Array.from(document.getElementsByClassName("userid:" + this.id)).forEach((_element) => {
|
||||
//(element as HTMLImageElement).src = src;
|
||||
//FIXME
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -719,12 +720,14 @@ class User extends SnowFlake {
|
|||
for (const badgejson of badges) {
|
||||
const badge = document.createElement(badgejson.link ? "a" : "div");
|
||||
badge.classList.add("badge");
|
||||
const img = document.createElement("img");
|
||||
let src: string;
|
||||
if (URL.canParse(badgejson.icon)) {
|
||||
img.src = badgejson.icon;
|
||||
src = badgejson.icon;
|
||||
} else {
|
||||
img.src = this.info.cdn + "/badge-icons/" + badgejson.icon + ".png";
|
||||
src = this.info.cdn + "/badge-icons/" + badgejson.icon + ".png";
|
||||
}
|
||||
const img = createImg(src, undefined, badgediv);
|
||||
|
||||
badge.append(img);
|
||||
let hovertxt: string;
|
||||
if (badgejson.translate) {
|
||||
|
@ -810,11 +813,11 @@ class User extends SnowFlake {
|
|||
return div;
|
||||
}
|
||||
getBanner(guild: Guild | null | Member): HTMLImageElement {
|
||||
const banner = document.createElement("img");
|
||||
const banner = createImg(undefined);
|
||||
|
||||
const bsrc = this.getBannerUrl();
|
||||
if (bsrc) {
|
||||
banner.src = bsrc;
|
||||
banner.setSrcs(bsrc);
|
||||
banner.classList.add("banner");
|
||||
}
|
||||
|
||||
|
@ -822,7 +825,7 @@ class User extends SnowFlake {
|
|||
if (guild instanceof Member) {
|
||||
const bsrc = guild.getBannerUrl();
|
||||
if (bsrc) {
|
||||
banner.src = bsrc;
|
||||
banner.setSrcs(bsrc);
|
||||
banner.classList.add("banner");
|
||||
}
|
||||
} else {
|
||||
|
@ -830,7 +833,7 @@ class User extends SnowFlake {
|
|||
if (!memb) return;
|
||||
const bsrc = memb.getBannerUrl();
|
||||
if (bsrc) {
|
||||
banner.src = bsrc;
|
||||
banner.setSrcs(bsrc);
|
||||
banner.classList.add("banner");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -583,6 +583,63 @@ export async function getapiurls(str: string): Promise<
|
|||
}
|
||||
return false;
|
||||
}
|
||||
function isAnimated(src: string) {
|
||||
return src.endsWith(".apng") || src.endsWith(".gif");
|
||||
}
|
||||
const staticImgMap = new Map<string, string | Promise<string>>();
|
||||
export function createImg(
|
||||
src: string | undefined,
|
||||
staticsrc: string | void,
|
||||
elm: HTMLElement | void,
|
||||
) {
|
||||
const settings =
|
||||
localStorage.getItem("gifSetting") || ("hover" as "hover") || "always" || "never";
|
||||
const img = document.createElement("img");
|
||||
elm ||= img;
|
||||
img.crossOrigin = "anonymous";
|
||||
img.onload = async () => {
|
||||
if (settings === "always") return;
|
||||
if (!src) return;
|
||||
if (isAnimated(src) && !staticsrc) {
|
||||
let s = staticImgMap.get(src);
|
||||
if (s) {
|
||||
staticsrc = await s;
|
||||
} else {
|
||||
staticImgMap.set(
|
||||
src,
|
||||
new Promise(async (res) => {
|
||||
const c = new OffscreenCanvas(img.naturalWidth, img.naturalHeight);
|
||||
const ctx = c.getContext("2d");
|
||||
if (!ctx) return;
|
||||
ctx.drawImage(img, 0, 0);
|
||||
const blob = await c.convertToBlob();
|
||||
res(URL.createObjectURL(blob));
|
||||
}),
|
||||
);
|
||||
staticsrc = (await staticImgMap.get(src)) as string;
|
||||
}
|
||||
img.src = staticsrc;
|
||||
}
|
||||
};
|
||||
elm.onmouseover = () => {
|
||||
if (settings === "never") return;
|
||||
if (img.src !== src && src) {
|
||||
img.src = src;
|
||||
}
|
||||
};
|
||||
elm.onmouseleave = () => {
|
||||
if (staticsrc && settings !== "always") {
|
||||
img.src = staticsrc;
|
||||
}
|
||||
};
|
||||
img.src = settings !== "always" ? staticsrc || src || "" : src || "";
|
||||
return Object.assign(img, {
|
||||
setSrcs: (nsrc: string, nstaticsrc: string | void) => {
|
||||
src = nsrc;
|
||||
staticsrc = nstaticsrc;
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
*
|
||||
* This function takes in a string and checks if the string is a valid instance
|
||||
|
|
|
@ -155,7 +155,7 @@ async function webhookMenu(
|
|||
const nameBox = document.createElement("div");
|
||||
nameBox.classList.add("flexttb");
|
||||
nameBox.append(name);
|
||||
const pfp = user.buildpfp();
|
||||
const pfp = user.buildpfp(undefined, div);
|
||||
div.append(pfp, nameBox);
|
||||
form.addHTMLArea(div);
|
||||
|
||||
|
|
|
@ -147,7 +147,13 @@
|
|||
"spoiler": "Spoiler",
|
||||
"accessibility": {
|
||||
"name": "Accessibility",
|
||||
"roleColors": "Disable role colors"
|
||||
"roleColors": "Disable role colors",
|
||||
"playGif": "Play gifs:",
|
||||
"gifSettings": {
|
||||
"hover": "Hover",
|
||||
"always": "Always",
|
||||
"never": "Never"
|
||||
}
|
||||
},
|
||||
"searchGifs": "Search Tenor",
|
||||
"channel": {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue