import { plugin } from "@vendetta"; import { useProxy } from "@vendetta/storage"; import { React, ReactNative as RN } from "@vendetta/metro/common"; import { Linking } from "react-native"; import { NavigationNative } from "@vendetta/metro/common"; import { findByProps } from "@vendetta/metro"; import { showToast } from "@vendetta/ui/toasts"; import { getAssetIDByName } from "@vendetta/ui/assets"; const { ScrollView } = findByProps("ScrollView"); const { TableRowGroup, TableSwitchRow, Stack, TableRow } = findByProps( "TableSwitchRow", "TableRowGroup", "Stack", "TableRow", ); const { TextInput } = findByProps("TextInput"); import Constants from "../../constants"; import { serviceFactory } from "../../services/ServiceFactory"; import { ServiceType } from "../../../../defs"; plugin.storage.username ??= ""; plugin.storage.apiKey ??= ""; plugin.storage.appName ??= "Music"; plugin.storage.timeInterval ??= 5; plugin.storage.showTimestamp ??= true; plugin.storage.listeningTo ??= true; plugin.storage.ignoreSpotify ??= 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; const get = (k: string, fallback?: any) => plugin.storage[k] ?? fallback; const set = (k: string, v: any) => (plugin.storage[k] = v); // Last.fm Settings Page function LastFmSettingsPage() { useProxy(plugin.storage); const [, forceUpdate] = React.useReducer((x) => x + 1, 0); const testConnection = async () => { showToast("Testing Last.fm connection...", getAssetIDByName("ClockIcon")); try { const isValid = await serviceFactory.testService("lastfm"); if (isValid) { showToast( "✅ Last.fm connection successful!", getAssetIDByName("CheckIcon"), ); } else { showToast("❌ Last.fm connection failed", getAssetIDByName("XIcon")); } } catch (error) { showToast("❌ Connection error", getAssetIDByName("XIcon")); } }; return ( { set("username", v); forceUpdate(); }} isClearable /> { set("apiKey", v); forceUpdate(); }} secureTextEntry={true} isClearable /> } onPress={testConnection} /> } onPress={async () => { try { await Linking.openURL("https://www.last.fm/api/account/create"); } catch (error) { console.error("Failed to open Last.fm API URL:", error); showToast( "Failed to open web browser. Please visit: https://www.last.fm/api/account/create", getAssetIDByName("XIcon"), ); } }} /> ); } // Libre.fm Settings Page function LibreFmSettingsPage() { useProxy(plugin.storage); const [, forceUpdate] = React.useReducer((x) => x + 1, 0); const testConnection = async () => { showToast("Testing Libre.fm connection...", getAssetIDByName("ClockIcon")); try { const isValid = await serviceFactory.testService("librefm"); if (isValid) { showToast( "✅ Libre.fm connection successful!", getAssetIDByName("CheckIcon"), ); } else { showToast("❌ Libre.fm connection failed", getAssetIDByName("XIcon")); } } catch (error) { showToast("❌ Connection error", getAssetIDByName("XIcon")); } }; return ( { set("librefmUsername", v); forceUpdate(); }} isClearable /> { set("librefmApiKey", v); forceUpdate(); }} secureTextEntry={true} isClearable /> } onPress={testConnection} /> } onPress={async () => { try { await Linking.openURL("https://www.last.fm/api/account/create"); } catch (error) { console.error("Failed to open Last.fm API URL:", error); showToast( "Failed to open web browser. Please visit: https://www.last.fm/api/account/create", getAssetIDByName("XIcon"), ); } }} /> ); } // ListenBrainz Settings Page function ListenBrainzSettingsPage() { useProxy(plugin.storage); const [, forceUpdate] = React.useReducer((x) => x + 1, 0); const testConnection = async () => { showToast( "Testing ListenBrainz connection...", getAssetIDByName("ClockIcon"), ); try { const isValid = await serviceFactory.testService("listenbrainz"); if (isValid) { showToast( "✅ ListenBrainz connection successful!", getAssetIDByName("CheckIcon"), ); } else { showToast( "❌ ListenBrainz connection failed", getAssetIDByName("XIcon"), ); } } catch (error) { showToast("❌ Connection error", getAssetIDByName("XIcon")); } }; return ( { set("listenbrainzUsername", v); forceUpdate(); }} isClearable /> { set("listenbrainzToken", v); forceUpdate(); }} secureTextEntry={true} isClearable /> } onPress={testConnection} /> } onPress={async () => { try { await Linking.openURL("https://listenbrainz.org/settings/"); } catch (error) { console.error( "Failed to open ListenBrainz settings URL:", error, ); showToast( "Failed to open web browser. Please visit: https://listenbrainz.org/settings/", getAssetIDByName("XIcon"), ); } }} /> ); } // Display Settings Page function DisplaySettingsPage() { useProxy(plugin.storage); const [, forceUpdate] = React.useReducer((x) => x + 1, 0); return ( { set("appName", v); forceUpdate(); }} isClearable /> { const interval = Number(v); if (interval >= Constants.MIN_UPDATE_INTERVAL) { set("timeInterval", interval); forceUpdate(); } }} keyboardType="numeric" isClearable /> { set("listeningTo", value); forceUpdate(); }} /> { set("showTimestamp", value); forceUpdate(); }} /> { set("ignoreSpotify", value); forceUpdate(); }} /> ); } // Logging Settings Page function LoggingSettingsPage() { useProxy(plugin.storage); const [, forceUpdate] = React.useReducer((x) => x + 1, 0); return ( { set("verboseLogging", value); forceUpdate(); }} /> ); } // Main Settings Page export default function Settings() { useProxy(plugin.storage); const navigation = NavigationNative.useNavigation(); const [, forceUpdate] = React.useReducer((x) => x + 1, 0); const currentService = get("service") as ServiceType; const getCredentialStatus = (service: ServiceType) => { switch (service) { case "lastfm": { return get("username") && get("apiKey") ? "✅ Configured" : "❌ Missing credentials"; } case "librefm": { return get("librefmUsername") && get("librefmApiKey") ? "✅ Configured" : "❌ Missing credentials"; } case "listenbrainz": { return get("listenbrainzUsername") ? "✅ Configured" : "❌ Missing username"; } default: return "❓ Unknown"; } }; return ( {/* Service Selection */} {(["lastfm", "librefm", "listenbrainz"] as ServiceType[]).map( (service) => ( { if (value && service !== currentService) { set("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: "Logging Settings", render: LoggingSettingsPage, }) } /> { set("addToSidebar", value); forceUpdate(); }} /> {/* About */} ); }