diff --git a/backend/config.go b/backend/config.go index 18b56be..3c7af37 100644 --- a/backend/config.go +++ b/backend/config.go @@ -4,6 +4,7 @@ import ( "encoding/json" "os" "path/filepath" + "strings" ) func GetDefaultMusicPath() string { @@ -67,3 +68,34 @@ func GetSpotFetchAPISettings() (bool, string) { return true, apiURL } + +func GetLinkResolverSetting() string { + settings, err := LoadConfigSettings() + if err != nil || settings == nil { + return linkResolverProviderSongstats + } + + resolver, _ := settings["linkResolver"].(string) + switch strings.TrimSpace(strings.ToLower(resolver)) { + case "songlink", linkResolverProviderDeezerSongLink: + return linkResolverProviderDeezerSongLink + case "", "songstats": + return linkResolverProviderSongstats + default: + return linkResolverProviderSongstats + } +} + +func GetLinkResolverAllowFallback() bool { + settings, err := LoadConfigSettings() + if err != nil || settings == nil { + return true + } + + allowFallback, ok := settings["allowResolverFallback"].(bool) + if !ok { + return true + } + + return allowFallback +} diff --git a/backend/link_resolver.go b/backend/link_resolver.go index b614ab1..3eaf044 100644 --- a/backend/link_resolver.go +++ b/backend/link_resolver.go @@ -30,32 +30,23 @@ func (s *SongLinkClient) resolveSpotifyTrackLinks(spotifyTrackID string, region } if links.ISRC != "" { - resolvers := prioritizeProviders("link_resolver", []string{ - linkResolverProviderSongstats, - linkResolverProviderDeezerSongLink, - }) + resolvers := orderedLinkResolvers() for _, resolver := range resolvers { switch resolver { case linkResolverProviderSongstats: addedData, songstatsErr := s.resolveLinksViaSongstats(links) - if addedData { - recordProviderSuccess("link_resolver", linkResolverProviderSongstats) - } else if songstatsErr != nil { - recordProviderFailure("link_resolver", linkResolverProviderSongstats) - } if songstatsErr != nil { attempts = append(attempts, fmt.Sprintf("songstats: %v", songstatsErr)) + } else if addedData { + fmt.Println("Using Songstats as configured link resolver") } case linkResolverProviderDeezerSongLink: addedData, deezerSongLinkErr := s.resolveLinksViaDeezerSongLink(links, region) - if addedData { - recordProviderSuccess("link_resolver", linkResolverProviderDeezerSongLink) - } else if deezerSongLinkErr != nil { - recordProviderFailure("link_resolver", linkResolverProviderDeezerSongLink) - } if deezerSongLinkErr != nil { attempts = append(attempts, fmt.Sprintf("deezer-songlink: %v", deezerSongLinkErr)) + } else if addedData { + fmt.Println("Using Songlink as configured link resolver") } } @@ -76,6 +67,28 @@ func (s *SongLinkClient) resolveSpotifyTrackLinks(spotifyTrackID string, region return links, errors.New(strings.Join(attempts, " | ")) } +func orderedLinkResolvers() []string { + preferred := GetLinkResolverSetting() + if !GetLinkResolverAllowFallback() { + if preferred == linkResolverProviderDeezerSongLink { + return []string{linkResolverProviderDeezerSongLink} + } + return []string{linkResolverProviderSongstats} + } + + if preferred == linkResolverProviderDeezerSongLink { + return []string{ + linkResolverProviderDeezerSongLink, + linkResolverProviderSongstats, + } + } + + return []string{ + linkResolverProviderSongstats, + linkResolverProviderDeezerSongLink, + } +} + func (s *SongLinkClient) resolveLinksViaSongstats(links *resolvedTrackLinks) (bool, error) { if links == nil || links.ISRC == "" { return false, fmt.Errorf("ISRC is required for Songstats resolver") diff --git a/frontend/src/assets/icons/songlink.ico b/frontend/src/assets/icons/songlink.ico new file mode 100644 index 0000000..4fdec81 Binary files /dev/null and b/frontend/src/assets/icons/songlink.ico differ diff --git a/frontend/src/assets/icons/songstats.png b/frontend/src/assets/icons/songstats.png new file mode 100644 index 0000000..fc8a223 Binary files /dev/null and b/frontend/src/assets/icons/songstats.png differ diff --git a/frontend/src/components/SettingsPage.tsx b/frontend/src/components/SettingsPage.tsx index 77a2ece..6249ac3 100644 --- a/frontend/src/components/SettingsPage.tsx +++ b/frontend/src/components/SettingsPage.tsx @@ -14,6 +14,8 @@ import { SelectFolder, OpenConfigFolder } from "../../wailsjs/go/main/App"; import { toastWithSound as toast } from "@/lib/toast-with-sound"; import { ApiStatusTab } from "./ApiStatusTab"; import { AmazonIcon, QobuzIcon, TidalIcon } from "./PlatformIcons"; +import songlinkIcon from "@/assets/icons/songlink.ico"; +import songstatsIcon from "@/assets/icons/songstats.png"; interface SettingsPageProps { onUnsavedChangesChange?: (hasUnsavedChanges: boolean) => void; onResetRequest?: (resetFn: () => void) => void; @@ -230,6 +232,44 @@ export function SettingsPage({ onUnsavedChangesChange, onResetRequest, }: Settin
+
+ +
+ + +
+ setTempSettings((prev) => ({ + ...prev, + allowResolverFallback: checked, + }))}/> + +
+
+
+
diff --git a/frontend/src/lib/settings.ts b/frontend/src/lib/settings.ts index 0920b4e..b80443f 100644 --- a/frontend/src/lib/settings.ts +++ b/frontend/src/lib/settings.ts @@ -5,6 +5,8 @@ export type FilenamePreset = "title" | "title-artist" | "artist-title" | "track- export interface Settings { downloadPath: string; downloader: "auto" | "tidal" | "qobuz" | "amazon"; + linkResolver: "songstats" | "songlink"; + allowResolverFallback: boolean; theme: string; themeMode: "auto" | "light" | "dark"; fontFamily: FontFamily; @@ -93,6 +95,8 @@ function detectOS(): "Windows" | "linux/MacOS" { export const DEFAULT_SETTINGS: Settings = { downloadPath: "", downloader: "auto", + linkResolver: "songstats", + allowResolverFallback: true, theme: "yellow", themeMode: "auto", fontFamily: "google-sans", @@ -225,6 +229,12 @@ function getSettingsFromLocalStorage(): Settings { if (!('allowFallback' in parsed)) { parsed.allowFallback = true; } + if (!('linkResolver' in parsed)) { + parsed.linkResolver = "songstats"; + } + if (!('allowResolverFallback' in parsed)) { + parsed.allowResolverFallback = true; + } if (!('separator' in parsed)) { parsed.separator = "semicolon"; } @@ -304,6 +314,12 @@ export async function loadSettings(): Promise { if (!('allowFallback' in parsed)) { parsed.allowFallback = true; } + if (!('linkResolver' in parsed)) { + parsed.linkResolver = "songstats"; + } + if (!('allowResolverFallback' in parsed)) { + parsed.allowResolverFallback = true; + } if (!('createPlaylistFolder' in parsed)) { parsed.createPlaylistFolder = true; }