mirror of
https://github.com/readest/readest.git
synced 2026-04-28 03:20:45 +00:00
When the main window has been destroyed (Windows/Linux default close), the reader's "go to library" button only closed the reader, leaving no library visible. Add ensureMainLibraryWindow() that shows an existing main window or recreates one with the 'main' label so the existing close-reader-window wiring keeps working. Also grant the cross-window show/unminimize permissions the call now needs. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ebbbf104b2
commit
6d798542f6
4 changed files with 78 additions and 7 deletions
|
|
@ -135,7 +135,9 @@
|
|||
"core:window:default",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-center",
|
||||
"core:window:allow-show",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-unminimize",
|
||||
"core:window:allow-maximize",
|
||||
"core:window:allow-unmaximize",
|
||||
"core:window:allow-set-size",
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ vi.mock('@tauri-apps/api/window', () => ({
|
|||
|
||||
vi.mock('@tauri-apps/api/webviewWindow', () => {
|
||||
const mockOnce = vi.fn();
|
||||
return {
|
||||
WebviewWindow: vi.fn().mockImplementation(function (this: Record<string, unknown>) {
|
||||
this['once'] = mockOnce;
|
||||
}),
|
||||
};
|
||||
const ctor = vi.fn().mockImplementation(function (this: Record<string, unknown>) {
|
||||
this['once'] = mockOnce;
|
||||
}) as unknown as { getByLabel: ReturnType<typeof vi.fn> };
|
||||
ctor.getByLabel = vi.fn();
|
||||
return { WebviewWindow: ctor };
|
||||
});
|
||||
|
||||
vi.mock('@/services/environment', () => ({
|
||||
|
|
@ -41,8 +41,11 @@ import {
|
|||
redirectToLibrary,
|
||||
showReaderWindow,
|
||||
showLibraryWindow,
|
||||
ensureMainLibraryWindow,
|
||||
} from '@/utils/nav';
|
||||
|
||||
const WebviewWindowCtor = WebviewWindow as unknown as { getByLabel: ReturnType<typeof vi.fn> };
|
||||
|
||||
// ── Helpers ──────────────────────────────────────────────────────────
|
||||
function mockRouter() {
|
||||
return {
|
||||
|
|
@ -348,3 +351,33 @@ describe('showLibraryWindow', () => {
|
|||
expect(url).toContain('file=file2.epub');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ensureMainLibraryWindow', () => {
|
||||
test('shows and focuses the existing main window when present', async () => {
|
||||
const main = {
|
||||
show: vi.fn().mockResolvedValue(undefined),
|
||||
unminimize: vi.fn().mockResolvedValue(undefined),
|
||||
setFocus: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
WebviewWindowCtor.getByLabel.mockResolvedValue(main);
|
||||
|
||||
await ensureMainLibraryWindow(makeAppService() as never);
|
||||
|
||||
expect(WebviewWindowCtor.getByLabel).toHaveBeenCalledWith('main');
|
||||
expect(main.show).toHaveBeenCalled();
|
||||
expect(main.unminimize).toHaveBeenCalled();
|
||||
expect(main.setFocus).toHaveBeenCalled();
|
||||
expect(WebviewWindow).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('creates a new main-labelled window pointing at /library when missing', async () => {
|
||||
WebviewWindowCtor.getByLabel.mockResolvedValue(null);
|
||||
|
||||
await ensureMainLibraryWindow(makeAppService() as never);
|
||||
|
||||
expect(WebviewWindow).toHaveBeenCalledTimes(1);
|
||||
const [label, options] = vi.mocked(WebviewWindow).mock.calls[0]!;
|
||||
expect(label).toBe('main');
|
||||
expect((options as { url: string }).url).toBe('/library');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import { isTauriAppPlatform } from '@/services/environment';
|
|||
import { uniqueId } from '@/utils/misc';
|
||||
import { throttle } from '@/utils/throttle';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { navigateToLibrary } from '@/utils/nav';
|
||||
import { ensureMainLibraryWindow, navigateToLibrary } from '@/utils/nav';
|
||||
import { clearDiscordPresence } from '@/utils/discord';
|
||||
import { BOOK_IDS_SEPARATOR } from '@/services/constants';
|
||||
import { BookDetailModal } from '@/components/metadata';
|
||||
|
|
@ -171,13 +171,16 @@ const ReaderContent: React.FC<{ ids?: string; settings: SystemSettings }> = ({ i
|
|||
await saveSettings(envConfig, settings);
|
||||
}, 200);
|
||||
|
||||
const handleCloseBooksToLibrary = () => {
|
||||
const handleCloseBooksToLibrary = async () => {
|
||||
handleCloseBooks();
|
||||
if (isTauriAppPlatform()) {
|
||||
const currentWindow = getCurrentWindow();
|
||||
if (currentWindow.label === 'main') {
|
||||
navigateBackToLibrary();
|
||||
} else {
|
||||
if (appService) {
|
||||
await ensureMainLibraryWindow(appService);
|
||||
}
|
||||
currentWindow.close();
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,39 @@ export const showLibraryWindow = (appService: AppService, filenames: string[]) =
|
|||
createReaderWindow(appService, url);
|
||||
};
|
||||
|
||||
// Bring the main library window back when a reader window asks to "go to library".
|
||||
// If main was hidden (macOS close-to-hide) we re-show it. If it was destroyed
|
||||
// (Windows/Linux default close), we recreate a window with the same 'main'
|
||||
// label so the existing emitTo('main', 'close-reader-window', ...) wiring
|
||||
// continues to work.
|
||||
export const ensureMainLibraryWindow = async (appService: AppService) => {
|
||||
const existing = await WebviewWindow.getByLabel('main');
|
||||
if (existing) {
|
||||
await existing.show();
|
||||
await existing.unminimize();
|
||||
await existing.setFocus();
|
||||
return;
|
||||
}
|
||||
const win = new WebviewWindow('main', {
|
||||
url: '/library',
|
||||
width: 800,
|
||||
height: 600,
|
||||
center: true,
|
||||
resizable: true,
|
||||
title: appService.isMacOSApp ? '' : 'Readest',
|
||||
decorations: !!appService.isMacOSApp,
|
||||
transparent: !appService.isMacOSApp,
|
||||
shadow: appService.isMacOSApp ? undefined : true,
|
||||
titleBarStyle: appService.isMacOSApp ? 'overlay' : undefined,
|
||||
scrollBarStyle: (appService.osPlatform === 'windows'
|
||||
? 'fluentOverlay'
|
||||
: 'default') as unknown as ScrollBarStyle,
|
||||
});
|
||||
win.once('tauri://error', (e) => {
|
||||
console.error('error recreating main window', e);
|
||||
});
|
||||
};
|
||||
|
||||
export const navigateToReader = (
|
||||
router: ReturnType<typeof useRouter>,
|
||||
bookIds: string[],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue