vd-plugins/plugins/Last.fm/src/index.tsx

154 lines
3.9 KiB
TypeScript
Raw Normal View History

2025-09-13 00:12:49 +02:00
import { plugin } from "@vendetta";
2025-09-13 22:10:01 +02:00
import { FluxDispatcher } from "@vendetta/metro/common";
import { getAssetIDByName } from "@vendetta/ui/assets";
import { showToast } from "@vendetta/ui/toasts";
2025-09-13 22:16:11 +02:00
import { React } from "@vendetta/metro/common";
2025-09-19 21:39:56 +02:00
import { ScrollView, View } from "react-native";
2025-09-13 22:16:11 +02:00
import { Forms } from "@vendetta/ui/components";
2025-09-13 00:12:49 +02:00
2025-09-13 22:10:01 +02:00
import { lazy } from "react";
import { LFMSettings } from "../../defs";
import Constants from "./constants";
import { initialize, stop } from "./manager";
2025-09-13 00:12:49 +02:00
import { UserStore } from "./modules";
2025-09-13 22:16:11 +02:00
const { FormText } = Forms;
2025-09-13 22:10:01 +02:00
export const pluginState = {
pluginStopped: false,
lastActivity: undefined,
updateInterval: undefined,
lastTrackUrl: undefined,
} as {
pluginStopped: boolean;
lastActivity?: any;
updateInterval?: NodeJS.Timer;
lastTrackUrl?: string;
};
2025-09-13 00:12:49 +02:00
2025-09-13 22:10:01 +02:00
// Initialize default settings
const defaultSettings: LFMSettings = Constants.DEFAULT_SETTINGS;
for (const key in defaultSettings) {
plugin.storage[key] =
plugin.storage[key] ?? defaultSettings[key as keyof typeof defaultSettings];
}
2025-09-13 00:12:49 +02:00
2025-09-13 22:10:01 +02:00
export const currentSettings = new Proxy(plugin.storage, {
get(target, prop) {
return target[prop];
},
set(target, prop, value) {
target[prop] = value;
return true;
},
});
2025-09-13 00:12:49 +02:00
2025-09-19 21:50:49 +02:00
// Simple Settings component for fallback
function FallbackSettings() {
return (
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ padding: 16 }}>
<FormText style={{ color: "#ED4245" }}>
Failed to load Last.fm settings. Please check your connection and reload
Discord.
</FormText>
</ScrollView>
);
}
2025-09-13 22:22:13 +02:00
// Settings component with error handling
2025-09-19 21:50:49 +02:00
const Settings = lazy(async () => {
try {
const module = await import("./ui/pages/Settings");
return { default: module.default || FallbackSettings };
} catch (err) {
console.error("[Last.fm] Failed to load settings:", err);
return { default: FallbackSettings };
}
});
2025-09-13 00:12:49 +02:00
2025-09-13 22:10:01 +02:00
// Connection status tracking
let connectionAttempts = 0;
const MAX_CONNECTION_ATTEMPTS = 3;
const RECONNECT_DELAY = 5000;
2025-09-13 00:12:49 +02:00
2025-09-13 22:10:01 +02:00
async function tryInitialize() {
try {
await initialize();
connectionAttempts = 0;
} catch (error) {
console.error("[Last.fm] Initialization error:", error);
connectionAttempts++;
2025-09-13 00:12:49 +02:00
2025-09-13 22:10:01 +02:00
if (connectionAttempts < MAX_CONNECTION_ATTEMPTS) {
showToast("Retrying connection...", getAssetIDByName("ic_clock"));
setTimeout(tryInitialize, RECONNECT_DELAY);
} else {
showToast("Failed to connect to Last.fm", getAssetIDByName("Small"));
2025-09-13 00:12:49 +02:00
}
2025-09-13 22:10:01 +02:00
}
2025-09-13 00:12:49 +02:00
}
2025-09-19 21:50:49 +02:00
// Create the plugin object
const pluginObj = {
2025-09-13 22:10:01 +02:00
onLoad() {
pluginState.pluginStopped = false;
2025-09-13 00:12:49 +02:00
2025-09-13 22:10:01 +02:00
if (!currentSettings.username || !currentSettings.apiKey) {
showToast(
"Please configure Last.fm username and API key in settings",
getAssetIDByName("ic_warning"),
);
return;
}
2025-09-13 00:12:49 +02:00
2025-09-13 22:10:01 +02:00
if (UserStore.getCurrentUser()) {
tryInitialize();
} else {
const waitForUser = () => {
if (UserStore.getCurrentUser()) {
tryInitialize();
FluxDispatcher.unsubscribe("CONNECTION_OPEN", waitForUser);
2025-09-13 00:12:49 +02:00
}
2025-09-13 22:10:01 +02:00
};
2025-09-13 00:12:49 +02:00
2025-09-13 22:10:01 +02:00
FluxDispatcher.subscribe("CONNECTION_OPEN", waitForUser);
}
},
onUnload() {
pluginState.pluginStopped = true;
stop();
},
// Handle settings updates
onSettingsUpdate(newSettings: any) {
Object.assign(currentSettings, newSettings);
tryInitialize();
},
// Handle Discord reconnection
onDiscordReconnect() {
if (!pluginState.pluginStopped) {
tryInitialize();
2025-09-13 00:12:49 +02:00
}
2025-09-13 22:10:01 +02:00
},
2025-09-13 00:12:49 +02:00
};
2025-09-19 21:50:49 +02:00
// Add settings property to the plugin object
Object.defineProperty(pluginObj, "settings", {
get: () => (
<React.Suspense
fallback={
<View
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
>
<FormText>Loading Last.fm settings...</FormText>
</View>
}
>
<Settings />
</React.Suspense>
),
enumerable: true,
configurable: true,
});
export default pluginObj;