fix(client): 登录页 tab 滑块塌陷 + 滚动弹性(design-distill 校准)
- 胶囊 tab 活动滑块高度塌成 0(FractionallySizedBox 缺 heightFactor)→ 活动态 不可见、和背景糊一起。补 heightFactor:1.0,滑块正常填满。 - 列表无弹性回弹:SingleChildScrollView 改 ClampingScrollPhysics,大窗口放得下 就不滚(无上下拖动/滚动条),仅窗口过矮才滚。 - 加 auth_redesign golden(900x700 明/暗),按 design-distill 截图 diff 校准: 与原型 design/preview/auth_redesign.html 对比,结构/位置/尺寸零偏移 (残余差异为 headless 测试缺 CJK 字体的豆腐块,真 app 字体正常)。 flutter analyze 0 error;测试通过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -154,6 +154,9 @@ class _AuthScreenState extends ConsumerState<AuthScreen>
|
|||||||
SafeArea(
|
SafeArea(
|
||||||
child: Center(
|
child: Center(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
|
// 无弹性回弹:内容放得下就不滚(大窗口不出现上下拖动/滚动条),
|
||||||
|
// 仅窗口太矮放不下时才滚动。
|
||||||
|
physics: const ClampingScrollPhysics(),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32),
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32),
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: const BoxConstraints(maxWidth: 420),
|
constraints: const BoxConstraints(maxWidth: 420),
|
||||||
@@ -277,6 +280,7 @@ class _AuthScreenState extends ConsumerState<AuthScreen>
|
|||||||
alignment: reg ? Alignment.centerRight : Alignment.centerLeft,
|
alignment: reg ? Alignment.centerRight : Alignment.centerLeft,
|
||||||
child: FractionallySizedBox(
|
child: FractionallySizedBox(
|
||||||
widthFactor: 0.5,
|
widthFactor: 0.5,
|
||||||
|
heightFactor: 1.0,
|
||||||
child: DecoratedBox(
|
child: DecoratedBox(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: c.accent,
|
color: c.accent,
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// auth_redesign_golden_test.dart — 登录页 Flutter 渲染图(供 design-distill 截图 diff)
|
||||||
|
// 900x700 @1x,与原型截图同 viewport;明/暗各一张。
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:pangolin_vpn/l10n/strings_zh.dart';
|
||||||
|
import 'package:pangolin_vpn/pangolin_theme.dart';
|
||||||
|
import 'package:pangolin_vpn/services/token_store.dart';
|
||||||
|
import 'package:pangolin_vpn/state/auth_provider.dart';
|
||||||
|
import 'package:pangolin_vpn/widgets/auth_screen.dart';
|
||||||
|
|
||||||
|
class _NullTokenStore implements TokenStore {
|
||||||
|
const _NullTokenStore();
|
||||||
|
@override
|
||||||
|
Future<void> saveTokens({required String access, required String refresh}) async {}
|
||||||
|
@override
|
||||||
|
Future<String?> loadAccessToken() async => null;
|
||||||
|
@override
|
||||||
|
Future<String?> loadRefreshToken() async => null;
|
||||||
|
@override
|
||||||
|
Future<void> clear() async {}
|
||||||
|
@override
|
||||||
|
Future<void> markOnboarded() async {}
|
||||||
|
@override
|
||||||
|
Future<bool> isOnboarded() async => true;
|
||||||
|
@override
|
||||||
|
Future<void> saveLastEmail(String email) async {}
|
||||||
|
@override
|
||||||
|
Future<String?> loadLastEmail() async => null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _shoot(WidgetTester tester, ThemeData theme, String name) async {
|
||||||
|
tester.view.physicalSize = const Size(900, 700);
|
||||||
|
tester.view.devicePixelRatio = 1.0;
|
||||||
|
addTearDown(tester.view.resetPhysicalSize);
|
||||||
|
addTearDown(tester.view.resetDevicePixelRatio);
|
||||||
|
await tester.pumpWidget(ProviderScope(
|
||||||
|
overrides: [tokenStoreProvider.overrideWithValue(const _NullTokenStore())],
|
||||||
|
child: MaterialApp(
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
theme: theme,
|
||||||
|
home: AuthScreen(t: const StringsZh(), onDone: () {}),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await expectLater(find.byType(AuthScreen), matchesGoldenFile('goldens/$name.png'));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('auth login light', (t) => _shoot(t, PangolinTheme.light, 'auth_login_light'));
|
||||||
|
testWidgets('auth login dark', (t) => _shoot(t, PangolinTheme.dark, 'auth_login_dark'));
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Reference in New Issue
Block a user