mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 15:51:00 +00:00
6906f80ff8
The Android shell now reports keyCommands and windowLayout, so the large screen layout no longer assumes an iPad: - The keyboard host hands the shortcuts to the app whenever the shell has the keyCommands feature, whatever the platform. Before it also required iOS, so an Android tablet with a keyboard answered the keys in the page and never listed them in the system's shortcuts. - useWindowFold follows the layout the Android shell reports (feature windowLayout). When a vertical fold separates the window, a foldable half open like a book, MobileShell marks it with data-fold and its place, and the leading pane (the trip's plan, a tab's summary, a list beside its detail) ends at the fold while the trailing one starts there, on either reading direction. A flat fold that does not separate stays one screen. - The split size class starts at 840pt, Android's expanded width, instead of 900pt, so a foldable unfolded on its side (about 841dp) gets two panes like an iPad does. An 11" iPad upright (834pt) stays a single pane. The address screen of the native shell follows the same width. - TrekShell exports NativeWindowLayout for it. Also: the sheet's width and anchor types and the collab board type stay private to their modules, which nothing else imports (knip).
86 lines
3.0 KiB
TypeScript
86 lines
3.0 KiB
TypeScript
// FE-NATIVE-FOLD-001 onwards: the fold an Android foldable reports, as two-pane screens use it.
|
|
import { act, renderHook, waitFor } from '@testing-library/react';
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import type { NativeWindowLayout } from './trekShell';
|
|
import { _resetWindowFold, foldOf, useWindowFold } from './windowFold';
|
|
|
|
const shell = vi.hoisted(() => ({
|
|
features: [] as string[],
|
|
layout: null as unknown,
|
|
listener: null as null | ((layout: unknown) => void),
|
|
}));
|
|
|
|
vi.mock('./capabilities', () => ({
|
|
hasNativeFeature: (feature: string) => shell.features.includes(feature),
|
|
useNativeCapabilities: () => ({
|
|
caps: { shellApi: 3, platform: 'android', appVersion: '', build: '', features: shell.features },
|
|
updateRequired: false,
|
|
}),
|
|
}));
|
|
vi.mock('./trekShell', () => ({
|
|
TrekShell: {
|
|
getWindowLayout: vi.fn(() => Promise.resolve(shell.layout)),
|
|
addListener: vi.fn((_event: string, fn: (layout: unknown) => void) => {
|
|
shell.listener = fn;
|
|
return Promise.resolve({ remove: () => Promise.resolve() });
|
|
}),
|
|
},
|
|
}));
|
|
|
|
function layout(over: Partial<NativeWindowLayout> = {}): NativeWindowLayout {
|
|
return {
|
|
width: 841,
|
|
height: 701,
|
|
widthClass: 'expanded',
|
|
heightClass: 'medium',
|
|
posture: 'halfOpened',
|
|
orientation: 'vertical',
|
|
separating: true,
|
|
hinge: { left: 420, top: 0, right: 421, bottom: 701 },
|
|
...over,
|
|
};
|
|
}
|
|
|
|
beforeEach(() => {
|
|
_resetWindowFold();
|
|
shell.features = [];
|
|
shell.layout = null;
|
|
shell.listener = null;
|
|
});
|
|
|
|
afterEach(() => _resetWindowFold());
|
|
|
|
describe('foldOf', () => {
|
|
it('FE-NATIVE-FOLD-001: a book posture splits the window at its hinge', () => {
|
|
expect(foldOf(layout())).toEqual({ start: 420, end: 421 });
|
|
});
|
|
|
|
it('FE-NATIVE-FOLD-002: a seamless flat fold, a horizontal one or none at all splits nothing', () => {
|
|
expect(foldOf(layout({ posture: 'flat', separating: false }))).toBeNull();
|
|
expect(foldOf(layout({ orientation: 'horizontal' }))).toBeNull();
|
|
expect(foldOf(layout({ posture: 'none', hinge: undefined }))).toBeNull();
|
|
expect(foldOf(null)).toBeNull();
|
|
// A hinge outside the window is not one to lay panes against.
|
|
expect(foldOf(layout({ hinge: { left: 0, top: 0, right: 0, bottom: 701 } }))).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('useWindowFold', () => {
|
|
it('FE-NATIVE-FOLD-003: without the shell feature there is no fold to follow', () => {
|
|
const { result } = renderHook(() => useWindowFold());
|
|
expect(result.current).toBeNull();
|
|
expect(shell.listener).toBeNull();
|
|
});
|
|
|
|
it('FE-NATIVE-FOLD-004: follows the layout the Android shell reports, as the device folds and unfolds', async () => {
|
|
shell.features = ['windowLayout'];
|
|
shell.layout = layout();
|
|
const { result } = renderHook(() => useWindowFold());
|
|
await waitFor(() => expect(result.current).toEqual({ start: 420, end: 421 }));
|
|
|
|
act(() => shell.listener?.(layout({ posture: 'flat', separating: false })));
|
|
expect(result.current).toBeNull();
|
|
});
|
|
});
|