(GifCollections) fix issues and add options (#443)

* add an option to refresh urls that are exired ( discord )

* add option for disabling multiple same to same collection
This commit is contained in:
creations 2025-10-06 18:23:28 -04:00 • committed by GitHub
parent 13d39e7fd9
commit c187450191
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 128 additions and 2 deletions

View file

@ -16,9 +16,10 @@ import { ModalContent, ModalFooter, ModalHeader, ModalRoot, ModalSize, openModal
import definePlugin, { OptionType } from "@utils/types";
import { Alerts, Button, ContextMenuApi, FluxDispatcher, Forms, Menu, React, showToast, TextInput, Toasts, useCallback, useState } from "@webpack/common";
import { addToCollection, cache_collections, createCollection, DATA_COLLECTION_NAME, deleteCollection, fixPrefix, getCollections, getGifById, getItemCollectionNameFromId, moveGifToCollection, refreshCacheCollection, removeFromCollection, renameCollection } from "./utils/collectionManager";
import { addToCollection, cache_collections, createCollection, DATA_COLLECTION_NAME, deleteCollection, fixPrefix, getCollections, getGifById, getItemCollectionNameFromId, moveGifToCollection, refreshCacheCollection, removeFromCollection, renameCollection, updateGif } from "./utils/collectionManager";
import { getFormat } from "./utils/getFormat";
import { getGif } from "./utils/getGif";
import { refreshGifUrl } from "./utils/refreshUrl";
import { downloadCollections, uploadGifCollections } from "./utils/settingsUtils";
import { uuidv4 } from "./utils/uuidv4";
@ -131,6 +132,11 @@ export const settings = definePluginSettings({
type: OptionType.BOOLEAN,
default: false,
},
preventDuplicates: {
description: "Prevent adding the same GIF to a collection multiple times",
type: OptionType.BOOLEAN,
default: false,
},
defaultEmptyCollectionImage: {
description: "The image / gif that will be shown when a collection has no images / gifs",
type: OptionType.STRING,
@ -539,6 +545,40 @@ const RemoveItemContextMenu = ({ type, nameOrId, instance }) => (
}}
/>
<Menu.MenuSeparator />
<Menu.MenuItem
key="refresh-url"
id="refresh-url"
label="Refresh URL"
action={async () => {
const gifInfo = getGifById(nameOrId);
if (!gifInfo) return;
if (!gifInfo.channelId || !gifInfo.messageId || !gifInfo.attachmentId) {
showToast("Cannot refresh: GIF missing metadata (re-add to collection)", Toasts.Type.FAILURE);
return;
}
showToast("Refreshing URL...", Toasts.Type.MESSAGE);
const refreshedGif = await refreshGifUrl(gifInfo);
if (refreshedGif) {
await updateGif(nameOrId, refreshedGif);
const collectionName = getItemCollectionNameFromId(nameOrId);
FluxDispatcher.dispatch({
type: "GIF_PICKER_QUERY",
query: `${collectionName} `
});
FluxDispatcher.dispatch({
type: "GIF_PICKER_QUERY",
query: `${collectionName}`
});
showToast("URL refreshed successfully", Toasts.Type.SUCCESS);
} else {
showToast("Failed to refresh URL", Toasts.Type.FAILURE);
}
}}
/>
<Menu.MenuSeparator />
<Menu.MenuItem
key="copy-url"
id="copy-url"

View file

@ -23,6 +23,9 @@ export interface Gif {
height: number,
width: number;
addedAt?: number;
channelId?: string;
messageId?: string;
attachmentId?: string;
}
export interface Props {

View file

@ -60,6 +60,21 @@ export const addToCollection = async (name: string, gif: Gif): Promise<void> =>
const collectionIndex = collections.findIndex(c => c.name === name);
if (collectionIndex === -1) return console.warn("collection not found");
if (settings.store.preventDuplicates) {
const isDuplicate = collections[collectionIndex].gifs.some(g => g.url === gif.url);
if (isDuplicate) {
return Toasts.show({
message: "This GIF is already in the collection",
type: Toasts.Type.FAILURE,
id: Toasts.genId(),
options: {
duration: 3000,
position: Toasts.Position.BOTTOM
}
});
}
}
collections[collectionIndex].gifs.push(gif);
collections[collectionIndex].src = gif.src;
collections[collectionIndex].format = getFormat(gif.src);
@ -164,3 +179,18 @@ export const moveGifToCollection = async (gifId: string, fromCollection: string,
await DataStore.set(DATA_COLLECTION_NAME, collections);
return await refreshCacheCollection();
};
export const updateGif = async (gifId: string, updatedGif: Gif): Promise<void> => {
const collections = await getCollections();
const collectionIndex = collections.findIndex(c => c.gifs.some(g => g.id === gifId));
if (collectionIndex === -1) return console.warn("collection not found");
const gifIndex = collections[collectionIndex].gifs.findIndex(g => g.id === gifId);
if (gifIndex === -1) return console.warn("gif not found");
collections[collectionIndex].gifs[gifIndex] = updatedGif;
collections[collectionIndex].lastUpdated = Date.now();
await DataStore.set(DATA_COLLECTION_NAME, collections);
return await refreshCacheCollection();
};

View file

@ -93,7 +93,10 @@ export function getGifByMessageAndUrl(url: string, message: Message): Gif | null
height: attachment.height ?? 50,
width: attachment.width ?? 50,
src: attachment.proxy_url,
url: attachment.url
url: attachment.url,
channelId: message.channel_id,
messageId: message.id,
attachmentId: attachment.id
};
return null;

View file

@ -0,0 +1,50 @@
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { RestAPI } from "@webpack/common";
import { Gif } from "../types";
async function fetchMessageFromAPI(channelId: string, messageId: string): Promise<any> {
try {
const response = await RestAPI.get({
url: `/channels/${channelId}/messages`,
query: {
limit: 1,
around: messageId
}
});
if (response.ok && response.body.length > 0) {
return response.body.find((m: any) => m.id === messageId);
}
} catch (error) {
console.error("Failed to fetch message for GIF refresh:", error);
}
return null;
}
export async function refreshGifUrl(gif: Gif): Promise<Gif | null> {
if (!gif.channelId || !gif.messageId || !gif.attachmentId) {
return null;
}
const message = await fetchMessageFromAPI(gif.channelId, gif.messageId);
if (!message) {
return null;
}
const attachment = message.attachments?.find((a: any) => a.id === gif.attachmentId);
if (!attachment) {
return null;
}
return {
...gif,
src: attachment.proxy_url,
url: attachment.url
};
}