VcNarrator: Fix voice selection setting (#3365)

This commit is contained in:
Vending Machine 2025-04-07 00:58:07 +02:00 committed by GitHub
parent d753478097
commit e5f6605c01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 240 additions and 95 deletions

View file

@ -16,17 +16,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Settings } from "@api/Settings";
import { ErrorCard } from "@components/ErrorCard";
import { Devs } from "@utils/constants";
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, { ReporterTestable } from "@utils/types";
import { findByPropsLazy } from "@webpack";
import { Button, ChannelStore, Forms, GuildMemberStore, SelectedChannelStore, SelectedGuildStore, useMemo, UserStore } from "@webpack/common";
import { ReactElement } from "react";
import { getCurrentVoice, settings } from "./settings";
interface VoiceState {
userId: string;
channelId?: string;
@ -43,25 +44,19 @@ const VoiceStateStore = findByPropsLazy("getVoiceStatesForChannel", "getCurrentC
// 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, { volume, rate } = settings.store) {
if (!text) return;
const speech = new SpeechSynthesisUtterance(text);
let voice = speechSynthesis.getVoices().find(v => v.voiceURI === settings.voice);
if (!voice) {
new Logger("VcNarrator").error(`Voice "${settings.voice}" not found. Resetting to default.`);
voice = speechSynthesis.getVoices().find(v => v.default);
settings.voice = voice?.voiceURI;
if (!voice) return; // This should never happen
}
const voice = getCurrentVoice();
speech.voice = voice!;
speech.volume = settings.volume;
speech.rate = settings.rate;
speech.volume = volume;
speech.rate = 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;
@ -145,11 +140,11 @@ function updateStatuses(type: string, { deaf, mute, selfDeaf, selfMute, userId,
*/
function playSample(tempSettings: any, type: string) {
const settings = Object.assign({}, Settings.plugins.VcNarrator, tempSettings);
const s = Object.assign({}, settings.plain, 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(s[type + "Message"], currentUser.username, "general", (currentUser as any).globalName ?? currentUser.username, GuildMemberStore.getNick(myGuildId, currentUser.id) ?? currentUser.username), s);
}
export default definePlugin({
@ -158,6 +153,8 @@ export default definePlugin({
authors: [Devs.Ven],
reporterTestable: ReporterTestable.None,
settings,
flux: {
VOICE_STATE_UPDATES({ voiceStates }: { voiceStates: VoiceState[]; }) {
const myGuildId = SelectedGuildStore.getGuildId();
@ -177,8 +174,8 @@ export default definePlugin({
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 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;
@ -195,7 +192,7 @@ export default definePlugin({
if (!s) return;
const event = s.mute || s.selfMute ? "unmute" : "mute";
speak(formatText(Settings.plugins.VcNarrator[event + "Message"], "", ChannelStore.getChannel(chanId).name, "", ""));
speak(formatText(settings.store[event + "Message"], "", ChannelStore.getChannel(chanId).name, "", ""));
},
AUDIO_TOGGLE_SELF_DEAF() {
@ -204,7 +201,7 @@ export default definePlugin({
if (!s) return;
const event = s.deaf || s.selfDeaf ? "undeafen" : "deafen";
speak(formatText(Settings.plugins.VcNarrator[event + "Message"], "", ChannelStore.getChannel(chanId).name, "", ""));
speak(formatText(settings.store[event + "Message"], "", ChannelStore.getChannel(chanId).name, "", ""));
}
},
@ -218,81 +215,6 @@ export default definePlugin({
},
optionsCache: null as Record<string, PluginOptionsItem> | null,
get options() {
return this.optionsCache ??= {
voice: {
type: OptionType.SELECT,
description: "Narrator Voice",
options: window.speechSynthesis?.getVoices().map(v => ({
label: v.name,
value: v.voiceURI,
default: v.default
})) ?? []
},
volume: {
type: OptionType.SLIDER,
description: "Narrator Volume",
default: 1,
markers: [0, 0.25, 0.5, 0.75, 1],
stickToMarkers: false
},
rate: {
type: OptionType.SLIDER,
description: "Narrator Speed",
default: 1,
markers: [0.1, 0.5, 1, 2, 5, 10],
stickToMarkers: false
},
sayOwnName: {
description: "Say own name",
type: OptionType.BOOLEAN,
default: false
},
latinOnly: {
description: "Strip non latin characters from names before saying them",
type: OptionType.BOOLEAN,
default: false
},
joinMessage: {
type: OptionType.STRING,
description: "Join Message",
default: "{{USER}} joined"
},
leaveMessage: {
type: OptionType.STRING,
description: "Leave Message",
default: "{{USER}} left"
},
moveMessage: {
type: OptionType.STRING,
description: "Move Message",
default: "{{USER}} moved to {{CHANNEL}}"
},
muteMessage: {
type: OptionType.STRING,
description: "Mute Message (only self for now)",
default: "{{USER}} muted"
},
unmuteMessage: {
type: OptionType.STRING,
description: "Unmute Message (only self for now)",
default: "{{USER}} unmuted"
},
deafenMessage: {
type: OptionType.STRING,
description: "Deafen Message (only self for now)",
default: "{{USER}} deafened"
},
undeafenMessage: {
type: OptionType.STRING,
description: "Undeafen Message (only self for now)",
default: "{{USER}} undeafened"
}
} satisfies Record<string, PluginOptionsItem>;
},
settingsAboutComponent({ tempSettings: s }) {
const [hasVoices, hasEnglishVoices] = useMemo(() => {
const voices = speechSynthesis.getVoices();
@ -300,7 +222,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)),
[],
);