Merge remote-tracking branch 'upstream/dev' into dev
This commit is contained in:
commit
d7a841f1b3
16 changed files with 129 additions and 294 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "equicord",
|
"name": "equicord",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"version": "1.14.11.0",
|
"version": "1.14.12.0",
|
||||||
"description": "The other cutest Discord client mod",
|
"description": "The other cutest Discord client mod",
|
||||||
"homepage": "https://github.com/Equicord/Equicord#readme",
|
"homepage": "https://github.com/Equicord/Equicord#readme",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ErrorBoundary from "@components/ErrorBoundary";
|
import ErrorBoundary from "@components/ErrorBoundary";
|
||||||
|
import { Logger } from "@utils/Logger";
|
||||||
import { JSX, ReactNode } from "react";
|
import { JSX, ReactNode } from "react";
|
||||||
|
|
||||||
export type MessageAccessoryFactory = (props: Record<string, any>) => ReactNode;
|
export type MessageAccessoryFactory = (props: Record<string, any>) => ReactNode;
|
||||||
|
|
@ -46,23 +47,28 @@ export function _modifyAccessories(
|
||||||
elements: JSX.Element[],
|
elements: JSX.Element[],
|
||||||
props: Record<string, any>
|
props: Record<string, any>
|
||||||
) {
|
) {
|
||||||
for (const [key, accessory] of accessories.entries()) {
|
try {
|
||||||
const res = (
|
for (const [key, accessory] of accessories.entries()) {
|
||||||
<ErrorBoundary noop message={`Failed to render ${key} Message Accessory`} key={key}>
|
const res = (
|
||||||
<accessory.render {...props} />
|
<ErrorBoundary noop message={`Failed to render ${key} Message Accessory`} key={key}>
|
||||||
</ErrorBoundary>
|
<accessory.render {...props} />
|
||||||
);
|
</ErrorBoundary>
|
||||||
|
);
|
||||||
|
|
||||||
elements.splice(
|
elements.splice(
|
||||||
accessory.position != null
|
accessory.position != null
|
||||||
? accessory.position < 0
|
? accessory.position < 0
|
||||||
? elements.length + accessory.position
|
? elements.length + accessory.position
|
||||||
: accessory.position
|
: accessory.position
|
||||||
: elements.length,
|
: elements.length,
|
||||||
0,
|
0,
|
||||||
res
|
res
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
} catch (e) {
|
||||||
|
new Logger("MessageAccessories").error("Failed to modify message accessories", e);
|
||||||
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
return elements;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ export default definePlugin({
|
||||||
find: "#{intl::REMOVE_ATTACHMENT_BODY}",
|
find: "#{intl::REMOVE_ATTACHMENT_BODY}",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /children:(\[[^\]]{0,100}?this.renderSuppressConfirmModal[^\]]{0,100}?\])/,
|
match: /children:(\[[^\]]{0,100}?this.renderSuppressConfirmModal[^\]]{0,100}?\])/,
|
||||||
replace: "children:Vencord.Api.MessageAccessories._modifyAccessories($1,this.props)",
|
replace: "children:Vencord.Api.MessageAccessories._modifyAccessories($1,this?.props)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ export default definePlugin({
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
match: /(\.renderReactions\(\i\).+?className:)/,
|
match: /(\.renderReactions\(\i\).+?className:)/,
|
||||||
replace: '$&(this.props?.channel?.nsfw || $self.settings.store.blurAllChannels ? "vc-nsfw-img ": "")+'
|
replace: '$&(this?.props?.channel?.nsfw || $self.settings.store.blurAllChannels ? "vc-nsfw-img ": "")+'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ export default definePlugin({
|
||||||
find: "renderConnectionStatus(){",
|
find: "renderConnectionStatus(){",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(renderConnectionStatus\(\).{0,1000}?lineClamp:1,children:)(\i)(?=,|}\))/,
|
match: /(renderConnectionStatus\(\).{0,1000}?lineClamp:1,children:)(\i)(?=,|}\))/,
|
||||||
replace: "$1[$2,$self.renderConnectionTimer(this.props?.channel?.id)]"
|
replace: "$1[$2,$self.renderTimer({ channelId: this?.props?.channel?.id })]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -270,11 +270,15 @@ export default definePlugin({
|
||||||
</ErrorBoundary>;
|
</ErrorBoundary>;
|
||||||
},
|
},
|
||||||
|
|
||||||
ConnectionTimer({ channelId }: { channelId: string; }) {
|
ConnectionTimer: ErrorBoundary.wrap(({ channelId }: { channelId: string; }) => {
|
||||||
const time = useTimer({
|
const time = useTimer({
|
||||||
deps: [channelId]
|
deps: [channelId]
|
||||||
});
|
});
|
||||||
|
|
||||||
return <p style={{ margin: 0, fontFamily: "var(--font-code)" }}>{formatDurationMs(time, settings.store.format === "human")}</p>;
|
return (
|
||||||
}
|
<p style={{ margin: 0, fontFamily: "var(--font-code)" }}>
|
||||||
|
{formatDurationMs(time, settings.store.format === "human")}
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}, { noop: true }),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ export default definePlugin({
|
||||||
// https://regex101.com/r/07gpzP/1
|
// https://regex101.com/r/07gpzP/1
|
||||||
// ($1 renderHeaderContent=function { ... switch (x) ... case FAVORITES:return) ($2) ($3 case default: ... return r.jsx(($<searchComp>), {...props}))
|
// ($1 renderHeaderContent=function { ... switch (x) ... case FAVORITES:return) ($2) ($3 case default: ... return r.jsx(($<searchComp>), {...props}))
|
||||||
match: /(renderHeaderContent\(\).{1,150}FAVORITES:return)(.{1,150});(case.{1,200}default:.{0,50}?return\(0,\i\.jsx\)\((?<searchComp>\i\.\i),)/,
|
match: /(renderHeaderContent\(\).{1,150}FAVORITES:return)(.{1,150});(case.{1,200}default:.{0,50}?return\(0,\i\.jsx\)\((?<searchComp>\i\.\i),)/,
|
||||||
replace: "$1 this.state.resultType === 'Favorites' ? $self.renderSearchBar(this, $<searchComp>) : $2;$3"
|
replace: "$1 this?.state?.resultType === 'Favorites' ? $self.renderSearchBar(this, $<searchComp>) : $2;$3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// to persist filtered favorites when component re-renders.
|
// to persist filtered favorites when component re-renders.
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export default definePlugin({
|
||||||
find: ".handleImageLoad)",
|
find: ".handleImageLoad)",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /getSrc\(\i\)\{/,
|
match: /getSrc\(\i\)\{/,
|
||||||
replace: "$&var _vcSrc=$self.getSrc(this.props,arguments[1]);if(_vcSrc)return _vcSrc;"
|
replace: "$&var _vcSrc=$self.getSrc(this?.props,arguments[1]);if(_vcSrc)return _vcSrc;"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export default definePlugin({
|
||||||
find: "handleSelectGIF=",
|
find: "handleSelectGIF=",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /handleSelectGIF=(\i)=>\{/,
|
match: /handleSelectGIF=(\i)=>\{/,
|
||||||
replace: "$&if (!this.props.className) return $self.handleSelect($1);"
|
replace: "$&if (!this?.props?.className) return $self.handleSelect($1);"
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* Vencord, a Discord client mod
|
|
||||||
* Copyright (c) 2023 Vendicated and contributors
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { definePluginSettings } from "@api/Settings";
|
|
||||||
import { Devs } from "@utils/constants";
|
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
|
||||||
inlineVideo: {
|
|
||||||
description: "Play videos without carousel modal",
|
|
||||||
type: OptionType.BOOLEAN,
|
|
||||||
default: true,
|
|
||||||
restartNeeded: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export default definePlugin({
|
|
||||||
name: "NoMosaic",
|
|
||||||
authors: [Devs.AutumnVN],
|
|
||||||
description: "Removes Discord image mosaic",
|
|
||||||
tags: ["Media", "Appearance", "Chat"],
|
|
||||||
searchTerms: ["image", "mosaic", "media"],
|
|
||||||
|
|
||||||
settings,
|
|
||||||
|
|
||||||
patches: [
|
|
||||||
{
|
|
||||||
find: '"PLAINTEXT_PREVIEW":"OTHER"',
|
|
||||||
replacement: {
|
|
||||||
match: /"IMAGE"===\i\|\|"VIDEO"===\i\|\|"CLIP"===\i/,
|
|
||||||
replace: "false"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
find: "renderAttachments(",
|
|
||||||
predicate: () => settings.store.inlineVideo,
|
|
||||||
replacement: {
|
|
||||||
match: /url:(\i)\.url\}\);return /,
|
|
||||||
replace: "$&$1.content_type?.startsWith('image/')&&"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
@ -30,7 +30,7 @@ export default definePlugin({
|
||||||
find: "hasThemeColors(){",
|
find: "hasThemeColors(){",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /get canUsePremiumProfileCustomization\(\){return /,
|
match: /get canUsePremiumProfileCustomization\(\){return /,
|
||||||
replace: "$&$self.isCurrentUser(this.userId)&&"
|
replace: "$&$self.isCurrentUser(this?.userId)&&"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -251,9 +251,6 @@ function RoleContextMenu({ guild, roleId, onClose }: { guild: Guild; roleId: str
|
||||||
label={getIntlMessage("VIEW_AS_ROLE")}
|
label={getIntlMessage("VIEW_AS_ROLE")}
|
||||||
icon={ViewAsRoleIcon}
|
icon={ViewAsRoleIcon}
|
||||||
action={() => {
|
action={() => {
|
||||||
const role = GuildRoleStore.getRole(guild.id, roleId);
|
|
||||||
if (!role) return;
|
|
||||||
|
|
||||||
onClose();
|
onClose();
|
||||||
FluxDispatcher.dispatch({
|
FluxDispatcher.dispatch({
|
||||||
type: "IMPERSONATE_UPDATE",
|
type: "IMPERSONATE_UPDATE",
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
// Override scrollToChannel to properly account for pinned channels
|
// Override scrollToChannel to properly account for pinned channels
|
||||||
match: /(?<=scrollTo\(\{to:\i\}\):\(\i\+=)(\d+)\*\(.+?(?=,)/,
|
match: /(?<=scrollTo\(\{to:\i\}\):\(\i\+=)(\d+)\*\(.+?(?=,)/,
|
||||||
replace: "$self.getScrollOffset(arguments[0],$1,this.props.padding,this.state.preRenderedChildren,$&)"
|
replace: "$self.getScrollOffset(arguments[0],$1,this?.props?.padding,this?.state?.preRenderedChildren,$&)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
match: /(scrollToChannel\(\i\){.{1,300})(this\.props\.privateChannelIds)/,
|
match: /(scrollToChannel\(\i\){.{1,300})(this\.props\.privateChannelIds)/,
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,7 @@ export default definePlugin({
|
||||||
"renderInviteButton",
|
"renderInviteButton",
|
||||||
].map(func => ({
|
].map(func => ({
|
||||||
match: new RegExp(`(?<=${func}\\(\\){)`, "g"), // Global because Discord has multiple declarations of the same functions
|
match: new RegExp(`(?<=${func}\\(\\){)`, "g"), // Global because Discord has multiple declarations of the same functions
|
||||||
replace: "if($self.isHiddenChannel(this.props.channel))return null;"
|
replace: "if($self.isHiddenChannel(this?.props?.channel))return null;"
|
||||||
}))
|
}))
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -161,7 +161,7 @@ export default definePlugin({
|
||||||
// Render null instead of the buttons if the channel is hidden
|
// Render null instead of the buttons if the channel is hidden
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(?<=renderOpenChatButton(?:",|=)\(\)=>{)/,
|
match: /(?<=renderOpenChatButton(?:",|=)\(\)=>{)/,
|
||||||
replace: "if($self.isHiddenChannel(this.props.channel))return null;"
|
replace: "if($self.isHiddenChannel(this?.props?.channel))return null;"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -268,11 +268,11 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
match: /(?<=renderSidebar\(\){)/,
|
match: /(?<=renderSidebar\(\){)/,
|
||||||
replace: "if($self.isHiddenChannel(this.props.channel))return null;"
|
replace: "if($self.isHiddenChannel(this?.props?.channel))return null;"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
match: /(?<=renderChat\(\){)/,
|
match: /(?<=renderChat\(\){)/,
|
||||||
replace: "if($self.isHiddenChannel(this.props.channel))return $self.HiddenChannelLockScreen(this.props.channel);"
|
replace: "if($self.isHiddenChannel(this?.props?.channel))return $self.HiddenChannelLockScreen(this?.props?.channel);"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -378,22 +378,22 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
// Render our HiddenChannelLockScreen component instead of the main voice channel component
|
// Render our HiddenChannelLockScreen component instead of the main voice channel component
|
||||||
match: /renderContent\(\i\){.+?this\.renderVoiceChannelEffects.+?children:/,
|
match: /renderContent\(\i\){.+?this\.renderVoiceChannelEffects.+?children:/,
|
||||||
replace: "$&!this.props.inCall&&$self.isHiddenChannel(this.props.channel,true)?$self.HiddenChannelLockScreen(this.props.channel):"
|
replace: "$&!this?.props?.inCall&&$self.isHiddenChannel(this?.props?.channel,true)?$self.HiddenChannelLockScreen(this?.props?.channel):"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Disable gradients for the HiddenChannelLockScreen of voice channels
|
// Disable gradients for the HiddenChannelLockScreen of voice channels
|
||||||
match: /renderContent\(\i\){.+?disableGradients:/,
|
match: /renderContent\(\i\){.+?disableGradients:/,
|
||||||
replace: "$&!this.props.inCall&&$self.isHiddenChannel(this.props.channel,true)||"
|
replace: "$&!this?.props?.inCall&&$self.isHiddenChannel(this?.props?.channel,true)||"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Disable useless components for the HiddenChannelLockScreen of voice channels
|
// Disable useless components for the HiddenChannelLockScreen of voice channels
|
||||||
match: /(?:{|,)render(?!Header|ExternalHeader).{0,30}?:/g,
|
match: /(?:{|,)render(?!Header|ExternalHeader).{0,30}?:/g,
|
||||||
replace: "$&!this.props.inCall&&$self.isHiddenChannel(this.props.channel,true)?()=>null:"
|
replace: "$&!this?.props?.inCall&&$self.isHiddenChannel(this?.props?.channel,true)?()=>null:"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Disable bad CSS class which mess up hidden voice channels styling
|
// Disable bad CSS class which mess up hidden voice channels styling
|
||||||
match: /(?=\i\|\|\i!==\i\.\i\.FULL_SCREEN.{0,100}?this\._callContainerRef)/,
|
match: /(?=\i\|\|\i!==\i\.\i\.FULL_SCREEN.{0,100}?this\._callContainerRef)/,
|
||||||
replace: '$&!this.props.inCall&&$self.isHiddenChannel(this.props.channel,true)?"":'
|
replace: '$&!this?.props?.inCall&&$self.isHiddenChannel(this?.props?.channel,true)?"":'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ export default definePlugin({
|
||||||
find: ".tabBarRef",
|
find: ".tabBarRef",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /style:this\.getStyle\(\),role:"tab"/,
|
match: /style:this\.getStyle\(\),role:"tab"/,
|
||||||
replace: "$&,'data-tab-id':this.props.id"
|
replace: "$&,'data-tab-id':this?.props?.id"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ export default definePlugin({
|
||||||
],
|
],
|
||||||
|
|
||||||
getAvatarStyles(src: string | null) {
|
getAvatarStyles(src: string | null) {
|
||||||
if (!src || src.startsWith("data:")) return {};
|
if (typeof src !== "string" || src.startsWith("data:")) return {};
|
||||||
|
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
[128, 256, 512, 1024, 2048, 4096].map(size => [
|
[128, 256, 512, 1024, 2048, 4096].map(size => [
|
||||||
|
|
|
||||||
|
|
@ -322,9 +322,9 @@ export function deeplLanguageToGoogleLanguage(language: string) {
|
||||||
|
|
||||||
// Generated using:
|
// Generated using:
|
||||||
// curl https://translate.kagi.com/api/list-languages | jq 'map({(.language | ascii_downcase): .name}) | add | to_entries | sort_by(.value) | from_entries'
|
// curl https://translate.kagi.com/api/list-languages | jq 'map({(.language | ascii_downcase): .name}) | add | to_entries | sort_by(.value) | from_entries'
|
||||||
// Add "auto": "Detect language", as kagi has no "language" for Detect Language, however anything not
|
// Add "auto": "Detect language", as Kagi has no "language" for Detect Language, however anything not
|
||||||
// in the list will work as auto. Using "auto" will have this work using Google Translate defaults.
|
// in the list will work as auto. Using "auto" will have this work using Google Translate defaults.
|
||||||
// Retrieved 2025.06.16
|
// Retrieved 2026-05-02. Meme languages and redundant entries removed.
|
||||||
export const KagiLanguages = {
|
export const KagiLanguages = {
|
||||||
"auto": "Detect language",
|
"auto": "Detect language",
|
||||||
"om": "(Afan)/Oromoor/Oriya",
|
"om": "(Afan)/Oromoor/Oriya",
|
||||||
|
|
@ -338,19 +338,6 @@ export const KagiLanguages = {
|
||||||
"alz": "Alur",
|
"alz": "Alur",
|
||||||
"am": "Amharic",
|
"am": "Amharic",
|
||||||
"ar": "Arabic",
|
"ar": "Arabic",
|
||||||
"ar_dz": "Arabic (Algeria)",
|
|
||||||
"ar_eg": "Arabic (Egypt)",
|
|
||||||
"ar_iq": "Arabic (Iraq)",
|
|
||||||
"ar_jo": "Arabic (Jordan)",
|
|
||||||
"ar_kw": "Arabic (Kuwait)",
|
|
||||||
"ar_lb": "Arabic (Lebanon)",
|
|
||||||
"ar_ly": "Arabic (Libya)",
|
|
||||||
"ar_ma": "Arabic (Morocco)",
|
|
||||||
"ar_qa": "Arabic (Qatar)",
|
|
||||||
"ar_sa": "Arabic (Saudi Arabia)",
|
|
||||||
"ar_sy": "Arabic (Syria)",
|
|
||||||
"ar_tn": "Arabic (Tunisia)",
|
|
||||||
"ar_ae": "Arabic (UAE)",
|
|
||||||
"an": "Aragonese",
|
"an": "Aragonese",
|
||||||
"hy": "Armenian",
|
"hy": "Armenian",
|
||||||
"as": "Assamese",
|
"as": "Assamese",
|
||||||
|
|
@ -358,7 +345,7 @@ export const KagiLanguages = {
|
||||||
"ae": "Avestan",
|
"ae": "Avestan",
|
||||||
"ava": "Awadhi",
|
"ava": "Awadhi",
|
||||||
"ay": "Aymara",
|
"ay": "Aymara",
|
||||||
"az": "Azeri",
|
"az": "Azerbaijani",
|
||||||
"ban": "Balinese",
|
"ban": "Balinese",
|
||||||
"bal": "Baluchi",
|
"bal": "Baluchi",
|
||||||
"bm": "Bambara",
|
"bm": "Bambara",
|
||||||
|
|
@ -366,11 +353,10 @@ export const KagiLanguages = {
|
||||||
"ba": "Bashkir",
|
"ba": "Bashkir",
|
||||||
"eu": "Basque",
|
"eu": "Basque",
|
||||||
"btk": "Batak",
|
"btk": "Batak",
|
||||||
|
"bar": "Bavarian",
|
||||||
"be": "Belarusian",
|
"be": "Belarusian",
|
||||||
"bem": "Bemba",
|
"bem": "Bemba",
|
||||||
"bn": "Bengali",
|
"bn": "Bengali",
|
||||||
"bn_bd": "Bengali (Bangladesh)",
|
|
||||||
"bn_in": "Bengali (India)",
|
|
||||||
"bew": "Betawi",
|
"bew": "Betawi",
|
||||||
"bho": "Bhojpuri",
|
"bho": "Bhojpuri",
|
||||||
"dz": "Bhutani",
|
"dz": "Bhutani",
|
||||||
|
|
@ -390,11 +376,7 @@ export const KagiLanguages = {
|
||||||
"ce": "Chechen",
|
"ce": "Chechen",
|
||||||
"chr": "Cherokee",
|
"chr": "Cherokee",
|
||||||
"ny": "Chichewa",
|
"ny": "Chichewa",
|
||||||
"zh": "Chinese",
|
|
||||||
"zh_hk": "Chinese (Hong Kong)",
|
|
||||||
"zh_mo": "Chinese (Macau)",
|
|
||||||
"zh_cn": "Chinese (Simplified)",
|
"zh_cn": "Chinese (Simplified)",
|
||||||
"zh_sg": "Chinese (Singapore)",
|
|
||||||
"zh_tw": "Chinese (Traditional)",
|
"zh_tw": "Chinese (Traditional)",
|
||||||
"cu": "Church Slavonic",
|
"cu": "Church Slavonic",
|
||||||
"chk": "Chuukese",
|
"chk": "Chuukese",
|
||||||
|
|
@ -404,65 +386,34 @@ export const KagiLanguages = {
|
||||||
"cr": "Cree",
|
"cr": "Cree",
|
||||||
"crh": "Crimean Tatar",
|
"crh": "Crimean Tatar",
|
||||||
"hr": "Croatian",
|
"hr": "Croatian",
|
||||||
"hr_ba": "Croatian (Bosnia and Herzegovina)",
|
|
||||||
"hr_hr": "Croatian (Croatia)",
|
|
||||||
"cs": "Czech",
|
"cs": "Czech",
|
||||||
"da": "Danish",
|
"da": "Danish",
|
||||||
"din": "Dinka",
|
"din": "Dinka",
|
||||||
"div": "Divehi",
|
"div": "Divehi",
|
||||||
"dv": "Divehi",
|
|
||||||
"doi": "Dogri",
|
"doi": "Dogri",
|
||||||
"dov": "Dombe",
|
"dov": "Dombe",
|
||||||
"nl": "Dutch",
|
"nl": "Dutch",
|
||||||
"nl_aw": "Dutch (Aruba)",
|
|
||||||
"nl_be": "Dutch (Belgium)",
|
|
||||||
"nl_cw": "Dutch (Curaçao)",
|
|
||||||
"nl_nl": "Dutch (Netherlands)",
|
|
||||||
"nl_sr": "Dutch (Suriname)",
|
|
||||||
"dyu": "Dyula",
|
"dyu": "Dyula",
|
||||||
"elvish": "Elvish (Sindarin)",
|
|
||||||
"emoji": "Emoji Speak",
|
|
||||||
"en": "English",
|
|
||||||
"en_au": "English (Australia)",
|
|
||||||
"en_ca": "English (Canada)",
|
|
||||||
"en_in": "English (India)",
|
|
||||||
"en_ie": "English (Ireland)",
|
|
||||||
"en_nz": "English (New Zealand)",
|
|
||||||
"en_ph": "English (Philippines)",
|
|
||||||
"en_sg": "English (Singapore)",
|
|
||||||
"en_za": "English (South Africa)",
|
|
||||||
"en_gb": "English (UK)",
|
"en_gb": "English (UK)",
|
||||||
"en_us": "English (US)",
|
"en_us": "English (US)",
|
||||||
"eo": "Esperanto",
|
"eo": "Esperanto",
|
||||||
"et": "Estonian",
|
"et": "Estonian",
|
||||||
"ee": "Ewe",
|
"ee": "Ewe",
|
||||||
"mk": "FYRO Macedonian",
|
|
||||||
"fo": "Faroese",
|
"fo": "Faroese",
|
||||||
"fa": "Farsi",
|
|
||||||
"fj": "Fiji",
|
"fj": "Fiji",
|
||||||
"fil": "Filipino",
|
"fil": "Filipino",
|
||||||
"fi": "Finnish",
|
"fi": "Finnish",
|
||||||
"fon": "Fon",
|
"fon": "Fon",
|
||||||
"fr": "French",
|
"fr": "French",
|
||||||
"fr_be": "French (Belgium)",
|
|
||||||
"fr_ca": "French (Canada)",
|
|
||||||
"fr_ci": "French (Côte d'Ivoire)",
|
|
||||||
"fr_fr": "French (France)",
|
|
||||||
"fr_sn": "French (Senegal)",
|
|
||||||
"fr_ch": "French (Switzerland)",
|
|
||||||
"fy": "Frisian",
|
"fy": "Frisian",
|
||||||
"fur": "Friulian",
|
"fur": "Friulian",
|
||||||
"ff": "Fulah",
|
"ff": "Fulah",
|
||||||
"gaa": "Ga",
|
"gaa": "Ga",
|
||||||
"gd": "Gaelic",
|
|
||||||
"gl": "Galician",
|
"gl": "Galician",
|
||||||
"lg": "Ganda",
|
"lg": "Ganda",
|
||||||
"ka": "Georgian",
|
"ka": "Georgian",
|
||||||
"de": "German",
|
"de": "German",
|
||||||
"de_at": "German (Austria)",
|
"hac": "Gorani (Hawrami)",
|
||||||
"de_de": "German (Germany)",
|
|
||||||
"de_li": "German (Liechtenstein)",
|
|
||||||
"de_lu": "German (Luxembourg)",
|
|
||||||
"el": "Greek",
|
"el": "Greek",
|
||||||
"kl": "Greenlandic",
|
"kl": "Greenlandic",
|
||||||
"gn": "Guarani",
|
"gn": "Guarani",
|
||||||
|
|
@ -474,8 +425,6 @@ export const KagiLanguages = {
|
||||||
"hz": "Herero",
|
"hz": "Herero",
|
||||||
"hil": "Hiligaynon",
|
"hil": "Hiligaynon",
|
||||||
"hi": "Hindi",
|
"hi": "Hindi",
|
||||||
"hi_fj": "Hindi (Fiji)",
|
|
||||||
"hi_in": "Hindi (India)",
|
|
||||||
"ho": "Hiri Motu",
|
"ho": "Hiri Motu",
|
||||||
"hu": "Hungarian",
|
"hu": "Hungarian",
|
||||||
"hrx": "Hunsrik",
|
"hrx": "Hunsrik",
|
||||||
|
|
@ -489,12 +438,8 @@ export const KagiLanguages = {
|
||||||
"ie": "Interlingue",
|
"ie": "Interlingue",
|
||||||
"iu": "Inuktitut",
|
"iu": "Inuktitut",
|
||||||
"ik": "Inupiak",
|
"ik": "Inupiak",
|
||||||
"ga": "Irish",
|
"ga": "Irish Gaelic",
|
||||||
"it": "Italian",
|
"it": "Italian",
|
||||||
"it_it": "Italian (Italy)",
|
|
||||||
"it_sm": "Italian (San Marino)",
|
|
||||||
"it_ch": "Italian (Switzerland)",
|
|
||||||
"it_va": "Italian (Vatican City)",
|
|
||||||
"jam": "Jamaican Patois",
|
"jam": "Jamaican Patois",
|
||||||
"ja": "Japanese",
|
"ja": "Japanese",
|
||||||
"jv": "Javanese",
|
"jv": "Javanese",
|
||||||
|
|
@ -509,16 +454,14 @@ export const KagiLanguages = {
|
||||||
"ky": "Kirghiz",
|
"ky": "Kirghiz",
|
||||||
"rn": "Kirundi",
|
"rn": "Kirundi",
|
||||||
"ktu": "Kituba",
|
"ktu": "Kituba",
|
||||||
"klingon": "Klingon",
|
|
||||||
"kv": "Komi",
|
"kv": "Komi",
|
||||||
"kg": "Kongo",
|
"kg": "Kongo",
|
||||||
"kok": "Konkani",
|
"kok": "Konkani",
|
||||||
"ko": "Korean",
|
"ko": "Korean",
|
||||||
"ko_kp": "Korean (North Korea)",
|
|
||||||
"ko_kr": "Korean (South Korea)",
|
|
||||||
"kj": "Kuanyama",
|
"kj": "Kuanyama",
|
||||||
"ku": "Kurdish",
|
"ku": "Kurdish (Kurmanji)",
|
||||||
"ckb": "Kurdish (Sorani)",
|
"ckb": "Kurdish (Sorani)",
|
||||||
|
"sdh": "Kurdish (Xwarin)",
|
||||||
"lo": "Laothian",
|
"lo": "Laothian",
|
||||||
"ltg": "Latgalian",
|
"ltg": "Latgalian",
|
||||||
"la": "Latin",
|
"la": "Latin",
|
||||||
|
|
@ -532,26 +475,22 @@ export const KagiLanguages = {
|
||||||
"lu": "Luba_Katanga",
|
"lu": "Luba_Katanga",
|
||||||
"luo": "Luo",
|
"luo": "Luo",
|
||||||
"lb": "Luxembourgish",
|
"lb": "Luxembourgish",
|
||||||
|
"mk": "Macedonian",
|
||||||
"mad": "Madurese",
|
"mad": "Madurese",
|
||||||
"mai": "Maithili",
|
"mai": "Maithili",
|
||||||
"mak": "Makassar",
|
"mak": "Makassar",
|
||||||
"mg": "Malagasy",
|
"mg": "Malagasy",
|
||||||
"ms": "Malay",
|
"ms": "Malay",
|
||||||
"ms_bn": "Malay (Brunei Darussalam)",
|
|
||||||
"ms_id": "Malay (Indonesia)",
|
|
||||||
"ms_arab": "Malay (Jawi)",
|
|
||||||
"ms_my": "Malay (Malaysia)",
|
|
||||||
"ms_sg": "Malay (Singapore)",
|
|
||||||
"ml": "Malayalam",
|
"ml": "Malayalam",
|
||||||
"mt": "Maltese",
|
"mt": "Maltese",
|
||||||
"gv": "Manx",
|
"gv": "Manx Gaelic",
|
||||||
"mi": "Maori",
|
"mi": "Maori",
|
||||||
"mr": "Marathi",
|
"mr": "Marathi",
|
||||||
"mh": "Marshallese",
|
"mh": "Marshallese",
|
||||||
"mwr": "Marwadi",
|
"mwr": "Marwadi",
|
||||||
"middle_english": "Middle English",
|
|
||||||
"mo": "Moldavian",
|
"mo": "Moldavian",
|
||||||
"mn": "Mongolian",
|
"mn": "Mongolian",
|
||||||
|
"cnr": "Montenegrin",
|
||||||
"nqo": "NKo",
|
"nqo": "NKo",
|
||||||
"nhe": "Nahuatl",
|
"nhe": "Nahuatl",
|
||||||
"na": "Nauru",
|
"na": "Nauru",
|
||||||
|
|
@ -561,7 +500,9 @@ export const KagiLanguages = {
|
||||||
"new": "Nepalbhasa",
|
"new": "Nepalbhasa",
|
||||||
"ne": "Nepali",
|
"ne": "Nepali",
|
||||||
"nd": "North Ndebele",
|
"nd": "North Ndebele",
|
||||||
|
"se": "Northern Sami",
|
||||||
"ns": "Northern Sotho",
|
"ns": "Northern Sotho",
|
||||||
|
"no": "Norwegian",
|
||||||
"nb": "Norwegian (Bokmål)",
|
"nb": "Norwegian (Bokmål)",
|
||||||
"nn": "Norwegian (Nynorsk)",
|
"nn": "Norwegian (Nynorsk)",
|
||||||
"nus": "Nuer",
|
"nus": "Nuer",
|
||||||
|
|
@ -573,99 +514,54 @@ export const KagiLanguages = {
|
||||||
"pag": "Pangasinan",
|
"pag": "Pangasinan",
|
||||||
"pap": "Papiamento",
|
"pap": "Papiamento",
|
||||||
"ps": "Pashto/Pushto",
|
"ps": "Pashto/Pushto",
|
||||||
"per": "Persian",
|
"fa": "Persian",
|
||||||
"fa_af": "Persian (Afghanistan)",
|
|
||||||
"fa_ir": "Persian (Iran)",
|
|
||||||
"fa_tj": "Persian (Tajikistan)",
|
|
||||||
"pirate": "Pirate Speak",
|
|
||||||
"pl": "Polish",
|
"pl": "Polish",
|
||||||
"pt": "Portuguese",
|
|
||||||
"pt_ao": "Portuguese (Angola)",
|
|
||||||
"pt_br": "Portuguese (Brazil)",
|
"pt_br": "Portuguese (Brazil)",
|
||||||
"pt_cv": "Portuguese (Cape Verde)",
|
|
||||||
"pt_mz": "Portuguese (Mozambique)",
|
|
||||||
"pt_pt": "Portuguese (Portugal)",
|
"pt_pt": "Portuguese (Portugal)",
|
||||||
"pa": "Punjabi",
|
"pa": "Punjabi",
|
||||||
"qu": "Quechua",
|
"qu": "Quechua",
|
||||||
"qu_bo": "Quechua (Bolivia)",
|
|
||||||
"qu_ec": "Quechua (Ecuador)",
|
|
||||||
"qu_pe": "Quechua (Peru)",
|
|
||||||
"kek": "Qʼeqchiʼ",
|
"kek": "Qʼeqchiʼ",
|
||||||
"rm": "Rhaeto_Romanic",
|
"rm": "Rhaeto_Romanic",
|
||||||
"rom": "Romani",
|
"rom": "Romani",
|
||||||
"ro": "Romanian",
|
"ro": "Romanian",
|
||||||
"ru": "Russian",
|
"ru": "Russian",
|
||||||
"ru_by": "Russian (Belarus)",
|
|
||||||
"ru_kz": "Russian (Kazakhstan)",
|
|
||||||
"ru_kg": "Russian (Kyrgyzstan)",
|
|
||||||
"ru_ru": "Russian (Russia)",
|
|
||||||
"se": "Sami",
|
|
||||||
"se_fi": "Sami (Finland)",
|
|
||||||
"se_no": "Sami (Norway)",
|
|
||||||
"se_se": "Sami (Sweden)",
|
|
||||||
"sm": "Samoan",
|
"sm": "Samoan",
|
||||||
"sg": "Sangro",
|
"sg": "Sangro",
|
||||||
"sa": "Sanskrit",
|
"sa": "Sanskrit",
|
||||||
"sat": "Santali",
|
"sat": "Santali",
|
||||||
"sc": "Sardinian",
|
"sc": "Sardinian",
|
||||||
|
"sco": "Scots",
|
||||||
|
"gd": "Scottish Gaelic",
|
||||||
"sr": "Serbian",
|
"sr": "Serbian",
|
||||||
"sr_ba": "Serbian (Bosnia and Herzegovina)",
|
|
||||||
"sr_sp": "Serbian (Serbia and Montenegro)",
|
|
||||||
"sh": "Serbo_Croatian",
|
"sh": "Serbo_Croatian",
|
||||||
"st": "Sesotho",
|
"st": "Sesotho",
|
||||||
|
"seto": "Seto",
|
||||||
"shn": "Shan",
|
"shn": "Shan",
|
||||||
"sn": "Shona",
|
"sn": "Shona",
|
||||||
"ii": "Sichuan Yi",
|
"ii": "Sichuan Yi",
|
||||||
"scn": "Sicilian",
|
"scn": "Sicilian",
|
||||||
"szl": "Silesian",
|
"szl": "Silesian",
|
||||||
"sd": "Sindhi",
|
"sd": "Sindhi",
|
||||||
"si": "Singhalese",
|
"si": "Sinhalese",
|
||||||
"ss": "Siswati",
|
"ss": "Siswati",
|
||||||
"sk": "Slovak",
|
"sk": "Slovak",
|
||||||
"sl": "Slovenian",
|
"sl": "Slovenian",
|
||||||
"so": "Somali",
|
"so": "Somali",
|
||||||
"sb": "Sorbian",
|
"sb": "Sorbian",
|
||||||
"nr": "South Ndebele",
|
"nr": "South Ndebele",
|
||||||
|
"sma": "Southern Sami",
|
||||||
"es": "Spanish",
|
"es": "Spanish",
|
||||||
"es_ar": "Spanish (Argentina)",
|
|
||||||
"es_bo": "Spanish (Bolivia)",
|
|
||||||
"es_cl": "Spanish (Chile)",
|
|
||||||
"es_co": "Spanish (Colombia)",
|
|
||||||
"es_cr": "Spanish (Costa Rica)",
|
|
||||||
"es_cu": "Spanish (Cuba)",
|
|
||||||
"es_do": "Spanish (Dominican Republic)",
|
|
||||||
"es_ec": "Spanish (Ecuador)",
|
|
||||||
"es_sv": "Spanish (El Salvador)",
|
|
||||||
"es_gq": "Spanish (Equatorial Guinea)",
|
|
||||||
"es_gt": "Spanish (Guatemala)",
|
|
||||||
"es_hn": "Spanish (Honduras)",
|
|
||||||
"es_mx": "Spanish (Mexico)",
|
|
||||||
"es_ni": "Spanish (Nicaragua)",
|
|
||||||
"es_pa": "Spanish (Panama)",
|
|
||||||
"es_py": "Spanish (Paraguay)",
|
|
||||||
"es_pe": "Spanish (Peru)",
|
|
||||||
"es_pr": "Spanish (Puerto Rico)",
|
|
||||||
"es_es": "Spanish (Spain)",
|
|
||||||
"es_uy": "Spanish (Uruguay)",
|
|
||||||
"es_ve": "Spanish (Venezuela)",
|
|
||||||
"su": "Sundanese",
|
"su": "Sundanese",
|
||||||
"sus": "Susu",
|
"sus": "Susu",
|
||||||
"sx": "Sutu",
|
"sx": "Sutu",
|
||||||
"sw": "Swahili",
|
"sw": "Swahili",
|
||||||
"sv": "Swedish",
|
"sv": "Swedish",
|
||||||
"sv_fi": "Swedish (Finland)",
|
|
||||||
"sv_se": "Swedish (Sweden)",
|
|
||||||
"gsw": "Swiss German",
|
"gsw": "Swiss German",
|
||||||
"de_ch": "Swiss High German",
|
|
||||||
"syr": "Syriac",
|
"syr": "Syriac",
|
||||||
"tl": "Tagalog",
|
"tl": "Tagalog",
|
||||||
"ty": "Tahitian",
|
"ty": "Tahitian",
|
||||||
"tg": "Tajik",
|
"tg": "Tajik",
|
||||||
"ta": "Tamil",
|
"ta": "Tamil",
|
||||||
"ta_in": "Tamil (India)",
|
|
||||||
"ta_my": "Tamil (Malaysia)",
|
|
||||||
"ta_sg": "Tamil (Singapore)",
|
|
||||||
"ta_lk": "Tamil (Sri Lanka)",
|
|
||||||
"tt": "Tatar",
|
"tt": "Tatar",
|
||||||
"te": "Telugu",
|
"te": "Telugu",
|
||||||
"tet": "Tetum",
|
"tet": "Tetum",
|
||||||
|
|
@ -679,8 +575,6 @@ export const KagiLanguages = {
|
||||||
"tn": "Tswana",
|
"tn": "Tswana",
|
||||||
"tum": "Tumbuka",
|
"tum": "Tumbuka",
|
||||||
"tr": "Turkish",
|
"tr": "Turkish",
|
||||||
"tr_cy": "Turkish (Cyprus)",
|
|
||||||
"tr_tr": "Turkish (Turkey)",
|
|
||||||
"tk": "Turkmen",
|
"tk": "Turkmen",
|
||||||
"tyv": "Tuvan",
|
"tyv": "Tuvan",
|
||||||
"tw": "Twi",
|
"tw": "Twi",
|
||||||
|
|
@ -688,13 +582,12 @@ export const KagiLanguages = {
|
||||||
"ug": "Uighur",
|
"ug": "Uighur",
|
||||||
"uk": "Ukrainian",
|
"uk": "Ukrainian",
|
||||||
"ur": "Urdu",
|
"ur": "Urdu",
|
||||||
"ur_in": "Urdu (India)",
|
|
||||||
"ur_pk": "Urdu (Pakistan)",
|
|
||||||
"uz": "Uzbek",
|
"uz": "Uzbek",
|
||||||
"ve": "Venda",
|
"ve": "Venda",
|
||||||
"vec": "Venetian",
|
"vec": "Venetian",
|
||||||
"vi": "Vietnamese",
|
"vi": "Vietnamese",
|
||||||
"vo": "Volapuk",
|
"vo": "Volapuk",
|
||||||
|
"vro": "Võro",
|
||||||
"wa": "Walloon",
|
"wa": "Walloon",
|
||||||
"war": "Waray",
|
"war": "Waray",
|
||||||
"cy": "Welsh",
|
"cy": "Welsh",
|
||||||
|
|
@ -705,6 +598,7 @@ export const KagiLanguages = {
|
||||||
"yo": "Yoruba",
|
"yo": "Yoruba",
|
||||||
"yua": "Yucatec Maya",
|
"yua": "Yucatec Maya",
|
||||||
"zap": "Zapotec",
|
"zap": "Zapotec",
|
||||||
|
"diq": "Zazaki",
|
||||||
"za": "Zhuang",
|
"za": "Zhuang",
|
||||||
"zu": "Zulu"
|
"zu": "Zulu"
|
||||||
} as const;
|
} as const;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,17 @@ import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { CustomEmoji, Message, ReactionEmoji, User } from "@vencord/discord-types";
|
import { CustomEmoji, Message, ReactionEmoji, User } from "@vencord/discord-types";
|
||||||
import { ChannelStore, Constants, FluxDispatcher, React, RestAPI, useEffect, useLayoutEffect, UserStore, UserSummaryItem } from "@webpack/common";
|
import { ChannelStore, Constants, FluxDispatcher, React, RestAPI, useEffect, useLayoutEffect, UserStore, UserSummaryItem } from "@webpack/common";
|
||||||
|
|
||||||
|
interface ReactionCacheEntry {
|
||||||
|
fetched: boolean;
|
||||||
|
users: Map<string, User>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ReactionProps {
|
||||||
|
message: Message;
|
||||||
|
emoji: CustomEmoji;
|
||||||
|
type: number;
|
||||||
|
}
|
||||||
|
|
||||||
let Scroll: any = null;
|
let Scroll: any = null;
|
||||||
const queue = new Queue();
|
const queue = new Queue();
|
||||||
let reactions: Record<string, ReactionCacheEntry> = {};
|
let reactions: Record<string, ReactionCacheEntry> = {};
|
||||||
|
|
@ -76,6 +87,46 @@ function handleClickAvatar(event: React.UIEvent<HTMLElement, Event>) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ReactionUsers({ message, emoji, type }: ReactionProps) {
|
||||||
|
const forceUpdate = useForceUpdater();
|
||||||
|
|
||||||
|
useLayoutEffect(() => { // bc need to prevent autoscrolling
|
||||||
|
if (Scroll?.scrollCounter > 0) {
|
||||||
|
Scroll.setAutomaticAnchor(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const cb = (e: any) => {
|
||||||
|
if (e?.messageId === message.id)
|
||||||
|
forceUpdate();
|
||||||
|
};
|
||||||
|
FluxDispatcher.subscribe("MESSAGE_REACTION_ADD_USERS", cb);
|
||||||
|
|
||||||
|
return () => FluxDispatcher.unsubscribe("MESSAGE_REACTION_ADD_USERS", cb);
|
||||||
|
}, [message.id, forceUpdate]);
|
||||||
|
|
||||||
|
const reactions = getReactionsWithQueue(message, emoji, type);
|
||||||
|
const users = Array.from(reactions, ([id]) => UserStore.getUser(id)).filter(Boolean);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{ marginLeft: "0.5em", transform: "scale(0.9)" }}
|
||||||
|
>
|
||||||
|
<div onClick={handleClickAvatar} onKeyDown={handleClickAvatar}>
|
||||||
|
<UserSummaryItem
|
||||||
|
users={users}
|
||||||
|
guildId={ChannelStore.getChannel(message.channel_id)?.guild_id}
|
||||||
|
renderIcon={false}
|
||||||
|
max={5}
|
||||||
|
showDefaultAvatarsForNullUsers
|
||||||
|
showUserPopout
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const settings = definePluginSettings({
|
const settings = definePluginSettings({
|
||||||
avatarClick: {
|
avatarClick: {
|
||||||
description: "Toggle clicking avatars in reactions",
|
description: "Toggle clicking avatars in reactions",
|
||||||
|
|
@ -96,8 +147,8 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
find: ",reactionRef:",
|
find: ",reactionRef:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /\(0,\i\.jsx\)\(\i\.\i,\{className:\i\.reactionCount,.{0,60}\}\),/,
|
match: /(\i)\?null:\(0,\i\.jsx\)\(\i\.\i,{className:\i\.reactionCount,.*?}\),(?<=(emoji:\i,message:\i,type:\i).+?)/,
|
||||||
replace: "$&$self.renderUsers(arguments[0]),"
|
replace: "$&$1?null:$self.renderUsers({$2}),"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -117,88 +168,17 @@ export default definePlugin({
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
renderUsers: ErrorBoundary.wrap((props: ReactionProps) => {
|
||||||
|
return props.message.reactions.length > 10
|
||||||
|
? null
|
||||||
|
: <ReactionUsers {...props} />;
|
||||||
|
}, { noop: true }),
|
||||||
|
|
||||||
setScrollObj(scroll: any) {
|
setScrollObj(scroll: any) {
|
||||||
Scroll = scroll;
|
Scroll = scroll;
|
||||||
},
|
},
|
||||||
|
|
||||||
renderUsers(props: RootObject) {
|
|
||||||
if (!props?.message || props.hideCount) return null;
|
|
||||||
return props.message.reactions.length > 10 ? null : (
|
|
||||||
<ErrorBoundary noop>
|
|
||||||
<this.UsersComponent {...props} />
|
|
||||||
</ErrorBoundary>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
UsersComponent({ message, emoji, type }: RootObject) {
|
|
||||||
const forceUpdate = useForceUpdater();
|
|
||||||
|
|
||||||
useLayoutEffect(() => { // bc need to prevent autoscrolling
|
|
||||||
if (Scroll?.scrollCounter > 0) {
|
|
||||||
Scroll.setAutomaticAnchor(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const cb = (e: any) => {
|
|
||||||
if (e?.messageId === message.id)
|
|
||||||
forceUpdate();
|
|
||||||
};
|
|
||||||
FluxDispatcher.subscribe("MESSAGE_REACTION_ADD_USERS", cb);
|
|
||||||
|
|
||||||
return () => FluxDispatcher.unsubscribe("MESSAGE_REACTION_ADD_USERS", cb);
|
|
||||||
}, [message.id, forceUpdate]);
|
|
||||||
|
|
||||||
const reactions = getReactionsWithQueue(message, emoji, type);
|
|
||||||
const users = Array.from(reactions, ([id]) => UserStore.getUser(id)).filter(Boolean);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
style={{ marginLeft: "0.5em", transform: "scale(0.9)" }}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
onClick={handleClickAvatar}
|
|
||||||
onKeyDown={handleClickAvatar}
|
|
||||||
style={settings.store.avatarClick ? {} : { pointerEvents: "none" }}
|
|
||||||
>
|
|
||||||
<UserSummaryItem
|
|
||||||
users={users}
|
|
||||||
guildId={ChannelStore.getChannel(message.channel_id)?.guild_id}
|
|
||||||
renderIcon={false}
|
|
||||||
max={5}
|
|
||||||
showDefaultAvatarsForNullUsers
|
|
||||||
showUserPopout
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
set reactions(value: any) {
|
set reactions(value: any) {
|
||||||
reactions = value;
|
reactions = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ReactionCacheEntry {
|
|
||||||
fetched: boolean;
|
|
||||||
users: Map<string, User>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface RootObject {
|
|
||||||
message: Message;
|
|
||||||
readOnly: boolean;
|
|
||||||
isLurking: boolean;
|
|
||||||
isPendingMember: boolean;
|
|
||||||
useChatFontScaling: boolean;
|
|
||||||
emoji: CustomEmoji;
|
|
||||||
count: number;
|
|
||||||
burst_user_ids: any[];
|
|
||||||
burst_count: number;
|
|
||||||
burst_colors: any[];
|
|
||||||
burst_me: boolean;
|
|
||||||
me: boolean;
|
|
||||||
type: number;
|
|
||||||
hideCount: boolean;
|
|
||||||
hideEmoji: boolean;
|
|
||||||
remainingBurstCurrency: number;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue