-
Failed to render Spotify Modal :(
-
Check the console for errors
+
+
Failed to render Modal :(
+
Check the console for errors
)}
>
-
+ {showTidalLyrics && LyricsPosition === "above" &&
}
+ {showTidalControls &&
}
+ {showTidalLyrics && LyricsPosition === "below" &&
}
+ {showSpotifyLyrics && LyricsPosition === "above" &&
}
+ {showSpotifyControls &&
}
+ {showSpotifyLyrics && LyricsPosition === "below" &&
}
>
);
- }
+ },
+
+ async start() {
+ await migrateOldLyrics();
+ toggleHoverControls(Settings.plugins.MusicControls.hoverControls);
+ },
});
diff --git a/src/equicordplugins/musicControls/settings.tsx b/src/equicordplugins/musicControls/settings.tsx
new file mode 100644
index 000000000..6b3c3cae5
--- /dev/null
+++ b/src/equicordplugins/musicControls/settings.tsx
@@ -0,0 +1,187 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import { definePluginSettings } from "@api/Settings";
+import { disableStyle, enableStyle } from "@api/Styles";
+import { useAwaiter } from "@utils/react";
+import { makeRange, OptionType } from "@utils/types";
+import { Button, Forms, MaskedLink, showToast, Text, Toasts, useMemo } from "@webpack/common";
+
+import hoverOnlyStyle from "./hoverOnly.css?managed";
+import { clearLyricsCache, getLyricsCount } from "./spotify/lyrics/api";
+import { useLyrics } from "./spotify/lyrics/components/util";
+import { Provider } from "./spotify/lyrics/providers/types";
+
+const sliderOptions = {
+ markers: makeRange(-2500, 2500, 250),
+ stickToMarkers: true,
+};
+
+export function toggleHoverControls(value: boolean) {
+ (value ? enableStyle : disableStyle)(hoverOnlyStyle);
+}
+
+function Details() {
+ const { lyricsInfo } = useLyrics();
+
+ const [count, error, loading] = useAwaiter(
+ useMemo(() => getLyricsCount, []),
+ {
+ onError: () => console.error("Failed to get lyrics count"),
+ fallbackValue: null,
+ }
+ );
+
+ return (
+ <>
+
Current lyrics provider: {lyricsInfo?.useLyric || "None"}
+ {loading ?
Loading lyrics count... : error ?
Failed to get lyrics count :
Lyrics count: {count}}
+ >
+ );
+}
+
+
+function InstallInstructions() {
+ return (
+
+ How to install
+
+ Install TidaLuna from here, then go to TidalLuna settings → Plugin stores → Install @vmohammad/api
+
+
+ );
+}
+
+export const settings = definePluginSettings({
+ showSpotifyControls: {
+ description: "Show Spotify Controls",
+ type: OptionType.BOOLEAN,
+ default: false,
+ },
+ showSpotifyLyrics: {
+ description: "Show Spotify Lyrics",
+ type: OptionType.BOOLEAN,
+ default: false,
+ },
+ installTidalWithWS: {
+ type: OptionType.COMPONENT,
+ component: () =>
+ },
+ showTidalControls: {
+ description: "Show Tidal Player",
+ type: OptionType.BOOLEAN,
+ default: false,
+ },
+ showTidalLyrics: {
+ description: "Show Tidal Controls",
+ type: OptionType.BOOLEAN,
+ default: false,
+ },
+ hoverControls: {
+ description: "Show controls on hover",
+ type: OptionType.BOOLEAN,
+ default: false,
+ onChange: v => toggleHoverControls(v)
+ },
+ useSpotifyUris: {
+ type: OptionType.BOOLEAN,
+ 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
+ },
+ previousButtonRestartsTrack: {
+ type: OptionType.BOOLEAN,
+ description: "Restart currently playing track when pressing the previous button if playtime is >3s",
+ default: true
+ },
+ ShowMusicNoteOnNoLyrics: {
+ description: "Show a music note icon when no lyrics are found",
+ type: OptionType.BOOLEAN,
+ default: true,
+ },
+ LyricsPosition: {
+ description: "Position of the lyrics",
+ type: OptionType.SELECT,
+ options: [
+ { value: "above", label: "Above Player(s)" },
+ { value: "below", label: "Below Player(s)", default: true },
+ ],
+ },
+ LyricsProvider: {
+ description: "Where lyrics are fetched from",
+ type: OptionType.SELECT,
+ options: [
+ { value: Provider.Spotify, label: "Spotify (Musixmatch)", default: true },
+ { value: Provider.Lrclib, label: "LRCLIB" },
+ ],
+ },
+ LyricsConversion: {
+ description: "Automatically translate or romanize lyrics",
+ type: OptionType.SELECT,
+ options: [
+ { value: Provider.None, label: "None", default: true },
+ { value: Provider.Translated, label: "Translate" },
+ { value: Provider.Romanized, label: "Romanize" },
+ ]
+ },
+ FallbackProvider: {
+ description: "When a lyrics provider fails, try other providers",
+ type: OptionType.BOOLEAN,
+ default: true,
+ },
+ ShowFailedToasts: {
+ description: "Hide toasts when lyrics fail to fetch",
+ type: OptionType.BOOLEAN,
+ default: true,
+ },
+ TidalLyricFetch: {
+ description: "Custom URL for fetching lyrics",
+ type: OptionType.STRING,
+ default: "https://api.vmohammad.dev/",
+ placeholder: "https://api.vmohammad.dev/",
+ onChange: (value: string) => {
+ if (!value.endsWith("/")) {
+ value += "/";
+ }
+ if (URL.canParse(value)) {
+ settings.store.TidalLyricFetch = value;
+ } else {
+ showToast("Invalid URL format for CustomUrl: " + value, Toasts.Type.FAILURE);
+ settings.store.TidalLyricFetch = "https://api.vmohammad.dev/";
+ }
+ }
+ },
+ LyricDelay: {
+ description: "",
+ type: OptionType.SLIDER,
+ default: 0,
+ ...sliderOptions
+ },
+ SyncMode: {
+ description: "Lyrics sync mode",
+ type: OptionType.SELECT,
+ options: [
+ { value: "line", label: "Line" },
+ { value: "word", label: "Word", default: true },
+ { value: "character", label: "Character" },
+ ],
+ default: "word",
+ },
+ PurgeLyricsCache: {
+ description: "Purge the lyrics cache",
+ type: OptionType.COMPONENT,
+ component: () => (
+
+ ),
+ },
+});
diff --git a/src/plugins/spotifyControls/PlayerComponent.tsx b/src/equicordplugins/musicControls/spotify/PlayerComponent.tsx
similarity index 98%
rename from src/plugins/spotifyControls/PlayerComponent.tsx
rename to src/equicordplugins/musicControls/spotify/PlayerComponent.tsx
index 32c78c364..1c4a2d0a9 100644
--- a/src/plugins/spotifyControls/PlayerComponent.tsx
+++ b/src/equicordplugins/musicControls/spotify/PlayerComponent.tsx
@@ -134,7 +134,7 @@ function Controls() {
@@ -347,7 +347,7 @@ function Info({ track }: { track: Track; }) {
);
}
-export function Player() {
+export function SpotifyPlayer() {
const track = useStateFromStores(
[SpotifyStore],
() => SpotifyStore.track,
diff --git a/src/plugins/spotifyControls/SeekBar.ts b/src/equicordplugins/musicControls/spotify/SeekBar.ts
similarity index 100%
rename from src/plugins/spotifyControls/SeekBar.ts
rename to src/equicordplugins/musicControls/spotify/SeekBar.ts
diff --git a/src/plugins/spotifyControls/SpotifyStore.ts b/src/equicordplugins/musicControls/spotify/SpotifyStore.ts
similarity index 97%
rename from src/plugins/spotifyControls/SpotifyStore.ts
rename to src/equicordplugins/musicControls/spotify/SpotifyStore.ts
index 65ee2c154..efdfa176f 100644
--- a/src/plugins/spotifyControls/SpotifyStore.ts
+++ b/src/equicordplugins/musicControls/spotify/SpotifyStore.ts
@@ -89,7 +89,7 @@ export const SpotifyStore = proxyLazyWebpack(() => {
public isSettingPosition = false;
public openExternal(path: string) {
- const url = Settings.plugins.SpotifyControls.useSpotifyUris || Vencord.Plugins.isPluginEnabled("OpenInApp")
+ const url = Settings.plugins.MusicControls.useSpotifyUris || Vencord.Plugins.isPluginEnabled("OpenInApp")
? "spotify:" + path.replaceAll("/", (_, idx) => idx === 0 ? "" : ":")
: "https://open.spotify.com" + path;
diff --git a/src/equicordplugins/spotifyLyrics/api.tsx b/src/equicordplugins/musicControls/spotify/lyrics/api.tsx
similarity index 97%
rename from src/equicordplugins/spotifyLyrics/api.tsx
rename to src/equicordplugins/musicControls/spotify/lyrics/api.tsx
index 379a564d1..a92381d77 100644
--- a/src/equicordplugins/spotifyLyrics/api.tsx
+++ b/src/equicordplugins/musicControls/spotify/lyrics/api.tsx
@@ -5,13 +5,12 @@
*/
import { DataStore } from "@api/index";
-import { Track } from "plugins/spotifyControls/SpotifyStore";
+import { settings } from "../../settings";
+import { Track } from "../SpotifyStore";
import { getLyricsLrclib } from "./providers/lrclibAPI";
import { getLyricsSpotify } from "./providers/SpotifyAPI";
import { LyricsData, Provider, SyncedLyric } from "./providers/types";
-import settings from "./settings";
-
const LyricsCacheKey = "SpotifyLyricsCacheNew";
diff --git a/src/equicordplugins/spotifyLyrics/components/ctxMenu.tsx b/src/equicordplugins/musicControls/spotify/lyrics/components/ctxMenu.tsx
similarity index 100%
rename from src/equicordplugins/spotifyLyrics/components/ctxMenu.tsx
rename to src/equicordplugins/musicControls/spotify/lyrics/components/ctxMenu.tsx
diff --git a/src/equicordplugins/spotifyLyrics/components/lyrics.tsx b/src/equicordplugins/musicControls/spotify/lyrics/components/lyrics.tsx
similarity index 94%
rename from src/equicordplugins/spotifyLyrics/components/lyrics.tsx
rename to src/equicordplugins/musicControls/spotify/lyrics/components/lyrics.tsx
index f323ab2ef..7a3770093 100644
--- a/src/equicordplugins/spotifyLyrics/components/lyrics.tsx
+++ b/src/equicordplugins/musicControls/spotify/lyrics/components/lyrics.tsx
@@ -6,10 +6,10 @@
import { openModal } from "@utils/modal";
import { ContextMenuApi, React, Text, TooltipContainer, useEffect, useState, useStateFromStores } from "@webpack/common";
-import { SpotifyStore } from "plugins/spotifyControls/SpotifyStore";
+import { settings } from "../../../settings";
+import { SpotifyStore } from "../../SpotifyStore";
import { SpotifyLrcStore } from "../providers/store";
-import settings from "../settings";
import { LyricsContextMenu } from "./ctxMenu";
import { LyricsModal } from "./modal";
import { cl, NoteSvg, useLyrics } from "./util";
@@ -63,7 +63,7 @@ function LyricsDisplay({ scroll = true }: { scroll?: boolean; }) {
);
}
-export function Lyrics({ scroll = true }: { scroll?: boolean; } = {}) {
+export function SpotifyLyrics({ scroll = true }: { scroll?: boolean; } = {}) {
SpotifyLrcStore.init();
const track = useStateFromStores(
[SpotifyStore],
diff --git a/src/equicordplugins/spotifyLyrics/components/modal.tsx b/src/equicordplugins/musicControls/spotify/lyrics/components/modal.tsx
similarity index 97%
rename from src/equicordplugins/spotifyLyrics/components/modal.tsx
rename to src/equicordplugins/musicControls/spotify/lyrics/components/modal.tsx
index 855bcf967..6a3423fec 100644
--- a/src/equicordplugins/spotifyLyrics/components/modal.tsx
+++ b/src/equicordplugins/musicControls/spotify/lyrics/components/modal.tsx
@@ -7,8 +7,8 @@
import { openImageModal } from "@utils/discord";
import { ModalContent, ModalHeader, ModalProps, ModalRoot } from "@utils/modal";
import { React, Text } from "@webpack/common";
-import { SpotifyStore, Track } from "plugins/spotifyControls/SpotifyStore";
+import { SpotifyStore, Track } from "../../SpotifyStore";
import { cl, NoteSvg, scrollClasses, useLyrics } from "./util";
const formatTime = (time: number) => {
diff --git a/src/equicordplugins/spotifyLyrics/components/util.tsx b/src/equicordplugins/musicControls/spotify/lyrics/components/util.tsx
similarity index 96%
rename from src/equicordplugins/spotifyLyrics/components/util.tsx
rename to src/equicordplugins/musicControls/spotify/lyrics/components/util.tsx
index a3ed7884b..176df03a7 100644
--- a/src/equicordplugins/spotifyLyrics/components/util.tsx
+++ b/src/equicordplugins/musicControls/spotify/lyrics/components/util.tsx
@@ -7,12 +7,11 @@
import { classNameFactory } from "@api/Styles";
import { findByPropsLazy } from "@webpack";
import { React, useEffect, useState, useStateFromStores } from "@webpack/common";
-import { SpotifyStore } from "plugins/spotifyControls/SpotifyStore";
+import { settings } from "../../../settings";
+import { SpotifyStore } from "../../SpotifyStore";
import { SpotifyLrcStore } from "../providers/store";
import { SyncedLyric } from "../providers/types";
-import settings from "../settings";
-
export const scrollClasses = findByPropsLazy("auto", "customTheme");
export const cl = classNameFactory("vc-spotify-lyrics-");
diff --git a/src/equicordplugins/spotifyLyrics/providers/SpotifyAPI/index.ts b/src/equicordplugins/musicControls/spotify/lyrics/providers/SpotifyAPI/index.ts
similarity index 100%
rename from src/equicordplugins/spotifyLyrics/providers/SpotifyAPI/index.ts
rename to src/equicordplugins/musicControls/spotify/lyrics/providers/SpotifyAPI/index.ts
diff --git a/src/equicordplugins/spotifyLyrics/providers/lrclibAPI/index.ts b/src/equicordplugins/musicControls/spotify/lyrics/providers/lrclibAPI/index.ts
similarity index 96%
rename from src/equicordplugins/spotifyLyrics/providers/lrclibAPI/index.ts
rename to src/equicordplugins/musicControls/spotify/lyrics/providers/lrclibAPI/index.ts
index e38be95b4..5ee570476 100644
--- a/src/equicordplugins/spotifyLyrics/providers/lrclibAPI/index.ts
+++ b/src/equicordplugins/musicControls/spotify/lyrics/providers/lrclibAPI/index.ts
@@ -4,8 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
-import { Track } from "plugins/spotifyControls/SpotifyStore";
-
+import { Track } from "../../../SpotifyStore";
import { LyricsData, Provider } from "../types";
const baseUrlLrclib = "https://lrclib.net/api/get";
diff --git a/src/equicordplugins/spotifyLyrics/providers/store.ts b/src/equicordplugins/musicControls/spotify/lyrics/providers/store.ts
similarity index 97%
rename from src/equicordplugins/spotifyLyrics/providers/store.ts
rename to src/equicordplugins/musicControls/spotify/lyrics/providers/store.ts
index 34c8a321c..5f9049891 100644
--- a/src/equicordplugins/spotifyLyrics/providers/store.ts
+++ b/src/equicordplugins/musicControls/spotify/lyrics/providers/store.ts
@@ -7,10 +7,10 @@
import { showNotification } from "@api/Notifications";
import { proxyLazyWebpack } from "@webpack";
import { Flux, FluxDispatcher } from "@webpack/common";
-import { SpotifyStore, type Track } from "plugins/spotifyControls/SpotifyStore";
+import { settings } from "../../../settings";
+import { SpotifyStore, type Track } from "../../SpotifyStore";
import { getLyrics, lyricFetchers, providers, updateLyrics } from "../api";
-import settings from "../settings";
import { lyricsAlternativeFetchers } from "./translator";
import { LyricsData, Provider } from "./types";
diff --git a/src/equicordplugins/spotifyLyrics/providers/translator/index.ts b/src/equicordplugins/musicControls/spotify/lyrics/providers/translator/index.ts
similarity index 98%
rename from src/equicordplugins/spotifyLyrics/providers/translator/index.ts
rename to src/equicordplugins/musicControls/spotify/lyrics/providers/translator/index.ts
index 37555103a..02d7308ec 100644
--- a/src/equicordplugins/spotifyLyrics/providers/translator/index.ts
+++ b/src/equicordplugins/musicControls/spotify/lyrics/providers/translator/index.ts
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
-import settings from "../../settings";
+import settings from "../../../..";
import { LyricsData, Provider, SyncedLyric } from "../types";
// stolen from src\plugins\translate\utils.ts
diff --git a/src/equicordplugins/spotifyLyrics/providers/translator/languages.ts b/src/equicordplugins/musicControls/spotify/lyrics/providers/translator/languages.ts
similarity index 100%
rename from src/equicordplugins/spotifyLyrics/providers/translator/languages.ts
rename to src/equicordplugins/musicControls/spotify/lyrics/providers/translator/languages.ts
diff --git a/src/equicordplugins/spotifyLyrics/providers/types.ts b/src/equicordplugins/musicControls/spotify/lyrics/providers/types.ts
similarity index 100%
rename from src/equicordplugins/spotifyLyrics/providers/types.ts
rename to src/equicordplugins/musicControls/spotify/lyrics/providers/types.ts
diff --git a/src/plugins/spotifyControls/spotifyStyles.css b/src/equicordplugins/musicControls/spotify/spotifyStyles.css
similarity index 100%
rename from src/plugins/spotifyControls/spotifyStyles.css
rename to src/equicordplugins/musicControls/spotify/spotifyStyles.css
diff --git a/src/equicordplugins/tidalLyrics/styles.css b/src/equicordplugins/musicControls/styles.css
similarity index 72%
rename from src/equicordplugins/tidalLyrics/styles.css
rename to src/equicordplugins/musicControls/styles.css
index d22c2718a..b0a42927f 100644
--- a/src/equicordplugins/tidalLyrics/styles.css
+++ b/src/equicordplugins/musicControls/styles.css
@@ -1,4 +1,82 @@
-/* Rework: polish container and sync mode visuals; modernize color notation; fix selector order; merge reduced-motion rules */
+/* stylelint-disable rule-empty-line-before */
+.vc-spotify-lyrics {
+ padding: 0.375rem 0.5rem;
+ text-align: center;
+ overflow: hidden;
+ max-height: 60px;
+ cursor: pointer;
+}
+
+.vc-spotify-lyrics-music-note {
+ font-size: 16px;
+ text-align: center;
+ animation: side-to-side 2s ease-in-out infinite;
+ color: var(--text-muted);
+ height: 18px;
+ margin: 3px;
+}
+
+.vc-spotify-lyrics-next,
+.vc-spotify-lyrics-prev {
+ color: var(--text-muted);
+ margin-bottom: 1%;
+}
+
+@keyframes side-to-side {
+
+ 0%,
+ 100% {
+ transform: translateX(0);
+ }
+
+ 50% {
+ transform: translateX(-10px);
+ }
+}
+
+.vc-spotify-lyrics-header-content {
+ display: flex;
+ align-items: center;
+ width: 100%;
+}
+
+.vc-spotify-lyrics-album-image {
+ width: 100px;
+ height: 100px;
+ margin-right: 5%;
+ border-radius: 5px;
+ cursor: pointer;
+}
+
+.vc-spotify-lyrics-modal-line-current,
+.vc-spotify-lyrics-modal-line {
+ margin: 4px 0;
+ padding: 4px 8px;
+ position: relative;
+}
+
+.vc-spotify-lyrics-modal-line-current {
+ font-weight: bold;
+}
+
+.vc-spotify-lyrics-modal-note {
+ height: 1lh;
+}
+
+.vc-spotify-lyrics-modal-timestamp {
+ color: var(--text-muted);
+ margin-right: 0.5em;
+ cursor: pointer;
+}
+
+.vc-spotify-lyrics-modal-timestamp:hover {
+ text-decoration: underline;
+}
+
+.vc-spotify-lyrics-modal-no-lyrics {
+ text-align: center;
+ padding: 1rem;
+}
.eq-tidal-lyrics {
padding: 0.375rem 0.5rem;
@@ -95,7 +173,6 @@
color: var(--brand-experiment);
font-weight: 600;
text-shadow: 0 0 .25em currentcolor;
- transform: scale(1.04);
}
.eq-tidal-lyrics-word {
@@ -118,7 +195,6 @@
background: none;
box-shadow: none;
text-shadow: 0 0 .25em currentcolor;
- transform: scale(1.04);
}
.eq-tidal-lyrics-current,
@@ -154,6 +230,7 @@
@media (prefers-reduced-motion: reduce) {
+
.eq-tidal-lyrics-current,
.eq-tidal-lyrics-next,
.eq-tidal-lyrics-prev,
@@ -167,4 +244,4 @@
.eq-tidal-lyrics-word-active {
transform: none;
}
-}
+}
\ No newline at end of file
diff --git a/src/equicordplugins/tidalControls/TidalPlayer.tsx b/src/equicordplugins/musicControls/tidal/TidalPlayer.tsx
similarity index 97%
rename from src/equicordplugins/tidalControls/TidalPlayer.tsx
rename to src/equicordplugins/musicControls/tidal/TidalPlayer.tsx
index ca4326c2f..e4651707e 100644
--- a/src/equicordplugins/tidalControls/TidalPlayer.tsx
+++ b/src/equicordplugins/musicControls/tidal/TidalPlayer.tsx
@@ -6,13 +6,14 @@
import "./tidalStyles.css";
+import { Settings } from "@api/Settings";
import { ImageIcon, LinkIcon, OpenExternalIcon } from "@components/Icons";
-import { SeekBar } from "@plugins/spotifyControls/SeekBar";
import { debounce } from "@shared/debounce";
import { openImageModal } from "@utils/discord";
import { classes, copyWithToast } from "@utils/misc";
import { ContextMenuApi, Flex, FluxDispatcher, Forms, Menu, React, useEffect, useState, useStateFromStores } from "@webpack/common";
+import { SeekBar } from "../spotify/SeekBar";
import { type PlayerState, type Repeat, TidalStore } from "./TidalStore";
const cl = (className: string) => `eq-tdl-${className}`;
@@ -120,7 +121,10 @@ function Controls() {
>
-