Dear Claudia (Claude)
This commit is contained in:
parent
183920dd37
commit
fae7c71fed
17 changed files with 148 additions and 55 deletions
|
|
@ -15,7 +15,7 @@ const settings = definePluginSettings({
|
|||
description: "Automatically fill command with all arguments instead of just required ones.",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
}, a
|
||||
},
|
||||
});
|
||||
|
||||
function fetchIndex(target: object) {
|
||||
|
|
|
|||
|
|
@ -155,15 +155,23 @@ export default function fathorse(cfg) {
|
|||
|
||||
if (config.shake) document.body.style.willChange = "transform";
|
||||
|
||||
window.addEventListener("mousemove", ev => {
|
||||
function handleMouseMove(ev) {
|
||||
mousePos.x = ev.clientX;
|
||||
mousePos.y = ev.clientY;
|
||||
|
||||
nextMove = Date.now() + freeroamStart;
|
||||
isRoaming = false;
|
||||
});
|
||||
}
|
||||
window.addEventListener("mousemove", handleMouseMove);
|
||||
|
||||
requestAnimationFrame(lifecycle);
|
||||
|
||||
return mousePos;
|
||||
return function destroy() {
|
||||
window.removeEventListener("mousemove", handleMouseMove);
|
||||
if (config.shake) {
|
||||
document.body.style.willChange = "";
|
||||
document.body.style.transform = "";
|
||||
}
|
||||
fathorse.remove();
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -196,7 +196,11 @@ const settings = definePluginSettings({
|
|||
}
|
||||
});
|
||||
|
||||
let destroyBuddy: (() => void) | undefined;
|
||||
|
||||
function unload() {
|
||||
destroyBuddy?.();
|
||||
destroyBuddy = undefined;
|
||||
document.getElementById("oneko")?.remove();
|
||||
document.getElementById("fathorse")?.remove();
|
||||
}
|
||||
|
|
@ -207,7 +211,7 @@ function load() {
|
|||
|
||||
switch (settings.store.buddy) {
|
||||
case "oneko": {
|
||||
oneko({
|
||||
destroyBuddy = oneko({
|
||||
speed: settings.store.speed,
|
||||
fps: settings.store.fps,
|
||||
image: ONEKO_IMAGE,
|
||||
|
|
@ -218,7 +222,7 @@ function load() {
|
|||
break;
|
||||
}
|
||||
case "fathorse": {
|
||||
fathorse({
|
||||
destroyBuddy = fathorse({
|
||||
speed: settings.store.speed,
|
||||
fps: settings.store.fps,
|
||||
size: settings.store.size,
|
||||
|
|
|
|||
|
|
@ -196,33 +196,43 @@ export default function oneko(options = {}) {
|
|||
|
||||
document.body.appendChild(nekoEl);
|
||||
|
||||
document.addEventListener("mousemove", function (event) {
|
||||
mousePosX = event.clientX;
|
||||
mousePosY = event.clientY;
|
||||
});
|
||||
document.addEventListener("mousemove", handleMouseMove);
|
||||
|
||||
if (persistPosition) {
|
||||
window.addEventListener("beforeunload", function (event) {
|
||||
window.localStorage.setItem(
|
||||
"oneko",
|
||||
JSON.stringify({
|
||||
nekoPosX: nekoPosX,
|
||||
nekoPosY: nekoPosY,
|
||||
mousePosX: mousePosX,
|
||||
mousePosY: mousePosY,
|
||||
frameCount: frameCount,
|
||||
idleTime: idleTime,
|
||||
idleAnimation: idleAnimation,
|
||||
idleAnimationFrame: idleAnimationFrame,
|
||||
bgPos: nekoEl.style.backgroundPosition,
|
||||
})
|
||||
);
|
||||
});
|
||||
window.addEventListener("beforeunload", handleBeforeUnload);
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(onAnimationFrame);
|
||||
}
|
||||
|
||||
function handleMouseMove(event) {
|
||||
mousePosX = event.clientX;
|
||||
mousePosY = event.clientY;
|
||||
}
|
||||
|
||||
function handleBeforeUnload(event) {
|
||||
window.localStorage.setItem(
|
||||
"oneko",
|
||||
JSON.stringify({
|
||||
nekoPosX: nekoPosX,
|
||||
nekoPosY: nekoPosY,
|
||||
mousePosX: mousePosX,
|
||||
mousePosY: mousePosY,
|
||||
frameCount: frameCount,
|
||||
idleTime: idleTime,
|
||||
idleAnimation: idleAnimation,
|
||||
idleAnimationFrame: idleAnimationFrame,
|
||||
bgPos: nekoEl.style.backgroundPosition,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
document.removeEventListener("mousemove", handleMouseMove);
|
||||
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||
nekoEl.remove();
|
||||
}
|
||||
|
||||
let lastFrameTimestamp;
|
||||
|
||||
function onAnimationFrame(timestamp) {
|
||||
|
|
@ -335,4 +345,6 @@ export default function oneko(options = {}) {
|
|||
}
|
||||
|
||||
init();
|
||||
|
||||
return destroy;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,12 +34,16 @@ async function loadFFmpeg(): Promise<FFmpeg> {
|
|||
const classWorkerBlob = new Blob([(new TextEncoder()).encode(classWorkerRaw)], { type: "text/javascript" });
|
||||
const classWorkerUrl = URL.createObjectURL(classWorkerBlob);
|
||||
|
||||
await ffmpeg.load({
|
||||
coreURL: `${baseURL}/ffmpeg-core.js`,
|
||||
wasmURL: `${baseURL}/ffmpeg-core.wasm`,
|
||||
workerURL: `${baseURL}/ffmpeg-core.worker.js`,
|
||||
classWorkerURL: classWorkerUrl,
|
||||
});
|
||||
try {
|
||||
await ffmpeg.load({
|
||||
coreURL: `${baseURL}/ffmpeg-core.js`,
|
||||
wasmURL: `${baseURL}/ffmpeg-core.wasm`,
|
||||
workerURL: `${baseURL}/ffmpeg-core.worker.js`,
|
||||
classWorkerURL: classWorkerUrl,
|
||||
});
|
||||
} finally {
|
||||
URL.revokeObjectURL(classWorkerUrl);
|
||||
}
|
||||
|
||||
ffmpegLoaded = true;
|
||||
console.log("[FileUpload] FFmpeg loaded");
|
||||
|
|
|
|||
|
|
@ -64,9 +64,10 @@ async function loadFontFace(family: string, url: string, descriptors: FontFaceDe
|
|||
document.fonts.add(font);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
} finally {
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
fontObjectUrls.delete(objectUrl);
|
||||
return false;
|
||||
}
|
||||
} catch {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -83,11 +83,13 @@ async function zipGuildAssets(guild: Guild, type: "emojis" | "stickers") {
|
|||
.then(results => {
|
||||
const zipped = zipSync(Object.fromEntries(results.map(({ file, filename }) => [filename, file])));
|
||||
const blob = new Blob([new Uint8Array(zipped)], { type: "application/zip" });
|
||||
const objectUrl = URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.href = objectUrl;
|
||||
link.download = `${guild.name}-${type}.zip`;
|
||||
link.click();
|
||||
link.remove();
|
||||
setTimeout(() => URL.revokeObjectURL(objectUrl), 1000);
|
||||
})
|
||||
.catch(console.error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,7 +242,10 @@ export function loadFriendImage(source: File | string): Promise<HTMLImageElement
|
|||
if (isFile) URL.revokeObjectURL(url);
|
||||
resolve(img);
|
||||
};
|
||||
img.onerror = (event, _source, _lineno, _colno, err) => reject(err || event);
|
||||
img.onerror = (event, _source, _lineno, _colno, err) => {
|
||||
if (isFile) URL.revokeObjectURL(url);
|
||||
reject(err || event);
|
||||
};
|
||||
img.crossOrigin = "anonymous";
|
||||
img.src = url;
|
||||
});
|
||||
|
|
@ -343,7 +346,10 @@ export function loadImage(source: File | string) {
|
|||
if (isFile) URL.revokeObjectURL(url);
|
||||
resolve(img);
|
||||
};
|
||||
img.onerror = (event, _source, _lineno, _colno, err) => reject(err || event);
|
||||
img.onerror = (event, _source, _lineno, _colno, err) => {
|
||||
if (isFile) URL.revokeObjectURL(url);
|
||||
reject(err || event);
|
||||
};
|
||||
img.crossOrigin = "Anonymous";
|
||||
img.src = url;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -388,10 +388,12 @@ export const Packs = () => {
|
|||
}
|
||||
}
|
||||
|
||||
const objectUrl = URL.createObjectURL(new Blob([JSON.stringify(result)], { type: "application/json" }));
|
||||
const a = document.createElement("a");
|
||||
a.href = URL.createObjectURL(new Blob([JSON.stringify(result)], { type: "application/json" }));
|
||||
a.href = objectUrl;
|
||||
a.download = "MoreStickers.stickerpacks";
|
||||
a.click();
|
||||
setTimeout(() => URL.revokeObjectURL(objectUrl), 1000);
|
||||
|
||||
Toasts.show({
|
||||
message: "Sticker Packs exported",
|
||||
|
|
|
|||
|
|
@ -133,7 +133,12 @@ export async function sendSticker({ channelId, sticker, ctrlKey, shiftKey, ffmpe
|
|||
const res = await corsFetch(sticker.image);
|
||||
if (!res.ok) throw new Error("Failed to fetch sticker image");
|
||||
const blobUrl = URL.createObjectURL(await res.blob());
|
||||
const processed = await resizeImage(blobUrl);
|
||||
let processed: Blob;
|
||||
try {
|
||||
processed = await resizeImage(blobUrl);
|
||||
} finally {
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
}
|
||||
const filename = sticker.filename ?? new URL(sticker.image).pathname.split("/").pop()!;
|
||||
const mimeType = getMimeFromExtension(filename.split(".").pop());
|
||||
|
||||
|
|
|
|||
|
|
@ -54,12 +54,16 @@ export async function loadFFmpeg(ffmpeg: FFmpeg, setLoaded: () => void) {
|
|||
const classWorkerBlob = new Blob([(new TextEncoder()).encode(classWorkerRaw)], { type: "text/javascript" });
|
||||
const classWorkerUrl = URL.createObjectURL(classWorkerBlob);
|
||||
|
||||
await ffmpeg.load({
|
||||
coreURL: `${baseURL}/ffmpeg-core.js`,
|
||||
wasmURL: `${baseURL}/ffmpeg-core.wasm`,
|
||||
workerURL: `${baseURL}/ffmpeg-core.worker.js`,
|
||||
classWorkerURL: classWorkerUrl,
|
||||
});
|
||||
try {
|
||||
await ffmpeg.load({
|
||||
coreURL: `${baseURL}/ffmpeg-core.js`,
|
||||
wasmURL: `${baseURL}/ffmpeg-core.wasm`,
|
||||
workerURL: `${baseURL}/ffmpeg-core.worker.js`,
|
||||
classWorkerURL: classWorkerUrl,
|
||||
});
|
||||
} finally {
|
||||
URL.revokeObjectURL(classWorkerUrl);
|
||||
}
|
||||
setLoaded();
|
||||
console.log("FFmpeg loaded!");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ import { migrateOldLyrics } from "./spotify/lyrics/api";
|
|||
import { SpotifyLyrics } from "./spotify/lyrics/components/lyrics";
|
||||
import { SpotifyPlayer } from "./spotify/PlayerComponent";
|
||||
import { TidalLyrics } from "./tidal/lyrics/components/lyrics";
|
||||
import { stopTidalLrcStore } from "./tidal/lyrics/providers/store";
|
||||
import { TidalPlayer } from "./tidal/TidalPlayer";
|
||||
import { stopTidalStore } from "./tidal/TidalStore";
|
||||
|
||||
export default definePlugin({
|
||||
name: "MusicControls",
|
||||
|
|
@ -115,4 +117,9 @@ export default definePlugin({
|
|||
await migrateOldLyrics();
|
||||
toggleHoverControls(settings.store.hoverControls);
|
||||
},
|
||||
|
||||
stop() {
|
||||
stopTidalLrcStore();
|
||||
stopTidalStore();
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { SYM_LAZY_CACHED } from "@utils/lazy";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { proxyLazyWebpack } from "@webpack";
|
||||
import { Flux, FluxDispatcher } from "@webpack/common";
|
||||
|
|
@ -59,8 +60,10 @@ type Message = { type: "update"; all: boolean; fields?: any; field?: string; val
|
|||
class TidalSocket {
|
||||
public onChange: (e: Message) => void;
|
||||
public ready = false;
|
||||
public destroyed = false;
|
||||
|
||||
public socket: WebSocket | undefined;
|
||||
private reconnectTimeout: ReturnType<typeof setTimeout> | undefined;
|
||||
|
||||
constructor(onChange: typeof this.onChange) {
|
||||
this.reconnect();
|
||||
|
|
@ -68,7 +71,7 @@ class TidalSocket {
|
|||
}
|
||||
|
||||
public reconnect() {
|
||||
if (this.ready) return;
|
||||
if (this.ready || this.destroyed) return;
|
||||
try {
|
||||
this.initWs();
|
||||
} catch (e) {
|
||||
|
|
@ -78,6 +81,12 @@ class TidalSocket {
|
|||
this.ready = true;
|
||||
}
|
||||
|
||||
public close() {
|
||||
this.destroyed = true;
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
this.socket?.close();
|
||||
}
|
||||
|
||||
get routes() {
|
||||
return {
|
||||
"play": () => this.socket?.send(JSON.stringify({ action: "resume" })),
|
||||
|
|
@ -105,13 +114,13 @@ class TidalSocket {
|
|||
});
|
||||
|
||||
this.socket.addEventListener("error", e => {
|
||||
if (!this.ready) setTimeout(() => this.reconnect(), 5_000);
|
||||
if (!this.ready && !this.destroyed) this.reconnectTimeout = setTimeout(() => this.reconnect(), 5_000);
|
||||
this.onChange({ type: "update", all: true, fields: { playing: false, track: null, currentTime: 0, repeatMode: 0, shuffle: false, volume: 100 } });
|
||||
});
|
||||
|
||||
this.socket.addEventListener("close", e => {
|
||||
this.ready = false;
|
||||
if (!this.ready) setTimeout(() => this.reconnect(), 10_000);
|
||||
if (!this.destroyed) this.reconnectTimeout = setTimeout(() => this.reconnect(), 10_000);
|
||||
this.onChange({ type: "update", all: true, fields: { playing: false, track: null, currentTime: 0, repeatMode: 0, shuffle: false, volume: 100 } });
|
||||
});
|
||||
|
||||
|
|
@ -242,9 +251,17 @@ export const TidalStore = proxyLazyWebpack(() => {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.socket.close();
|
||||
}
|
||||
}
|
||||
|
||||
const store = new TidalStore(FluxDispatcher);
|
||||
|
||||
return store;
|
||||
});
|
||||
|
||||
export function stopTidalStore() {
|
||||
TidalStore[SYM_LAZY_CACHED]?.destroy();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ function showNotif(title: string, body: string) {
|
|||
}
|
||||
}
|
||||
|
||||
let tidalStoreChangeListener: (() => void) | undefined;
|
||||
|
||||
export const TidalLrcStore = proxyLazyWebpack(() => {
|
||||
let lyrics: EnhancedLyric[] | null = null;
|
||||
let lastTrackId: string | null = null;
|
||||
|
|
@ -49,6 +51,14 @@ export const TidalLrcStore = proxyLazyWebpack(() => {
|
|||
}
|
||||
|
||||
TidalStore.addChangeListener(handleTidalStoreChange);
|
||||
tidalStoreChangeListener = handleTidalStoreChange;
|
||||
|
||||
return store;
|
||||
});
|
||||
|
||||
export function stopTidalLrcStore() {
|
||||
if (tidalStoreChangeListener) {
|
||||
TidalStore.removeChangeListener(tidalStoreChangeListener);
|
||||
tidalStoreChangeListener = undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,9 +45,11 @@ export const Canvas = ({ file }: { file: File; }) => {
|
|||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const objectUrl = URL.createObjectURL(file);
|
||||
image = new Image();
|
||||
image.src = URL.createObjectURL(file);
|
||||
image.src = objectUrl;
|
||||
image.onload = () => {
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
canvas = canvasRef.current;
|
||||
|
||||
if (!canvas) return;
|
||||
|
|
@ -66,7 +68,9 @@ export const Canvas = ({ file }: { file: File; }) => {
|
|||
|
||||
initInput();
|
||||
};
|
||||
});
|
||||
|
||||
return () => URL.revokeObjectURL(objectUrl);
|
||||
}, [file]);
|
||||
|
||||
return (<canvas ref={canvasRef} className="vc-remix-canvas"></canvas>);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -96,7 +96,8 @@ function OutputVolumeComponent() {
|
|||
useEffect(() => {
|
||||
const listener = () => setOutputVolume(configModule.getOutputVolume());
|
||||
FluxDispatcher.subscribe("AUDIO_SET_OUTPUT_VOLUME", listener);
|
||||
});
|
||||
return () => FluxDispatcher.unsubscribe("AUDIO_SET_OUTPUT_VOLUME", listener);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -117,7 +118,8 @@ function InputVolumeComponent() {
|
|||
useEffect(() => {
|
||||
const listener = () => setInputVolume(configModule.getInputVolume());
|
||||
FluxDispatcher.subscribe("AUDIO_SET_INPUT_VOLUME", listener);
|
||||
});
|
||||
return () => FluxDispatcher.unsubscribe("AUDIO_SET_INPUT_VOLUME", listener);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -138,7 +140,8 @@ function OutputDeviceComponent() {
|
|||
useEffect(() => {
|
||||
const listener = () => setOutputDevice(configModule.getOutputDeviceId());
|
||||
FluxDispatcher.subscribe("AUDIO_SET_OUTPUT_DEVICE", listener);
|
||||
});
|
||||
return () => FluxDispatcher.unsubscribe("AUDIO_SET_OUTPUT_DEVICE", listener);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -166,7 +169,8 @@ function InputDeviceComponent() {
|
|||
useEffect(() => {
|
||||
const listener = () => setInputDevice(configModule.getInputDeviceId());
|
||||
FluxDispatcher.subscribe("AUDIO_SET_INPUT_DEVICE", listener);
|
||||
});
|
||||
return () => FluxDispatcher.unsubscribe("AUDIO_SET_INPUT_DEVICE", listener);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
|
|
@ -194,7 +198,8 @@ function VideoDeviceComponent() {
|
|||
useEffect(() => {
|
||||
const listener = () => setVideoDevice(configModule.getVideoDeviceId());
|
||||
FluxDispatcher.subscribe("MEDIA_ENGINE_SET_VIDEO_DEVICE", listener);
|
||||
});
|
||||
return () => FluxDispatcher.unsubscribe("MEDIA_ENGINE_SET_VIDEO_DEVICE", listener);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
|
|
|
|||
|
|
@ -291,7 +291,9 @@ export class TranscriptionWorker {
|
|||
this.onPartial = onPartial;
|
||||
|
||||
const blob = new Blob([workerCode], { type: "text/javascript" });
|
||||
this.worker = new Worker(URL.createObjectURL(blob), { type: "module" });
|
||||
const objectUrl = URL.createObjectURL(blob);
|
||||
this.worker = new Worker(objectUrl, { type: "module" });
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
this.worker.onmessage = this.handleMessage.bind(this);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue