Option to transform emotes/stickers in compound messages (#876)
+ ContextMenu refactor to not call callbacks for same children multiple times Co-authored-by: V <vendicated@riseup.net>
This commit is contained in:
parent
cfe41ef656
commit
e34da54271
|
@ -118,7 +118,12 @@ interface ContextMenuProps {
|
||||||
onClose: (callback: (...args: Array<any>) => any) => void;
|
onClose: (callback: (...args: Array<any>) => any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const patchedMenus = new WeakSet();
|
||||||
|
|
||||||
export function _patchContextMenu(props: ContextMenuProps) {
|
export function _patchContextMenu(props: ContextMenuProps) {
|
||||||
|
if (patchedMenus.has(props)) return;
|
||||||
|
patchedMenus.add(props);
|
||||||
|
|
||||||
props.contextMenuApiArguments ??= [];
|
props.contextMenuApiArguments ??= [];
|
||||||
const contextMenuPatches = navPatches.get(props.navId);
|
const contextMenuPatches = navPatches.get(props.navId);
|
||||||
|
|
||||||
|
|
|
@ -238,8 +238,6 @@ function initWs(isManual = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const contextMenuPatch: NavContextMenuPatchCallback = kids => {
|
const contextMenuPatch: NavContextMenuPatchCallback = kids => {
|
||||||
if (kids.some(k => k?.props?.id === NAV_ID)) return;
|
|
||||||
|
|
||||||
kids.unshift(
|
kids.unshift(
|
||||||
<Menu.MenuItem
|
<Menu.MenuItem
|
||||||
id={NAV_ID}
|
id={NAV_ID}
|
||||||
|
|
|
@ -220,8 +220,7 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) =
|
||||||
const name = match[1] ?? "FakeNitroEmoji";
|
const name = match[1] ?? "FakeNitroEmoji";
|
||||||
|
|
||||||
const group = findGroupChildrenByChildId("copy-link", children);
|
const group = findGroupChildrenByChildId("copy-link", children);
|
||||||
if (group && !group.some(child => child?.props?.id === "emote-cloner"))
|
if (group) group.push(buildMenuItem(favoriteableId, name, isGifUrl(itemHref ?? itemSrc)));
|
||||||
group.push(buildMenuItem(favoriteableId, name, isGifUrl(itemHref ?? itemSrc)));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { target: HTMLElement; }) => {
|
const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { target: HTMLElement; }) => {
|
||||||
|
@ -230,8 +229,7 @@ const expressionPickerPatch: NavContextMenuPatchCallback = (children, props: { t
|
||||||
|
|
||||||
const firstChild = props.target.firstChild as HTMLImageElement;
|
const firstChild = props.target.firstChild as HTMLImageElement;
|
||||||
|
|
||||||
if (!children.some(c => c?.props?.id === "emote-cloner"))
|
children.push(buildMenuItem(id, name, firstChild && isGifUrl(firstChild.src)));
|
||||||
children.push(buildMenuItem(id, name, firstChild && isGifUrl(firstChild.src)));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
|
|
|
@ -136,6 +136,11 @@ const settings = definePluginSettings({
|
||||||
default: true,
|
default: true,
|
||||||
restartNeeded: true
|
restartNeeded: true
|
||||||
},
|
},
|
||||||
|
transformCompoundSentence: {
|
||||||
|
description: "Whether to transform fake stickers and emojis in compound sentences (sentences with more content than just the fake emoji or sticker link)",
|
||||||
|
type: OptionType.BOOLEAN,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
enableStreamQualityBypass: {
|
enableStreamQualityBypass: {
|
||||||
description: "Allow streaming in nitro quality",
|
description: "Allow streaming in nitro quality",
|
||||||
type: OptionType.BOOLEAN,
|
type: OptionType.BOOLEAN,
|
||||||
|
@ -305,45 +310,6 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
options: {
|
|
||||||
enableEmojiBypass: {
|
|
||||||
description: "Allow sending fake emojis",
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
default: true,
|
|
||||||
restartNeeded: true,
|
|
||||||
},
|
|
||||||
emojiSize: {
|
|
||||||
description: "Size of the emojis when sending",
|
|
||||||
type: OptionType.SLIDER,
|
|
||||||
default: 48,
|
|
||||||
markers: [32, 48, 64, 128, 160, 256, 512],
|
|
||||||
},
|
|
||||||
transformEmojis: {
|
|
||||||
description: "Whether to transform fake emojis into real ones",
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
default: true,
|
|
||||||
restartNeeded: true,
|
|
||||||
},
|
|
||||||
enableStickerBypass: {
|
|
||||||
description: "Allow sending fake stickers",
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
default: true,
|
|
||||||
restartNeeded: true,
|
|
||||||
},
|
|
||||||
stickerSize: {
|
|
||||||
description: "Size of the stickers when sending",
|
|
||||||
type: OptionType.SLIDER,
|
|
||||||
default: 160,
|
|
||||||
markers: [32, 64, 128, 160, 256, 512],
|
|
||||||
},
|
|
||||||
enableStreamQualityBypass: {
|
|
||||||
description: "Allow streaming in nitro quality",
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
default: true,
|
|
||||||
restartNeeded: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
get guildId() {
|
get guildId() {
|
||||||
return getCurrentGuild()?.id;
|
return getCurrentGuild()?.id;
|
||||||
},
|
},
|
||||||
|
@ -419,7 +385,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
patchFakeNitroEmojisOrRemoveStickersLinks(content: Array<any>, inline: boolean) {
|
patchFakeNitroEmojisOrRemoveStickersLinks(content: Array<any>, inline: boolean) {
|
||||||
if (content.length > 1) return content;
|
if (content.length > 1 && !settings.store.transformCompoundSentence) return content;
|
||||||
|
|
||||||
const newContent: Array<any> = [];
|
const newContent: Array<any> = [];
|
||||||
|
|
||||||
|
@ -442,7 +408,7 @@ export default definePlugin({
|
||||||
const emojiName = EmojiStore.getCustomEmojiById(fakeNitroMatch[1])?.name ?? url?.searchParams.get("name") ?? "FakeNitroEmoji";
|
const emojiName = EmojiStore.getCustomEmojiById(fakeNitroMatch[1])?.name ?? url?.searchParams.get("name") ?? "FakeNitroEmoji";
|
||||||
|
|
||||||
newContent.push(Parser.defaultRules.customEmoji.react({
|
newContent.push(Parser.defaultRules.customEmoji.react({
|
||||||
jumboable: !inline,
|
jumboable: !inline && content.length === 1,
|
||||||
animated: fakeNitroMatch[2] === "gif",
|
animated: fakeNitroMatch[2] === "gif",
|
||||||
emojiId: fakeNitroMatch[1],
|
emojiId: fakeNitroMatch[1],
|
||||||
name: emojiName,
|
name: emojiName,
|
||||||
|
@ -466,8 +432,8 @@ export default definePlugin({
|
||||||
newContent.push(element);
|
newContent.push(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstTextElementIdx = newContent.findIndex(element => typeof element === "string");
|
const firstContent = newContent[0];
|
||||||
if (firstTextElementIdx !== -1) newContent[firstTextElementIdx] = newContent[firstTextElementIdx].trimStart();
|
if (typeof firstContent === "string") newContent[0] = firstContent.trimStart();
|
||||||
|
|
||||||
return newContent;
|
return newContent;
|
||||||
},
|
},
|
||||||
|
@ -476,7 +442,8 @@ export default definePlugin({
|
||||||
const itemsToMaybePush: Array<string> = [];
|
const itemsToMaybePush: Array<string> = [];
|
||||||
|
|
||||||
const contentItems = message.content.split(/\s/);
|
const contentItems = message.content.split(/\s/);
|
||||||
if (contentItems.length === 1) itemsToMaybePush.push(contentItems[0]);
|
if (contentItems.length === 1 && !settings.store.transformCompoundSentence) itemsToMaybePush.push(contentItems[0]);
|
||||||
|
else itemsToMaybePush.push(...contentItems);
|
||||||
|
|
||||||
itemsToMaybePush.push(...message.attachments.filter(attachment => attachment.content_type === "image/gif").map(attachment => attachment.url));
|
itemsToMaybePush.push(...message.attachments.filter(attachment => attachment.content_type === "image/gif").map(attachment => attachment.url));
|
||||||
|
|
||||||
|
@ -517,7 +484,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
|
|
||||||
shouldIgnoreEmbed(embed: Message["embeds"][number], message: Message) {
|
shouldIgnoreEmbed(embed: Message["embeds"][number], message: Message) {
|
||||||
if (message.content.split(/\s/).length > 1) return false;
|
if (message.content.split(/\s/).length > 1 && !settings.store.transformCompoundSentence) return false;
|
||||||
|
|
||||||
switch (embed.type) {
|
switch (embed.type) {
|
||||||
case "image": {
|
case "image": {
|
||||||
|
|
|
@ -76,56 +76,54 @@ export const settings = definePluginSettings({
|
||||||
|
|
||||||
|
|
||||||
const imageContextMenuPatch: NavContextMenuPatchCallback = (children, _) => {
|
const imageContextMenuPatch: NavContextMenuPatchCallback = (children, _) => {
|
||||||
if (!children.some(child => child?.props?.id === "image-zoom")) {
|
children.push(
|
||||||
children.push(
|
<Menu.MenuGroup id="image-zoom">
|
||||||
<Menu.MenuGroup id="image-zoom">
|
{/* thanks SpotifyControls */}
|
||||||
{/* thanks SpotifyControls */}
|
<Menu.MenuControlItem
|
||||||
<Menu.MenuControlItem
|
id="zoom"
|
||||||
id="zoom"
|
label="Zoom"
|
||||||
label="Zoom"
|
control={(props, ref) => (
|
||||||
control={(props, ref) => (
|
<Menu.MenuSliderControl
|
||||||
<Menu.MenuSliderControl
|
ref={ref}
|
||||||
ref={ref}
|
{...props}
|
||||||
{...props}
|
minValue={1}
|
||||||
minValue={1}
|
maxValue={50}
|
||||||
maxValue={50}
|
value={settings.store.zoom}
|
||||||
value={settings.store.zoom}
|
onChange={debounce((value: number) => settings.store.zoom = value, 100)}
|
||||||
onChange={debounce((value: number) => settings.store.zoom = value, 100)}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
<Menu.MenuControlItem
|
||||||
<Menu.MenuControlItem
|
id="size"
|
||||||
id="size"
|
label="Lens Size"
|
||||||
label="Lens Size"
|
control={(props, ref) => (
|
||||||
control={(props, ref) => (
|
<Menu.MenuSliderControl
|
||||||
<Menu.MenuSliderControl
|
ref={ref}
|
||||||
ref={ref}
|
{...props}
|
||||||
{...props}
|
minValue={50}
|
||||||
minValue={50}
|
maxValue={1000}
|
||||||
maxValue={1000}
|
value={settings.store.size}
|
||||||
value={settings.store.size}
|
onChange={debounce((value: number) => settings.store.size = value, 100)}
|
||||||
onChange={debounce((value: number) => settings.store.size = value, 100)}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
<Menu.MenuControlItem
|
||||||
<Menu.MenuControlItem
|
id="zoom-speed"
|
||||||
id="zoom-speed"
|
label="Zoom Speed"
|
||||||
label="Zoom Speed"
|
control={(props, ref) => (
|
||||||
control={(props, ref) => (
|
<Menu.MenuSliderControl
|
||||||
<Menu.MenuSliderControl
|
ref={ref}
|
||||||
ref={ref}
|
{...props}
|
||||||
{...props}
|
minValue={0.1}
|
||||||
minValue={0.1}
|
maxValue={5}
|
||||||
maxValue={5}
|
value={settings.store.zoomSpeed}
|
||||||
value={settings.store.zoomSpeed}
|
onChange={debounce((value: number) => settings.store.zoomSpeed = value, 100)}
|
||||||
onChange={debounce((value: number) => settings.store.zoomSpeed = value, 100)}
|
renderValue={(value: number) => `${value.toFixed(3)}x`}
|
||||||
renderValue={(value: number) => `${value.toFixed(3)}x`}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
</Menu.MenuGroup>
|
||||||
</Menu.MenuGroup>
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
|
|
|
@ -49,7 +49,6 @@ const patchMessageContextMenu: NavContextMenuPatchCallback = (children, props) =
|
||||||
const { deleted, editHistory, id, channel_id } = message;
|
const { deleted, editHistory, id, channel_id } = message;
|
||||||
|
|
||||||
if (!deleted && !editHistory?.length) return;
|
if (!deleted && !editHistory?.length) return;
|
||||||
if (children.some(c => c?.props?.id === MENU_ITEM_ID)) return;
|
|
||||||
|
|
||||||
children.push((
|
children.push((
|
||||||
<Menu.MenuItem
|
<Menu.MenuItem
|
||||||
|
|
|
@ -35,7 +35,7 @@ const bulkFetch = debounce(async () => {
|
||||||
const pronouns = await bulkFetchPronouns(ids);
|
const pronouns = await bulkFetchPronouns(ids);
|
||||||
for (const id of ids) {
|
for (const id of ids) {
|
||||||
// Call all callbacks for the id
|
// Call all callbacks for the id
|
||||||
requestQueue[id].forEach(c => c(pronouns[id]));
|
requestQueue[id]?.forEach(c => c(pronouns[id]));
|
||||||
delete requestQueue[id];
|
delete requestQueue[id];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -43,7 +43,7 @@ const imageContextMenuPatch: NavContextMenuPatchCallback = (children, props) =>
|
||||||
const src = itemHref ?? itemSrc;
|
const src = itemHref ?? itemSrc;
|
||||||
|
|
||||||
const group = findGroupChildrenByChildId("copy-link", children);
|
const group = findGroupChildrenByChildId("copy-link", children);
|
||||||
if (group && !group.some(child => child?.props?.id === "search-image")) {
|
if (group) {
|
||||||
group.push((
|
group.push((
|
||||||
<Menu.MenuItem
|
<Menu.MenuItem
|
||||||
label="Search Image"
|
label="Search Image"
|
||||||
|
|
|
@ -80,12 +80,7 @@ function openImage(url: string) {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
const seen = new WeakSet();
|
|
||||||
|
|
||||||
const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: UserContextProps) => {
|
const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: UserContextProps) => {
|
||||||
if (seen.has(children)) return;
|
|
||||||
seen.add(children);
|
|
||||||
|
|
||||||
const memberAvatar = GuildMemberStore.getMember(guildId!, user.id)?.avatar || null;
|
const memberAvatar = GuildMemberStore.getMember(guildId!, user.id)?.avatar || null;
|
||||||
|
|
||||||
children.splice(1, 0, (
|
children.splice(1, 0, (
|
||||||
|
@ -111,9 +106,6 @@ const UserContext: NavContextMenuPatchCallback = (children, { user, guildId }: U
|
||||||
};
|
};
|
||||||
|
|
||||||
const GuildContext: NavContextMenuPatchCallback = (children, { guild: { id, icon, banner } }: GuildContextProps) => {
|
const GuildContext: NavContextMenuPatchCallback = (children, { guild: { id, icon, banner } }: GuildContextProps) => {
|
||||||
if (seen.has(children)) return;
|
|
||||||
seen.add(children);
|
|
||||||
|
|
||||||
if (!banner && !icon) return;
|
if (!banner && !icon) return;
|
||||||
|
|
||||||
// before copy id (if it exists)
|
// before copy id (if it exists)
|
||||||
|
|
Loading…
Reference in a new issue