summaryrefslogtreecommitdiff
path: root/apps/web/app/reader/settings/_components
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-08 00:18:30 -0800
committerFuwn <[email protected]>2026-02-08 00:18:30 -0800
commite6cfa9ccc0b51e34690c3db38216daa659ae147f (patch)
treed8b0a471fa86e08034ed412da1e163fae2263685 /apps/web/app/reader/settings/_components
parentfeat: add option to show favicons next to feed names in entry list (diff)
downloadasa.news-e6cfa9ccc0b51e34690c3db38216daa659ae147f.tar.xz
asa.news-e6cfa9ccc0b51e34690c3db38216daa659ae147f.zip
feat: add feed URL editing in subscription settings, fix notification badge styling and HTML entity decoding
Diffstat (limited to 'apps/web/app/reader/settings/_components')
-rw-r--r--apps/web/app/reader/settings/_components/subscriptions-settings.tsx61
1 files changed, 60 insertions, 1 deletions
diff --git a/apps/web/app/reader/settings/_components/subscriptions-settings.tsx b/apps/web/app/reader/settings/_components/subscriptions-settings.tsx
index 7257231..2c79238 100644
--- a/apps/web/app/reader/settings/_components/subscriptions-settings.tsx
+++ b/apps/web/app/reader/settings/_components/subscriptions-settings.tsx
@@ -4,6 +4,7 @@ import { useState } from "react"
import { useSubscriptions } from "@/lib/queries/use-subscriptions"
import {
useUpdateSubscriptionTitle,
+ useUpdateFeedUrl,
useMoveSubscriptionToFolder,
useUnsubscribe,
useRequestFeedRefresh,
@@ -39,8 +40,11 @@ function SubscriptionRow({
const [editedTitle, setEditedTitle] = useState(
subscription.customTitle ?? ""
)
+ const [isEditingUrl, setIsEditingUrl] = useState(false)
+ const [editedUrl, setEditedUrl] = useState(subscription.feedUrl)
const [showUnsubscribeConfirm, setShowUnsubscribeConfirm] = useState(false)
const updateTitle = useUpdateSubscriptionTitle()
+ const updateFeedUrl = useUpdateFeedUrl()
const moveToFolder = useMoveSubscriptionToFolder()
const unsubscribe = useUnsubscribe()
const requestRefresh = useRequestFeedRefresh()
@@ -55,6 +59,19 @@ function SubscriptionRow({
setIsEditingTitle(false)
}
+ function handleSaveUrl() {
+ const trimmedUrl = editedUrl.trim()
+ if (!trimmedUrl || trimmedUrl === subscription.feedUrl) {
+ setIsEditingUrl(false)
+ return
+ }
+ updateFeedUrl.mutate({
+ feedIdentifier: subscription.feedIdentifier,
+ feedUrl: trimmedUrl,
+ })
+ setIsEditingUrl(false)
+ }
+
function handleFolderChange(folderIdentifier: string) {
const sourceFolder = folderOptions.find(
(folder) => folder.identifier === subscription.folderIdentifier
@@ -118,7 +135,49 @@ function SubscriptionRow({
</button>
</div>
)}
- <p className="truncate text-text-dim">{subscription.feedUrl}</p>
+ {isEditingUrl ? (
+ <div className="flex items-center gap-2">
+ <input
+ type="text"
+ value={editedUrl}
+ onChange={(event) => setEditedUrl(event.target.value)}
+ className="min-w-0 flex-1 border border-border bg-background-primary px-2 py-1 text-text-primary outline-none focus:border-text-dim"
+ onKeyDown={(event) => {
+ if (event.key === "Enter") handleSaveUrl()
+ if (event.key === "Escape") setIsEditingUrl(false)
+ }}
+ autoFocus
+ />
+ <button
+ onClick={handleSaveUrl}
+ className="px-2 py-1 text-text-secondary transition-colors hover:text-text-primary"
+ >
+ save
+ </button>
+ <button
+ onClick={() => {
+ setEditedUrl(subscription.feedUrl)
+ setIsEditingUrl(false)
+ }}
+ className="px-2 py-1 text-text-secondary transition-colors hover:text-text-primary"
+ >
+ cancel
+ </button>
+ </div>
+ ) : (
+ <div className="flex items-center gap-2">
+ <p className="min-w-0 truncate text-text-dim">{subscription.feedUrl}</p>
+ <button
+ onClick={() => {
+ setEditedUrl(subscription.feedUrl)
+ setIsEditingUrl(true)
+ }}
+ className="shrink-0 px-2 py-1 text-text-dim transition-colors hover:text-text-secondary"
+ >
+ edit url
+ </button>
+ </div>
+ )}
<div className="mt-1 flex flex-wrap gap-x-3 gap-y-0.5 text-text-dim">
<span>last fetched: {formatRelativeTime(subscription.lastFetchedAt)}</span>
<span>interval: {formatRefreshInterval(subscription.fetchIntervalSeconds)}</span>