feat(auth): 登录页改为 ymb 品牌并支持后台配置背景图

This commit is contained in:
Vicky authored and trae-solo-agent committed 2026-10-30 17:14:30 +08:00
1 parent 22cc669bbe
commit e7399fa3fd
24 files changed
+378 -188

No files matched your search

+59 -33
View File
@@ -9,13 +9,16 @@ import 'package:shared_preferences_platform_interface/shared_preferences_async_p
import 'package:fruitshorts/core/data/models/auth_session.dart';
import 'package:fruitshorts/core/data/remote/api_client.dart';
import 'package:fruitshorts/core/data/remote/auth_api.dart';
import 'package:fruitshorts/core/data/services/app_config_controller.dart';
import 'package:fruitshorts/core/data/services/auth_controller.dart';
import 'package:fruitshorts/core/data/services/auth_session_store.dart';
import 'package:fruitshorts/core/platform/haptics.dart';
import 'package:fruitshorts/core/theme/app_colors.dart';
import 'package:fruitshorts/core/widgets/remote_image.dart';
import 'package:fruitshorts/l10n/app_localizations.dart';
import 'package:fruitshorts/pages/auth/auth_view.dart';
import '../support/fake_app_config.dart';
import '../support/fake_haptics.dart';
import '../support/fake_http_adapter.dart';
@@ -29,6 +32,7 @@ void main() {
WidgetTester tester, {
AuthApi? api,
FakeHaptics? haptics,
String loginBackgroundUrl = '',
bool openEmail = true,
bool asRoute = false,
}) async {
@@ -44,10 +48,14 @@ void main() {
),
AuthSessionStore(),
);
final appConfig = await fakeAppConfigController(
loginBackgroundUrl: loginBackgroundUrl,
);
await tester.pumpWidget(
MultiProvider(
providers: [
ChangeNotifierProvider<AuthController>.value(value: auth),
ChangeNotifierProvider<AppConfigController>.value(value: appConfig),
Provider<Haptics>.value(value: haptics ?? FakeHaptics()),
],
child: MaterialApp(
@@ -76,11 +84,8 @@ void main() {
await pumpAuthPage(tester, openEmail: false);
expect(find.byKey(const Key('auth-landing')), findsOneWidget);
expect(find.text('FruitShorts'), findsOneWidget);
final brand = tester.widget<Text>(find.text('FruitShorts'));
expect(brand.style?.fontSize, 26);
expect(brand.style?.fontWeight, FontWeight.w700);
expect(brand.style?.letterSpacing, 2);
// 落地页只留图标,不再显示品牌文字。
expect(find.text('ymb'), findsNothing);
expect(
tester.getSize(find.byKey(const Key('auth-brand-logo'))),
const Size(88, 88),
@@ -136,10 +141,7 @@ void main() {
final email = tester.widget<TextField>(
find.byKey(const Key('auth-email')),
);
expect(
email.decoration?.fillColor,
Colors.white.withValues(alpha: 0.05),
);
expect(email.decoration?.fillColor, Colors.white.withValues(alpha: 0.05));
expect(email.style?.color, AppColors.onSurface);
expect(email.style?.fontSize, 15);
expect(email.cursorColor, AppColors.brandRed);
@@ -182,37 +184,63 @@ void main() {
},
);
testWidgets('should_use_backend_login_background_when_configured', (
tester,
) async {
await pumpAuthPage(
tester,
openEmail: false,
loginBackgroundUrl: '/files/login_bg/bg.jpg',
);
final backdrop = tester.widget<RemoteImage>(
find.byKey(const Key('auth-poster-backdrop')),
);
expect(backdrop.path, '/files/login_bg/bg.jpg');
});
testWidgets(
'should_show_app_logo_lower_on_the_page_when_landing_opens',
'should_fall_back_to_bundled_login_background_when_not_configured',
(tester) async {
tester.view.physicalSize = const Size(390, 844);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
await pumpAuthPage(tester, openEmail: false);
final image = tester.widget<Image>(
find.descendant(
of: find.byKey(const Key('auth-brand-logo')),
matching: find.byType(Image),
),
final backdrop = tester.widget<RemoteImage>(
find.byKey(const Key('auth-poster-backdrop')),
);
expect(backdrop.path, isEmpty);
// 兜底图是我们塞给 RemoteImage 的 fallbackWidget,用 auth-poster-default 定位。
expect(
(image.image as AssetImage).assetName,
'assets/icon/fruitshorts.png',
);
// 新版落地页用三等分 Spacer 排版,Logo 居中且落在两个入口按钮上方。
final logo = find.byKey(const Key('auth-brand-logo'));
expect(tester.getCenter(logo).dx, closeTo(195, 0.1));
expect(
tester.getBottomLeft(logo).dy,
lessThan(
tester.getTopLeft(find.byKey(const Key('auth-entry-phone'))).dy,
),
find.byKey(const Key('auth-poster-default')),
findsOneWidget,
);
},
);
testWidgets('should_show_app_logo_lower_on_the_page_when_landing_opens', (
tester,
) async {
tester.view.physicalSize = const Size(390, 844);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
await pumpAuthPage(tester, openEmail: false);
final image = tester.widget<Image>(
find.descendant(
of: find.byKey(const Key('auth-brand-logo')),
matching: find.byType(Image),
),
);
expect((image.image as AssetImage).assetName, 'assets/icon/ymb.png');
// 新版落地页用三等分 Spacer 排版,Logo 居中且落在两个入口按钮上方。
final logo = find.byKey(const Key('auth-brand-logo'));
expect(tester.getCenter(logo).dx, closeTo(195, 0.1));
expect(
tester.getBottomLeft(logo).dy,
lessThan(tester.getTopLeft(find.byKey(const Key('auth-entry-phone'))).dy),
);
});
testWidgets('should_render_40px_back_button_when_page_is_pushed', (
tester,
) async {
@@ -335,9 +363,7 @@ void main() {
);
expect(
tester
.widget<GestureDetector>(
find.byKey(const Key('auth-mode-sign-up')),
)
.widget<GestureDetector>(find.byKey(const Key('auth-mode-sign-up')))
.onTap,
isNull,
);