forked from akai/readest
7b60b1bb0c
On iOS, navigating to a book group in the library caused the WebKit GPU
process to exceed its 300 MB jetsam limit (peaking at ~328 MB), resulting
in a blank screen flash and broken scroll state.
Three changes reduce peak GPU memory usage:
- Add overscan={200} to VirtuosoGrid/Virtuoso so only items within 200px
of the viewport are rendered, limiting simultaneous image decoding
- Add loading="lazy" to both Image components in BookCover so the browser
defers decoding offscreen cover images
- Conditionally mount the <video> and <audio> elements in AtmosphereOverlay
only when atmosphere mode is active, eliminating idle H.264 decoder
memory overhead
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
42 lines
1.3 KiB
TypeScript
42 lines
1.3 KiB
TypeScript
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
import { render, cleanup } from '@testing-library/react';
|
|
|
|
// Mock zustand stores before importing the component
|
|
vi.mock('@/store/atmosphereStore', () => ({
|
|
useAtmosphereStore: vi.fn(),
|
|
}));
|
|
vi.mock('@/store/themeStore', () => ({
|
|
useThemeStore: vi.fn(),
|
|
}));
|
|
|
|
import AtmosphereOverlay from '@/components/AtmosphereOverlay';
|
|
import { useAtmosphereStore } from '@/store/atmosphereStore';
|
|
import { useThemeStore } from '@/store/themeStore';
|
|
|
|
afterEach(cleanup);
|
|
|
|
const setupStores = (active: boolean) => {
|
|
vi.mocked(useAtmosphereStore).mockImplementation((selector: unknown) =>
|
|
(selector as (s: { active: boolean }) => unknown)({ active }),
|
|
);
|
|
vi.mocked(useThemeStore).mockImplementation((selector: unknown) =>
|
|
(selector as (s: { isDarkMode: boolean }) => unknown)({ isDarkMode: false }),
|
|
);
|
|
};
|
|
|
|
describe('AtmosphereOverlay', () => {
|
|
it('does not render <video> element when inactive', () => {
|
|
setupStores(false);
|
|
const { container } = render(<AtmosphereOverlay />);
|
|
const video = container.querySelector('video');
|
|
expect(video).toBeNull();
|
|
});
|
|
|
|
it('renders <video> element when active', () => {
|
|
setupStores(true);
|
|
const { container } = render(<AtmosphereOverlay />);
|
|
const video = container.querySelector('video');
|
|
expect(video).toBeTruthy();
|
|
});
|
|
});
|