feat(client): 节点地区图标改国旗(SVG 填满裁切),未知码回退码块
CountryCode 由 2 字母码块改为渲染真国旗:country_flags 包按 region 码出 SVG 旗(BoxFit.cover 填满裁切),全平台含 Windows 都显示(emoji 国旗在 Windows 不渲染,故走 SVG)。FlagCode 判定无效码(AUTO/占位/非地区码)时回退原码块; 选中态由 accent 底色改为 accent 边框环。 CountryCode 共享于节点列表/连接页/统计页,故三处节点图标统一变国旗, 对应 tablet_servers/connect/stats + desktop_stats golden 已 Mac 重生成 (这些页非 CI golden 闸;CI 闸的 components/auth 基线未动)。 依赖:country_flags ^3.1.0(解析 3.3.0)。analyze 干净,非 golden 测试全过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@@ -1,7 +1,10 @@
|
||||
// country_code.dart — 国家码方块 + 信号条
|
||||
// country_code.dart — 节点地区图标(国旗,未知码回退码块) + 信号条
|
||||
import 'package:country_flags/country_flags.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../pangolin_theme.dart';
|
||||
|
||||
/// 节点地区图标:有效 2 字母地区码渲染国旗(SVG,填满裁切,全平台含 Windows 都显示);
|
||||
/// 未知码(AUTO / ·· / 空等)回退为原 2 字母码块。选中态加 accent 边框环。
|
||||
class CountryCode extends StatelessWidget {
|
||||
const CountryCode({super.key, required this.code, this.active = false, this.size = 38});
|
||||
final String code;
|
||||
@@ -11,21 +14,43 @@ class CountryCode extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final c = context.pangolin;
|
||||
final radius = BorderRadius.circular(PangolinRadius.md);
|
||||
final hasFlag = FlagCode.fromCountryCode(code.toUpperCase()) != null;
|
||||
|
||||
if (!hasFlag) {
|
||||
// 回退:原码块样式(AUTO / 占位 / 非地区码)。
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: active ? c.accent : c.bgSubtle,
|
||||
borderRadius: radius,
|
||||
),
|
||||
child: Text(
|
||||
code,
|
||||
style: PangolinText.mono.copyWith(
|
||||
fontSize: size * 0.31,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: active ? PangolinColors.white : c.fg2,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 国旗:外层 Container 控圆角 + 选中边框,内层 CountryFlag 以 BoxFit.cover 填满裁切。
|
||||
return Container(
|
||||
width: size,
|
||||
height: size,
|
||||
alignment: Alignment.center,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: BoxDecoration(
|
||||
color: active ? c.accent : c.bgSubtle,
|
||||
borderRadius: BorderRadius.circular(PangolinRadius.md),
|
||||
borderRadius: radius,
|
||||
border: active ? Border.all(color: c.accent, width: 2) : null,
|
||||
),
|
||||
child: Text(
|
||||
code,
|
||||
style: PangolinText.mono.copyWith(
|
||||
fontSize: size * 0.31,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: active ? PangolinColors.white : c.fg2,
|
||||
),
|
||||
child: CountryFlag.fromCountryCode(
|
||||
code.toUpperCase(),
|
||||
width: size,
|
||||
height: size,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_svg: ^2.0.10 # 加载 assets/ 下的矢量 logo
|
||||
country_flags: ^3.1.0 # 节点国旗(SVG,全平台含 Windows;按 region 码渲染)
|
||||
lucide_icons: ^0.257.0 # Lucide 细线条图标
|
||||
google_fonts: ^6.2.1 # 运行时加载 Sora / Manrope / Noto Sans SC / JetBrains Mono
|
||||
flutter_riverpod: ^2.5.1 # 状态层(连接状态机 / 免费额度 / 节点选择 / 语言 / 主题)
|
||||
|
||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 44 KiB |