mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-01 00:07:01 +00:00
fix: show the file name in the tablet split view's preview header
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
vi.mock('react-native', () => ({ useWindowDimensions: () => ({ width: 800, height: 1280 }) }));
|
||||
vi.mock('react-native-safe-area-context', () => ({ useSafeAreaInsets: () => ({ top: 0, bottom: 0, left: 0, right: 0 }) }));
|
||||
|
||||
import { FILES_LIST_MIN, PREVIEW_HEADER_CHROME, PREVIEW_TITLE_MIN, filesListWidth } from '../files-split';
|
||||
|
||||
// In the tablet split view the docked file preview had a fixed 45 % of the
|
||||
// row. On a Pixel Tablet in portrait (about 720 dp next to the tab rail)
|
||||
// that left the header's file name 2 px between its six buttons.
|
||||
const titleRoom = (contentWidth: number) => contentWidth - filesListWidth(contentWidth) - PREVIEW_HEADER_CHROME;
|
||||
|
||||
describe('filesListWidth', () => {
|
||||
it('leaves the file name room in the preview header on a tablet in portrait', () => {
|
||||
expect(titleRoom(720)).toBeGreaterThanOrEqual(PREVIEW_TITLE_MIN);
|
||||
expect(filesListWidth(720)).toBeGreaterThanOrEqual(FILES_LIST_MIN);
|
||||
});
|
||||
|
||||
it('gives the list its usual pane width on a wide window', () => {
|
||||
expect(filesListWidth(1200)).toBe(408);
|
||||
expect(titleRoom(1200)).toBeGreaterThan(400);
|
||||
});
|
||||
|
||||
it('keeps the list usable on a narrow split', () => {
|
||||
expect(filesListWidth(600)).toBe(FILES_LIST_MIN);
|
||||
});
|
||||
});
|
||||
|
||||
describe('the Files split view', () => {
|
||||
it('sizes the list column with filesListWidth and lets the preview take the rest', () => {
|
||||
const source = fs.readFileSync(path.resolve(__dirname, '../../screens/FilesScreen.tsx'), 'utf8');
|
||||
expect(source).toContain('width: filesListWidth(contentWidth)');
|
||||
expect(source).not.toMatch(/previewPane: \{[^}]*width: '45%'/);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import { listPaneWidth } from './use-layout';
|
||||
|
||||
/**
|
||||
* Fixed chrome of the docked file preview's header: 16 dp padding on each
|
||||
* side and six 40 dp buttons (close, previous, next, open, download, share)
|
||||
* with 8 dp gaps, the title's gap included.
|
||||
*/
|
||||
export const PREVIEW_HEADER_CHROME = 2 * 16 + 6 * 40 + 6 * 8;
|
||||
/** Room the file name keeps in the docked preview's header. */
|
||||
export const PREVIEW_TITLE_MIN = 120;
|
||||
/** The file list never gets narrower than this next to a preview. */
|
||||
export const FILES_LIST_MIN = 280;
|
||||
|
||||
/**
|
||||
* Width of the file list next to the docked preview. The preview had a fixed
|
||||
* 45 %: on a tablet in portrait (about 720 dp next to the tab rail) that was
|
||||
* 324 dp, and the six header buttons left the file name 2 px. The list takes
|
||||
* the usual list-pane width (listPaneWidth, as in Mail and Contacts) and
|
||||
* gives way, down to FILES_LIST_MIN, until the name has PREVIEW_TITLE_MIN.
|
||||
*/
|
||||
export function filesListWidth(contentWidth: number): number {
|
||||
const previewMin = PREVIEW_HEADER_CHROME + PREVIEW_TITLE_MIN;
|
||||
return Math.max(FILES_LIST_MIN, Math.min(listPaneWidth(contentWidth), contentWidth - previewMin));
|
||||
}
|
||||
@@ -71,6 +71,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { formatListDate } from '../lib/date-format';
|
||||
import { useLayout, useSheetInsets } from '../lib/use-layout';
|
||||
import { useSheetBottomInset } from '../lib/sheet-bottom-inset';
|
||||
import { filesListWidth } from '../lib/files-split';
|
||||
import { useBackWhileFocused } from '../lib/use-back-while-focused';
|
||||
import { filesBackStep } from '../lib/files-back';
|
||||
import { driveChange, type DriveScope } from '../lib/files-drive';
|
||||
@@ -258,6 +259,8 @@ export default function FilesScreen() {
|
||||
const [actionsTarget, setActionsTarget] = useState<FileRow | null>(null);
|
||||
// The menu of a starred folder or a recent file.
|
||||
const [placeMenu, setPlaceMenu] = useState<PlaceMenu | null>(null);
|
||||
// Width inside the side insets, for the list next to a docked preview.
|
||||
const [contentWidth, setContentWidth] = useState(0);
|
||||
const [shareTarget, setShareTarget] = useState<FileRow | null>(null);
|
||||
const [moveTarget, setMoveTarget] = useState<FileRow | null>(null);
|
||||
const [previewTarget, setPreviewTarget] = useState<FileRow | null>(null);
|
||||
@@ -1563,8 +1566,11 @@ export default function FilesScreen() {
|
||||
// On a wide window an open file shows beside the list instead of covering it.
|
||||
const previewDocked = isSplit && previewTarget != null;
|
||||
return (
|
||||
<View style={[styles.container, previewDocked && styles.splitRow, { paddingLeft: insets.left, paddingRight: insets.right }]}>
|
||||
<View style={styles.listColumn}>
|
||||
<View
|
||||
style={[styles.container, previewDocked && styles.splitRow, { paddingLeft: insets.left, paddingRight: insets.right }]}
|
||||
onLayout={(e) => setContentWidth(e.nativeEvent.layout.width - insets.left - insets.right)}
|
||||
>
|
||||
<View style={[styles.listColumn, previewDocked && { flex: 0, width: filesListWidth(contentWidth) }]}>
|
||||
{renderHeader()}
|
||||
{body}
|
||||
</View>
|
||||
@@ -2177,7 +2183,8 @@ function makeStyles(c: ThemePalette) {
|
||||
},
|
||||
splitRow: { flexDirection: 'row' },
|
||||
listColumn: { flex: 1 },
|
||||
previewPane: { width: '45%', borderLeftWidth: 1, borderLeftColor: c.border },
|
||||
// The rest of the row; the list column gets filesListWidth.
|
||||
previewPane: { flex: 1, borderLeftWidth: 1, borderLeftColor: c.border },
|
||||
header: {
|
||||
paddingBottom: spacing.sm,
|
||||
borderBottomWidth: 1,
|
||||
|
||||
Reference in New Issue
Block a user