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:
co-authored by
Cursor
multica-agent
parent
714794f7fe
commit
9bde926c81
@@ -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);
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import 'dart:async';
|
||||
|
||||
import '../brand/app_tokens.dart';
|
||||
|
||||
/// 一对一语音会话防护:占线、超时、重复信令、销毁时释放计时器。
|
||||
/// 不自建第二套信令,只约束官方 OpenIMLive 的进出场。
|
||||
enum VoiceCallPhase { idle, outgoing, incoming, inCall }
|
||||
|
||||
class CallSessionGuard {
|
||||
CallSessionGuard({this.inviteTimeout = const Duration(seconds: 30)});
|
||||
CallSessionGuard({this.inviteTimeout = AppDuration.callInviteTimeout});
|
||||
|
||||
final Duration inviteTimeout;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import '../brand/app_tokens.dart';
|
||||
import '../config/app_endpoints.dart';
|
||||
|
||||
/// Android 一对一语音通话配置门。入口只在配置齐全且本卡已落地时打开。
|
||||
@@ -7,7 +8,8 @@ class LiveKitCallConfig {
|
||||
/// 公司账号服务换票路径,对应 account-service `POST /api/rtc_token`。
|
||||
static const String rtcTokenPath = '/api/rtc_token';
|
||||
|
||||
static const Duration inviteTimeout = Duration(seconds: 30);
|
||||
/// 未接超时,唯一业务来源;界面层经 `Styles.callInviteTimeout` 对齐同一 Token。
|
||||
static const Duration inviteTimeout = AppDuration.callInviteTimeout;
|
||||
|
||||
/// 薄适配与构建验证通过后为 true;配置不齐时 [enabled] 仍为 false。
|
||||
static const bool shipped = true;
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:openim_live/openim_live.dart';
|
||||
import '../../company/feature_flags.dart';
|
||||
import '../../company/rtc/call_permissions.dart';
|
||||
import '../../company/rtc/call_session_guard.dart';
|
||||
import '../../company/rtc/livekit_call_config.dart';
|
||||
import '../../company/rtc/rtc_token_api.dart';
|
||||
import '../im_callback.dart';
|
||||
|
||||
@@ -19,7 +20,7 @@ class IMController extends GetxController with IMCallback, OpenIMLive {
|
||||
late Rx<UserFullInfo> userInfo;
|
||||
late String atAllTag;
|
||||
final _rtcTokenApi = RtcTokenApi();
|
||||
final callGuard = CallSessionGuard();
|
||||
final callGuard = CallSessionGuard(inviteTimeout: LiveKitCallConfig.inviteTimeout);
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
|
||||
Reference in New Issue
Block a user