Merge branch 'immediate-finds' into immediate-finds-modules-proxy
This commit is contained in:
commit
bb22355a57
|
@ -40,7 +40,7 @@ import { Alerts, Button, Card, Forms, lodash, Parser, React, Select, Text, TextI
|
|||
import Plugins from "~plugins";
|
||||
|
||||
// Avoid circular dependency
|
||||
const { startDependenciesRecursive, startPlugin, stopPlugin } = proxyLazy(() => require("../../plugins"));
|
||||
const { startDependenciesRecursive, startPlugin, stopPlugin } = proxyLazy(() => require("../../plugins")) as typeof import("../../plugins");
|
||||
|
||||
const cl = classNameFactory("vc-plugins-");
|
||||
const logger = new Logger("PluginSettings", "#a6d189");
|
||||
|
|
|
@ -250,7 +250,7 @@ function ThemesTab() {
|
|||
Edit QuickCSS
|
||||
</Button>
|
||||
|
||||
{Vencord.Settings.plugins.ClientTheme.enabled && (
|
||||
{Vencord.Plugins.isPluginEnabled("ClientTheme") && (
|
||||
<Button
|
||||
onClick={() => openModal(modalProps => (
|
||||
<PluginModal
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import BackupAndRestoreTab from "@components/VencordSettings/BackupAndRestoreTab";
|
||||
import CloudTab from "@components/VencordSettings/CloudTab";
|
||||
import PatchHelperTab from "@components/VencordSettings/PatchHelperTab";
|
||||
|
@ -33,11 +33,27 @@ import gitHash from "~git-hash";
|
|||
type SectionType = "HEADER" | "DIVIDER" | "CUSTOM";
|
||||
type SectionTypes = Record<SectionType, SectionType>;
|
||||
|
||||
const settings = definePluginSettings({
|
||||
settingsLocation: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Where to put the Vencord settings section",
|
||||
options: [
|
||||
{ label: "At the very top", value: "top" },
|
||||
{ label: "Above the Nitro section", value: "aboveNitro", default: true },
|
||||
{ label: "Below the Nitro section", value: "belowNitro" },
|
||||
{ label: "Above Activity Settings", value: "aboveActivity" },
|
||||
{ label: "Below Activity Settings", value: "belowActivity" },
|
||||
{ label: "At the very bottom", value: "bottom" },
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "Settings",
|
||||
description: "Adds Settings UI and debug info",
|
||||
authors: [Devs.Ven, Devs.Megu],
|
||||
required: true,
|
||||
settings,
|
||||
|
||||
patches: [
|
||||
{
|
||||
|
@ -63,7 +79,7 @@ export default definePlugin({
|
|||
noWarn: true,
|
||||
replacement: {
|
||||
get match() {
|
||||
switch (Settings.plugins.Settings.settingsLocation) {
|
||||
switch (settings.store.settingsLocation) {
|
||||
case "top": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS/;
|
||||
case "aboveNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS/;
|
||||
case "belowNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS/;
|
||||
|
@ -158,12 +174,12 @@ export default definePlugin({
|
|||
].filter(Boolean);
|
||||
},
|
||||
|
||||
isRightSpot({ header, settings }: { header?: string; settings?: string[]; }) {
|
||||
const firstChild = settings?.[0];
|
||||
isRightSpot({ header, settingsChilds }: { header?: string; settingsChilds?: string[]; }) {
|
||||
const firstChild = settingsChilds?.[0];
|
||||
// lowest two elements... sanity backup
|
||||
if (firstChild === "LOGOUT" || firstChild === "SOCIAL_LINKS") return true;
|
||||
|
||||
const { settingsLocation } = Settings.plugins.Settings;
|
||||
const { settingsLocation } = settings.store;
|
||||
|
||||
if (settingsLocation === "bottom") return firstChild === "LOGOUT";
|
||||
if (settingsLocation === "belowActivity") return firstChild === "CHANGELOG";
|
||||
|
@ -203,21 +219,6 @@ export default definePlugin({
|
|||
};
|
||||
},
|
||||
|
||||
options: {
|
||||
settingsLocation: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Where to put the Vencord settings section",
|
||||
options: [
|
||||
{ label: "At the very top", value: "top" },
|
||||
{ label: "Above the Nitro section", value: "aboveNitro", default: true },
|
||||
{ label: "Below the Nitro section", value: "belowNitro" },
|
||||
{ label: "Above Activity Settings", value: "aboveActivity" },
|
||||
{ label: "Below Activity Settings", value: "belowActivity" },
|
||||
{ label: "At the very bottom", value: "bottom" },
|
||||
]
|
||||
},
|
||||
},
|
||||
|
||||
get electronVersion() {
|
||||
return VencordNative.native.getVersions().electron || window.armcord?.electron || null;
|
||||
},
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
|
@ -28,16 +29,17 @@ export default definePlugin({
|
|||
find: "BAN_CONFIRM_TITLE.",
|
||||
replacement: {
|
||||
match: /src:\i\("\d+"\)/g,
|
||||
replace: "src: Vencord.Settings.plugins.BANger.source"
|
||||
replace: "src: $self.settings.store.source"
|
||||
}
|
||||
}
|
||||
],
|
||||
options: {
|
||||
|
||||
settings: definePluginSettings({
|
||||
source: {
|
||||
description: "Source to replace ban GIF with (Video or Gif)",
|
||||
type: OptionType.STRING,
|
||||
default: "https://i.imgur.com/wp5q52C.mp4",
|
||||
restartNeeded: true,
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { canonicalizeMatch } from "@utils/patches";
|
||||
|
@ -25,10 +25,26 @@ import { findByProps } from "@webpack";
|
|||
|
||||
const UserPopoutSectionCssClasses = findByProps("section", "lastSection");
|
||||
|
||||
const settings = definePluginSettings({
|
||||
hide: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Hide notes",
|
||||
default: false,
|
||||
restartNeeded: true
|
||||
},
|
||||
noSpellCheck: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Disable spellcheck in notes",
|
||||
disabled: () => settings.store.hide,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "BetterNotesBox",
|
||||
description: "Hide notes or disable spellcheck (Configure in settings!!)",
|
||||
authors: [Devs.Ven],
|
||||
settings,
|
||||
|
||||
patches: [
|
||||
{
|
||||
|
@ -36,7 +52,7 @@ export default definePlugin({
|
|||
all: true,
|
||||
// Some modules match the find but the replacement is returned untouched
|
||||
noWarn: true,
|
||||
predicate: () => Vencord.Settings.plugins.BetterNotesBox.hide,
|
||||
predicate: () => settings.store.hide,
|
||||
replacement: {
|
||||
match: /hideNote:.+?(?=([,}].*?\)))/g,
|
||||
replace: (m, rest) => {
|
||||
|
@ -54,7 +70,7 @@ export default definePlugin({
|
|||
find: "Messages.NOTE_PLACEHOLDER",
|
||||
replacement: {
|
||||
match: /\.NOTE_PLACEHOLDER,/,
|
||||
replace: "$&spellCheck:!Vencord.Settings.plugins.BetterNotesBox.noSpellCheck,"
|
||||
replace: "$&spellCheck:!$self.settings.store.noSpellCheck,"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -66,21 +82,6 @@ export default definePlugin({
|
|||
}
|
||||
],
|
||||
|
||||
options: {
|
||||
hide: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Hide notes",
|
||||
default: false,
|
||||
restartNeeded: true
|
||||
},
|
||||
noSpellCheck: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Disable spellcheck in notes",
|
||||
disabled: () => Settings.plugins.BetterNotesBox.hide,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
patchPadding: ErrorBoundary.wrap(({ lastSection }) => {
|
||||
if (!lastSection) return null;
|
||||
return (
|
||||
|
|
|
@ -16,16 +16,32 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { Clipboard, Toasts } from "@webpack/common";
|
||||
|
||||
const settings = definePluginSettings({
|
||||
bothStyles: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show both role dot and coloured names",
|
||||
restartNeeded: true,
|
||||
default: false,
|
||||
},
|
||||
copyRoleColorInProfilePopout: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Allow click on role dot in profile popout to copy role color",
|
||||
restartNeeded: true,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "BetterRoleDot",
|
||||
authors: [Devs.Ven, Devs.AutumnVN],
|
||||
description:
|
||||
"Copy role colour on RoleDot (accessibility setting) click. Also allows using both RoleDot and coloured names simultaneously",
|
||||
settings,
|
||||
|
||||
patches: [
|
||||
{
|
||||
|
@ -39,7 +55,7 @@ export default definePlugin({
|
|||
find: '"dot"===',
|
||||
all: true,
|
||||
noWarn: true,
|
||||
predicate: () => Settings.plugins.BetterRoleDot.bothStyles,
|
||||
predicate: () => settings.store.bothStyles,
|
||||
replacement: {
|
||||
match: /"(?:username|dot)"===\i(?!\.\i)/g,
|
||||
replace: "true",
|
||||
|
@ -49,7 +65,7 @@ export default definePlugin({
|
|||
{
|
||||
find: ".ADD_ROLE_A11Y_LABEL",
|
||||
all: true,
|
||||
predicate: () => Settings.plugins.BetterRoleDot.copyRoleColorInProfilePopout && !Settings.plugins.BetterRoleDot.bothStyles,
|
||||
predicate: () => settings.store.copyRoleColorInProfilePopout && !settings.store.bothStyles,
|
||||
noWarn: true,
|
||||
replacement: {
|
||||
match: /"dot"===\i/,
|
||||
|
@ -59,7 +75,7 @@ export default definePlugin({
|
|||
{
|
||||
find: ".roleVerifiedIcon",
|
||||
all: true,
|
||||
predicate: () => Settings.plugins.BetterRoleDot.copyRoleColorInProfilePopout && !Settings.plugins.BetterRoleDot.bothStyles,
|
||||
predicate: () => settings.store.copyRoleColorInProfilePopout && !settings.store.bothStyles,
|
||||
noWarn: true,
|
||||
replacement: {
|
||||
match: /"dot"===\i/,
|
||||
|
@ -68,21 +84,6 @@ export default definePlugin({
|
|||
}
|
||||
],
|
||||
|
||||
options: {
|
||||
bothStyles: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Show both role dot and coloured names",
|
||||
restartNeeded: true,
|
||||
default: false,
|
||||
},
|
||||
copyRoleColorInProfilePopout: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Allow click on role dot in profile popout to copy role color",
|
||||
restartNeeded: true,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
copyToClipBoard(color: string) {
|
||||
Clipboard.copy(color);
|
||||
Toasts.show({
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
|
@ -26,7 +26,7 @@ function setCss() {
|
|||
style.textContent = `
|
||||
.vc-nsfw-img [class^=imageWrapper] img,
|
||||
.vc-nsfw-img [class^=wrapperPaused] video {
|
||||
filter: blur(${Settings.plugins.BlurNSFW.blurAmount}px);
|
||||
filter: blur(${settings.store.blurAmount}px);
|
||||
transition: filter 0.2s;
|
||||
}
|
||||
.vc-nsfw-img [class^=imageWrapper]:hover img,
|
||||
|
@ -36,10 +36,20 @@ function setCss() {
|
|||
`;
|
||||
}
|
||||
|
||||
const settings = definePluginSettings({
|
||||
blurAmount: {
|
||||
type: OptionType.NUMBER,
|
||||
description: "Blur Amount",
|
||||
default: 10,
|
||||
onChange: setCss
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "BlurNSFW",
|
||||
description: "Blur attachments in NSFW channels until hovered",
|
||||
authors: [Devs.Ven],
|
||||
settings,
|
||||
|
||||
patches: [
|
||||
{
|
||||
|
@ -51,15 +61,6 @@ export default definePlugin({
|
|||
}
|
||||
],
|
||||
|
||||
options: {
|
||||
blurAmount: {
|
||||
type: OptionType.NUMBER,
|
||||
description: "Blur Amount",
|
||||
default: 10,
|
||||
onChange: setCss
|
||||
}
|
||||
},
|
||||
|
||||
start() {
|
||||
style = document.createElement("style");
|
||||
style.id = "VcBlurNsfw";
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { useTimer } from "@utils/react";
|
||||
|
@ -25,7 +25,7 @@ import { React } from "@webpack/common";
|
|||
|
||||
function formatDuration(ms: number) {
|
||||
// here be dragons (moment fucking sucks)
|
||||
const human = Settings.plugins.CallTimer.format === "human";
|
||||
const human = settings.store.format === "human";
|
||||
|
||||
const format = (n: number) => human ? n : n.toString().padStart(2, "0");
|
||||
const unit = (s: string) => human ? s : "";
|
||||
|
@ -46,15 +46,7 @@ function formatDuration(ms: number) {
|
|||
return res;
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "CallTimer",
|
||||
description: "Adds a timer to vcs",
|
||||
authors: [Devs.Ven],
|
||||
|
||||
startTime: 0,
|
||||
interval: void 0 as NodeJS.Timeout | undefined,
|
||||
|
||||
options: {
|
||||
const settings = definePluginSettings({
|
||||
format: {
|
||||
type: OptionType.SELECT,
|
||||
description: "The timer format. This can be any valid moment.js format",
|
||||
|
@ -70,7 +62,16 @@ export default definePlugin({
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "CallTimer",
|
||||
description: "Adds a timer to vcs",
|
||||
authors: [Devs.Ven],
|
||||
settings,
|
||||
|
||||
startTime: 0,
|
||||
interval: void 0 as NodeJS.Timeout | undefined,
|
||||
|
||||
patches: [{
|
||||
find: "renderConnectionStatus(){",
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { definePluginSettings, Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { ErrorCard } from "@components/ErrorCard";
|
||||
import { Link } from "@components/Link";
|
||||
import { Devs } from "@utils/constants";
|
||||
|
@ -258,7 +258,7 @@ const settings = definePluginSettings({
|
|||
|
||||
function onChange() {
|
||||
setRpc(true);
|
||||
if (Settings.plugins.CustomRPC.enabled) setRpc();
|
||||
if (Vencord.Plugins.isPluginEnabled("CustomRPC")) setRpc();
|
||||
}
|
||||
|
||||
function isStreamLinkDisabled() {
|
||||
|
|
|
@ -21,20 +21,25 @@ import { Devs } from "@utils/constants";
|
|||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findByProps, findStore } from "@webpack";
|
||||
import { ChannelStore, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserStore } from "@webpack/common";
|
||||
import { Settings } from "Vencord";
|
||||
|
||||
const UserAffinitiesStore = findStore("UserAffinitiesStore");
|
||||
const { FriendsSections } = findByProps("FriendsSections");
|
||||
|
||||
interface UserAffinity {
|
||||
user_id: string;
|
||||
affinity: number;
|
||||
const settings = definePluginSettings({
|
||||
sortByAffinity: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Whether to sort implicit relationships by their affinity to you.",
|
||||
restartNeeded: true
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "ImplicitRelationships",
|
||||
description: "Shows your implicit relationships in the Friends tab.",
|
||||
authors: [Devs.Dolfies],
|
||||
settings,
|
||||
|
||||
patches: [
|
||||
// Counts header
|
||||
{
|
||||
|
@ -81,7 +86,7 @@ export default definePlugin({
|
|||
{
|
||||
find: "getRelationshipCounts(){",
|
||||
replacement: {
|
||||
predicate: () => Settings.plugins.ImplicitRelationships.sortByAffinity,
|
||||
predicate: () => settings.store.sortByAffinity,
|
||||
match: /\}\)\.sortBy\((.+?)\)\.value\(\)/,
|
||||
replace: "}).sortBy(row => $self.wrapSort(($1), row)).value()"
|
||||
}
|
||||
|
@ -110,16 +115,6 @@ export default definePlugin({
|
|||
},
|
||||
}
|
||||
],
|
||||
settings: definePluginSettings(
|
||||
{
|
||||
sortByAffinity: {
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true,
|
||||
description: "Whether to sort implicit relationships by their affinity to you.",
|
||||
restartNeeded: true
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
wrapSort(comparator: Function, row: any) {
|
||||
return row.type === 5
|
||||
|
|
|
@ -20,7 +20,7 @@ import "./messageLogger.css";
|
|||
|
||||
import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/ContextMenu";
|
||||
import { updateMessage } from "@api/MessageUpdater";
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { disableStyle, enableStyle } from "@api/Styles";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
|
@ -41,7 +41,7 @@ interface MLMessage extends Message {
|
|||
const styles = findByProps("edited", "communicationDisabled", "isSystemMessage");
|
||||
|
||||
function addDeleteStyle() {
|
||||
if (Settings.plugins.MessageLogger.deleteStyle === "text") {
|
||||
if (settings.store.deleteStyle === "text") {
|
||||
enableStyle(textStyle);
|
||||
disableStyle(overlayStyle);
|
||||
} else {
|
||||
|
@ -125,57 +125,7 @@ const patchChannelContextMenu: NavContextMenuPatchCallback = (children, { channe
|
|||
);
|
||||
};
|
||||
|
||||
export default definePlugin({
|
||||
name: "MessageLogger",
|
||||
description: "Temporarily logs deleted and edited messages.",
|
||||
authors: [Devs.rushii, Devs.Ven, Devs.AutumnVN, Devs.Nickyux],
|
||||
dependencies: ["MessageUpdaterAPI"],
|
||||
|
||||
contextMenus: {
|
||||
"message": patchMessageContextMenu,
|
||||
"channel-context": patchChannelContextMenu,
|
||||
"user-context": patchChannelContextMenu,
|
||||
"gdm-context": patchChannelContextMenu
|
||||
},
|
||||
|
||||
start() {
|
||||
addDeleteStyle();
|
||||
},
|
||||
|
||||
renderEdits: ErrorBoundary.wrap(({ message: { id: messageId, channel_id: channelId } }: { message: Message; }) => {
|
||||
const message = useStateFromStores(
|
||||
[MessageStore],
|
||||
() => MessageStore.getMessage(channelId, messageId) as MLMessage,
|
||||
null,
|
||||
(oldMsg, newMsg) => oldMsg?.editHistory === newMsg?.editHistory
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{message.editHistory?.map(edit => (
|
||||
<div className="messagelogger-edited">
|
||||
{Parser.parse(edit.content)}
|
||||
<Timestamp
|
||||
timestamp={edit.timestamp}
|
||||
isEdited={true}
|
||||
isInline={false}
|
||||
>
|
||||
<span className={styles.edited}>{" "}({i18n.Messages.MESSAGE_EDITED})</span>
|
||||
</Timestamp>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}, { noop: true }),
|
||||
|
||||
makeEdit(newMessage: any, oldMessage: any): any {
|
||||
return {
|
||||
timestamp: new Date(newMessage.edited_timestamp),
|
||||
content: oldMessage.content
|
||||
};
|
||||
},
|
||||
|
||||
options: {
|
||||
const settings = definePluginSettings({
|
||||
deleteStyle: {
|
||||
type: OptionType.SELECT,
|
||||
description: "The style of deleted messages",
|
||||
|
@ -221,6 +171,57 @@ export default definePlugin({
|
|||
description: "Comma-separated list of guild IDs to ignore",
|
||||
default: ""
|
||||
},
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "MessageLogger",
|
||||
description: "Temporarily logs deleted and edited messages.",
|
||||
authors: [Devs.rushii, Devs.Ven, Devs.AutumnVN, Devs.Nickyux],
|
||||
dependencies: ["MessageUpdaterAPI"],
|
||||
settings,
|
||||
|
||||
contextMenus: {
|
||||
"message": patchMessageContextMenu,
|
||||
"channel-context": patchChannelContextMenu,
|
||||
"user-context": patchChannelContextMenu,
|
||||
"gdm-context": patchChannelContextMenu
|
||||
},
|
||||
|
||||
start() {
|
||||
addDeleteStyle();
|
||||
},
|
||||
|
||||
renderEdits: ErrorBoundary.wrap(({ message: { id: messageId, channel_id: channelId } }: { message: Message; }) => {
|
||||
const message = useStateFromStores(
|
||||
[MessageStore],
|
||||
() => MessageStore.getMessage(channelId, messageId) as MLMessage,
|
||||
null,
|
||||
(oldMsg, newMsg) => oldMsg?.editHistory === newMsg?.editHistory
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{message.editHistory?.map(edit => (
|
||||
<div className="messagelogger-edited">
|
||||
{Parser.parse(edit.content)}
|
||||
<Timestamp
|
||||
timestamp={edit.timestamp}
|
||||
isEdited={true}
|
||||
isInline={false}
|
||||
>
|
||||
<span className={styles.edited}>{" "}({i18n.Messages.MESSAGE_EDITED})</span>
|
||||
</Timestamp>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}, { noop: true }),
|
||||
|
||||
makeEdit(newMessage: any, oldMessage: any): any {
|
||||
return {
|
||||
timestamp: new Date(newMessage.edited_timestamp),
|
||||
content: oldMessage.content
|
||||
};
|
||||
},
|
||||
|
||||
handleDelete(cache: any, data: { ids: string[], id: string; mlDeleted?: boolean; }, isBulk: boolean) {
|
||||
|
@ -257,7 +258,7 @@ export default definePlugin({
|
|||
},
|
||||
|
||||
shouldIgnore(message: any, isEdit = false) {
|
||||
const { ignoreBots, ignoreSelf, ignoreUsers, ignoreChannels, ignoreGuilds, logEdits, logDeletes } = Settings.plugins.MessageLogger;
|
||||
const { ignoreBots, ignoreSelf, ignoreUsers, ignoreChannels, ignoreGuilds, logEdits, logDeletes } = settings.store;
|
||||
const myId = UserStore.getCurrentUser().id;
|
||||
|
||||
return ignoreBots && message.author?.bot ||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, registerCommand, sendBotMessage, unregisterCommand } from "@api/Commands";
|
||||
import * as DataStore from "@api/DataStore";
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
||||
|
@ -60,7 +60,7 @@ function createTagCommand(tag: Tag) {
|
|||
return { content: `/${tag.name}` };
|
||||
}
|
||||
|
||||
if (Settings.plugins.MessageTags.clyde) sendBotMessage(ctx.channel.id, {
|
||||
if (settings.store.clyde) sendBotMessage(ctx.channel.id, {
|
||||
content: `${EMOTE} The tag **${tag.name}** has been sent!`
|
||||
});
|
||||
return { content: tag.message.replaceAll("\\n", "\n") };
|
||||
|
@ -69,19 +69,21 @@ function createTagCommand(tag: Tag) {
|
|||
}, "CustomTags");
|
||||
}
|
||||
|
||||
|
||||
export default definePlugin({
|
||||
name: "MessageTags",
|
||||
description: "Allows you to save messages and to use them with a simple command.",
|
||||
authors: [Devs.Luna],
|
||||
options: {
|
||||
const settings = definePluginSettings({
|
||||
clyde: {
|
||||
name: "Clyde message on send",
|
||||
description: "If enabled, clyde will send you an ephemeral message when a tag was used.",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "MessageTags",
|
||||
description: "Allows you to save messages and to use them with a simple command.",
|
||||
authors: [Devs.Luna],
|
||||
settings,
|
||||
|
||||
dependencies: ["CommandsAPI"],
|
||||
|
||||
async start() {
|
||||
|
|
|
@ -16,17 +16,28 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
import { findByProps } from "@webpack";
|
||||
|
||||
const RelationshipStore = findByProps("getRelationships", "isBlocked");
|
||||
|
||||
const settings = definePluginSettings({
|
||||
ignoreBlockedMessages: {
|
||||
description: "Completely ignores (recent) incoming messages from blocked users (locally).",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
restartNeeded: true,
|
||||
},
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "NoBlockedMessages",
|
||||
description: "Hides all blocked messages from chat completely.",
|
||||
authors: [Devs.rushii, Devs.Samu],
|
||||
settings,
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: "Messages.BLOCKED_MESSAGES_HIDE",
|
||||
|
@ -42,7 +53,7 @@ export default definePlugin({
|
|||
'"displayName","ReadStateStore")'
|
||||
].map(find => ({
|
||||
find,
|
||||
predicate: () => Settings.plugins.NoBlockedMessages.ignoreBlockedMessages === true,
|
||||
predicate: () => settings.store.ignoreBlockedMessages === true,
|
||||
replacement: [
|
||||
{
|
||||
match: /(?<=MESSAGE_CREATE:function\((\i)\){)/,
|
||||
|
@ -51,14 +62,6 @@ export default definePlugin({
|
|||
]
|
||||
}))
|
||||
],
|
||||
options: {
|
||||
ignoreBlockedMessages: {
|
||||
description: "Completely ignores (recent) incoming messages from blocked users (locally).",
|
||||
type: OptionType.BOOLEAN,
|
||||
default: false,
|
||||
restartNeeded: true,
|
||||
},
|
||||
},
|
||||
isBlocked: message =>
|
||||
RelationshipStore.isBlocked(message.author.id)
|
||||
});
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import { addBadge, BadgePosition, ProfileBadge, removeBadge } from "@api/Badges";
|
||||
import { addDecorator, removeDecorator } from "@api/MemberListDecorators";
|
||||
import { addDecoration, removeDecoration } from "@api/MessageDecorations";
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
@ -162,27 +162,34 @@ const indicatorLocations = {
|
|||
}
|
||||
};
|
||||
|
||||
const settings = definePluginSettings({
|
||||
...Object.fromEntries(
|
||||
Object.entries(indicatorLocations).map(([key, value]) => {
|
||||
return [key, {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: `Show indicators ${value.description.toLowerCase()}`,
|
||||
// onChange doesn't give any way to know which setting was changed, so restart required
|
||||
restartNeeded: true,
|
||||
default: true
|
||||
}];
|
||||
})
|
||||
) as Record<"list" | "badges" | "messages", { type: OptionType.BOOLEAN; description: string; restartNeeded: boolean; default: boolean; }>,
|
||||
colorMobileIndicator: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Whether to make the mobile indicator match the color of the user status.",
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
}
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "PlatformIndicators",
|
||||
description: "Adds platform indicators (Desktop, Mobile, Web...) to users",
|
||||
authors: [Devs.kemo, Devs.TheSun, Devs.Nuckyz, Devs.Ven],
|
||||
dependencies: ["MessageDecorationsAPI", "MemberListDecoratorsAPI"],
|
||||
settings,
|
||||
|
||||
start() {
|
||||
const settings = Settings.plugins.PlatformIndicators;
|
||||
const { displayMode } = settings;
|
||||
|
||||
// transfer settings from the old ones, which had a select menu instead of booleans
|
||||
if (displayMode) {
|
||||
if (displayMode !== "both") settings[displayMode] = true;
|
||||
else {
|
||||
settings.list = true;
|
||||
settings.badges = true;
|
||||
}
|
||||
settings.messages = true;
|
||||
delete settings.displayMode;
|
||||
}
|
||||
|
||||
Object.entries(indicatorLocations).forEach(([key, value]) => {
|
||||
if (settings[key]) value.onEnable();
|
||||
});
|
||||
|
@ -197,7 +204,7 @@ export default definePlugin({
|
|||
patches: [
|
||||
{
|
||||
find: ".Masks.STATUS_ONLINE_MOBILE",
|
||||
predicate: () => Settings.plugins.PlatformIndicators.colorMobileIndicator,
|
||||
predicate: () => settings.store.colorMobileIndicator,
|
||||
replacement: [
|
||||
{
|
||||
// Return the STATUS_ONLINE_MOBILE mask if the user is on mobile, no matter the status
|
||||
|
@ -213,7 +220,7 @@ export default definePlugin({
|
|||
},
|
||||
{
|
||||
find: ".AVATAR_STATUS_MOBILE_16;",
|
||||
predicate: () => Settings.plugins.PlatformIndicators.colorMobileIndicator,
|
||||
predicate: () => settings.store.colorMobileIndicator,
|
||||
replacement: [
|
||||
{
|
||||
// Return the AVATAR_STATUS_MOBILE size mask if the user is on mobile, no matter the status
|
||||
|
@ -234,32 +241,12 @@ export default definePlugin({
|
|||
},
|
||||
{
|
||||
find: "}isMobileOnline(",
|
||||
predicate: () => Settings.plugins.PlatformIndicators.colorMobileIndicator,
|
||||
predicate: () => settings.store.colorMobileIndicator,
|
||||
replacement: {
|
||||
// Make isMobileOnline return true no matter what is the user status
|
||||
match: /(?<=\i\[\i\.\i\.MOBILE\])===\i\.\i\.ONLINE/,
|
||||
replace: "!= null"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
options: {
|
||||
...Object.fromEntries(
|
||||
Object.entries(indicatorLocations).map(([key, value]) => {
|
||||
return [key, {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: `Show indicators ${value.description.toLowerCase()}`,
|
||||
// onChange doesn't give any way to know which setting was changed, so restart required
|
||||
restartNeeded: true,
|
||||
default: true
|
||||
}];
|
||||
})
|
||||
),
|
||||
colorMobileIndicator: {
|
||||
type: OptionType.BOOLEAN,
|
||||
description: "Whether to make the mobile indicator match the color of the user status.",
|
||||
default: true,
|
||||
restartNeeded: true
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { debounce } from "@shared/debounce";
|
||||
import { VENCORD_USER_AGENT } from "@shared/vencordUserAgent";
|
||||
import { getCurrentChannel } from "@utils/discord";
|
||||
|
@ -147,11 +146,11 @@ async function bulkFetchPronouns(ids: string[]): Promise<PronounsResponse> {
|
|||
}
|
||||
}
|
||||
|
||||
export function extractPronouns(pronounSet?: { [locale: string]: PronounCode[] }): string {
|
||||
export function extractPronouns(pronounSet?: { [locale: string]: PronounCode[]; }): string {
|
||||
if (!pronounSet || !pronounSet.en) return PronounMapping.unspecified;
|
||||
// PronounDB returns an empty set instead of {sets: {en: ["unspecified"]}}.
|
||||
const pronouns = pronounSet.en;
|
||||
const { pronounsFormat } = Settings.plugins.PronounDB as { pronounsFormat: PronounsFormat, enabled: boolean; };
|
||||
const { pronounsFormat } = settings.store;
|
||||
|
||||
if (pronouns.length === 1) {
|
||||
// For capitalized pronouns or special codes (any, ask, avoid), we always return the normal (capitalized) string
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import { addServerListElement, removeServerListElement, ServerListRenderPosition } from "@api/ServerList";
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { useForceUpdater } from "@utils/react";
|
||||
|
@ -89,13 +89,7 @@ function handleGuildUpdate() {
|
|||
forceUpdateGuildCount?.();
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "ServerListIndicators",
|
||||
description: "Add online friend count or server count in the server list",
|
||||
authors: [Devs.dzshn],
|
||||
dependencies: ["ServerListAPI"],
|
||||
|
||||
options: {
|
||||
const settings = definePluginSettings({
|
||||
mode: {
|
||||
description: "mode",
|
||||
type: OptionType.SELECT,
|
||||
|
@ -105,10 +99,17 @@ export default definePlugin({
|
|||
{ label: "Both server and online friend counts", value: IndicatorType.BOTH },
|
||||
]
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "ServerListIndicators",
|
||||
description: "Add online friend count or server count in the server list",
|
||||
authors: [Devs.dzshn],
|
||||
dependencies: ["ServerListAPI"],
|
||||
settings,
|
||||
|
||||
renderIndicator: () => {
|
||||
const { mode } = Settings.plugins.ServerListIndicators;
|
||||
const { mode } = settings.store;
|
||||
return <ErrorBoundary noop>
|
||||
<div style={{ marginBottom: "4px" }}>
|
||||
{!!(mode & IndicatorType.FRIEND) && <FriendsIndicator />}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { formatDuration } from "@utils/text";
|
||||
import { findByProps, findComponentByCode } from "@webpack";
|
||||
|
@ -157,7 +156,7 @@ function HiddenChannelLockScreen({ channel }: { channel: ExtendedChannel; }) {
|
|||
});
|
||||
}
|
||||
|
||||
if (Settings.plugins.PermissionsViewer.enabled) {
|
||||
if (Vencord.Plugins.isPluginEnabled("PermissionsViewer")) {
|
||||
setPermissions(sortPermissionOverwrites(Object.values(permissionOverwrites).map(overwrite => ({
|
||||
type: overwrite.type as PermissionType,
|
||||
id: overwrite.id,
|
||||
|
@ -274,7 +273,7 @@ function HiddenChannelLockScreen({ channel }: { channel: ExtendedChannel; }) {
|
|||
}
|
||||
<div className="shc-lock-screen-allowed-users-and-roles-container">
|
||||
<div className="shc-lock-screen-allowed-users-and-roles-container-title">
|
||||
{Settings.plugins.PermissionsViewer.enabled && (
|
||||
{Vencord.Plugins.isPluginEnabled("PermissionsViewer") && (
|
||||
<Tooltip text="Permission Details">
|
||||
{({ onMouseLeave, onMouseEnter }) => (
|
||||
<button
|
||||
|
|
|
@ -16,10 +16,13 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { proxyLazy } from "@utils/lazy";
|
||||
import { findByProps, webpackDependantLazy } from "@webpack";
|
||||
import { Flux, FluxDispatcher } from "@webpack/common";
|
||||
|
||||
// Avoid circular dependency
|
||||
const { settings } = proxyLazy(() => require(".")) as typeof import(".");
|
||||
|
||||
export interface Track {
|
||||
id: string;
|
||||
name: string;
|
||||
|
@ -88,7 +91,7 @@ export const SpotifyStore = webpackDependantLazy(() => {
|
|||
public isSettingPosition = false;
|
||||
|
||||
public openExternal(path: string) {
|
||||
const url = Settings.plugins.SpotifyControls.useSpotifyUris || Vencord.Plugins.isPluginEnabled("OpenInApp")
|
||||
const url = settings.store.useSpotifyUris || Vencord.Plugins.isPluginEnabled("OpenInApp")
|
||||
? "spotify:" + path.replaceAll("/", (_, idx) => idx === 0 ? "" : ":")
|
||||
: "https://open.spotify.com" + path;
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { disableStyle, enableStyle } from "@api/Styles";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
|
@ -29,11 +29,7 @@ function toggleHoverControls(value: boolean) {
|
|||
(value ? enableStyle : disableStyle)(hoverOnlyStyle);
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "SpotifyControls",
|
||||
description: "Adds a Spotify player above the account panel",
|
||||
authors: [Devs.Ven, Devs.afn, Devs.KraXen72, Devs.Av32000],
|
||||
options: {
|
||||
export const settings = definePluginSettings({
|
||||
hoverControls: {
|
||||
description: "Show controls on hover",
|
||||
type: OptionType.BOOLEAN,
|
||||
|
@ -45,7 +41,14 @@ export default definePlugin({
|
|||
description: "Open Spotify URIs instead of Spotify URLs. Will only work if you have Spotify installed and might not work on all platforms",
|
||||
default: false
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "SpotifyControls",
|
||||
description: "Adds a Spotify player above the account panel",
|
||||
authors: [Devs.Ven, Devs.afn, Devs.KraXen72, Devs.Av32000],
|
||||
settings,
|
||||
|
||||
patches: [
|
||||
{
|
||||
find: "showTaglessAccountPanel:",
|
||||
|
@ -87,7 +90,7 @@ export default definePlugin({
|
|||
}
|
||||
],
|
||||
|
||||
start: () => toggleHoverControls(Settings.plugins.SpotifyControls.hoverControls),
|
||||
start: () => toggleHoverControls(settings.store.hoverControls),
|
||||
|
||||
PanelWrapper({ VencordOriginal, ...props }) {
|
||||
return (
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import "./style.css";
|
||||
|
||||
import { definePluginSettings, Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import ErrorBoundary from "@components/ErrorBoundary";
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { OptionType } from "@utils/types";
|
||||
|
@ -87,7 +87,7 @@ function TypingIndicator({ channelId }: { channelId: string; }) {
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
tooltipText = Settings.plugins.TypingTweaks.enabled
|
||||
tooltipText = Vencord.Plugins.isPluginEnabled("TypingTweaks")
|
||||
? buildSeveralUsers({ a: getDisplayName(guildId, typingUsersArray[0]), b: getDisplayName(guildId, typingUsersArray[1]), count: typingUsersArray.length - 2 })
|
||||
: i18n.Messages.SEVERAL_USERS_TYPING;
|
||||
break;
|
||||
|
|
|
@ -16,13 +16,14 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Settings } from "@api/Settings";
|
||||
import { definePluginSettings } from "@api/Settings";
|
||||
import { ErrorCard } from "@components/ErrorCard";
|
||||
import { Devs } from "@utils/constants";
|
||||
import { proxyLazy } from "@utils/lazy";
|
||||
import { Logger } from "@utils/Logger";
|
||||
import { Margins } from "@utils/margins";
|
||||
import { wordsToTitle } from "@utils/text";
|
||||
import definePlugin, { OptionType, PluginOptionsItem, ReporterTestable } from "@utils/types";
|
||||
import definePlugin, { OptionType, ReporterTestable } from "@utils/types";
|
||||
import { findByProps } from "@webpack";
|
||||
import { Button, ChannelStore, Forms, GuildMemberStore, SelectedChannelStore, SelectedGuildStore, useMemo, UserStore } from "@webpack/common";
|
||||
|
||||
|
@ -42,25 +43,25 @@ const VoiceStateStore = findByProps("getVoiceStatesForChannel", "getCurrentClien
|
|||
// Filtering out events is not as simple as just dropping duplicates, as otherwise mute, unmute, mute would
|
||||
// not say the second mute, which would lead you to believe they're unmuted
|
||||
|
||||
function speak(text: string, settings: any = Settings.plugins.VcNarrator) {
|
||||
function speak(text: string, mergedSettings: typeof settings.store = settings.store) {
|
||||
if (!text) return;
|
||||
|
||||
const speech = new SpeechSynthesisUtterance(text);
|
||||
let voice = speechSynthesis.getVoices().find(v => v.voiceURI === settings.voice);
|
||||
let voice = speechSynthesis.getVoices().find(v => v.voiceURI === mergedSettings.voice);
|
||||
if (!voice) {
|
||||
new Logger("VcNarrator").error(`Voice "${settings.voice}" not found. Resetting to default.`);
|
||||
new Logger("VcNarrator").error(`Voice "${mergedSettings.voice}" not found. Resetting to default.`);
|
||||
voice = speechSynthesis.getVoices().find(v => v.default);
|
||||
settings.voice = voice?.voiceURI;
|
||||
mergedSettings.voice = voice?.voiceURI as string;
|
||||
if (!voice) return; // This should never happen
|
||||
}
|
||||
speech.voice = voice!;
|
||||
speech.volume = settings.volume;
|
||||
speech.rate = settings.rate;
|
||||
speech.voice = voice;
|
||||
speech.volume = mergedSettings.volume;
|
||||
speech.rate = mergedSettings.rate;
|
||||
speechSynthesis.speak(speech);
|
||||
}
|
||||
|
||||
function clean(str: string) {
|
||||
const replacer = Settings.plugins.VcNarrator.latinOnly
|
||||
const replacer = settings.store.latinOnly
|
||||
? /[^\p{Script=Latin}\p{Number}\p{Punctuation}\s]/gu
|
||||
: /[^\p{Letter}\p{Number}\p{Punctuation}\s]/gu;
|
||||
|
||||
|
@ -143,92 +144,23 @@ function updateStatuses(type: string, { deaf, mute, selfDeaf, selfMute, userId,
|
|||
}
|
||||
*/
|
||||
|
||||
function playSample(tempSettings: any, type: string) {
|
||||
const settings = Object.assign({}, Settings.plugins.VcNarrator, tempSettings);
|
||||
function playSample(tempSettings: typeof settings.store, type: string) {
|
||||
const mergedSettings = Object.assign({}, settings.store, tempSettings);
|
||||
const currentUser = UserStore.getCurrentUser();
|
||||
const myGuildId = SelectedGuildStore.getGuildId();
|
||||
|
||||
speak(formatText(settings[type + "Message"], currentUser.username, "general", (currentUser as any).globalName ?? currentUser.username, GuildMemberStore.getNick(myGuildId, currentUser.id) ?? currentUser.username), settings);
|
||||
speak(formatText(mergedSettings[type + "Message"], currentUser.username, "general", (currentUser as any).globalName ?? currentUser.username, GuildMemberStore.getNick(myGuildId, currentUser.id) ?? currentUser.username), mergedSettings);
|
||||
}
|
||||
|
||||
export default definePlugin({
|
||||
name: "VcNarrator",
|
||||
description: "Announces when users join, leave, or move voice channels via narrator",
|
||||
authors: [Devs.Ven],
|
||||
reporterTestable: ReporterTestable.None,
|
||||
|
||||
flux: {
|
||||
VOICE_STATE_UPDATES({ voiceStates }: { voiceStates: VoiceState[]; }) {
|
||||
const myGuildId = SelectedGuildStore.getGuildId();
|
||||
const myChanId = SelectedChannelStore.getVoiceChannelId();
|
||||
const myId = UserStore.getCurrentUser().id;
|
||||
|
||||
if (ChannelStore.getChannel(myChanId!)?.type === 13 /* Stage Channel */) return;
|
||||
|
||||
for (const state of voiceStates) {
|
||||
const { userId, channelId, oldChannelId } = state;
|
||||
const isMe = userId === myId;
|
||||
if (!isMe) {
|
||||
if (!myChanId) continue;
|
||||
if (channelId !== myChanId && oldChannelId !== myChanId) continue;
|
||||
}
|
||||
|
||||
const [type, id] = getTypeAndChannelId(state, isMe);
|
||||
if (!type) continue;
|
||||
|
||||
const template = Settings.plugins.VcNarrator[type + "Message"];
|
||||
const user = isMe && !Settings.plugins.VcNarrator.sayOwnName ? "" : UserStore.getUser(userId).username;
|
||||
const displayName = user && ((UserStore.getUser(userId) as any).globalName ?? user);
|
||||
const nickname = user && (GuildMemberStore.getNick(myGuildId, userId) ?? user);
|
||||
const channel = ChannelStore.getChannel(id).name;
|
||||
|
||||
speak(formatText(template, user, channel, displayName, nickname));
|
||||
|
||||
// updateStatuses(type, state, isMe);
|
||||
}
|
||||
},
|
||||
|
||||
AUDIO_TOGGLE_SELF_MUTE() {
|
||||
const chanId = SelectedChannelStore.getVoiceChannelId()!;
|
||||
const s = VoiceStateStore.getVoiceStateForChannel(chanId) as VoiceState;
|
||||
if (!s) return;
|
||||
|
||||
const event = s.mute || s.selfMute ? "unmute" : "mute";
|
||||
speak(formatText(Settings.plugins.VcNarrator[event + "Message"], "", ChannelStore.getChannel(chanId).name, "", ""));
|
||||
},
|
||||
|
||||
AUDIO_TOGGLE_SELF_DEAF() {
|
||||
const chanId = SelectedChannelStore.getVoiceChannelId()!;
|
||||
const s = VoiceStateStore.getVoiceStateForChannel(chanId) as VoiceState;
|
||||
if (!s) return;
|
||||
|
||||
const event = s.deaf || s.selfDeaf ? "undeafen" : "deafen";
|
||||
speak(formatText(Settings.plugins.VcNarrator[event + "Message"], "", ChannelStore.getChannel(chanId).name, "", ""));
|
||||
}
|
||||
},
|
||||
|
||||
start() {
|
||||
if (typeof speechSynthesis === "undefined" || speechSynthesis.getVoices().length === 0) {
|
||||
new Logger("VcNarrator").warn(
|
||||
"SpeechSynthesis not supported or no Narrator voices found. Thus, this plugin will not work. Check my Settings for more info"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
optionsCache: null as Record<string, PluginOptionsItem> | null,
|
||||
|
||||
get options() {
|
||||
return this.optionsCache ??= {
|
||||
const settings = definePluginSettings({
|
||||
voice: {
|
||||
type: OptionType.SELECT,
|
||||
description: "Narrator Voice",
|
||||
options: window.speechSynthesis?.getVoices().map(v => ({
|
||||
options: proxyLazy(() => window.speechSynthesis?.getVoices().map(v => ({
|
||||
label: v.name,
|
||||
value: v.voiceURI,
|
||||
default: v.default
|
||||
})) ?? []
|
||||
})) ?? [])
|
||||
},
|
||||
volume: {
|
||||
type: OptionType.SLIDER,
|
||||
|
@ -289,7 +221,73 @@ export default definePlugin({
|
|||
description: "Undeafen Message (only self for now)",
|
||||
default: "{{USER}} undeafened"
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
export default definePlugin({
|
||||
name: "VcNarrator",
|
||||
description: "Announces when users join, leave, or move voice channels via narrator",
|
||||
authors: [Devs.Ven],
|
||||
reporterTestable: ReporterTestable.None,
|
||||
settings,
|
||||
|
||||
flux: {
|
||||
VOICE_STATE_UPDATES({ voiceStates }: { voiceStates: VoiceState[]; }) {
|
||||
const myGuildId = SelectedGuildStore.getGuildId();
|
||||
const myChanId = SelectedChannelStore.getVoiceChannelId();
|
||||
const myId = UserStore.getCurrentUser().id;
|
||||
|
||||
if (ChannelStore.getChannel(myChanId!)?.type === 13 /* Stage Channel */) return;
|
||||
|
||||
for (const state of voiceStates) {
|
||||
const { userId, channelId, oldChannelId } = state;
|
||||
const isMe = userId === myId;
|
||||
if (!isMe) {
|
||||
if (!myChanId) continue;
|
||||
if (channelId !== myChanId && oldChannelId !== myChanId) continue;
|
||||
}
|
||||
|
||||
const [type, id] = getTypeAndChannelId(state, isMe);
|
||||
if (!type) continue;
|
||||
|
||||
const template = settings.store[type + "Message"];
|
||||
const user = isMe && !settings.store.sayOwnName ? "" : UserStore.getUser(userId).username;
|
||||
const displayName = user && ((UserStore.getUser(userId) as any).globalName ?? user);
|
||||
const nickname = user && (GuildMemberStore.getNick(myGuildId, userId) ?? user);
|
||||
const channel = ChannelStore.getChannel(id).name;
|
||||
|
||||
speak(formatText(template, user, channel, displayName, nickname));
|
||||
|
||||
// updateStatuses(type, state, isMe);
|
||||
}
|
||||
},
|
||||
|
||||
AUDIO_TOGGLE_SELF_MUTE() {
|
||||
const chanId = SelectedChannelStore.getVoiceChannelId()!;
|
||||
const s = VoiceStateStore.getVoiceStateForChannel(chanId) as VoiceState;
|
||||
if (!s) return;
|
||||
|
||||
const event = s.mute || s.selfMute ? "unmute" : "mute";
|
||||
speak(formatText(settings.store[event + "Message"], "", ChannelStore.getChannel(chanId).name, "", ""));
|
||||
},
|
||||
|
||||
AUDIO_TOGGLE_SELF_DEAF() {
|
||||
const chanId = SelectedChannelStore.getVoiceChannelId()!;
|
||||
const s = VoiceStateStore.getVoiceStateForChannel(chanId) as VoiceState;
|
||||
if (!s) return;
|
||||
|
||||
const event = s.deaf || s.selfDeaf ? "undeafen" : "deafen";
|
||||
speak(formatText(settings.store[event + "Message"], "", ChannelStore.getChannel(chanId).name, "", ""));
|
||||
}
|
||||
},
|
||||
|
||||
start() {
|
||||
if (typeof speechSynthesis === "undefined" || speechSynthesis.getVoices().length === 0) {
|
||||
new Logger("VcNarrator").warn(
|
||||
"SpeechSynthesis not supported or no Narrator voices found. Thus, this plugin will not work. Check my Settings for more info"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
settingsAboutComponent({ tempSettings: s }) {
|
||||
|
@ -299,7 +297,7 @@ export default definePlugin({
|
|||
}, []);
|
||||
|
||||
const types = useMemo(
|
||||
() => Object.keys(Vencord.Plugins.plugins.VcNarrator.options!).filter(k => k.endsWith("Message")).map(k => k.slice(0, -7)),
|
||||
() => Object.keys(settings.def).filter(k => k.endsWith("Message")).map(k => k.slice(0, -7)),
|
||||
[],
|
||||
);
|
||||
|
||||
|
@ -335,7 +333,7 @@ export default definePlugin({
|
|||
className={"vc-narrator-buttons"}
|
||||
>
|
||||
{types.map(t => (
|
||||
<Button key={t} onClick={() => playSample(s, t)}>
|
||||
<Button key={t} onClick={() => playSample(s as typeof settings.store, t)}>
|
||||
{wordsToTitle([t])}
|
||||
</Button>
|
||||
))}
|
||||
|
|
1
src/webpack/common/types/utils.d.ts
vendored
1
src/webpack/common/types/utils.d.ts
vendored
|
@ -124,6 +124,7 @@ export type Permissions = "ADD_REACTIONS"
|
|||
| "USE_APPLICATION_COMMANDS"
|
||||
| "USE_CLYDE_AI"
|
||||
| "USE_EMBEDDED_ACTIVITIES"
|
||||
| "USE_EXTERNAL_APPS"
|
||||
| "USE_EXTERNAL_EMOJIS"
|
||||
| "USE_EXTERNAL_SOUNDS"
|
||||
| "USE_EXTERNAL_STICKERS"
|
||||
|
|
Loading…
Reference in a new issue