mirror of
https://github.com/dergigi/boris.git
synced 2026-02-15 03:54:43 +01:00
feat(bookmarks): add refresh button to sidebar header with loading state
This commit is contained in:
@@ -17,6 +17,8 @@ interface BookmarkListProps {
|
||||
onViewModeChange: (mode: ViewMode) => void
|
||||
selectedUrl?: string
|
||||
onOpenSettings: () => void
|
||||
onRefresh?: () => void
|
||||
isRefreshing?: boolean
|
||||
}
|
||||
|
||||
export const BookmarkList: React.FC<BookmarkListProps> = ({
|
||||
@@ -28,7 +30,9 @@ export const BookmarkList: React.FC<BookmarkListProps> = ({
|
||||
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<BookmarkListProps> = ({
|
||||
viewMode={viewMode}
|
||||
onViewModeChange={onViewModeChange}
|
||||
onOpenSettings={onOpenSettings}
|
||||
onRefresh={onRefresh}
|
||||
isRefreshing={isRefreshing}
|
||||
/>
|
||||
|
||||
{bookmarks.length === 0 ? (
|
||||
|
||||
@@ -47,6 +47,7 @@ const Bookmarks: React.FC<BookmarksProps> = ({ relayPool, onLogout }) => {
|
||||
mine: true
|
||||
})
|
||||
const [followedPubkeys, setFollowedPubkeys] = useState<Set<string>>(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<BookmarksProps> = ({ 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<BookmarksProps> = ({ relayPool, onLogout }) => {
|
||||
setIsCollapsed(true)
|
||||
setIsHighlightsCollapsed(true)
|
||||
}}
|
||||
onRefresh={handleRefreshBookmarks}
|
||||
isRefreshing={isRefreshing}
|
||||
/>
|
||||
</div>
|
||||
<div className="pane main">
|
||||
|
||||
@@ -9,6 +9,8 @@ interface IconButtonProps {
|
||||
ariaLabel?: string
|
||||
variant?: 'primary' | 'success' | 'ghost'
|
||||
size?: number
|
||||
disabled?: boolean
|
||||
spin?: boolean
|
||||
}
|
||||
|
||||
const IconButton: React.FC<IconButtonProps> = ({
|
||||
@@ -17,7 +19,9 @@ const IconButton: React.FC<IconButtonProps> = ({
|
||||
title,
|
||||
ariaLabel,
|
||||
variant = 'ghost',
|
||||
size = 33
|
||||
size = 33,
|
||||
disabled = false,
|
||||
spin = false
|
||||
}) => {
|
||||
return (
|
||||
<button
|
||||
@@ -26,8 +30,9 @@ const IconButton: React.FC<IconButtonProps> = ({
|
||||
title={title}
|
||||
aria-label={ariaLabel || title}
|
||||
style={{ width: size, height: size }}
|
||||
disabled={disabled}
|
||||
>
|
||||
<FontAwesomeIcon icon={icon} />
|
||||
<FontAwesomeIcon icon={icon} spin={spin} />
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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<SidebarHeaderProps> = ({ onToggleCollapse, onLogout, viewMode, onViewModeChange, onOpenSettings }) => {
|
||||
const SidebarHeader: React.FC<SidebarHeaderProps> = ({ 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<SidebarHeaderProps> = ({ onToggleCollapse, onLogou
|
||||
<FontAwesomeIcon icon={faUser} />
|
||||
)}
|
||||
</div>
|
||||
{onRefresh && (
|
||||
<IconButton
|
||||
icon={faRotate}
|
||||
onClick={onRefresh}
|
||||
title="Refresh bookmarks"
|
||||
ariaLabel="Refresh bookmarks"
|
||||
variant="ghost"
|
||||
disabled={isRefreshing}
|
||||
spin={isRefreshing}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
icon={faGear}
|
||||
onClick={onOpenSettings}
|
||||
|
||||
Reference in New Issue
Block a user