fix: harden automatic mobile boards
This commit is contained in:
1 parent
7959c20d88
commit
d0b9348b86
37 files changed
+619
-143
No files matched your search
@@ -18,6 +18,20 @@ describe("resolveMobileItemPresentation", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("does not unmount apps that use the eager default", () => {
|
||||
expect(
|
||||
resolveMobileItemPresentation(
|
||||
{ kind: "app", height: 1 },
|
||||
{
|
||||
unmountWhenOffscreen: true,
|
||||
},
|
||||
),
|
||||
).toMatchObject({
|
||||
eager: true,
|
||||
unmountWhenOffscreen: false,
|
||||
});
|
||||
});
|
||||
|
||||
test("defaults widgets to full width without inventing a detail view", () => {
|
||||
expect(resolveMobileItemPresentation({ kind: "calendar", height: 8 }, undefined)).toMatchObject({
|
||||
width: 2,
|
||||
|
||||
@@ -8,6 +8,7 @@ export const resolveMobileItemPresentation = (
|
||||
const supportsCompactSummary = mobile?.supportsCompactSummary === true;
|
||||
const supportsDetails = mobile?.supportsDetailView === true;
|
||||
const usesGenericSummary = supportsDetails && !supportsCompactSummary;
|
||||
const eager = mobile?.eager ?? (item.kind === "app" || item.kind === "bookmarks");
|
||||
|
||||
return {
|
||||
width: mobile?.width ?? (item.kind === "app" ? 1 : 2),
|
||||
@@ -15,8 +16,8 @@ export const resolveMobileItemPresentation = (
|
||||
displayMode: supportsCompactSummary || usesGenericSummary ? ("mobileSummary" as const) : ("default" as const),
|
||||
supportsDetails,
|
||||
usesGenericSummary,
|
||||
eager: mobile?.eager ?? (item.kind === "app" || item.kind === "bookmarks"),
|
||||
unmountWhenOffscreen: mobile?.eager === true ? false : (mobile?.unmountWhenOffscreen ?? false),
|
||||
eager,
|
||||
unmountWhenOffscreen: eager ? false : (mobile?.unmountWhenOffscreen ?? false),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ describe("resolveMobileBoardViewport", () => {
|
||||
resolveMobileBoardViewport({
|
||||
deviceClass: "phone",
|
||||
matchesMobileWidth: false,
|
||||
hasResolvedClientWidth: true,
|
||||
hasMounted: true,
|
||||
}),
|
||||
).toEqual({
|
||||
deviceClass: "phone",
|
||||
@@ -29,7 +29,7 @@ describe("resolveMobileBoardViewport", () => {
|
||||
resolveMobileBoardViewport({
|
||||
deviceClass: "tablet",
|
||||
matchesMobileWidth,
|
||||
hasResolvedClientWidth: true,
|
||||
hasMounted: true,
|
||||
}).isMobile,
|
||||
).toBe(expectedIsMobile);
|
||||
});
|
||||
@@ -39,7 +39,7 @@ describe("resolveMobileBoardViewport", () => {
|
||||
resolveMobileBoardViewport({
|
||||
deviceClass: "tablet",
|
||||
matchesMobileWidth: false,
|
||||
hasResolvedClientWidth: false,
|
||||
hasMounted: false,
|
||||
}).isResolved,
|
||||
).toBe(false);
|
||||
});
|
||||
@@ -52,7 +52,7 @@ describe("resolveMobileBoardViewport", () => {
|
||||
resolveMobileBoardViewport({
|
||||
deviceClass: "desktop",
|
||||
matchesMobileWidth,
|
||||
hasResolvedClientWidth: true,
|
||||
hasMounted: true,
|
||||
}),
|
||||
).toMatchObject({
|
||||
isMobile: expectedIsMobile,
|
||||
@@ -73,7 +73,9 @@ describe("resolveIsAutomaticMobileBoard", () => {
|
||||
expect(resolveIsAutomaticMobileBoard({ isMobileViewport, enableAutomaticMobileLayout })).toBe(expected);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe("shouldShowMobileBoardViewportSkeleton", () => {
|
||||
test("does not show the tablet resolution skeleton in legacy mode", () => {
|
||||
expect(
|
||||
shouldShowMobileBoardViewportSkeleton({
|
||||
@@ -82,4 +84,13 @@ describe("resolveIsAutomaticMobileBoard", () => {
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("shows a skeleton while an automatic mobile viewport is unresolved", () => {
|
||||
expect(
|
||||
shouldShowMobileBoardViewportSkeleton({
|
||||
enableAutomaticMobileLayout: true,
|
||||
isResolved: false,
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -26,15 +26,15 @@ const MobileBoardViewportContext = createContext<MobileBoardViewport>({
|
||||
export const resolveMobileBoardViewport = ({
|
||||
deviceClass,
|
||||
matchesMobileWidth,
|
||||
hasResolvedClientWidth,
|
||||
hasMounted,
|
||||
}: {
|
||||
deviceClass: MobileBoardDeviceClass;
|
||||
matchesMobileWidth: boolean;
|
||||
hasResolvedClientWidth: boolean;
|
||||
hasMounted: boolean;
|
||||
}): MobileBoardViewport => ({
|
||||
deviceClass,
|
||||
isMobile: deviceClass === "phone" || matchesMobileWidth,
|
||||
isResolved: deviceClass !== "tablet" || hasResolvedClientWidth,
|
||||
isResolved: deviceClass !== "tablet" || hasMounted,
|
||||
});
|
||||
|
||||
const MobileBoardViewportSkeleton = () => (
|
||||
@@ -73,19 +73,19 @@ export const MobileBoardViewportProvider = ({
|
||||
children,
|
||||
}: PropsWithChildren<{ initialDeviceClass: MobileBoardDeviceClass }>) => {
|
||||
const { enableAutomaticMobileLayout } = useSettings();
|
||||
const [hasResolvedClientWidth, setHasResolvedClientWidth] = useState(false);
|
||||
const [hasMounted, setHasMounted] = useState(false);
|
||||
const matchesMobileWidth = useMediaQuery(mobileBoardMediaQuery, initialDeviceClass === "phone", {
|
||||
getInitialValueInEffect: true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setHasResolvedClientWidth(true);
|
||||
setHasMounted(true);
|
||||
}, []);
|
||||
|
||||
const viewport = resolveMobileBoardViewport({
|
||||
deviceClass: initialDeviceClass,
|
||||
matchesMobileWidth,
|
||||
hasResolvedClientWidth,
|
||||
hasMounted,
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
Reference in new issue
Block a user