feat(auth): 接入 Google 登录

- 登录页保留邮箱与 Google 两个入口,Google 按钮按官方规范改为白底四色图标
- 新增 GoogleAuthService:封装 initialize/authenticate,失败以结果对象返回
- AuthApi 增加 googleLogin,AuthController 增加 signInWithGoogle
- iOS 补充 CFBundleURLTypes 与 GIDClientID,Bundle ID 统一为 com.stormg.lumadrama
- Google 请求期间按钮显示转圈并禁止重复点击
This commit is contained in:
Vicky committed 2026-11-13 12:30:47 +08:00
1 parent 7b90bd59b9
commit 67670d46b1
18 files changed
+335 -55

No files matched your search

+2 -9
View File
@@ -53,22 +53,15 @@ void main() {
);
await tester.pumpAndSettle();
expect(find.byKey(const Key('auth-entry-google')), findsNothing);
expect(find.byKey(const Key('auth-entry-phone')), findsOneWidget);
expect(find.byKey(const Key('auth-entry-phone')), findsNothing);
expect(find.byKey(const Key('auth-entry-email')), findsOneWidget);
expect(find.byKey(const Key('auth-entry-google')), findsOneWidget);
expect(find.byKey(const Key('auth-legal')), findsOneWidget);
expect(
tester.getTopLeft(find.byKey(const Key('auth-landing'))).dy,
lessThan(80),
);
await tester.tap(find.byKey(const Key('auth-entry-phone')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('phone-auth-sheet')), findsOneWidget);
await tester.tapAt(const Offset(8, 8));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('auth-entry-email')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('auth-email')), findsOneWidget);
+19 -18
View File
@@ -90,28 +90,17 @@ void main() {
tester.getSize(find.byKey(const Key('auth-brand-logo'))),
const Size(88, 88),
);
expect(find.byKey(const Key('auth-entry-google')), findsNothing);
expect(find.byKey(const Key('auth-entry-phone')), findsOneWidget);
expect(find.byKey(const Key('auth-entry-google')), findsOneWidget);
expect(find.byKey(const Key('auth-entry-phone')), findsNothing);
expect(find.byKey(const Key('auth-entry-email')), findsOneWidget);
expect(find.byKey(const Key('auth-legal')), findsOneWidget);
expect(
tester.getSize(find.byKey(const Key('auth-entry-phone'))).height,
52,
);
expect(
tester.getSize(find.byKey(const Key('auth-entry-email'))).height,
52,
);
final phoneButton = tester.widget<Material>(
find.descendant(
of: find.byKey(const Key('auth-entry-phone')),
matching: find.byType(Material),
),
);
expect(phoneButton.color, AppColors.brandRed);
expect(
(phoneButton.shape! as RoundedRectangleBorder).borderRadius,
BorderRadius.circular(26),
tester.getSize(find.byKey(const Key('auth-entry-google'))).height,
52,
);
final emailButton = tester.widget<Material>(
find.descendant(
@@ -119,8 +108,20 @@ void main() {
matching: find.byType(Material),
),
);
// 次按钮是「白 6%」玻璃拟态,不再有描边。
expect(emailButton.color, Colors.white.withValues(alpha: 0.06));
// 邮箱是主入口,用品牌红。
expect(emailButton.color, AppColors.brandRed);
expect(
(emailButton.shape! as RoundedRectangleBorder).borderRadius,
BorderRadius.circular(26),
);
final googleButton = tester.widget<Material>(
find.descendant(
of: find.byKey(const Key('auth-entry-google')),
matching: find.byType(Material),
),
);
// 第三方登录按 Google 规范用白底深字。
expect(googleButton.color, Colors.white);
final glow = tester.widget<DecoratedBox>(
find.byKey(const Key('auth-red-glow')),
@@ -237,7 +238,7 @@ void main() {
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),
lessThan(tester.getTopLeft(find.byKey(const Key('auth-entry-email'))).dy),
);
});