Skip to content

Commit 5aa0f25

Browse files
RenjiYuuseiclaudeCodFrm
authored
💄 修复安卓端界面适配:动态视口高度 + 窄屏表格/设置行/日志统计条重排 (#1636)
* 💄 修复安卓端界面适配:动态视口高度 + 窄屏表格/设置行重排 安卓浏览器(Firefox / Edge / Kiwi 等)上: - 整页外壳用 100vh,而 vh 取「大视口」,显示地址栏时外壳比可见区域高, 且外壳内部滚动导致文档本身不可滚动,底部 Tab 栏/操作栏落在可视区外无法触达; 软键盘默认只压缩可视视口,编辑器底部工具栏与输入框被键盘遮挡。 改为 h-dvh / min-h-dvh,并在整页入口声明 interactive-widget=resizes-content。 - 编辑器「储存 / 资源」子视图是桌面表格:工具栏单行溢出(清空按钮被裁切)、 固定列宽让表头文案在窄屏重叠。移动端改为竖排卡片行 + 换行工具栏, 桌面端用 md:contents 保持原有列对齐。 - 设置 / 工具页的 SettingRow 横排 + 固定宽控件,把文案挤成每行一两个词; 移动端改为竖排。脚本设置子视图的固定宽控件补 max-w-full 避免越界。 close #1555 Co-authored-by: RenjiYuusei <daoluc.yy@gmail.com> * 💄 修复日志页统计条窄屏文字重叠 日志页「范围 / 统计条」在窄屏(移动端)下,统计文字会压到右侧「自动清理超过 N 天 的日志」上。原因是该条为单行 flex justify-between:左侧分组带 min-w-0 会被压缩, 但其中的计数 span 是 shrink-0,被压缩后内容溢出自身盒子并直接画到右侧分组上—— 是溢出,而不是换行或截断,所以两段文字叠在一起。 改为窄屏竖向堆叠(md 以上仍是原来的单行左右分布):两个分组各 w-full 独占一行, 长文本才能在行内截断;「自动清理」分组允许换行,避免超窄屏横向溢出。同时给 「当前 / 实时」两个徽标补 shrink-0 whitespace-nowrap,避免被挤成两行折字;统计 分隔符从全角「,」改为「 ·」,与顶栏一致,在非中文语言下更易读。 真实构建下用 Playwright 复现与验证(vi-VN,400px 宽):修复前两段文字 X 轴重叠 57.6px、Y 轴完全重叠;修复后 400/360/1280 宽在浅色与深色主题下均无重叠、无横向 溢出,桌面端布局不变。 Co-authored-by: RenjiYuusei <daoluc.yy@gmail.com> * 💄 修复日志页统计条在窄桌面宽度下仍压字 上一版只把窄屏(<768px)改成竖向堆叠,≥768px 仍是单行 flex justify-between, 因此手机横屏、平板、以及浏览器「请求桌面版网站」(980px 布局视口)这类宽度只要 内容放不下,统计文字仍会溢出压到「自动清理超过 N 天的日志」上。 实测 vi-VN + 开启自动刷新(多出「实时 · 5 秒」徽标)时,768px 宽下 「Tổng 2 · Đã lọc 2」与「Tự động xóa nhật ký cũ hơn」重叠 30.2px。根因与窄屏 同一个:统计文字是 shrink-0,单行装不下时压缩只能发生在别处并溢出。 给统计条补 md:flex-wrap(配合 md:gap-x-2 md:gap-y-1 md:py-1),放不下时让自动 清理分组整行下移;宽度足够时(1280px)仍是原来的单行左右分布,未回归。 验证:vi-VN 下 320/360/388/412/480/600/767 及 768/820/900/980/1024 宽逐一测量 两分组全部子元素两两包围盒,无任何重叠、无横向溢出(docScrollWidth == clientWidth)。 Co-authored-by: RenjiYuusei <daoluc.yy@gmail.com> * 💄 外部接入确认页跟进移动端视口适配 #1573 新增的 external_access_confirm 页在本 PR 分支之后合入,未跟上 #1555 的 动态视口处理:声明 interactive-widget=resizes-content 并把外壳换成 min-h-dvh。 --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: 王一之 <yz@ggnb.top>
1 parent 92077a4 commit 5aa0f25

27 files changed

Lines changed: 230 additions & 126 deletions

docs/references/design-patterns.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ function Page() {
1919
}
2020
```
2121

22+
### Viewport height & on-screen keyboard
23+
24+
Page shells are height-locked to the viewport (`TopBar + scroll container + ActionBar`), so they must use the
25+
**dynamic** viewport units — `h-dvh` / `min-h-dvh`, never `h-screen` / `100vh`. `vh` resolves against the
26+
*large* viewport (browser UI retracted), so on Android — Firefox, Edge, Kiwi alike — a `100vh` shell is taller
27+
than the visible area while the toolbar is showing, and because the shell scrolls internally the document
28+
itself can't scroll, leaving `BottomTabBar` / ActionBar unreachable below the fold (issue #1555).
29+
30+
The full-page entries (`options` / `install` / `import` / `batchupdate` / `confirm`) additionally declare
31+
`interactive-widget=resizes-content` in their `<meta name="viewport">`: the default `resizes-visual` shrinks
32+
only the visual viewport when the on-screen keyboard opens, leaving a `dvh` shell (and the editor toolbar under
33+
it) hidden behind the keyboard. `resizes-content` shrinks the layout viewport instead, so the shell reflows
34+
above the keyboard. `popup.html` is excluded — it is a fixed-size panel that scrolls as a whole.
35+
2236
### Desktop ↔ mobile transforms
2337

2438
| Desktop (≥768px) | Mobile (<768px) |

src/pages/batchupdate.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content" />
66
<script src="common.js"></script>
77
<title>ScriptCat</title>
88
<style>

src/pages/batchupdate/components.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ export function DesktopView({ view }: { view: BatchUpdateViewProps }) {
444444
const { t } = useTranslation();
445445
const empty = view.updates.length === 0 && view.ignored.length === 0;
446446
return (
447-
<div className="flex h-screen flex-col bg-background text-foreground">
447+
<div className="flex h-dvh flex-col bg-background text-foreground">
448448
<header className="flex h-[60px] shrink-0 items-center justify-between border-b border-border bg-card px-6">
449449
<div className="flex min-w-0 items-center gap-3">
450450
<PackageCheck className="size-[22px] shrink-0 text-primary" />

src/pages/batchupdate/mobile.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ export function MobileView({ view }: { view: BatchUpdateViewProps }) {
188188
.join(" · ");
189189

190190
return (
191-
<div className="flex h-screen flex-col bg-background text-foreground">
191+
<div className="flex h-dvh flex-col bg-background text-foreground">
192192
<header className="flex h-[62px] shrink-0 items-center gap-3 border-b border-border bg-card px-4">
193193
<PackageCheck className="size-[22px] shrink-0 text-primary" />
194194
<div className="flex min-w-0 flex-col">

src/pages/confirm.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content" />
66
<script src="common.js"></script>
77
<title>ScriptCat</title>
88
<style>

src/pages/confirm/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ function PageShell({ children }: { children: React.ReactNode }) {
5454
return (
5555
<div
5656
data-testid="confirm-shell"
57-
className="flex min-h-screen flex-col items-center justify-center gap-6 bg-background px-4 py-10"
57+
className="flex min-h-dvh flex-col items-center justify-center gap-6 bg-background px-4 py-10"
5858
>
5959
<BrandMark />
6060
{children}

src/pages/external_access_confirm.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content" />
66
<script src="common.js"></script>
77
<title>ScriptCat</title>
88
<style>

src/pages/external_access_confirm/App.test.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,16 @@ describe("外部接入 · 操作确认页(三档决策)", () => {
146146
);
147147
});
148148

149+
// 100vh 是「大视口」,安卓上软键盘/可收起工具栏出现时外壳仍按最大高度撑开,
150+
// 确认按钮被挤出可视区(issue #1555);动态视口单位才跟随可见高度。
151+
it("外壳高度使用动态视口单位而非 100vh", async () => {
152+
getOperation.mockResolvedValue(baseOp({ kind: "enable" }));
153+
render(<ExternalAccessConfirmView operationId="op-1" />);
154+
const shell = await screen.findByTestId("external-access-confirm-shell");
155+
expect(shell.className).toContain("min-h-dvh");
156+
expect(shell.className).not.toContain("min-h-screen");
157+
});
158+
149159
it("提交失败时保留确认页、显示错误并允许重试", async () => {
150160
decideOperation.mockRejectedValueOnce(new Error("temporary failure")).mockResolvedValueOnce(undefined);
151161
getOperation.mockResolvedValue(baseOp({ kind: "enable" }));

src/pages/external_access_confirm/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function BrandMark() {
2626
function PageShell({ topRight, children }: { topRight?: React.ReactNode; children: React.ReactNode }) {
2727
const { t } = useTranslation("external_access");
2828
return (
29-
<div data-testid="external-access-confirm-shell" className="flex min-h-screen flex-col bg-muted">
29+
<div data-testid="external-access-confirm-shell" className="flex min-h-dvh flex-col bg-muted">
3030
{/* 顶栏:品牌 + 「外部接入 · 操作确认」面包屑 + 右侧 TTL 倒计时(设计稿 Th6Hv) */}
3131
<header className="flex items-center justify-between gap-3 border-b bg-card px-6 py-3">
3232
<div className="flex min-w-0 items-center gap-2.5">

src/pages/import.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content" />
66
<script src="common.js"></script>
77
<title>ScriptCat</title>
88
<style>

0 commit comments

Comments
 (0)