From e093583889abaffd6ce619ba140575d703824506 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 22 Dec 2025 13:35:51 +0100 Subject: [PATCH 1/3] feat(Shell): implement discord rich presence --- src/App/App.js | 5 +- src/common/index.js | 2 + src/common/useDiscord.ts | 83 ++++++++++++++++++++++++ src/routes/Player/Player.js | 19 +++++- src/routes/Settings/General/General.less | 6 ++ src/routes/Settings/General/General.tsx | 19 +++++- src/services/Discord/Discord.ts | 73 +++++++++++++++++++++ src/services/Discord/index.ts | 5 ++ src/services/index.js | 2 + 9 files changed, 211 insertions(+), 3 deletions(-) create mode 100644 src/common/useDiscord.ts create mode 100644 src/services/Discord/Discord.ts create mode 100644 src/services/Discord/index.ts diff --git a/src/App/App.js b/src/App/App.js index 7a1383dc4..adab67d3c 100644 --- a/src/App/App.js +++ b/src/App/App.js @@ -4,7 +4,7 @@ require('spatial-navigation-polyfill'); const React = require('react'); const { useTranslation } = require('react-i18next'); const { Router } = require('stremio-router'); -const { Core, Shell, Chromecast, DragAndDrop, KeyboardShortcuts, ServicesProvider } = require('stremio/services'); +const { Core, Shell, Chromecast, Discord, DragAndDrop, KeyboardShortcuts, ServicesProvider } = require('stremio/services'); const { NotFound } = require('stremio/routes'); const { FileDropProvider, PlatformProvider, ToastProvider, TooltipProvider, ShortcutsProvider, CONSTANTS, withCoreSuspender, useShell, useBinaryState } = require('stremio/common'); const ServicesToaster = require('./ServicesToaster'); @@ -33,6 +33,7 @@ const App = () => { return { core, shell: new Shell(), + discord: new Discord(), chromecast: new Chromecast(), keyboardShortcuts: new KeyboardShortcuts(), dragAndDrop: new DragAndDrop({ core }) @@ -95,6 +96,8 @@ const App = () => { services.chromecast.start(); services.keyboardShortcuts.start(); services.dragAndDrop.start(); + services.discord.init(services.shell); + window.services = services; return () => { services.core.stop(); diff --git a/src/common/index.js b/src/common/index.js index 0b9cb252f..ebcd89a95 100644 --- a/src/common/index.js +++ b/src/common/index.js @@ -17,6 +17,7 @@ const useAnimationFrame = require('./useAnimationFrame'); const useBinaryState = require('./useBinaryState'); const { default: useFullscreen } = require('./useFullscreen'); const { default: useInterval } = require('./useInterval'); +const { default: useDiscord } = require('./useDiscord'); const useLiveRef = require('./useLiveRef'); const useModelState = require('./useModelState'); const useNotifications = require('./useNotifications'); @@ -55,6 +56,7 @@ module.exports = { useBinaryState, useFullscreen, useInterval, + useDiscord, useLiveRef, useModelState, useNotifications, diff --git a/src/common/useDiscord.ts b/src/common/useDiscord.ts new file mode 100644 index 000000000..f28e5b71d --- /dev/null +++ b/src/common/useDiscord.ts @@ -0,0 +1,83 @@ +// Copyright (C) 2017-2025 Smart code 203358507 + +import { useCallback, useEffect, useState } from 'react'; +import { useServices } from 'stremio/services'; + +type Service = { + available: boolean; + connected: boolean; + connect: () => void; + disconnect: () => void; + setActivity: (state: string, details: string, image?: string, startTimestamp?: number) => void; + clearActivity: () => void; + on: (name: string, listener: (data: unknown) => void) => void; + off: (name: string, listener: (data: unknown) => void) => void; +}; + +type Result = { + available: boolean; + connected: boolean; + connect: () => void; + disconnect: () => void; + setActivity: (state: string, details: string, image?: string, startTimestamp?: number) => void; + clearActivity: () => void; +}; + +const useDiscord = (): Result => { + const { discord } = useServices() as { discord?: Service }; + const [connected, setConnected] = useState(discord?.connected ?? false); + + useEffect(() => { + if (!discord) return; + + const onStatusChanged = (isConnected: boolean) => { + setConnected(isConnected); + }; + + discord.on('statusChanged', onStatusChanged as (data: unknown) => void); + + return () => { + discord.off('statusChanged', onStatusChanged as (data: unknown) => void); + }; + }, [discord]); + + const connect = useCallback(() => { + if (discord) { + discord.connect(); + } + }, [discord]); + + const disconnect = useCallback(() => { + if (discord) { + discord.disconnect(); + } + }, [discord]); + + const setActivity = useCallback(( + state: string, + details: string, + image?: string, + startTimestamp?: number + ) => { + if (discord) { + discord.setActivity(state, details, image, startTimestamp); + } + }, [discord]); + + const clearActivity = useCallback(() => { + if (discord) { + discord.clearActivity(); + } + }, [discord]); + + return { + available: discord?.available ?? false, + connected, + connect, + disconnect, + setActivity, + clearActivity + }; +}; + +export default useDiscord; diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index 27f705be8..df6a738b5 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -8,7 +8,7 @@ const langs = require('langs'); const { useTranslation } = require('react-i18next'); const { useRouteFocused } = require('stremio-router'); const { useServices } = require('stremio/services'); -const { onFileDrop, useSettings, useProfile, useFullscreen, useBinaryState, useToast, useStreamingServer, withCoreSuspender, CONSTANTS, useShell, usePlatform } = require('stremio/common'); +const { onFileDrop, useSettings, useProfile, useFullscreen, useBinaryState, useToast, useStreamingServer, withCoreSuspender, CONSTANTS, useShell, usePlatform, useDiscord } = require('stremio/common'); const { HorizontalNavBar, Transition, ContextMenu } = require('stremio/components'); const BufferingLoader = require('./BufferingLoader'); const VolumeChangeIndicator = require('./VolumeChangeIndicator'); @@ -45,6 +45,7 @@ const Player = ({ urlParams, queryParams }) => { const routeFocused = useRouteFocused(); const platform = usePlatform(); const toast = useToast(); + const discord = useDiscord(); const [seeking, setSeeking] = React.useState(false); @@ -550,6 +551,22 @@ const Player = ({ urlParams, queryParams }) => { } }, [settings.pauseOnMinimize, shell.windowClosed, shell.windowHidden]); + React.useEffect(() => { + if (!discord.connected || !discord.available) return; + + const state = video.state.paused ? 'Paused' : 'Watching'; + + const startTimestamp = !video.state.paused && video.state.time !== null && video.state.duration !== null + ? Math.floor((Date.now() / 1000) - video.state.time) + : null; + + discord.setActivity(state, player?.title, player?.metaItem?.poster, startTimestamp); + + return () => { + discord.clearActivity(); + }; + }, [discord.connected, discord.available, player?.title, player?.metaItem, video.state]); + // Media Session PlaybackState React.useEffect(() => { if (!navigator.mediaSession) return; diff --git a/src/routes/Settings/General/General.less b/src/routes/Settings/General/General.less index 8c253dcff..6b0afc03a 100644 --- a/src/routes/Settings/General/General.less +++ b/src/routes/Settings/General/General.less @@ -9,3 +9,9 @@ color: var(--color-trakt) !important; } } + +.discord-container { + .option-icon { + color: #5865F2 !important; + } +} diff --git a/src/routes/Settings/General/General.tsx b/src/routes/Settings/General/General.tsx index 8f5496dbd..ba137a101 100644 --- a/src/routes/Settings/General/General.tsx +++ b/src/routes/Settings/General/General.tsx @@ -2,7 +2,7 @@ import React, { forwardRef, useCallback, useEffect, useMemo, useState } from 're import { useTranslation } from 'react-i18next'; import { Button, MultiselectMenu, Toggle } from 'stremio/components'; import { useServices } from 'stremio/services'; -import { usePlatform, useToast } from 'stremio/common'; +import { usePlatform, useToast, useDiscord } from 'stremio/common'; import { Section, Option, Link } from '../components'; import User from './User'; import useDataExport from './useDataExport'; @@ -18,6 +18,7 @@ const General = forwardRef(({ profile }: Props, ref) => { const { core, shell } = useServices(); const platform = usePlatform(); const toast = useToast(); + const { available: discordAvailable, connected: isDiscordConnected, connect: connectDiscord, disconnect: disconnectDiscord } = useDiscord(); const [dataExport, loadDataExport] = useDataExport(); const { @@ -69,6 +70,14 @@ const General = forwardRef(({ profile }: Props, ref) => { } }, [isTraktAuthenticated, profile.auth]); + const onToggleDiscord = useCallback(() => { + if (isDiscordConnected) { + disconnectDiscord(); + } else { + connectDiscord(); + } + }, [isDiscordConnected, connectDiscord, disconnectDiscord]); + useEffect(() => { if (dataExport.exportUrl) { platform.openExternal(dataExport.exportUrl); @@ -142,6 +151,14 @@ const General = forwardRef(({ profile }: Props, ref) => { {isTraktAuthenticated ? t('LOG_OUT') : t('SETTINGS_TRAKT_AUTHENTICATE')} + { + discordAvailable && + + }
diff --git a/src/services/Discord/Discord.ts b/src/services/Discord/Discord.ts new file mode 100644 index 000000000..d9af3b21c --- /dev/null +++ b/src/services/Discord/Discord.ts @@ -0,0 +1,73 @@ +// Copyright (C) 2017-2025 Smart code 203358507 + +import EventEmitter from 'eventemitter3'; + +type DiscordStatusData = { + connected: boolean; +}; + +class Discord { + private events: EventEmitter; + private connected: boolean; + private shell: any; + + constructor() { + this.events = new EventEmitter(); + this.connected = false; + this.shell = null; + } + + init(shellService: any): void { + this.shell = shellService; + + if (this.shell && this.shell.transport) { + this.shell.transport.on('discord-status', (data: DiscordStatusData) => { + this.connected = data.connected; + this.events.emit('statusChanged', this.connected); + }); + } + } + + connect(): void { + if (this.shell && this.shell.active) { + this.shell.transport.send('discord-connect', {}); + } + } + + disconnect(): void { + if (this.shell && this.shell.active) { + this.shell.transport.send('discord-disconnect', {}); + } + } + + setActivity(state: string, details: string, image?: string | null, startTimestamp?: number | null): void { + if (this.shell && this.shell.active && this.connected) { + this.shell.transport.send('discord-set-activity', { + state, + details, + image: image || null, + startTimestamp: startTimestamp || null + }); + } + } + + clearActivity(): void { + if (this.shell && this.shell.active && this.connected) { + this.shell.transport.send('discord-clear-activity', {}); + } + } + + get available(): boolean { + return this.shell && this.shell.active; + } + + on(name: string, listener: (data: any) => void): void { + this.events.on(name, listener); + } + + off(name: string, listener: (data: any) => void): void { + this.events.off(name, listener); + } +} + +export default Discord; diff --git a/src/services/Discord/index.ts b/src/services/Discord/index.ts new file mode 100644 index 000000000..ddcd51cfc --- /dev/null +++ b/src/services/Discord/index.ts @@ -0,0 +1,5 @@ +// Copyright (C) 2017-2025 Smart code 203358507 + +import Discord from './Discord'; + +export default Discord; diff --git a/src/services/index.js b/src/services/index.js index 84cfcc8b8..2816f27f2 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -2,6 +2,7 @@ const Chromecast = require('./Chromecast'); const Core = require('./Core'); +const Discord = require('./Discord'); const DragAndDrop = require('./DragAndDrop'); const KeyboardShortcuts = require('./KeyboardShortcuts'); const { ServicesProvider, useServices } = require('./ServicesContext'); @@ -10,6 +11,7 @@ const Shell = require('./Shell'); module.exports = { Chromecast, Core, + Discord, DragAndDrop, KeyboardShortcuts, ServicesProvider, From bbbf505e10498246e795bd27a6506891a35ad634 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Mon, 22 Dec 2025 13:40:47 +0100 Subject: [PATCH 2/3] refactor: add persistance --- src/routes/Settings/General/General.tsx | 24 ++++++++++++++++++++++++ src/types/models/Ctx.d.ts | 1 + 2 files changed, 25 insertions(+) diff --git a/src/routes/Settings/General/General.tsx b/src/routes/Settings/General/General.tsx index ba137a101..d3f5b8e33 100644 --- a/src/routes/Settings/General/General.tsx +++ b/src/routes/Settings/General/General.tsx @@ -73,8 +73,26 @@ const General = forwardRef(({ profile }: Props, ref) => { const onToggleDiscord = useCallback(() => { if (isDiscordConnected) { disconnectDiscord(); + core.transport.dispatch({ + action: 'Ctx', + args: { + action: 'UpdateSettings', + args: { + discordRpcEnabled: false + } + } + }); } else { connectDiscord(); + core.transport.dispatch({ + action: 'Ctx', + args: { + action: 'UpdateSettings', + args: { + discordRpcEnabled: true + } + } + }); } }, [isDiscordConnected, connectDiscord, disconnectDiscord]); @@ -84,6 +102,12 @@ const General = forwardRef(({ profile }: Props, ref) => { } }, [dataExport.exportUrl]); + useEffect(() => { + if (discordAvailable && profile.settings.discordRpcEnabled && !isDiscordConnected) { + connectDiscord(); + } + }, [discordAvailable, profile.settings.discordRpcEnabled]); + useEffect(() => { if (isTraktAuthenticated && traktAuthStarted) { core.transport.dispatch({ diff --git a/src/types/models/Ctx.d.ts b/src/types/models/Ctx.d.ts index e6c0e14e4..3dc6e825f 100644 --- a/src/types/models/Ctx.d.ts +++ b/src/types/models/Ctx.d.ts @@ -18,6 +18,7 @@ type Settings = { audioPassthrough: boolean, autoFrameRateMatching: boolean, bingeWatching: boolean, + discordRpcEnabled: boolean, hardwareDecoding: boolean, videoMode: string | null, escExitFullscreen: boolean, From 2576d25a12ebaf2dee1ea0cb88f5d605f9e93f26 Mon Sep 17 00:00:00 2001 From: "Timothy Z." Date: Tue, 12 May 2026 18:23:52 +0200 Subject: [PATCH 3/3] Fix Discord rich presence setting flow --- src/App/App.js | 28 ++--- src/common/Discord/Discord.tsx | 129 +++++++++++++++++++++++ src/common/Discord/index.ts | 6 ++ src/common/index.js | 5 +- src/common/useDiscord.ts | 83 --------------- src/routes/Player/Player.js | 26 +++-- src/routes/Settings/General/General.less | 2 +- src/routes/Settings/General/General.tsx | 47 +++------ 8 files changed, 184 insertions(+), 142 deletions(-) create mode 100644 src/common/Discord/Discord.tsx create mode 100644 src/common/Discord/index.ts delete mode 100644 src/common/useDiscord.ts diff --git a/src/App/App.js b/src/App/App.js index adab67d3c..f4b9f1b1e 100644 --- a/src/App/App.js +++ b/src/App/App.js @@ -6,7 +6,7 @@ const { useTranslation } = require('react-i18next'); const { Router } = require('stremio-router'); const { Core, Shell, Chromecast, Discord, DragAndDrop, KeyboardShortcuts, ServicesProvider } = require('stremio/services'); const { NotFound } = require('stremio/routes'); -const { FileDropProvider, PlatformProvider, ToastProvider, TooltipProvider, ShortcutsProvider, CONSTANTS, withCoreSuspender, useShell, useBinaryState } = require('stremio/common'); +const { FileDropProvider, PlatformProvider, ToastProvider, TooltipProvider, ShortcutsProvider, DiscordProvider, CONSTANTS, withCoreSuspender, useShell, useBinaryState } = require('stremio/common'); const ServicesToaster = require('./ServicesToaster'); const DeepLinkHandler = require('./DeepLinkHandler'); const SearchParamsHandler = require('./SearchParamsHandler'); @@ -217,18 +217,20 @@ const App = () => { - { - shortcutModalOpen && - } - - - - - + + { + shortcutModalOpen && + } + + + + + + diff --git a/src/common/Discord/Discord.tsx b/src/common/Discord/Discord.tsx new file mode 100644 index 000000000..5be7b8177 --- /dev/null +++ b/src/common/Discord/Discord.tsx @@ -0,0 +1,129 @@ +import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; +import { useServices } from 'stremio/services'; +import useProfile from '../useProfile'; + +type Activity = { + state: string, + details?: string | null, + image?: string | null, + startTimestamp?: number | null, +}; + +type DiscordContextValue = { + available: boolean, + connected: boolean, + enabled: boolean, + setActivity: (activity: Activity | null) => void, +}; + +const DiscordContext = createContext(null); + +const sameActivity = (first: Activity | null, second: Activity | null) => { + return first?.state === second?.state && + first?.details === second?.details && + first?.image === second?.image && + first?.startTimestamp === second?.startTimestamp; +}; + +type Props = { + children: React.ReactNode, +}; + +const DiscordProvider = ({ children }: Props) => { + const { discord } = useServices(); + const profile = useProfile(); + const enabled = profile.settings?.discordRpcEnabled === true; + const available = discord?.available === true; + const [connected, setConnected] = useState(false); + const [activity, setActivityState] = useState(null); + const sentActivity = useRef(null); + const connectRequested = useRef(false); + + useEffect(() => { + if (!discord) return; + + const onStatusChanged = (isConnected: boolean) => { + connectRequested.current = false; + setConnected(isConnected); + }; + + discord.on('statusChanged', onStatusChanged); + return () => { + discord.off('statusChanged', onStatusChanged); + }; + }, [discord]); + + useEffect(() => { + if (!discord || !available) { + connectRequested.current = false; + setConnected(false); + sentActivity.current = null; + return; + } + + if (enabled) { + if (!connected && !connectRequested.current) { + connectRequested.current = true; + discord.connect(); + } + } else { + connectRequested.current = false; + if (connected) { + discord.disconnect(); + } + sentActivity.current = null; + } + }, [available, connected, discord, enabled]); + + useEffect(() => { + if (!discord || !available || !enabled || !connected) return; + + if (activity === null) { + if (sentActivity.current !== null) { + discord.clearActivity(); + sentActivity.current = null; + } + return; + } + + if (sameActivity(sentActivity.current, activity)) return; + + discord.setActivity( + activity.state, + activity.details || '', + activity.image || null, + activity.startTimestamp || null + ); + sentActivity.current = activity; + }, [activity, available, connected, discord, enabled]); + + const setActivity = useCallback((nextActivity: Activity | null) => { + setActivityState((currentActivity) => sameActivity(currentActivity, nextActivity) ? currentActivity : nextActivity); + }, []); + + const value = useMemo(() => ({ + available, + connected, + enabled, + setActivity, + }), [available, connected, enabled, setActivity]); + + return ( + + {children} + + ); +}; + +const useDiscord = () => { + const value = useContext(DiscordContext); + if (value === null) { + throw new Error('useDiscord must be used inside DiscordProvider'); + } + return value; +}; + +export { + DiscordProvider, + useDiscord, +}; diff --git a/src/common/Discord/index.ts b/src/common/Discord/index.ts new file mode 100644 index 000000000..f16f4bc47 --- /dev/null +++ b/src/common/Discord/index.ts @@ -0,0 +1,6 @@ +import { DiscordProvider, useDiscord } from './Discord'; + +export { + DiscordProvider, + useDiscord, +}; diff --git a/src/common/index.js b/src/common/index.js index f118ec1a7..e4b2c1f4c 100644 --- a/src/common/index.js +++ b/src/common/index.js @@ -5,6 +5,7 @@ const { PlatformProvider, usePlatform } = require('./Platform'); const { ToastProvider, useToast } = require('./Toast'); const { TooltipProvider, Tooltip } = require('./Tooltips'); const { ShortcutsProvider, useShortcuts, onShortcut } = require('./Shortcuts'); +const { DiscordProvider, useDiscord } = require('./Discord'); const CONSTANTS = require('./CONSTANTS'); const { withCoreSuspender, useCoreSuspender } = require('./CoreSuspender'); const getVisibleChildrenRange = require('./getVisibleChildrenRange'); @@ -16,7 +17,6 @@ const useAnimationFrame = require('./useAnimationFrame'); const useBinaryState = require('./useBinaryState'); const { default: useFullscreen } = require('./useFullscreen'); const { default: useInterval } = require('./useInterval'); -const { default: useDiscord } = require('./useDiscord'); const useLiveRef = require('./useLiveRef'); const useModelState = require('./useModelState'); const useNotifications = require('./useNotifications'); @@ -44,6 +44,8 @@ module.exports = { useToast, TooltipProvider, Tooltip, + DiscordProvider, + useDiscord, CONSTANTS, withCoreSuspender, useCoreSuspender, @@ -56,7 +58,6 @@ module.exports = { useBinaryState, useFullscreen, useInterval, - useDiscord, useLiveRef, useModelState, useNotifications, diff --git a/src/common/useDiscord.ts b/src/common/useDiscord.ts deleted file mode 100644 index f28e5b71d..000000000 --- a/src/common/useDiscord.ts +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2017-2025 Smart code 203358507 - -import { useCallback, useEffect, useState } from 'react'; -import { useServices } from 'stremio/services'; - -type Service = { - available: boolean; - connected: boolean; - connect: () => void; - disconnect: () => void; - setActivity: (state: string, details: string, image?: string, startTimestamp?: number) => void; - clearActivity: () => void; - on: (name: string, listener: (data: unknown) => void) => void; - off: (name: string, listener: (data: unknown) => void) => void; -}; - -type Result = { - available: boolean; - connected: boolean; - connect: () => void; - disconnect: () => void; - setActivity: (state: string, details: string, image?: string, startTimestamp?: number) => void; - clearActivity: () => void; -}; - -const useDiscord = (): Result => { - const { discord } = useServices() as { discord?: Service }; - const [connected, setConnected] = useState(discord?.connected ?? false); - - useEffect(() => { - if (!discord) return; - - const onStatusChanged = (isConnected: boolean) => { - setConnected(isConnected); - }; - - discord.on('statusChanged', onStatusChanged as (data: unknown) => void); - - return () => { - discord.off('statusChanged', onStatusChanged as (data: unknown) => void); - }; - }, [discord]); - - const connect = useCallback(() => { - if (discord) { - discord.connect(); - } - }, [discord]); - - const disconnect = useCallback(() => { - if (discord) { - discord.disconnect(); - } - }, [discord]); - - const setActivity = useCallback(( - state: string, - details: string, - image?: string, - startTimestamp?: number - ) => { - if (discord) { - discord.setActivity(state, details, image, startTimestamp); - } - }, [discord]); - - const clearActivity = useCallback(() => { - if (discord) { - discord.clearActivity(); - } - }, [discord]); - - return { - available: discord?.available ?? false, - connected, - connect, - disconnect, - setActivity, - clearActivity - }; -}; - -export default useDiscord; diff --git a/src/routes/Player/Player.js b/src/routes/Player/Player.js index ac47789a4..3440f03ae 100644 --- a/src/routes/Player/Player.js +++ b/src/routes/Player/Player.js @@ -609,20 +609,26 @@ const Player = ({ urlParams, queryParams }) => { }, [settings.pauseOnMinimize, shell.windowClosed, shell.windowHidden]); React.useEffect(() => { - if (!discord.connected || !discord.available) return; + if (video.state.stream === null || typeof player?.title !== 'string') { + discord.setActivity(null); + return; + } - const state = video.state.paused ? 'Paused' : 'Watching'; - - const startTimestamp = !video.state.paused && video.state.time !== null && video.state.duration !== null - ? Math.floor((Date.now() / 1000) - video.state.time) - : null; - - discord.setActivity(state, player?.title, player?.metaItem?.poster, startTimestamp); + discord.setActivity({ + state: video.state.paused ? 'Paused' : 'Watching', + details: player.title, + image: player.metaItem?.poster || null, + startTimestamp: !video.state.paused && typeof video.state.time === 'number' ? + Math.floor((Date.now() / 1000) - video.state.time) : + null, + }); + }, [discord.setActivity, player?.title, player.metaItem?.poster, video.state.paused, video.state.stream]); + React.useEffect(() => { return () => { - discord.clearActivity(); + discord.setActivity(null); }; - }, [discord.connected, discord.available, player?.title, player?.metaItem, video.state]); + }, [discord.setActivity]); useMediaSession(video.state, player, onPlayRequested, onPauseRequested, onNextVideoRequested); diff --git a/src/routes/Settings/General/General.less b/src/routes/Settings/General/General.less index 6b0afc03a..6f8ce9bfb 100644 --- a/src/routes/Settings/General/General.less +++ b/src/routes/Settings/General/General.less @@ -12,6 +12,6 @@ .discord-container { .option-icon { - color: #5865F2 !important; + color: #5865f2 !important; } } diff --git a/src/routes/Settings/General/General.tsx b/src/routes/Settings/General/General.tsx index 2273aeb80..a31052113 100644 --- a/src/routes/Settings/General/General.tsx +++ b/src/routes/Settings/General/General.tsx @@ -17,7 +17,7 @@ const General = forwardRef(({ profile }: Props, ref) => { const { core } = useServices(); const platform = usePlatform(); const toast = useToast(); - const { available: discordAvailable, connected: isDiscordConnected, connect: connectDiscord, disconnect: disconnectDiscord } = useDiscord(); + const discord = useDiscord(); const [dataExport, loadDataExport] = useDataExport(); const [traktAuthStarted, setTraktAuthStarted] = useState(false); @@ -63,30 +63,17 @@ const General = forwardRef(({ profile }: Props, ref) => { }, [isTraktAuthenticated, profile.auth]); const onToggleDiscord = useCallback(() => { - if (isDiscordConnected) { - disconnectDiscord(); - core.transport.dispatch({ - action: 'Ctx', + core.transport.dispatch({ + action: 'Ctx', + args: { + action: 'UpdateSettings', args: { - action: 'UpdateSettings', - args: { - discordRpcEnabled: false - } + ...profile.settings, + discordRpcEnabled: !profile.settings.discordRpcEnabled } - }); - } else { - connectDiscord(); - core.transport.dispatch({ - action: 'Ctx', - args: { - action: 'UpdateSettings', - args: { - discordRpcEnabled: true - } - } - }); - } - }, [isDiscordConnected, connectDiscord, disconnectDiscord]); + } + }); + }, [profile.settings]); useEffect(() => { if (dataExport.exportUrl) { @@ -94,12 +81,6 @@ const General = forwardRef(({ profile }: Props, ref) => { } }, [dataExport.exportUrl]); - useEffect(() => { - if (discordAvailable && profile.settings.discordRpcEnabled && !isDiscordConnected) { - connectDiscord(); - } - }, [discordAvailable, profile.settings.discordRpcEnabled]); - useEffect(() => { if (isTraktAuthenticated && traktAuthStarted) { core.transport.dispatch({ @@ -168,10 +149,10 @@ const General = forwardRef(({ profile }: Props, ref) => { { - discordAvailable && - }