Fix errors on setups with no Notifications/SpeechSynthesis support

This commit is contained in:
Vendicated 2023-04-17 00:21:49 +02:00
parent cb3bd4b881
commit ca5d24385f
No known key found for this signature in database
GPG key ID: A1DC0CFB5615D905
3 changed files with 33 additions and 22 deletions

View file

@ -77,6 +77,8 @@ function _showNotification(notification: NotificationData, id: number) {
} }
function shouldBeNative() { function shouldBeNative() {
if (typeof Notification === "undefined") return false;
const { useNative } = Settings.notifications; const { useNative } = Settings.notifications;
if (useNative === "always") return true; if (useNative === "always") return true;
if (useNative === "not-focused") return !document.hasFocus(); if (useNative === "not-focused") return !document.hasFocus();

View file

@ -18,7 +18,7 @@
import { openNotificationLogModal } from "@api/Notifications/notificationLog"; import { openNotificationLogModal } from "@api/Notifications/notificationLog";
import { useSettings } from "@api/settings"; import { Settings, useSettings } from "@api/settings";
import { classNameFactory } from "@api/Styles"; import { classNameFactory } from "@api/Styles";
import DonateButton from "@components/DonateButton"; import DonateButton from "@components/DonateButton";
import ErrorBoundary from "@components/ErrorBoundary"; import ErrorBoundary from "@components/ErrorBoundary";
@ -43,7 +43,6 @@ function VencordSettings() {
fallbackValue: "Loading..." fallbackValue: "Loading..."
}); });
const settings = useSettings(); const settings = useSettings();
const notifSettings = settings.notifications;
const donateImage = React.useMemo(() => Math.random() > 0.5 ? DEFAULT_DONATE_IMAGE : SHIGGY_DONATE_IMAGE, []); const donateImage = React.useMemo(() => Math.random() > 0.5 ? DEFAULT_DONATE_IMAGE : SHIGGY_DONATE_IMAGE, []);
@ -158,8 +157,16 @@ function VencordSettings() {
</Forms.FormSection> </Forms.FormSection>
{typeof Notification !== "undefined" && <NotificationSection settings={settings.notifications} />}
</React.Fragment>
);
}
function NotificationSection({ settings }: { settings: typeof Settings["notifications"]; }) {
return (
<>
<Forms.FormTitle tag="h5">Notification Style</Forms.FormTitle> <Forms.FormTitle tag="h5">Notification Style</Forms.FormTitle>
{notifSettings.useNative !== "never" && Notification.permission === "denied" && ( {settings.useNative !== "never" && Notification?.permission === "denied" && (
<ErrorCard style={{ padding: "1em" }} className={Margins.bottom8}> <ErrorCard style={{ padding: "1em" }} className={Margins.bottom8}>
<Forms.FormTitle tag="h5">Desktop Notification Permission denied</Forms.FormTitle> <Forms.FormTitle tag="h5">Desktop Notification Permission denied</Forms.FormTitle>
<Forms.FormText>You have denied Notification Permissions. Thus, Desktop notifications will not work!</Forms.FormText> <Forms.FormText>You have denied Notification Permissions. Thus, Desktop notifications will not work!</Forms.FormText>
@ -178,35 +185,35 @@ function VencordSettings() {
{ label: "Only use Desktop notifications when Discord is not focused", value: "not-focused", default: true }, { label: "Only use Desktop notifications when Discord is not focused", value: "not-focused", default: true },
{ label: "Always use Desktop notifications", value: "always" }, { label: "Always use Desktop notifications", value: "always" },
{ label: "Always use Vencord notifications", value: "never" }, { label: "Always use Vencord notifications", value: "never" },
] satisfies Array<{ value: typeof settings["notifications"]["useNative"]; } & Record<string, any>>} ] satisfies Array<{ value: typeof settings["useNative"]; } & Record<string, any>>}
closeOnSelect={true} closeOnSelect={true}
select={v => notifSettings.useNative = v} select={v => settings.useNative = v}
isSelected={v => v === notifSettings.useNative} isSelected={v => v === settings.useNative}
serialize={identity} serialize={identity}
/> />
<Forms.FormTitle tag="h5" className={Margins.top16 + " " + Margins.bottom8}>Notification Position</Forms.FormTitle> <Forms.FormTitle tag="h5" className={Margins.top16 + " " + Margins.bottom8}>Notification Position</Forms.FormTitle>
<Select <Select
isDisabled={notifSettings.useNative === "always"} isDisabled={settings.useNative === "always"}
placeholder="Notification Position" placeholder="Notification Position"
options={[ options={[
{ label: "Bottom Right", value: "bottom-right", default: true }, { label: "Bottom Right", value: "bottom-right", default: true },
{ label: "Top Right", value: "top-right" }, { label: "Top Right", value: "top-right" },
] satisfies Array<{ value: typeof settings["notifications"]["position"]; } & Record<string, any>>} ] satisfies Array<{ value: typeof settings["position"]; } & Record<string, any>>}
select={v => notifSettings.position = v} select={v => settings.position = v}
isSelected={v => v === notifSettings.position} isSelected={v => v === settings.position}
serialize={identity} serialize={identity}
/> />
<Forms.FormTitle tag="h5" className={Margins.top16 + " " + Margins.bottom8}>Notification Timeout</Forms.FormTitle> <Forms.FormTitle tag="h5" className={Margins.top16 + " " + Margins.bottom8}>Notification Timeout</Forms.FormTitle>
<Forms.FormText className={Margins.bottom16}>Set to 0s to never automatically time out</Forms.FormText> <Forms.FormText className={Margins.bottom16}>Set to 0s to never automatically time out</Forms.FormText>
<Slider <Slider
disabled={notifSettings.useNative === "always"} disabled={settings.useNative === "always"}
markers={[0, 1000, 2500, 5000, 10_000, 20_000]} markers={[0, 1000, 2500, 5000, 10_000, 20_000]}
minValue={0} minValue={0}
maxValue={20_000} maxValue={20_000}
initialValue={notifSettings.timeout} initialValue={settings.timeout}
onValueChange={v => notifSettings.timeout = v} onValueChange={v => settings.timeout = v}
onValueRender={v => (v / 1000).toFixed(2) + "s"} onValueRender={v => (v / 1000).toFixed(2) + "s"}
onMarkerRender={v => (v / 1000) + "s"} onMarkerRender={v => (v / 1000) + "s"}
stickToMarkers={false} stickToMarkers={false}
@ -222,23 +229,22 @@ function VencordSettings() {
minValue={0} minValue={0}
maxValue={200} maxValue={200}
stickToMarkers={true} stickToMarkers={true}
initialValue={notifSettings.logLimit} initialValue={settings.logLimit}
onValueChange={v => notifSettings.logLimit = v} onValueChange={v => settings.logLimit = v}
onValueRender={v => v === 200 ? "∞" : v} onValueRender={v => v === 200 ? "∞" : v}
onMarkerRender={v => v === 200 ? "∞" : v} onMarkerRender={v => v === 200 ? "∞" : v}
/> />
<Button <Button
onClick={openNotificationLogModal} onClick={openNotificationLogModal}
disabled={notifSettings.logLimit === 0} disabled={settings.logLimit === 0}
> >
Open Notification Log Open Notification Log
</Button> </Button>
</React.Fragment> </>
); );
} }
interface DonateCardProps { interface DonateCardProps {
image: string; image: string;
} }

View file

@ -192,10 +192,13 @@ export default definePlugin({
authors: [Devs.Ven], authors: [Devs.Ven],
start() { start() {
if (speechSynthesis.getVoices().length === 0) { if (typeof speechSynthesis === "undefined" || speechSynthesis.getVoices().length === 0) {
new Logger("VcNarrator").warn("No Narrator voices found. Thus, this plugin will not work. Check my Settings for more info"); 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; return;
} }
FluxDispatcher.subscribe("VOICE_STATE_UPDATES", handleVoiceStates); FluxDispatcher.subscribe("VOICE_STATE_UPDATES", handleVoiceStates);
FluxDispatcher.subscribe("AUDIO_TOGGLE_SELF_MUTE", handleToggleSelfMute); FluxDispatcher.subscribe("AUDIO_TOGGLE_SELF_MUTE", handleToggleSelfMute);
FluxDispatcher.subscribe("AUDIO_TOGGLE_SELF_DEAF", handleToggleSelfDeafen); FluxDispatcher.subscribe("AUDIO_TOGGLE_SELF_DEAF", handleToggleSelfDeafen);
@ -214,11 +217,11 @@ export default definePlugin({
voice: { voice: {
type: OptionType.SELECT, type: OptionType.SELECT,
description: "Narrator Voice", description: "Narrator Voice",
options: speechSynthesis.getVoices().map(v => ({ options: speechSynthesis?.getVoices().map(v => ({
label: v.name, label: v.name,
value: v.voiceURI, value: v.voiceURI,
default: v.default default: v.default
})) })) ?? []
}, },
volume: { volume: {
type: OptionType.SLIDER, type: OptionType.SLIDER,