Fix: MoreStickers tab (#94)

* feat(MoreStickers): ready for dynamic sticker pack feature

* fix(MoreStickers): Sticker+ tab

---------

Co-authored-by: thororen1234 <thororen1234@users.noreply.github.com>
Co-authored-by: thororen1234 <78185467+thororen1234@users.noreply.github.com>
This commit is contained in:
leko 2024-11-11 04:10:06 +08:00 committed by GitHub
parent 22751c00eb
commit 70066cae7f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 123 additions and 9 deletions

View file

@ -11,7 +11,7 @@ import { Button, Forms, React, TabBar, Text, TextArea, Toasts } from "@webpack/c
import { convert as convertLineEP, getIdFromUrl as getLineEmojiPackIdFromUrl, getStickerPackById as getLineEmojiPackById, isLineEmojiPackHtml, parseHtml as getLineEPFromHtml } from "../lineEmojis";
import { convert as convertLineSP, getIdFromUrl as getLineStickerPackIdFromUrl, getStickerPackById as getLineStickerPackById, isLineStickerPackHtml, parseHtml as getLineSPFromHtml } from "../lineStickers";
import { migrate } from "../migrate-v1";
import { isV1, migrate } from "../migrate-v1";
import { deleteStickerPack, getStickerPack, getStickerPackMetas, saveStickerPack } from "../stickers";
import { SettingsTabsKey, Sticker, StickerPack, StickerPackMeta } from "../types";
import { cl, clPicker, Mutex } from "../utils";
@ -92,6 +92,7 @@ export const Settings = () => {
const [addStickerHtml, setAddStickerHtml] = React.useState<string>("");
const [tab, setTab] = React.useState<SettingsTabsKey>(SettingsTabsKey.ADD_STICKER_PACK_URL);
const [hoveredStickerPackId, setHoveredStickerPackId] = React.useState<string | null>(null);
const [_isV1, setV1] = React.useState<boolean>(false);
async function refreshStickerPackMetas() {
setstickerPackMetas(await getStickerPackMetas());
@ -99,6 +100,9 @@ export const Settings = () => {
React.useEffect(() => {
refreshStickerPackMetas();
}, []);
React.useEffect(() => {
isV1().then(setV1);
}, []);
return (
<div className={cl("settings")}>
@ -365,7 +369,7 @@ export const Settings = () => {
<Flex flexDirection="row" style={{
alignItems: "center",
justifyContent: "center"
justifyContent: "start"
}} >
<Button
size={Button.Sizes.SMALL}
@ -399,6 +403,9 @@ export const Settings = () => {
onClick={async e => {
await migrate();
}}
style={{
display: _isV1 ? "unset" : "none"
}}
>Migrate from v1</Button>
</Flex>
</div>

View file

@ -64,11 +64,11 @@ export default definePlugin({
}
},
{
find: "#{intl::EXPRESSION_PICKER_GIF}",
find: `role:"tablist","aria-label":`,
replacement: {
match: /role:"tablist",.+?#{intl::EXPRESSION_PICKER_CATEGORIES_A11Y_LABEL}\),children:(\[.*?\)\]}\)}\):null,)(.*?closePopout:\w.*?:null)/s,
match: /role:"tablist",.*?,?"aria-label":.+?\),children:(\[.*?\)\]}\)}\):null,)(.*?closePopout:\w.*?:null)/s,
replace: m => {
const stickerTabRegex = /(\w+?)\?(\([^()]+?\))\((.{1,2}),{.{0,128},isActive:(.{1,2})===.{1,150},children:(.{1,10}#{intl::EXPRESSION_PICKER_STICKER}).*?:null/s;
const stickerTabRegex = /(\w+?)\?(\([^()]+?\))\((.{1,2}),{.{0,128},isActive:(.{1,2})===.{1,6}\.STICKER.{1,140},children:(.{1,2}\.intl\.string\(.+?\)).*?:null/s;
const res = m.replace(stickerTabRegex, (_m, canUseStickers, jsx, tabHeaderComp, currentTab, stickerText) => {
const isActive = `${currentTab}==="stickers+"`;
return (

View file

@ -57,6 +57,20 @@ function migrateStickerPack(oldStickerPack: StickerPack): StickerPack {
};
}
export async function isV1() {
const newPackMetas = await getStickerPackMetas(PACKS_KEY);
if (newPackMetas.length > 0) {
return false;
}
const oldPackMetas = await getStickerPackMetas(PACKS_KEY_OLD);
if (oldPackMetas.length === 0) {
return false;
}
return true;
}
export async function migrate() {
const newPackMetas = await getStickerPackMetas(PACKS_KEY);
if (newPackMetas.length > 0) {

View file

@ -7,11 +7,12 @@
import * as DataStore from "@api/DataStore";
import { removeRecentStickerByPackId } from "./components";
import { StickerPack, StickerPackMeta } from "./types";
import { DynamicPackSetMeta, DynamicStickerPackMeta, StickerPack, StickerPackMeta } from "./types";
import { Mutex } from "./utils";
const mutex = new Mutex();
const PACKS_KEY = "MoreStickers:Packs";
const DYNAMIC_PACK_SET_METAS_KEY = "MoreStickers:DynamicPackSetMetas";
/**
* Convert StickerPack to StickerPackMeta
@ -24,7 +25,8 @@ function stickerPackToMeta(sp: StickerPack): StickerPackMeta {
id: sp.id,
title: sp.title,
author: sp.author,
logo: sp.logo
logo: sp.logo,
dynamic: sp.dynamic,
};
}
@ -43,8 +45,11 @@ export async function saveStickerPack(sp: StickerPack, packsKey: string = PACKS_
const unlock = await mutex.lock();
try {
const packs = (await DataStore.get(packsKey) ?? null) as (StickerPackMeta[] | null);
await DataStore.set(packsKey, packs === null ? [meta] : [...packs, meta]);
let packs = (await DataStore.get(packsKey) ?? null) as (StickerPackMeta[] | null);
if (packs?.some(p => p.id === sp.id)) {
packs = packs.map(p => p.id === sp.id ? meta : p);
}
await DataStore.set(packsKey, packs === null ? [meta] : packs);
} finally {
unlock();
}
@ -106,3 +111,66 @@ export async function deleteStickerPack(id: string, packsKey: string = PACKS_KEY
})()
]);
}
// ---------------------------- Dynamic Packs ----------------------------
export async function getDynamicStickerPack(dspm: DynamicStickerPackMeta): Promise<StickerPack | null> {
const dsp = await fetch(dspm.dynamic.refreshUrl, {
headers: dspm.dynamic.authHeaders,
});
if (!dsp.ok) return null;
return await dsp.json();
}
export async function getDynamicPackSetMetas(dpsmKey: string = DYNAMIC_PACK_SET_METAS_KEY): Promise<DynamicPackSetMeta[] | null> {
return (await DataStore.get(dpsmKey)) ?? null as DynamicPackSetMeta[] | null;
}
function hasDynamicPackSetMeta(dpsm: DynamicPackSetMeta, metas?: DynamicPackSetMeta[] | null): boolean {
return !!metas?.some(m => m.id === dpsm.id);
}
export async function fetchDynamicPackSetMeta(dpsm: DynamicPackSetMeta): Promise<DynamicPackSetMeta | null> {
const dpsm_ = await fetch(dpsm.refreshUrl, {
headers: dpsm.authHeaders,
});
if (!dpsm_.ok) return null;
const dpsmData = await dpsm_.json();
return dpsmData as DynamicPackSetMeta;
}
export async function refreshDynamicPackSet(old: DynamicPackSetMeta, _new: DynamicPackSetMeta): Promise<void> {
const oldPacks = old.packs.map(p => p.id);
const newPacks = _new.packs.map(p => p.id);
const toRemove = oldPacks.filter(p => !newPacks.includes(p));
const toAdd = newPacks.filter(p => !oldPacks.includes(p));
await Promise.all([
...toRemove.map(id => deleteStickerPack(id)),
...toAdd.map(id => getDynamicStickerPack(_new.packs.find(p => p.id === id)!).then(sp => sp && saveStickerPack(sp)))
]);
}
export async function saveDynamicPackSetMeta(dpsm: DynamicPackSetMeta, dpsmKey: string = DYNAMIC_PACK_SET_METAS_KEY): Promise<void> {
let metas = (await DataStore.get(dpsmKey) ?? null) as (DynamicPackSetMeta[] | null);
if (hasDynamicPackSetMeta(dpsm, metas)) {
await refreshDynamicPackSet(metas!.find(m => m.id === dpsm.id)!, dpsm);
metas = metas!.map(m => m.id === dpsm.id ? dpsm : m);
}
const unlock = await mutex.lock();
try {
await DataStore.set(dpsmKey, metas === null ? [dpsm] : metas);
} finally {
unlock();
}
}
export async function fetchAndRefreshDynamicPackSet(dpsm: DynamicPackSetMeta, dpsmKey: string = DYNAMIC_PACK_SET_METAS_KEY): Promise<void> {
const _new = await fetchDynamicPackSetMeta(dpsm);
if (!_new) return;
await saveDynamicPackSetMeta(_new, dpsmKey);
}

View file

@ -138,6 +138,16 @@ export interface StickerPackMeta {
url?: string;
};
logo: Sticker;
dynamic?: DynamicStickerPackMeta["dynamic"];
}
export interface DynamicStickerPackMeta extends StickerPackMeta {
dynamic: {
version?: string;
refreshUrl: string;
authHeaders?: Record<string, string>;
};
}
export interface StickerPack extends StickerPackMeta {
@ -148,3 +158,18 @@ export interface FFmpegState {
ffmpeg?: FFmpeg;
isLoaded: boolean;
}
export interface DynamicPackSetMeta {
id: string;
version?: string;
title?: string;
author?: {
name: string;
url?: string;
};
packs: DynamicStickerPackMeta[];
refreshUrl: string;
authHeaders?: Record<string, string>;
}