fix(mobile-next): 按 B-91 收口 Android 通话视觉打回项

呼出/通话中按钮、计时器、底色、60s 未接与进出场动效对齐视觉规范。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
编码工程师
2026-08-20 09:58:28 +08:00
co-authored by Cursor multica-agent
parent 714794f7fe
commit 9bde926c81
20 changed files with 640 additions and 210 deletions
@@ -24,6 +24,9 @@ class AppColors {
static const Color maskBg = Color(0xFF000000);
static const Color success = Color(0xFF00B42A);
static const Color warning = Color(0xFFFF7D00);
/// 通话页纯色深底。与 [textPrimary] 同值(`#1D2129`),不得改用 [maskBg]。
static const Color callBg = textPrimary;
}
class AppFont {
@@ -33,6 +36,9 @@ class AppFont {
static const double sub = 14;
static const double body = 16;
static const double title = 18;
/// 语音通话计时器,B-91 §2 唯一字号例外。
static const double callTimer = 32;
}
class AppGap {
@@ -45,6 +51,9 @@ class AppGap {
static const double x6 = 24;
static const double x8 = 32;
static const double x12 = 48;
/// 来电拒绝/接听间距,B-91 §4.10。
static const double x24 = 96;
}
class AppRadius {
@@ -66,6 +75,18 @@ class AppIconSize {
static const double lg = 24;
}
/// 安卓语音通话页尺寸,取值只来自 B-91 §4.10。
class AppCallSize {
AppCallSize._();
static const double nameTop = 96;
static const double avatar = 96;
static const double primaryBtn = 64;
static const double secondaryBtn = 48;
static const double incomingGap = AppGap.x24;
static const double minimizeHit = 48;
}
class AppDuration {
AppDuration._();
@@ -77,6 +98,10 @@ class AppDuration {
static const toastStay = Duration(seconds: 2);
static const bannerCollapse = Duration(milliseconds: 300);
static const picture = Duration(milliseconds: 200);
static const callPage = Duration(milliseconds: 250);
static const callEndHold = Duration(milliseconds: 1500);
static const callInviteTimeout = Duration(seconds: 60);
static const callVibrate = Duration(seconds: 1);
}
class AppMotion {
@@ -21,6 +21,10 @@ void applyOfficialStylesFromTokens() {
Styles.c_F2F8FF = AppColors.primaryActive;
Styles.durationOverlay = AppDuration.overlay;
Styles.durationOverlaySwitch = AppDuration.overlaySwitch;
Styles.callPageMotion = AppDuration.callPage;
Styles.callEndHold = AppDuration.callEndHold;
Styles.callInviteTimeout = AppDuration.callInviteTimeout;
Styles.callVibrate = AppDuration.callVibrate;
Styles.reduceMotion = AppMotion.reduce;
Styles.motionOf = AppMotion.of;
Styles.c_18E875 = AppColors.success;
@@ -28,6 +32,15 @@ void applyOfficialStylesFromTokens() {
Styles.c_6085B1 = AppColors.avatarGray;
Styles.c_000000 = AppColors.maskBg;
Styles.c_000000_opacity70 = AppColors.maskBg.withOpacity(.7);
Styles.c_callBg = AppColors.callBg;
Styles.c_callSecondaryBg = AppColors.pageBg.withOpacity(.12);
Styles.callNameTop = AppCallSize.nameTop;
Styles.callAvatar = AppCallSize.avatar;
Styles.callPrimaryBtn = AppCallSize.primaryBtn;
Styles.callSecondaryBtn = AppCallSize.secondaryBtn;
Styles.callIncomingGap = AppCallSize.incomingGap;
Styles.callMinimizeHit = AppCallSize.minimizeHit;
Styles.callIconSize = AppIconSize.lg;
Styles.ts_FFFFFF_20sp_medium = TextStyle(
color: AppColors.pageBg,
@@ -42,6 +55,20 @@ void applyOfficialStylesFromTokens() {
color: AppColors.pageBg.withOpacity(.7),
fontSize: AppFont.sub,
);
Styles.ts_callName = TextStyle(
color: AppColors.pageBg,
fontSize: AppFont.title,
fontWeight: FontWeight.w500,
);
Styles.ts_callStatus = TextStyle(
color: AppColors.pageBg.withOpacity(.6),
fontSize: AppFont.sub,
);
Styles.ts_callTimer = TextStyle(
color: AppColors.pageBg,
fontSize: AppFont.callTimer,
fontFeatures: const [FontFeature.tabularFigures()],
);
Styles.c_0089FF_opacity10 = AppColors.primary.withOpacity(.1);
Styles.c_0089FF_opacity20 = AppColors.primary.withOpacity(.2);