Skip to content

Commit 1115440

Browse files
committed
Network: ⌘↑ in the share list goes back to the host list, like Backspace
In the SMB share browser (a host's share listing), `Escape` and `Backspace` already returned to the host list, but `⌘↑` fell into the cursor-move arrow handler instead — inconsistent with the file list, where `⌘↑` = parent. `⌘↑` now also goes back, via a shared `handleBackToHostKey` helper (Escape / Backspace / ⌘↑), checked before the arrow handler. Does NOT cover the related dead-end where parent-nav from inside a *mounted* SMB share's root returns nothing (the file browser, not the share list) — that needs reconstructing the `NetworkHost` from the mounted volume's server and a cross-volume switch into the virtual `network` volume. Separate, riskier change.
1 parent 54e8bde commit 1115440

3 files changed

Lines changed: 46 additions & 7 deletions

File tree

apps/desktop/src/lib/commands/command-registry.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,9 @@ const commandSources: CommandSource[] = [
844844
nameKey: 'commands.shareBack.label',
845845
scope: 'Main window/Share browser',
846846
showInPalette: true,
847-
shortcuts: ['Backspace', 'Escape'],
847+
// `⌘↑` mirrors the file list's `⌘↑` = parent; ShareBrowser handles all three
848+
// keys (`handleBackToHostKey`). Display-only — `fixedKey` handling is in-component.
849+
shortcuts: ['Backspace', 'Escape', '⌘↑'],
848850
fixedKey: true,
849851
},
850852
{

apps/desktop/src/lib/file-explorer/network/ShareBrowser.svelte

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,20 @@
448448
return e.metaKey && (e.key === 'ArrowLeft' || e.key === 'ArrowRight')
449449
}
450450
451+
/**
452+
* Escape, Backspace, and `⌘↑` all return to the host list. `⌘↑` mirrors the
453+
* file list's `⌘↑` = parent, and must be handled before the arrow handler,
454+
* which would otherwise treat it as a cursor move.
455+
*/
456+
function handleBackToHostKey(e: KeyboardEvent): boolean {
457+
if (e.key === 'Escape' || e.key === 'Backspace' || (e.key === 'ArrowUp' && e.metaKey)) {
458+
e.preventDefault()
459+
onBack?.()
460+
return true
461+
}
462+
return false
463+
}
464+
451465
export function handleKeyDown(e: KeyboardEvent): boolean {
452466
if (showLoginForm) {
453467
// Login form handles its own keyboard events
@@ -460,6 +474,9 @@
460474
461475
if (sortedShares.length === 0) return false
462476
477+
// Escape / Backspace / ⌘↑ → back to the host list (before the arrow handler).
478+
if (handleBackToHostKey(e)) return true
479+
463480
// Try centralized navigation shortcuts first (PageUp, PageDown, Home, End, Option+arrows)
464481
const visibleItems = Math.max(1, Math.floor(containerHeight / SHARE_ROW_HEIGHT))
465482
const navResult = handleNavigationShortcut(e, {
@@ -489,12 +506,6 @@
489506
return true
490507
}
491508
492-
if (e.key === 'Escape' || e.key === 'Backspace') {
493-
e.preventDefault()
494-
onBack?.()
495-
return true
496-
}
497-
498509
return false
499510
}
500511

apps/desktop/src/lib/file-explorer/network/ShareBrowser.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ const naspi: ShareInfo = { name: 'naspi', isDisk: true, comment: null }
6464
/** The exported ShareBrowser API surface the tests drive. */
6565
interface ShareBrowserApi {
6666
openCursorItem: () => void
67+
handleKeyDown: (e: KeyboardEvent) => boolean
6768
}
6869

6970
function mountBrowser(
@@ -146,3 +147,28 @@ describe('ShareBrowser credential gate', () => {
146147
await unmount(component)
147148
})
148149
})
150+
151+
describe('ShareBrowser back-navigation', () => {
152+
beforeEach(() => {
153+
vi.clearAllMocks()
154+
document.body.innerHTML = ''
155+
h.getSmbCredentials.mockRejectedValue(new Error('not found'))
156+
})
157+
158+
it('⌘↑ goes back to the host list (like Escape / Backspace), not a cursor move', async () => {
159+
h.fetchShares.mockResolvedValue({ shares: [naspi], authMode: 'guest_allowed', fromCache: false })
160+
const onShareSelect = vi.fn()
161+
const onBack = vi.fn()
162+
const { target, component, api } = mountBrowser(onShareSelect, onBack)
163+
await waitForShareList(target)
164+
165+
const handled = api.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowUp', metaKey: true }))
166+
167+
expect(handled).toBe(true)
168+
expect(onBack).toHaveBeenCalledOnce()
169+
// The cursor-move path must NOT have fired (no share got activated).
170+
expect(onShareSelect).not.toHaveBeenCalled()
171+
172+
await unmount(component)
173+
})
174+
})

0 commit comments

Comments
 (0)