106 lines
4.7 KiB
TypeScript
106 lines
4.7 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { X, RefreshCw, CheckCircle, AlertCircle } from "lucide-react";
|
|
import { api } from "@/services/apiClient";
|
|
|
|
interface SettingsModalProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
}
|
|
|
|
export default function SettingsModal({ isOpen, onClose }: SettingsModalProps) {
|
|
const [updating, setUpdating] = useState(false);
|
|
const [status, setStatus] = useState<{ type: "success" | "error" | null; message: string }>({ type: null, message: "" });
|
|
|
|
if (!isOpen) return null;
|
|
|
|
const handleUpdate = async (module: 'ytdlp' | 'spotdl') => {
|
|
setUpdating(true);
|
|
setStatus({ type: null, message: "" });
|
|
try {
|
|
const endpoint = module === 'ytdlp' ? "/settings/update-ytdlp" : "/settings/update-spotdl";
|
|
await api.post(endpoint, {});
|
|
setStatus({ type: "success", message: `${module} updated! Server is restarting...` });
|
|
// Reload page after a delay to reflect restart
|
|
setTimeout(() => {
|
|
window.location.reload();
|
|
}, 5000);
|
|
} catch (e: any) {
|
|
console.error(e); // Debugging
|
|
setStatus({ type: "error", message: e.message || "Update failed. Check console." });
|
|
} finally {
|
|
setUpdating(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4">
|
|
<div className="bg-[#1e1e1e] rounded-xl p-6 w-full max-w-md shadow-2xl border border-white/10">
|
|
<div className="flex justify-between items-center mb-6">
|
|
<h2 className="text-xl font-bold">Settings</h2>
|
|
<button onClick={onClose} className="p-2 hover:bg-white/10 rounded-full transition">
|
|
<X size={20} />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="space-y-6">
|
|
<div className="bg-[#2a2a2a] p-4 rounded-lg flex flex-col gap-4">
|
|
<div>
|
|
<h3 className="font-semibold mb-2">Core Components</h3>
|
|
<p className="text-sm text-gray-400 mb-2">
|
|
Update core libraries to fix playback or download issues.
|
|
</p>
|
|
</div>
|
|
|
|
<button
|
|
onClick={() => handleUpdate('ytdlp')}
|
|
disabled={updating}
|
|
className={`w-full py-3 rounded-lg font-medium flex items-center justify-center gap-2 transition ${updating ? "bg-blue-600/50 cursor-not-allowed" : "bg-blue-600 hover:bg-blue-500"
|
|
}`}
|
|
>
|
|
{updating ? (
|
|
<>
|
|
<RefreshCw className="animate-spin" size={18} />
|
|
Updating yt-dlp...
|
|
</>
|
|
) : (
|
|
<>
|
|
<RefreshCw size={18} />
|
|
Update yt-dlp (Nightly)
|
|
</>
|
|
)}
|
|
</button>
|
|
|
|
<button
|
|
onClick={() => handleUpdate('spotdl')}
|
|
disabled={updating}
|
|
className={`w-full py-3 rounded-lg font-medium flex items-center justify-center gap-2 transition ${updating ? "bg-green-600/50 cursor-not-allowed" : "bg-green-600 hover:bg-green-500"
|
|
}`}
|
|
>
|
|
{updating ? (
|
|
<>
|
|
<RefreshCw className="animate-spin" size={18} />
|
|
Updating spotdl...
|
|
</>
|
|
) : (
|
|
<>
|
|
<RefreshCw size={18} />
|
|
Update spotdl (Latest)
|
|
</>
|
|
)}
|
|
</button>
|
|
</div>
|
|
|
|
{status.message && (
|
|
<div className={`p-4 rounded-lg flex items-start gap-3 ${status.type === "success" ? "bg-green-500/10 text-green-400" : "bg-red-500/10 text-red-400"
|
|
}`}>
|
|
{status.type === "success" ? <CheckCircle size={20} /> : <AlertCircle size={20} />}
|
|
<p className="text-sm">{status.message}</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|