feat(mobile): improve image viewer and install entry
Docker Image / Build and Push Docker Image (push) Successful in 1m58s
Docker Image / Build and Push Docker Image (push) Successful in 1m58s
(cherry picked from commit 556bfd2919)
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { act } from "react";
|
||||
import { createRoot, type Root } from "react-dom/client";
|
||||
import {
|
||||
afterEach,
|
||||
beforeEach,
|
||||
describe,
|
||||
expect,
|
||||
it,
|
||||
type Mock,
|
||||
vi,
|
||||
} from "vitest";
|
||||
|
||||
import { FullscreenImageViewer } from "../fullscreen-image-viewer";
|
||||
|
||||
describe("FullscreenImageViewer", () => {
|
||||
let container: HTMLDivElement;
|
||||
let root: Root;
|
||||
let onClose: Mock<() => void>;
|
||||
|
||||
beforeEach(() => {
|
||||
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean })
|
||||
.IS_REACT_ACT_ENVIRONMENT = true;
|
||||
container = document.createElement("div");
|
||||
document.body.append(container);
|
||||
root = createRoot(container);
|
||||
onClose = vi.fn<() => void>();
|
||||
|
||||
act(() => {
|
||||
root.render(
|
||||
<FullscreenImageViewer
|
||||
characterId="elio-silvestri"
|
||||
remoteMessageId="message-1"
|
||||
imageUrl="/chat-image.png"
|
||||
onClose={onClose}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
act(() => root.unmount());
|
||||
container.remove();
|
||||
});
|
||||
|
||||
it("closes exactly once when the fullscreen image is tapped", () => {
|
||||
const image = container.querySelector("img");
|
||||
expect(image).not.toBeNull();
|
||||
|
||||
act(() => image?.click());
|
||||
|
||||
expect(onClose).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("closes exactly once from the visible back button", () => {
|
||||
const backButton = container.querySelector<HTMLButtonElement>(
|
||||
'button[aria-label="Back"]',
|
||||
);
|
||||
expect(backButton).not.toBeNull();
|
||||
|
||||
act(() => backButton?.click());
|
||||
|
||||
expect(onClose).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("closes from the backdrop and Escape key", () => {
|
||||
const viewer = container.querySelector<HTMLDivElement>(
|
||||
'[aria-label="Fullscreen image"]',
|
||||
);
|
||||
expect(viewer).not.toBeNull();
|
||||
|
||||
act(() => viewer?.click());
|
||||
act(() =>
|
||||
document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" })),
|
||||
);
|
||||
|
||||
expect(onClose).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
@@ -123,13 +123,14 @@
|
||||
|
||||
.compactButton {
|
||||
display: grid;
|
||||
width: min(100%, 240px);
|
||||
min-width: 0;
|
||||
max-width: 224px;
|
||||
min-height: 44px;
|
||||
max-width: 240px;
|
||||
min-height: 50px;
|
||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
padding: 5px 8px;
|
||||
gap: 8px;
|
||||
padding: 7px 10px;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(255, 255, 255, 0.42);
|
||||
border-radius: 16px;
|
||||
@@ -146,8 +147,8 @@
|
||||
|
||||
.compactIcon {
|
||||
display: inline-flex;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 10px;
|
||||
@@ -160,7 +161,7 @@
|
||||
min-width: 0;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
font-size: 10px;
|
||||
font-size: 11px;
|
||||
font-weight: 800;
|
||||
line-height: 1.05;
|
||||
text-transform: uppercase;
|
||||
@@ -180,7 +181,7 @@
|
||||
|
||||
.compactCopy strong {
|
||||
color: #ec006d;
|
||||
font-size: 15px;
|
||||
font-size: 17px;
|
||||
font-weight: 950;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* - 双指缩放(CSS `touch-action: pinch-zoom`)
|
||||
*/
|
||||
import { ChevronLeft } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, type MouseEvent } from "react";
|
||||
|
||||
import { BackButton } from "@/app/_components";
|
||||
|
||||
@@ -44,6 +44,10 @@ export function FullscreenImageViewer({
|
||||
return () => document.removeEventListener("keydown", handleKey);
|
||||
}, [onClose]);
|
||||
|
||||
const handleBackdropClick = (event: MouseEvent<HTMLDivElement>) => {
|
||||
if (event.target === event.currentTarget) onClose();
|
||||
};
|
||||
|
||||
if (imagePaywalled) {
|
||||
return (
|
||||
<div
|
||||
@@ -90,7 +94,7 @@ export function FullscreenImageViewer({
|
||||
return (
|
||||
<div
|
||||
className={styles.viewer}
|
||||
onClick={onClose}
|
||||
onClick={handleBackdropClick}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label="Fullscreen image"
|
||||
@@ -110,7 +114,7 @@ export function FullscreenImageViewer({
|
||||
errorClassName="error"
|
||||
width={800}
|
||||
height={800}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
onClick={onClose}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user