From 6fa13a06411048f3217397f4285b3e64e7b9ee58 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Sat, 14 Feb 2026 09:42:14 -0800 Subject: feature: implement full OPML and Text import/export (fixing NK-r6nhj0) --- frontend/src/components/Settings.tsx | 64 +++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) (limited to 'frontend/src/components/Settings.tsx') diff --git a/frontend/src/components/Settings.tsx b/frontend/src/components/Settings.tsx index 3f508e9..6b6dab1 100644 --- a/frontend/src/components/Settings.tsx +++ b/frontend/src/components/Settings.tsx @@ -9,6 +9,8 @@ export default function Settings() { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); + const [importFile, setImportFile] = useState(null); + const fetchFeeds = () => { setLoading(true); apiFetch('/api/feed/') @@ -30,8 +32,6 @@ export default function Settings() { fetchFeeds(); }, []); - - const handleAddFeed = (e: React.FormEvent) => { e.preventDefault(); if (!newFeedUrl) return; @@ -48,7 +48,7 @@ export default function Settings() { }) .then(() => { setNewFeedUrl(''); - fetchFeeds(); // Refresh list (or we could append if server returns full feed object) + fetchFeeds(); }) .catch((err) => { setError(err.message); @@ -74,6 +74,34 @@ export default function Settings() { }); }; + const handleImport = (e: React.FormEvent) => { + e.preventDefault(); + if (!importFile) return; + + setLoading(true); + const formData = new FormData(); + formData.append('file', importFile); + formData.append('format', 'opml'); + + apiFetch('/api/import', { + method: 'POST', + body: formData, + }) + .then((res) => { + if (!res.ok) throw new Error('Failed to import feeds'); + return res.json(); + }) + .then(() => { + setImportFile(null); + fetchFeeds(); + alert('Import successful!'); + }) + .catch((err) => { + setError(err.message); + setLoading(false); + }); + }; + return (

Settings

@@ -94,9 +122,37 @@ export default function Settings() { Add Feed - {error &&

{error}

}
+
+
+

Import Feeds (OPML)

+
+ setImportFile(e.target.files?.[0] || null)} + className="file-input" + disabled={loading} + /> + +
+
+ +
+

Export Feeds

+
+ OPML + Text + JSON +
+
+
+ + {error &&

{error}

} +

Manage Feeds

{loading &&

Loading...

} -- cgit v1.2.3