From aac4adeda6fddda47901e00702e0d3b6d7d0823b Mon Sep 17 00:00:00 2001 From: Gigi Date: Sun, 5 Oct 2025 22:00:18 +0100 Subject: [PATCH] feat(bookmarks): add refresh button to sidebar header with loading state --- src/components/BookmarkList.tsx | 8 +++++++- src/components/Bookmarks.tsx | 18 ++++++++++++++++++ src/components/IconButton.tsx | 9 +++++++-- src/components/SidebarHeader.tsx | 17 +++++++++++++++-- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/components/BookmarkList.tsx b/src/components/BookmarkList.tsx index 26f17975..e8f7ecd4 100644 --- a/src/components/BookmarkList.tsx +++ b/src/components/BookmarkList.tsx @@ -17,6 +17,8 @@ interface BookmarkListProps { onViewModeChange: (mode: ViewMode) => void selectedUrl?: string onOpenSettings: () => void + onRefresh?: () => void + isRefreshing?: boolean } export const BookmarkList: React.FC = ({ @@ -28,7 +30,9 @@ export const BookmarkList: React.FC = ({ viewMode, onViewModeChange, selectedUrl, - onOpenSettings + onOpenSettings, + onRefresh, + isRefreshing }) => { if (isCollapsed) { // Check if the selected URL is in bookmarks @@ -60,6 +64,8 @@ export const BookmarkList: React.FC = ({ viewMode={viewMode} onViewModeChange={onViewModeChange} onOpenSettings={onOpenSettings} + onRefresh={onRefresh} + isRefreshing={isRefreshing} /> {bookmarks.length === 0 ? ( diff --git a/src/components/Bookmarks.tsx b/src/components/Bookmarks.tsx index 200843dd..fdd7cc93 100644 --- a/src/components/Bookmarks.tsx +++ b/src/components/Bookmarks.tsx @@ -47,6 +47,7 @@ const Bookmarks: React.FC = ({ relayPool, onLogout }) => { mine: true }) const [followedPubkeys, setFollowedPubkeys] = useState>(new Set()) + const [isRefreshing, setIsRefreshing] = useState(false) const activeAccount = Hooks.useActiveAccount() const accountManager = Hooks.useAccountManager() const eventStore = useEventStore() @@ -132,6 +133,21 @@ const Bookmarks: React.FC = ({ relayPool, onLogout }) => { } } + const handleRefreshBookmarks = async () => { + if (!relayPool || !activeAccount || isRefreshing) return + + setIsRefreshing(true) + try { + await handleFetchBookmarks() + await handleFetchHighlights() + await handleFetchContacts() + } catch (err) { + console.error('Failed to refresh bookmarks:', err) + } finally { + setIsRefreshing(false) + } + } + // Classify highlights with levels based on user context const classifiedHighlights = useMemo(() => { return highlights.map(h => { @@ -182,6 +198,8 @@ const Bookmarks: React.FC = ({ relayPool, onLogout }) => { setIsCollapsed(true) setIsHighlightsCollapsed(true) }} + onRefresh={handleRefreshBookmarks} + isRefreshing={isRefreshing} />
diff --git a/src/components/IconButton.tsx b/src/components/IconButton.tsx index cec739e5..ccfe70cd 100644 --- a/src/components/IconButton.tsx +++ b/src/components/IconButton.tsx @@ -9,6 +9,8 @@ interface IconButtonProps { ariaLabel?: string variant?: 'primary' | 'success' | 'ghost' size?: number + disabled?: boolean + spin?: boolean } const IconButton: React.FC = ({ @@ -17,7 +19,9 @@ const IconButton: React.FC = ({ title, ariaLabel, variant = 'ghost', - size = 33 + size = 33, + disabled = false, + spin = false }) => { return ( ) } diff --git a/src/components/SidebarHeader.tsx b/src/components/SidebarHeader.tsx index 708cb195..a83a74ae 100644 --- a/src/components/SidebarHeader.tsx +++ b/src/components/SidebarHeader.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faChevronRight, faRightFromBracket, faRightToBracket, faUser, faList, faThLarge, faImage, faGear } from '@fortawesome/free-solid-svg-icons' +import { faChevronRight, faRightFromBracket, faRightToBracket, faUser, faList, faThLarge, faImage, faGear, faRotate } from '@fortawesome/free-solid-svg-icons' import { Hooks } from 'applesauce-react' import { useEventModel } from 'applesauce-react/hooks' import { Models } from 'applesauce-core' @@ -14,9 +14,11 @@ interface SidebarHeaderProps { viewMode: ViewMode onViewModeChange: (mode: ViewMode) => void onOpenSettings: () => void + onRefresh?: () => void + isRefreshing?: boolean } -const SidebarHeader: React.FC = ({ onToggleCollapse, onLogout, viewMode, onViewModeChange, onOpenSettings }) => { +const SidebarHeader: React.FC = ({ onToggleCollapse, onLogout, viewMode, onViewModeChange, onOpenSettings, onRefresh, isRefreshing }) => { const [isConnecting, setIsConnecting] = useState(false) const activeAccount = Hooks.useActiveAccount() const accountManager = Hooks.useAccountManager() @@ -68,6 +70,17 @@ const SidebarHeader: React.FC = ({ onToggleCollapse, onLogou )}
+ {onRefresh && ( + + )}