mirror of
https://github.com/Vendicated/Vencord.git
synced 2025-02-24 15:35:11 +00:00
Merge branch 'Vendicated:main' into listenbrainz
This commit is contained in:
commit
351d3eb387
13 changed files with 65 additions and 43 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "vencord",
|
"name": "vencord",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"version": "1.11.0",
|
"version": "1.11.2",
|
||||||
"description": "The cutest Discord client mod",
|
"description": "The cutest Discord client mod",
|
||||||
"homepage": "https://github.com/Vendicated/Vencord#readme",
|
"homepage": "https://github.com/Vendicated/Vencord#readme",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { User } from "discord-types/general";
|
||||||
interface UserProfileProps {
|
interface UserProfileProps {
|
||||||
popoutProps: Record<string, any>;
|
popoutProps: Record<string, any>;
|
||||||
currentUser: User;
|
currentUser: User;
|
||||||
OriginalPopout: () => React.ReactNode;
|
originalRenderPopout: () => React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const UserProfile = findComponentByCodeLazy("UserProfilePopoutWrapper: user cannot be undefined");
|
const UserProfile = findComponentByCodeLazy("UserProfilePopoutWrapper: user cannot be undefined");
|
||||||
|
@ -78,7 +78,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
match: /(\.AVATAR,children:.+?renderPopout:(\i)=>){(.+?)}(?=,position)(?<=currentUser:(\i).+?)/,
|
match: /(\.AVATAR,children:.+?renderPopout:(\i)=>){(.+?)}(?=,position)(?<=currentUser:(\i).+?)/,
|
||||||
replace: (_, rest, popoutProps, originalPopout, currentUser) => `${rest}$self.UserProfile({popoutProps:${popoutProps},currentUser:${currentUser},OriginalPopout:()=>{${originalPopout}}})`
|
replace: (_, rest, popoutProps, originalPopout, currentUser) => `${rest}$self.UserProfile({popoutProps:${popoutProps},currentUser:${currentUser},originalRenderPopout:()=>{${originalPopout}}})`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
match: /\.AVATAR,children:.+?(?=renderPopout:)/,
|
match: /\.AVATAR,children:.+?(?=renderPopout:)/,
|
||||||
|
@ -112,17 +112,17 @@ export default definePlugin({
|
||||||
openAlternatePopout = false;
|
openAlternatePopout = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
UserProfile: ErrorBoundary.wrap(({ popoutProps, currentUser, OriginalPopout }: UserProfileProps) => {
|
UserProfile: ErrorBoundary.wrap(({ popoutProps, currentUser, originalRenderPopout }: UserProfileProps) => {
|
||||||
if (
|
if (
|
||||||
(settings.store.prioritizeServerProfile && openAlternatePopout) ||
|
(settings.store.prioritizeServerProfile && openAlternatePopout) ||
|
||||||
(!settings.store.prioritizeServerProfile && !openAlternatePopout)
|
(!settings.store.prioritizeServerProfile && !openAlternatePopout)
|
||||||
) {
|
) {
|
||||||
return <OriginalPopout />;
|
return originalRenderPopout();
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentChannel = getCurrentChannel();
|
const currentChannel = getCurrentChannel();
|
||||||
if (currentChannel?.getGuildId() == null) {
|
if (currentChannel?.getGuildId() == null) {
|
||||||
return <OriginalPopout />;
|
return originalRenderPopout();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -41,7 +41,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Status emojis
|
// Status emojis
|
||||||
find: "#{intl::GUILD_OWNER}",
|
find: "#{intl::GUILD_OWNER}),children:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(?<=\.activityEmoji,.+?animate:)\i/,
|
match: /(?<=\.activityEmoji,.+?animate:)\i/,
|
||||||
replace: "!0"
|
replace: "!0"
|
||||||
|
|
|
@ -27,7 +27,7 @@ export default definePlugin({
|
||||||
{
|
{
|
||||||
find: '"ChannelAttachButton"',
|
find: '"ChannelAttachButton"',
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /\.attachButtonInner,"aria-label":.{0,50},onDoubleClick:(.+?:void 0),\.\.\.(\i),/,
|
match: /\.attachButtonInner,"aria-label":.{0,50},onDoubleClick:(.+?:void 0),.{0,30}?\.\.\.(\i),/,
|
||||||
replace: "$&onClick:$1,onContextMenu:$2.onClick,",
|
replace: "$&onClick:$1,onContextMenu:$2.onClick,",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
import { definePluginSettings, Settings } from "@api/Settings";
|
import { definePluginSettings, Settings } from "@api/Settings";
|
||||||
import { getUserSettingLazy } from "@api/UserSettings";
|
import { getUserSettingLazy } from "@api/UserSettings";
|
||||||
import { ErrorCard } from "@components/ErrorCard";
|
import { ErrorCard } from "@components/ErrorCard";
|
||||||
|
import { Flex } from "@components/Flex";
|
||||||
import { Link } from "@components/Link";
|
import { Link } from "@components/Link";
|
||||||
import { Devs } from "@utils/constants";
|
import { Devs } from "@utils/constants";
|
||||||
import { isTruthy } from "@utils/guards";
|
import { isTruthy } from "@utils/guards";
|
||||||
|
@ -27,15 +28,14 @@ import { classes } from "@utils/misc";
|
||||||
import { useAwaiter } from "@utils/react";
|
import { useAwaiter } from "@utils/react";
|
||||||
import definePlugin, { OptionType } from "@utils/types";
|
import definePlugin, { OptionType } from "@utils/types";
|
||||||
import { findByCodeLazy, findComponentByCodeLazy } from "@webpack";
|
import { findByCodeLazy, findComponentByCodeLazy } from "@webpack";
|
||||||
import { ApplicationAssetUtils, Button, FluxDispatcher, Forms, GuildStore, React, SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common";
|
import { ApplicationAssetUtils, Button, FluxDispatcher, Forms, React, UserStore } from "@webpack/common";
|
||||||
|
|
||||||
const useProfileThemeStyle = findByCodeLazy("profileThemeStyle:", "--profile-gradient-primary-color");
|
const useProfileThemeStyle = findByCodeLazy("profileThemeStyle:", "--profile-gradient-primary-color");
|
||||||
const ActivityComponent = findComponentByCodeLazy("onOpenGameProfile");
|
const ActivityView = findComponentByCodeLazy(".party?(0", ".card");
|
||||||
|
|
||||||
const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame")!;
|
const ShowCurrentGame = getUserSettingLazy<boolean>("status", "showCurrentGame")!;
|
||||||
|
|
||||||
async function getApplicationAsset(key: string): Promise<string> {
|
async function getApplicationAsset(key: string): Promise<string> {
|
||||||
if (/https?:\/\/(cdn|media)\.discordapp\.(com|net)\/attachments\//.test(key)) return "mp:" + key.replace(/https?:\/\/(cdn|media)\.discordapp\.(com|net)\//, "");
|
|
||||||
return (await ApplicationAssetUtils.fetchAssetIds(settings.store.appID!, [key]))[0];
|
return (await ApplicationAssetUtils.fetchAssetIds(settings.store.appID!, [key]))[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ const settings = definePluginSettings({
|
||||||
value: TimestampMode.NOW
|
value: TimestampMode.NOW
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Same as your current time",
|
label: "Same as your current time (not reset after 24h)",
|
||||||
value: TimestampMode.TIME
|
value: TimestampMode.TIME
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -269,6 +269,7 @@ function isStreamLinkDisabled() {
|
||||||
|
|
||||||
function isStreamLinkValid(value: string) {
|
function isStreamLinkValid(value: string) {
|
||||||
if (!isStreamLinkDisabled() && !/https?:\/\/(www\.)?(twitch\.tv|youtube\.com)\/\w+/.test(value)) return "Streaming link must be a valid URL.";
|
if (!isStreamLinkDisabled() && !/https?:\/\/(www\.)?(twitch\.tv|youtube\.com)\/\w+/.test(value)) return "Streaming link must be a valid URL.";
|
||||||
|
if (value && value.length > 512) return "Streaming link must be not longer than 512 characters.";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,8 +278,9 @@ function isTimestampDisabled() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isImageKeyValid(value: string) {
|
function isImageKeyValid(value: string) {
|
||||||
if (/https?:\/\/(?!i\.)?imgur\.com\//.test(value)) return "Imgur link must be a direct link to the image. (e.g. https://i.imgur.com/...)";
|
if (/https?:\/\/(cdn|media)\.discordapp\.(com|net)\//.test(value)) return "Don't use a Discord link. Use an Imgur image link instead.";
|
||||||
if (/https?:\/\/(?!media\.)?tenor\.com\//.test(value)) return "Tenor link must be a direct link to the image. (e.g. https://media.tenor.com/...)";
|
if (/https?:\/\/(?!i\.)?imgur\.com\//.test(value)) return "Imgur link must be a direct link to the image (e.g. https://i.imgur.com/...). Right click the image and click 'Copy image address'";
|
||||||
|
if (/https?:\/\/(?!media\.)?tenor\.com\//.test(value)) return "Tenor link must be a direct link to the image (e.g. https://media.tenor.com/...). Right click the GIF and click 'Copy image address'";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,13 +392,24 @@ async function setRpc(disable?: boolean) {
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
name: "CustomRPC",
|
name: "CustomRPC",
|
||||||
description: "Allows you to set a custom rich presence.",
|
description: "Add a fully customisable Rich Presence (Game status) to your Discord profile",
|
||||||
authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev],
|
authors: [Devs.captain, Devs.AutumnVN, Devs.nin0dev],
|
||||||
dependencies: ["UserSettingsAPI"],
|
dependencies: ["UserSettingsAPI"],
|
||||||
start: setRpc,
|
start: setRpc,
|
||||||
stop: () => setRpc(true),
|
stop: () => setRpc(true),
|
||||||
settings,
|
settings,
|
||||||
|
|
||||||
|
patches: [
|
||||||
|
{
|
||||||
|
find: ".party?(0",
|
||||||
|
all: true,
|
||||||
|
replacement: {
|
||||||
|
match: /\i\.id===\i\.id\?null:/,
|
||||||
|
replace: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
settingsAboutComponent: () => {
|
settingsAboutComponent: () => {
|
||||||
const activity = useAwaiter(createActivity);
|
const activity = useAwaiter(createActivity);
|
||||||
const gameActivityEnabled = ShowCurrentGame.useSetting();
|
const gameActivityEnabled = ShowCurrentGame.useSetting();
|
||||||
|
@ -410,7 +423,7 @@ export default definePlugin({
|
||||||
style={{ padding: "1em" }}
|
style={{ padding: "1em" }}
|
||||||
>
|
>
|
||||||
<Forms.FormTitle>Notice</Forms.FormTitle>
|
<Forms.FormTitle>Notice</Forms.FormTitle>
|
||||||
<Forms.FormText>Game activity isn't enabled, people won't be able to see your custom rich presence!</Forms.FormText>
|
<Forms.FormText>Activity Sharing isn't enabled, people won't be able to see your custom rich presence!</Forms.FormText>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
color={Button.Colors.TRANSPARENT}
|
color={Button.Colors.TRANSPARENT}
|
||||||
|
@ -422,24 +435,33 @@ export default definePlugin({
|
||||||
</ErrorCard>
|
</ErrorCard>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Forms.FormText>
|
<Flex flexDirection="column" style={{ gap: ".5em" }} className={Margins.top16}>
|
||||||
Go to <Link href="https://discord.com/developers/applications">Discord Developer Portal</Link> to create an application and
|
<Forms.FormText>
|
||||||
get the application ID.
|
Go to the <Link href="https://discord.com/developers/applications">Discord Developer Portal</Link> to create an application and
|
||||||
</Forms.FormText>
|
get the application ID.
|
||||||
<Forms.FormText>
|
</Forms.FormText>
|
||||||
Upload images in the Rich Presence tab to get the image keys.
|
<Forms.FormText>
|
||||||
</Forms.FormText>
|
Upload images in the Rich Presence tab to get the image keys.
|
||||||
<Forms.FormText>
|
</Forms.FormText>
|
||||||
If you want to use image link, download your image and reupload the image to <Link href="https://imgur.com">Imgur</Link> and get the image link by right-clicking the image and select "Copy image address".
|
<Forms.FormText>
|
||||||
</Forms.FormText>
|
If you want to use an image link, download your image and reupload the image to <Link href="https://imgur.com">Imgur</Link> and get the image link by right-clicking the image and selecting "Copy image address".
|
||||||
|
</Forms.FormText>
|
||||||
|
<Forms.FormText>
|
||||||
|
You can't see your own buttons on your profile, but everyone else can see it fine.
|
||||||
|
</Forms.FormText>
|
||||||
|
<Forms.FormText>
|
||||||
|
Some weird unicode text ("fonts" 𝖑𝖎𝖐𝖊 𝖙𝖍𝖎𝖘) may cause the rich presence to not show up, try using normal letters instead.
|
||||||
|
</Forms.FormText>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
<Forms.FormDivider className={Margins.top8} />
|
<Forms.FormDivider className={Margins.top8} />
|
||||||
|
|
||||||
<div style={{ width: "284px", ...profileThemeStyle, padding: 8, marginTop: 8, borderRadius: 8, background: "var(--bg-mod-faint)" }}>
|
<div style={{ width: "284px", ...profileThemeStyle, marginTop: 8, borderRadius: 8, background: "var(--bg-mod-faint)" }}>
|
||||||
{activity[0] && <ActivityComponent activity={activity[0]} channelId={SelectedChannelStore.getChannelId()}
|
{activity[0] && <ActivityView
|
||||||
guild={GuildStore.getGuild(SelectedGuildStore.getLastSelectedGuildId())}
|
activity={activity[0]}
|
||||||
application={{ id: settings.store.appID }}
|
user={UserStore.getCurrentUser()}
|
||||||
user={UserStore.getCurrentUser()} />}
|
currentUser={UserStore.getCurrentUser()}
|
||||||
|
/>}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -391,7 +391,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
// Separate patch for allowing using custom app icons
|
// Separate patch for allowing using custom app icons
|
||||||
{
|
{
|
||||||
find: /\.getCurrentDesktopIcon.{0,25}\.isPremium/,
|
find: "?24:30,",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /\i\.\i\.isPremium\(\i\.\i\.getCurrentUser\(\)\)/,
|
match: /\i\.\i\.isPremium\(\i\.\i\.getCurrentUser\(\)\)/,
|
||||||
replace: "true"
|
replace: "true"
|
||||||
|
|
|
@ -13,7 +13,7 @@ export default definePlugin({
|
||||||
authors: [Devs.Nuckyz],
|
authors: [Devs.Nuckyz],
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: "getFormatQuality(){",
|
find: ".handleImageLoad)",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(?<=null;return )\i\.\i&&\(\i\|\|!\i\.isAnimated.+?:(?=\i&&\(\i="png"\))/,
|
match: /(?<=null;return )\i\.\i&&\(\i\|\|!\i\.isAnimated.+?:(?=\i&&\(\i="png"\))/,
|
||||||
replace: ""
|
replace: ""
|
||||||
|
|
|
@ -27,7 +27,7 @@ export default definePlugin({
|
||||||
authors: [Devs.D3SOX, Devs.Nickyux],
|
authors: [Devs.D3SOX, Devs.Nickyux],
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: "#{intl::GUILD_OWNER}",
|
find: "#{intl::GUILD_OWNER}),children:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /,isOwner:(\i),/,
|
match: /,isOwner:(\i),/,
|
||||||
replace: ",_isOwner:$1=$self.isGuildOwner(e),"
|
replace: ",_isOwner:$1=$self.isGuildOwner(e),"
|
||||||
|
|
|
@ -16,7 +16,7 @@ interface UserMentionComponentProps {
|
||||||
id: string;
|
id: string;
|
||||||
channelId: string;
|
channelId: string;
|
||||||
guildId: string;
|
guildId: string;
|
||||||
OriginalComponent: () => ReactNode;
|
originalComponent: () => ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default definePlugin({
|
export default definePlugin({
|
||||||
|
@ -29,7 +29,7 @@ export default definePlugin({
|
||||||
find: ':"text":',
|
find: ':"text":',
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(hidePersonalInformation\).+?)(if\(null!=\i\){.+?return \i)(?=})/,
|
match: /(hidePersonalInformation\).+?)(if\(null!=\i\){.+?return \i)(?=})/,
|
||||||
replace: "$1return $self.UserMentionComponent({...arguments[0],OriginalComponent:()=>{$2}});"
|
replace: "$1return $self.UserMentionComponent({...arguments[0],originalComponent:()=>{$2}});"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -42,6 +42,6 @@ export default definePlugin({
|
||||||
channelId={props.channelId}
|
channelId={props.channelId}
|
||||||
/>
|
/>
|
||||||
), {
|
), {
|
||||||
fallback: ({ wrappedProps: { OriginalComponent } }) => <OriginalComponent />
|
fallback: ({ wrappedProps: { originalComponent } }) => originalComponent()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -218,7 +218,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
// in the member list
|
// in the member list
|
||||||
{
|
{
|
||||||
find: "#{intl::GUILD_OWNER}",
|
find: "#{intl::GUILD_OWNER}),children:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(?<type>\i)=\(null==.{0,100}\.BOT;return null!=(?<user>\i)&&\i\.bot/,
|
match: /(?<type>\i)=\(null==.{0,100}\.BOT;return null!=(?<user>\i)&&\i\.bot/,
|
||||||
replace: "$<type> = $self.getTag({user: $<user>, channel: arguments[0].channel, origType: $<user>.bot ? 0 : null, location: 'not-chat' }); return typeof $<type> === 'number'"
|
replace: "$<type> = $self.getTag({user: $<user>, channel: arguments[0].channel, origType: $<user>.bot ? 0 : null, location: 'not-chat' }); return typeof $<type> === 'number'"
|
||||||
|
|
|
@ -55,7 +55,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Clicking on replied messages to jump
|
// Clicking on replied messages to jump
|
||||||
find: "flash:!0,returnMessageId",
|
find: '("interactionUsernameProfile',
|
||||||
replacement: [
|
replacement: [
|
||||||
{
|
{
|
||||||
match: /.\?(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/,
|
match: /.\?(.{1,10}\.show\({.{1,50}#{intl::UNBLOCK_TO_JUMP_TITLE})/,
|
||||||
|
|
|
@ -108,7 +108,7 @@ export default definePlugin({
|
||||||
|
|
||||||
patches: [
|
patches: [
|
||||||
{
|
{
|
||||||
find: "#{intl::MESSAGE_ACTIONS_MENU_LABEL}",
|
find: "#{intl::MESSAGE_ACTIONS_MENU_LABEL}),shouldHideMediaOptions:",
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /favoriteableType:\i,(?<=(\i)\.getAttribute\("data-type"\).+?)/,
|
match: /favoriteableType:\i,(?<=(\i)\.getAttribute\("data-type"\).+?)/,
|
||||||
replace: (m, target) => `${m}reverseImageSearchType:${target}.getAttribute("data-role"),`
|
replace: (m, target) => `${m}reverseImageSearchType:${target}.getAttribute("data-role"),`
|
||||||
|
|
|
@ -58,7 +58,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
find: /context:\i,checkElevated:!1\}\),\i\.\i.{0,200}autoTrackExposure/,
|
find: /,checkElevated:!1}\),\i\.\i\)}(?<=getCurrentUser\(\);return.+?)/,
|
||||||
predicate: () => settings.store.showModView,
|
predicate: () => settings.store.showModView,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /return \i\.\i\(\i\.\i\(\{user:\i,context:\i,checkElevated:!1\}\),\i\.\i\)/,
|
match: /return \i\.\i\(\i\.\i\(\{user:\i,context:\i,checkElevated:!1\}\),\i\.\i\)/,
|
||||||
|
@ -67,7 +67,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
// fixes a bug where Members page must be loaded to see highest role, why is Discord depending on MemberSafetyStore.getEnhancedMember for something that can be obtained here?
|
// fixes a bug where Members page must be loaded to see highest role, why is Discord depending on MemberSafetyStore.getEnhancedMember for something that can be obtained here?
|
||||||
{
|
{
|
||||||
find: "#{intl::GUILD_MEMBER_MOD_VIEW_PERMISSION_GRANTED_BY_ARIA_LABEL}",
|
find: "#{intl::GUILD_MEMBER_MOD_VIEW_PERMISSION_GRANTED_BY_ARIA_LABEL}),allowOverflow:",
|
||||||
predicate: () => settings.store.showModView,
|
predicate: () => settings.store.showModView,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /(role:)\i(?=,guildId.{0,100}role:(\i\[))/,
|
match: /(role:)\i(?=,guildId.{0,100}role:(\i\[))/,
|
||||||
|
@ -76,7 +76,7 @@ export default definePlugin({
|
||||||
},
|
},
|
||||||
// allows you to open mod view on yourself
|
// allows you to open mod view on yourself
|
||||||
{
|
{
|
||||||
find: ".MEMBER_SAFETY,{modViewPanel:",
|
find: 'action:"PRESS_MOD_VIEW",icon:',
|
||||||
predicate: () => settings.store.showModView,
|
predicate: () => settings.store.showModView,
|
||||||
replacement: {
|
replacement: {
|
||||||
match: /\i(?=\?null)/,
|
match: /\i(?=\?null)/,
|
||||||
|
|
Loading…
Add table
Reference in a new issue