mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-31 21:52:54 +00:00
Keep large diffs responsive across web and mobile (#4174)
* perf(app): keep large diffs responsive Render file headers on the canvas and bound expensive text shaping to the active viewport while preserving sticky, hover, and horizontal-scroll behavior. Let native scroll cancellation arbitrate header presses so finger scrolling cannot expand files. * test(app): assert canvas diff header accessibility * test(app): assert canvas diff header semantics
This commit is contained in:
@@ -23,6 +23,66 @@ export interface NativeTextLayout {
|
||||
paragraphs: Array<Array<Array<SkParagraph | null>>>;
|
||||
}
|
||||
|
||||
export interface NativeHeaderTextLayout {
|
||||
families: string[] | undefined;
|
||||
fontSize: number;
|
||||
statFontSize: number;
|
||||
palette: Pick<DiffPalette, "foreground" | "foregroundMuted" | "statusSuccess" | "statusDanger">;
|
||||
}
|
||||
|
||||
export interface NativeShapedHeaderText {
|
||||
paragraph: SkParagraph;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export type NativeHeaderTextTone = keyof NativeHeaderTextLayout["palette"];
|
||||
|
||||
export function createNativeHeaderTextLayout(input: {
|
||||
configuredFamily: string;
|
||||
fontSize: number;
|
||||
statFontSize: number;
|
||||
palette: NativeHeaderTextLayout["palette"];
|
||||
}): NativeHeaderTextLayout {
|
||||
const configured = input.configuredFamily
|
||||
.split(",")
|
||||
.map((family) => family.trim().replace(/^['"]|['"]$/g, ""))
|
||||
// These are React Native's platform-default UI sentinels, not custom faces.
|
||||
// Omitting the family lets Skia resolve the same platform system font.
|
||||
.filter((family) => family && family !== "normal" && family !== "system-ui");
|
||||
const families = configured.length > 0 ? [...new Set(configured)] : undefined;
|
||||
return {
|
||||
families,
|
||||
fontSize: input.fontSize,
|
||||
statFontSize: input.statFontSize,
|
||||
palette: input.palette,
|
||||
};
|
||||
}
|
||||
|
||||
export function shapeNativeHeaderText(input: {
|
||||
layout: NativeHeaderTextLayout;
|
||||
text: string;
|
||||
size: "body" | "stat";
|
||||
tone: NativeHeaderTextTone;
|
||||
maximumWidth?: number;
|
||||
}): NativeShapedHeaderText {
|
||||
const paragraph = Skia.ParagraphBuilder.Make({ maxLines: 1, ellipsis: "…" })
|
||||
.pushStyle({
|
||||
...(input.layout.families ? { fontFamilies: input.layout.families } : {}),
|
||||
fontSize: input.size === "body" ? input.layout.fontSize : input.layout.statFontSize,
|
||||
color: Skia.Color(input.layout.palette[input.tone]),
|
||||
})
|
||||
.addText(input.text)
|
||||
.pop()
|
||||
.build();
|
||||
paragraph.layout(input.maximumWidth ?? PARAGRAPH_WIDTH);
|
||||
return {
|
||||
paragraph,
|
||||
width: paragraph.getLongestLine(),
|
||||
height: paragraph.getHeight(),
|
||||
};
|
||||
}
|
||||
|
||||
export interface NativeTextLayoutStore {
|
||||
font: SkFont;
|
||||
asciiMetrics: CachedAsciiTextMetrics;
|
||||
|
||||
Reference in New Issue
Block a user