diff --git a/apps/desktop/src/app/right-sidebar/file-actions.test.tsx b/apps/desktop/src/app/right-sidebar/file-actions.test.tsx new file mode 100644 index 0000000000..e7ebb04cd6 --- /dev/null +++ b/apps/desktop/src/app/right-sidebar/file-actions.test.tsx @@ -0,0 +1,50 @@ +import { cleanup, fireEvent, render, screen } from '@testing-library/react' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' + +import { I18nProvider } from '@/i18n' + +const { openFileWithSystemApp } = vi.hoisted(() => ({ openFileWithSystemApp: vi.fn() })) + +vi.mock('@/lib/desktop-fs', () => ({ isDesktopFsRemoteMode: () => false })) +vi.mock('@/lib/office-files', () => ({ openFileWithSystemApp })) + +import { FileEntryContextMenu } from './file-actions' + +function renderMenu(isDirectory = false) { + return render( + + + + + + ) +} + +beforeEach(() => { + openFileWithSystemApp.mockReset().mockResolvedValue(true) +}) + +afterEach(cleanup) + +describe('FileEntryContextMenu system open action', () => { + it('opens files with the system app', async () => { + renderMenu() + + fireEvent.contextMenu(screen.getByRole('button', { name: 'Row' })) + fireEvent.click(await screen.findByRole('menuitem', { name: '用系统应用打开' })) + + expect(openFileWithSystemApp).toHaveBeenCalledWith('/w/notes.md') + }) + + it('does not offer system open for directories', () => { + renderMenu(true) + + fireEvent.contextMenu(screen.getByRole('button', { name: 'Row' })) + + expect(screen.queryByRole('menuitem', { name: '用系统应用打开' })).toBeNull() + }) +}) diff --git a/apps/desktop/src/app/right-sidebar/file-actions.tsx b/apps/desktop/src/app/right-sidebar/file-actions.tsx index 9a0853634d..405e5ce408 100644 --- a/apps/desktop/src/app/right-sidebar/file-actions.tsx +++ b/apps/desktop/src/app/right-sidebar/file-actions.tsx @@ -13,6 +13,7 @@ import { translateNow, useI18n } from '@/i18n' import { isDesktopFsRemoteMode } from '@/lib/desktop-fs' import { isSubmitEnter } from '@/lib/ime' import { IS_MAC } from '@/lib/keybinds/combo' +import { openFileWithSystemApp } from '@/lib/office-files' import { cn } from '@/lib/utils' import { $fileActionDialog, @@ -73,6 +74,14 @@ export function FileEntryContextMenu({ children, isDirectory, name, path, relati {/* Don't restore focus to the row on close: "Rename" mounts an autofocused inline input, and the default focus-return would blur it immediately. */} event.preventDefault()}> + {!isDirectory && ( + <> + void openFileWithSystemApp(path)}> + {t.preview.openWithSystemApp} + + + + )} {localFs && ( <> void revealFile(path)}>{revealLabel}