From 72afe7294b1f815b837946d2178b781d9ae7ad25 Mon Sep 17 00:00:00 2001 From: UtopiaXC Date: Thu, 19 Mar 2026 11:18:05 +0800 Subject: [PATCH] Title: Fix step control and score text display [fix] Details: 1. Fix fail of step control 2. Fix score text shows ellipsis instead real number. Type: Bugfix. Test: Local Passed. Related Issue: #1 --- .../release_note/{0.0.2.md => 0.0.3.md} | 0 .../release_note/archive/0.0.2.md | 29 ++++++++++++++ lib/providers/settings_provider.dart | 26 ++++++++++++ lib/screens/score_steps_editor.dart | 6 +++ lib/widgets/game/score_row.dart | 4 +- lib/widgets/player_avatar.dart | 40 +++++++++++-------- lib/widgets/score_panel.dart | 9 ++++- pubspec.yaml | 2 +- 8 files changed, 95 insertions(+), 21 deletions(-) rename assets/documentations/release_note/{0.0.2.md => 0.0.3.md} (100%) create mode 100644 assets/documentations/release_note/archive/0.0.2.md diff --git a/assets/documentations/release_note/0.0.2.md b/assets/documentations/release_note/0.0.3.md similarity index 100% rename from assets/documentations/release_note/0.0.2.md rename to assets/documentations/release_note/0.0.3.md diff --git a/assets/documentations/release_note/archive/0.0.2.md b/assets/documentations/release_note/archive/0.0.2.md new file mode 100644 index 0000000..38232de --- /dev/null +++ b/assets/documentations/release_note/archive/0.0.2.md @@ -0,0 +1,29 @@ +## 更新内容 + +这是一个预览版本。仅用于早期技术预览。 +1. 修复了步长控制 +2. 修复了分数过长时显示不全的问题 + +## 我应该下载哪个文件? + +| 文件 | 描述 | +|-------------------------------------------------|-------------------------------------------------------------------------------------------------| +| **安卓** | | +| UtopiaScoreboard-x.x.x-Android-v8a.apk | 64位包,适用于常见主流的安卓手机 | +| UtopiaScoreboard-x.x.x-Android-v7a.apk | 32位包,适用于非常老旧的安卓手机 | +| UtopiaScoreboard-x.x.x-Android-x86_64.apk | 桌面模拟器或x86架构的设备如Chrome Book等 | +| **iPhone** | | +| UtopiaScoreboard-x.x.x-iOS-universal.ipa | 请使用[AltStore](https://altstore.io/)进行侧载安装。具体教程请参考[官方文档](https://faq.altstore.io/)。 | +| **macOS** | | +| UtopiaScoreboard-x.x.x-macOS-universal.dmg | 请开启信任任何来源,请参考: [打开来自未知开发者的 Mac App](https://support.apple.com/zh-cn/guide/mac-help/mh40616/mac) | +| **Windows** | | +| UtopiaScoreboard-x.x.x-Windows-x64-setup.exe | 推荐。需要安装。 | +| UtopiaScoreboard-x.x.x-Windows-x64-setup.msi | 暂无,无法打包。 | +| UtopiaScoreboard-x.x.x-Windows-x64-portable.zip | 便携版。如不希望安装可以使用本包。 | +| **Linux** | | +| UtopiaScoreboard-x.x.x-Linux-x64.AppImage | 推荐,通用不限平台 | +| UtopiaScoreboard-x.x.x-Linux-x64.rpm | RHEL、CentOS、Fedora等 (RedHat系) | +| UtopiaScoreboard-x.x.x-Linux-x64.deb | Debian、Ubuntu等 (Debian系) | +| **Web** | | +| UtopiaScoreboard-x.x.x-Web.zip | 静态前端APP | + diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index b306c39..8109732 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -1,12 +1,15 @@ +import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class SettingsProvider extends ChangeNotifier { double _uiScale = 1.0; bool _initialized = false; + List _globalScoreSteps = [1, 2, 4, 8, 16, 32, 64, 128]; double get uiScale => _uiScale; bool get initialized => _initialized; + List get globalScoreSteps => _globalScoreSteps; SettingsProvider() { _loadSettings(); @@ -21,6 +24,10 @@ class SettingsProvider extends ChangeNotifier { _uiScale = 1.0; _initialized = false; } + final stepsJson = prefs.getString('global_score_steps'); + if (stepsJson != null) { + _globalScoreSteps = (jsonDecode(stepsJson) as List).cast(); + } notifyListeners(); } @@ -40,4 +47,23 @@ class SettingsProvider extends ChangeNotifier { await prefs.setDouble('uiScale', _uiScale); notifyListeners(); } + + Future setGlobalScoreSteps(List steps) async { + _globalScoreSteps = steps; + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('global_score_steps', jsonEncode(_globalScoreSteps)); + notifyListeners(); + } + + /// Reload global score steps from SharedPreferences (call after ScoreStepsEditor saves) + Future reloadGlobalScoreSteps() async { + final prefs = await SharedPreferences.getInstance(); + final stepsJson = prefs.getString('global_score_steps'); + if (stepsJson != null) { + _globalScoreSteps = (jsonDecode(stepsJson) as List).cast(); + } else { + _globalScoreSteps = [1, 2, 4, 8, 16, 32, 64, 128]; + } + notifyListeners(); + } } diff --git a/lib/screens/score_steps_editor.dart b/lib/screens/score_steps_editor.dart index cfa110a..6f472d5 100644 --- a/lib/screens/score_steps_editor.dart +++ b/lib/screens/score_steps_editor.dart @@ -1,7 +1,9 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import '../providers/settings_provider.dart'; /// Editor for customizing the score step values. class ScoreStepsEditor extends StatefulWidget { @@ -33,6 +35,10 @@ class _ScoreStepsEditorState extends State { Future _saveSteps() async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('global_score_steps', jsonEncode(_steps)); + if (mounted) { + Provider.of(context, listen: false) + .reloadGlobalScoreSteps(); + } } @override diff --git a/lib/widgets/game/score_row.dart b/lib/widgets/game/score_row.dart index fad8fff..68968d2 100644 --- a/lib/widgets/game/score_row.dart +++ b/lib/widgets/game/score_row.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:provider/provider.dart'; import '../../models/player.dart'; import '../../providers/game_provider.dart'; +import '../../providers/settings_provider.dart'; /// Inline score adjustment row shown when a player is selected. class ScoreRow extends StatelessWidget { @@ -49,7 +51,7 @@ class ScoreRow extends StatelessWidget { const SizedBox(width: 8), _SignToggle(game: game), const SizedBox(width: 6), - ...game.scoreSteps.map((step) => _ScoreStepButton( + ...Provider.of(context).globalScoreSteps.map((step) => _ScoreStepButton( game: game, step: step, )), diff --git a/lib/widgets/player_avatar.dart b/lib/widgets/player_avatar.dart index db9d301..ad82ad8 100644 --- a/lib/widgets/player_avatar.dart +++ b/lib/widgets/player_avatar.dart @@ -73,28 +73,34 @@ class PlayerAvatar extends StatelessWidget { Row( children: [ Flexible( - child: Text( - '积分:${player.totalScore}', - style: GoogleFonts.notoSansSc( - color: Colors.white.withValues(alpha: 0.9), - fontSize: 15, - fontWeight: FontWeight.w500, + child: FittedBox( + fit: BoxFit.scaleDown, + alignment: Alignment.centerLeft, + child: Text( + '积分:${player.totalScore}', + style: GoogleFonts.notoSansSc( + color: Colors.white.withValues(alpha: 0.9), + fontSize: 15, + fontWeight: FontWeight.w500, + ), ), - overflow: TextOverflow.ellipsis, ), ), if (player.currentRoundChange != 0) ...[ const SizedBox(width: 8), - Text( - player.currentRoundChange > 0 - ? '+${player.currentRoundChange}' - : '${player.currentRoundChange}', - style: GoogleFonts.outfit( - color: player.currentRoundChange > 0 - ? Colors.greenAccent - : Colors.redAccent, - fontSize: 13, - fontWeight: FontWeight.bold, + FittedBox( + fit: BoxFit.scaleDown, + child: Text( + player.currentRoundChange > 0 + ? '+${player.currentRoundChange}' + : '${player.currentRoundChange}', + style: GoogleFonts.outfit( + color: player.currentRoundChange > 0 + ? Colors.greenAccent + : Colors.redAccent, + fontSize: 13, + fontWeight: FontWeight.bold, + ), ), ), ], diff --git a/lib/widgets/score_panel.dart b/lib/widgets/score_panel.dart index b7bbe52..13b97b8 100644 --- a/lib/widgets/score_panel.dart +++ b/lib/widgets/score_panel.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import '../providers/game_provider.dart'; +import '../providers/settings_provider.dart'; import 'control_panel.dart'; /// Floating score panel that appears above/below the [ControlPanel] @@ -32,6 +33,7 @@ class ScorePanel extends StatelessWidget { @override Widget build(BuildContext context) { final game = Provider.of(context); + final settings = Provider.of(context); final selected = game.selectedPlayer; if (selected == null || game.isZeroSum) { return const SizedBox.shrink(); @@ -67,7 +69,7 @@ class ScorePanel extends StatelessWidget { final double controlCenterX = barPos.dx + ControlPanel.expandedWidth / 2; final double maxWidth = screenSize.width - _hMargin * 2; final double estimatedW = _estimatePanelWidth( - game.scoreSteps.length, + settings.globalScoreSteps.length, selected.name, ).clamp(0.0, maxWidth); @@ -82,6 +84,7 @@ class ScorePanel extends StatelessWidget { onTap: () {}, // absorb taps child: _ScorePanelContent( game: game, + scoreSteps: settings.globalScoreSteps, maxWidth: maxWidth, ), ), @@ -91,17 +94,19 @@ class ScorePanel extends StatelessWidget { class _ScorePanelContent extends StatelessWidget { final GameProvider game; + final List scoreSteps; final double maxWidth; const _ScorePanelContent({ required this.game, + required this.scoreSteps, required this.maxWidth, }); @override Widget build(BuildContext context) { final selected = game.selectedPlayer!; - final steps = game.scoreSteps; + final steps = scoreSteps; return Container( constraints: BoxConstraints(maxWidth: maxWidth), diff --git a/pubspec.yaml b/pubspec.yaml index 4d31ab9..0f98086 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: utopia_scoreboard description: "A cross-platform scoreboard for Mahjong, Card Game or Table Game." publish_to: 'none' -version: 0.0.2 +version: 0.0.3 environment: sdk: '>=3.2.3 <4.0.0'