import { plugin } from "@vendetta"; import { useProxy } from "@vendetta/storage"; import { React } from "@vendetta/metro/common"; import { NavigationNative } from "@vendetta/metro/common"; import { Stack, TableRowGroup, TableRow, TableSwitchRow, TableCheckboxRow, ScrollView, } from "./pages/components/TableComponents"; // Import pages import LastFmSettingsPage from "./pages/LastFmSettingsPage"; import LibreFmSettingsPage from "./pages/LibreFmSettingsPage"; import ListenBrainzSettingsPage from "./pages/ListenBrainzSettingsPage"; import DisplaySettingsPage from "./pages/DisplaySettingsPage"; import RPCCustomizationSettingsPage from "./pages/RPCCustomizationSettingsPage"; import IgnoreListSettingsPage from "./pages/IgnoreListSettingsPage"; import LoggingSettingsPage from "./pages/LoggingSettingsPage"; import { ServiceType } from "../../../../defs"; // Storage defaults plugin.storage.username ??= ""; plugin.storage.apiKey ??= ""; plugin.storage.appName ??= "Music"; plugin.storage.timeInterval ??= 5; plugin.storage.showTimestamp ??= true; plugin.storage.listeningTo ??= true; plugin.storage.verboseLogging ??= false; plugin.storage.service ??= "lastfm"; plugin.storage.librefmUsername ??= ""; plugin.storage.librefmApiKey ??= ""; plugin.storage.listenbrainzUsername ??= ""; plugin.storage.listenbrainzToken ??= ""; plugin.storage.addToSidebar ??= true; plugin.storage.showLargeText ??= true; plugin.storage.ignoreList ??= []; plugin.storage.showAlbumInTooltip ??= true; plugin.storage.showDurationInTooltip ??= true; export const getStorage = (k: string, fallback?: any) => plugin.storage[k] ?? fallback; export const setStorage = (k: string, v: any) => (plugin.storage[k] = v); // Integrated ServiceFactory class ServiceFactory { static getServiceDisplayName(service: ServiceType): string { switch (service) { case "lastfm": return "Last.fm"; case "librefm": return "Libre.fm"; case "listenbrainz": return "ListenBrainz"; default: return "Unknown"; } } static async testService(service: ServiceType): Promise { try { switch (service) { case "lastfm": return await this.testLastFmConnection(); case "librefm": return await this.testLibreFmConnection(); case "listenbrainz": return await this.testListenBrainzConnection(); default: return false; } } catch (error) { console.error(`Error testing ${service}:`, error); return false; } } private static async testLastFmConnection(): Promise { const username = getStorage("username"); const apiKey = getStorage("apiKey"); if (!username || !apiKey) return false; try { const response = await fetch( `https://ws.audioscrobbler.com/2.0/?method=user.getinfo&user=${username}&api_key=${apiKey}&format=json`, ); const data = await response.json(); return !data.error; } catch (error) { console.error("Last.fm connection test failed:", error); return false; } } private static async testLibreFmConnection(): Promise { const username = getStorage("librefmUsername"); const apiKey = getStorage("librefmApiKey"); if (!username || !apiKey) return false; try { const response = await fetch( `https://libre.fm/2.0/?method=user.getinfo&user=${username}&api_key=${apiKey}&format=json`, ); const data = await response.json(); return !data.error; } catch (error) { console.error("Libre.fm connection test failed:", error); return false; } } private static async testListenBrainzConnection(): Promise { const username = getStorage("listenbrainzUsername"); const token = getStorage("listenbrainzToken"); if (!username) return false; try { const headers: Record = { "Content-Type": "application/json", }; if (token) headers["Authorization"] = `Token ${token}`; const response = await fetch( `https://api.listenbrainz.org/1/user/${username}/listen-count`, { headers }, ); return response.status === 200; } catch (error) { console.error("ListenBrainz connection test failed:", error); return false; } } } export const serviceFactory = ServiceFactory; export default function Settings() { useProxy(plugin.storage); const navigation = NavigationNative.useNavigation(); const [, forceUpdate] = React.useReducer((x) => x + 1, 0); const currentService = getStorage("service") as ServiceType; const getCredentialStatus = (service: ServiceType) => { switch (service) { case "lastfm": return getStorage("username") && getStorage("apiKey") ? "✅ Configured" : "❌ Missing credentials"; case "librefm": return getStorage("librefmUsername") && getStorage("librefmApiKey") ? "✅ Configured" : "❌ Missing credentials"; case "listenbrainz": return getStorage("listenbrainzUsername") ? "✅ Configured" : "❌ Missing username"; default: return "❓ Unknown"; } }; return ( {/* Service Selection */} {(["lastfm", "librefm", "listenbrainz"] as ServiceType[]).map( (service) => ( { // Only update if clicking a service that isn't already selected if (service !== currentService) { setStorage("service", service); forceUpdate(); } }} /> ), )} {/* Service Configuration */} } onPress={() => navigation.push("VendettaCustomPage", { title: "Last.fm Settings", render: LastFmSettingsPage, }) } /> } onPress={() => navigation.push("VendettaCustomPage", { title: "Libre.fm Settings", render: LibreFmSettingsPage, }) } /> } onPress={() => navigation.push("VendettaCustomPage", { title: "ListenBrainz Settings", render: ListenBrainzSettingsPage, }) } /> {/* Plugin Configuration */} } onPress={() => navigation.push("VendettaCustomPage", { title: "Display Settings", render: DisplaySettingsPage, }) } /> } onPress={() => navigation.push("VendettaCustomPage", { title: "RPC Customization", render: RPCCustomizationSettingsPage, }) } /> } onPress={() => navigation.push("VendettaCustomPage", { title: "Ignore List Settings", render: IgnoreListSettingsPage, }) } /> } onPress={() => navigation.push("VendettaCustomPage", { title: "Logging Settings", render: LoggingSettingsPage, }) } /> { setStorage("addToSidebar", value); forceUpdate(); }} /> {/* About */} ); }