Files
tongxunruanjian/mobile-next/lib/company/brand/app_tokens.dart
T
9bde926c81 fix(mobile-next): 按 B-91 收口 Android 通话视觉打回项
呼出/通话中按钮、计时器、底色、60s 未接与进出场动效对齐视觉规范。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-08-20 09:58:28 +08:00

124 lines
3.8 KiB
Dart

import 'package:flutter/material.dart';
/// 双端唯一视觉 Token。取值只来自 B-91 v2 规范第 2 节,禁止在页面内硬编码色值/字号/间距/圆角。
///
/// 官方 widget 通过 [openim_common] `Styles` 映射到本表(见 apply_official_styles.dart),
/// 公司自建页面直接引用本文件。本阶段保留 OpenIM 标识,不做「畅联」换标。
class AppColors {
AppColors._();
static const Color primary = Color(0xFF3B87F5);
static const Color primaryActive = Color(0xFFEBF3FE);
static const Color primaryPressed = Color(0xFF2E75E0);
static const Color avatarGray = Color(0xFF8593A8);
static const Color pageBg = Color(0xFFFFFFFF);
static const Color chatBg = Color(0xFFF5F6F8);
static const Color searchBg = Color(0xFFF2F3F5);
static const Color bubbleMine = Color(0xFFD6E7FC);
static const Color bubbleOther = Color(0xFFFFFFFF);
static const Color textPrimary = Color(0xFF1D2129);
static const Color textSecondary = Color(0xFF86909C);
static const Color danger = Color(0xFFF53F3F);
static const Color divider = Color(0xFFEEEEEE);
static const Color bannerBg = Color(0xFF3A3F47);
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 {
AppFont._();
static const double small = 12;
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 {
AppGap._();
static const double x1 = 4;
static const double x2 = 8;
static const double x3 = 12;
static const double x4 = 16;
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 {
AppRadius._();
static const double control = 8;
static const double modal = 12;
static const double bubble = 8;
static const double logo = 16;
static double avatar(double size) => size * 0.18;
}
class AppIconSize {
AppIconSize._();
static const double sm = 20;
static const double md = 22;
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._();
static const hover = Duration(milliseconds: 100);
static const overlay = Duration(milliseconds: 150);
static const overlaySwitch = Duration(milliseconds: 100);
static const route = Duration(milliseconds: 200);
static const toastOut = Duration(milliseconds: 200);
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 {
AppMotion._();
static bool reduce(BuildContext context) =>
MediaQuery.maybeOf(context)?.disableAnimations ?? false;
static Duration of(BuildContext context, Duration normal) =>
reduce(context) ? Duration.zero : normal;
}
class AppShadows {
AppShadows._();
static const List<BoxShadow> modal = [
BoxShadow(color: Color(0x14000000), offset: Offset(0, 4), blurRadius: 16),
];
}