"use client" import { useState, useRef } from "react" import { useSubscriptions } from "@/lib/queries/use-subscriptions" import { useSubscribeToFeed } from "@/lib/queries/use-subscribe-to-feed" import { useUserProfile } from "@/lib/queries/use-user-profile" import { downloadOpml, parseOpml } from "@/lib/opml" import type { ParsedOpmlGroup } from "@/lib/opml" import { notify } from "@/lib/notify" export function ImportExportSettings() { const { data: subscriptionsData } = useSubscriptions() const { data: userProfile } = useUserProfile() const subscribeToFeed = useSubscribeToFeed() const [parsedGroups, setParsedGroups] = useState( null ) const [isImporting, setIsImporting] = useState(false) const [isExportingData, setIsExportingData] = useState(false) const fileInputReference = useRef(null) const tier = userProfile?.tier ?? "free" function handleExport() { if (!subscriptionsData) return downloadOpml(subscriptionsData.subscriptions, subscriptionsData.folders) notify("subscriptions exported") } function handleFileSelect(event: React.ChangeEvent) { const file = event.target.files?.[0] if (!file) return const reader = new FileReader() reader.onload = (loadEvent) => { const xmlString = loadEvent.target?.result as string try { const groups = parseOpml(xmlString) setParsedGroups(groups) } catch { notify("failed to parse opml file") } } reader.readAsText(file) if (fileInputReference.current) { fileInputReference.current.value = "" } } async function handleImport() { if (!parsedGroups) return setIsImporting(true) let importedCount = 0 let failedCount = 0 for (const group of parsedGroups) { for (const feed of group.feeds) { try { await new Promise((resolve) => { subscribeToFeed.mutate( { feedUrl: feed.url, customTitle: feed.title || null, }, { onSuccess: () => { importedCount++ resolve() }, onError: () => { failedCount++ resolve() }, } ) }) } catch { failedCount++ } } } setIsImporting(false) setParsedGroups(null) if (failedCount > 0) { notify(`imported ${importedCount} feeds, ${failedCount} failed`) } else { notify(`imported ${importedCount} feeds`) } } async function handleDataExport() { setIsExportingData(true) try { const response = await fetch("/api/export") if (!response.ok) throw new Error("export failed") const blob = await response.blob() const url = URL.createObjectURL(blob) const anchor = document.createElement("a") anchor.href = url anchor.download = `asa-news-export-${new Date().toISOString().slice(0, 10)}.json` anchor.click() URL.revokeObjectURL(url) notify("data exported") } catch { notify("failed to export data") } finally { setIsExportingData(false) } } const totalFeedsInImport = parsedGroups?.reduce((sum, group) => sum + group.feeds.length, 0) ?? 0 return (

import

import subscriptions from an opml file

{parsedGroups === null ? (
) : (

found {totalFeedsInImport} feed {totalFeedsInImport !== 1 && "s"} to import:

{parsedGroups.map((group, groupIndex) => (
{group.folderName && (
{group.folderName}
)} {group.feeds.map((feed, feedIndex) => (

{feed.title}

{feed.url}

))}
))}
)}

export opml

download your subscriptions as an opml file

export data

{tier === "pro" || tier === "developer" ? "download all your data as json (subscriptions, folders, saved entries)" : "download your saved entries as json (upgrade to pro for full export)"}

) }