diff --git a/src/app/ConnectionIndicator.test.tsx b/src/app/ConnectionIndicator.test.tsx index 9bbe6e59..d7c8670f 100644 --- a/src/app/ConnectionIndicator.test.tsx +++ b/src/app/ConnectionIndicator.test.tsx @@ -6,7 +6,10 @@ import { resetAuthStore } from '@/test/helpers/storeReset'; import { useAuthStore } from '@/store/authStore'; import { DragDropProvider } from '@/lib/dnd/DragDropContext'; import ConnectionIndicator from './ConnectionIndicator'; -import { setServerReachability } from '@/lib/network/serverReachability'; +import { + resetServerReachabilitySnapshot, + setServerReachability, +} from '@/lib/network/serverReachability'; const switchActiveServerMock = vi.fn(); @@ -46,6 +49,7 @@ function renderIndicator() { beforeEach(() => { resetAuthStore(); + resetServerReachabilitySnapshot(); switchActiveServerMock.mockReset(); switchActiveServerMock.mockResolvedValue(true); }); @@ -104,4 +108,19 @@ describe('ConnectionIndicator Library server selection', () => { expect(screen.getByText('3 servers').tagName).toBe('SPAN'); expect(screen.queryByText('3→2 servers')).not.toBeInTheDocument(); }); + + it('marks an unavailable server in the switch menu with an explanatory warning', async () => { + const user = userEvent.setup(); + const { b } = setupServers(); + setServerReachability(b, 'unavailable'); + renderIndicator(); + + await user.click(screen.getByText('Home')); + + const remote = screen.getByRole('menuitem', { name: /Remote.*Cannot reach Remote/ }); + expect(remote.querySelector('.server-choice-warning')).toHaveAttribute( + 'data-tooltip', + 'Cannot reach Remote. Check your network or server.', + ); + }); }); diff --git a/src/app/ConnectionIndicator.tsx b/src/app/ConnectionIndicator.tsx index aa159f67..a24e359a 100644 --- a/src/app/ConnectionIndicator.tsx +++ b/src/app/ConnectionIndicator.tsx @@ -16,6 +16,7 @@ import { useListReorderDnd } from '@/lib/hooks/useListReorderDnd'; import { applyListReorderById } from '@/lib/util/listReorder'; import { deriveEffectiveLibraryBrowseServerIds } from '@/lib/library/libraryBrowseScope'; import { useUnavailableServerIds } from '@/lib/network/serverReachability'; +import { ServerChoiceWarning } from '@/ui/ServerChoiceList'; interface Props { status: ConnectionStatus; @@ -247,6 +248,9 @@ export default function ConnectionIndicator({ status, isLan, serverName }: Props const finalIncluded = included && libraryBrowseServerIds.length === 1; const busy = switchingId === srv.id; const labelText = serverListDisplayLabel(srv, servers); + const warning = unavailableServerIds.has(srv.id) + ? t('connection.offlineSubtitle', { server: labelText }) + : undefined; const edge = isDragging ? dropEdge(srv.id) : null; return (
onPickServer(srv)} > - {labelText} + + {labelText} + + {switchingId === srv.id ? (
) : ( diff --git a/src/styles/components/connection-indicator.css b/src/styles/components/connection-indicator.css index 7573f767..2399db5d 100644 --- a/src/styles/components/connection-indicator.css +++ b/src/styles/components/connection-indicator.css @@ -39,6 +39,13 @@ background: var(--menu-item-hover); } +.connection-indicator-server-label { + display: flex; + min-width: 0; + align-items: center; + gap: var(--space-2); +} + .connection-indicator-server-row .sidebar-customizer-grip { flex-shrink: 0; cursor: grab;