Plugin

SpotifyControls

Adds a Spotify player above the account panel

Media Activity
index.tsx
Download

Source

src/plugins/spotifyControls/index.tsx
1/*
2 * FiveCord — a Discord client mod
3 * Copyright (c) 2025 FiveCord
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
7import { definePluginSettings } from "@api/Settings";
8import { disableStyle, enableStyle } from "@api/Styles";
9import ErrorBoundary from "@components/ErrorBoundary";
10import { Devs } from "@utils/constants";
11import definePlugin, { OptionType } from "@utils/types";
12
13import hoverOnlyStyle from "./hoverOnly.css?managed";
14import { Player } from "./PlayerComponent";
15
16export const settings = definePluginSettings({
17 hoverControls: {
18 description: "Show controls on hover",
19 type: OptionType.BOOLEAN,
20 default: false,
21 onChange: v => toggleHoverControls(v)
22 },
23 useSpotifyUris: {
24 type: OptionType.BOOLEAN,
25 description: "Open Spotify URIs instead of Spotify URLs. Will only work if you have Spotify installed and might not work on all platforms",
26 default: false
27 },
28 previousButtonRestartsTrack: {
29 type: OptionType.BOOLEAN,
30 description: "Restart currently playing track when pressing the previous button if playtime is >3s",
31 default: true
32 }
33});
34
35function toggleHoverControls(value: boolean) {
36 (value ? enableStyle : disableStyle)(hoverOnlyStyle);
37}
38
39export default definePlugin({
40 name: "SpotifyControls",
41 description: "Adds a Spotify player above the account panel",
42 tags: ["Media", "Activity"],
43 authors: [Devs.Ven, Devs.afn, Devs.KraXen72, Devs.Av32000, Devs.nin0dev],
44 settings,
45 patches: [
46 {
47 find: ".DISPLAY_NAME_STYLES_COACHMARK)",
48 replacement: {
49 // react.jsx)(AccountPanel, { ..., showTaglessAccountPanel: blah })
50 match: /(?<=\i\.jsxs?\)\()(\i),{(?=[^}]*?userTag:\i,occluded:)/,
51 // react.jsx(WrapperComponent, { VencordOriginal: AccountPanel, ...
52 replace: "$self.PanelWrapper,{VencordOriginal:$1,"
53 }
54 },
55 {
56 find: ".PLAYER_DEVICES",
57 replacement: [{
58 // Adds POST and a Marker to the SpotifyAPI (so we can easily find it)
59 match: /get:(\i)\.bind\(null,(\i\.\i)\.get\)/,
60 replace: "post:$1.bind(null,$2.post),vcSpotifyMarker:1,$&"
61 },
62 {
63 // Spotify Connect API returns status 202 instead of 204 when skipping tracks.
64 // Discord rejects 202 which causes the request to send twice. This patch prevents this.
65 match: /202===\i\.status/,
66 replace: "false",
67 }]
68 },
69 {
70 find: &#039;repeat:"off"!==&#039;,
71 replacement: [
72 {
73 // Discord doesn't give you shuffle state and the repeat kind, only a boolean
74 match: /repeat:"off"!==(\i),/,
75 replace: "shuffle:arguments[2]?.shuffle_state??false,actual_repeat:$1,$&"
76 },
77 {
78 match: /(?<=artists.filter\(\i=>).{0,10}\i\.id\)&&/,
79 replace: ""
80 }
81 ]
82 },
83 ],
84
85 start: () => toggleHoverControls(settings.store.hoverControls),
86
87 PanelWrapper({ VencordOriginal, ...props }) {
88 return (
89 <>
90 <ErrorBoundary
91 fallback={() => (
92 <div className="vc-spotify-fallback">
93 <p>Failed to render Spotify Modal :(</p>
94 <p >Check the console for errors</p>
95 </div>
96 )}
97 >
98 <Player />
99 </ErrorBoundary>
100
101 <VencordOriginal {...props} />
102 </>
103 );
104 }
105});
106