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 */}
);
}