feat(flutter): 应用克莱因蓝主题与印尼语适配

This commit is contained in:
Zhou Weidong committed 2026-10-17 15:58:17 +08:00
1 parent e1147cfcba
commit 10d448c8ba
31 files changed
+891 -521

No files matched your search

+6 -1
View File
@@ -20,6 +20,7 @@ import '../../core/data/services/playback_queue.dart';
import '../../core/data/services/playback_session.dart';
import '../../core/data/services/video_player_port.dart';
import '../../core/formatting/localized_content.dart';
import '../../core/theme/app_colors.dart';
import '../../l10n/app_localizations.dart';
import '../discover/discover_logic.dart';
import '../discover/discover_view.dart';
@@ -48,12 +49,15 @@ class PlayerLogic extends ChangeNotifier {
Episode? trackedEpisode;
Drama? trackedDrama;
DateTime lastProgressWrite = DateTime.fromMillisecondsSinceEpoch(0);
/// 进度上报节流:契约建议每 10 秒一次
Duration progressInterval = const Duration(seconds: 10);
Future<void> pendingWrite = Future<void>.value();
/// 服务端续看点:进入播放页时定位到"那一集的哪一秒"
ResumePoint? resumePoint;
bool resumeLoaded = false;
/// 票据三态:加载中 / 失败(可重试)/ 被后端判定为不可播放
bool ticketLoading = false;
String? ticketError;
@@ -86,6 +90,7 @@ class PlayerLogic extends ChangeNotifier {
ValueChanged<Drama>? onDramaChanged;
ValueChanged<bool>? onImmersiveChanged;
bool _disposed = false;
/// [start] 是否已经跑过:没跑过时 session/pages 还是 late 未初始化,
/// dispose 不能直接碰它们(例如页面构建失败或纯逻辑测试)。
bool _started = false;
@@ -702,7 +707,7 @@ class PlayerLogic extends ChangeNotifier {
) {
final selected = episode.number == currentNumber;
return Material(
color: selected ? const Color(0xFF2F7BFF) : const Color(0xFF2A2C33),
color: selected ? AppColors.bluePressed : const Color(0xFF2A2C33),
borderRadius: BorderRadius.circular(8),
child: InkWell(
borderRadius: BorderRadius.circular(8),
+8 -8
View File
@@ -15,6 +15,8 @@ import '../../core/data/services/playback_session.dart';
import '../../core/data/services/video_player_port.dart';
import '../../core/formatting/error_text.dart';
import '../../core/formatting/localized_content.dart';
import '../../core/theme/app_colors.dart';
import '../../core/theme/app_theme.dart';
import '../../core/widgets/auth_gate.dart';
import '../../core/widgets/download_action.dart';
import '../../l10n/app_localizations.dart';
@@ -130,7 +132,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: Theme(
data: ThemeData.dark(useMaterial3: true),
data: AppTheme.dark(),
child: widget.embedded
? content
: Scaffold(backgroundColor: Colors.black, body: content),
@@ -203,7 +205,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
// 票据三态之一:起播前正在向后端要签名地址
if (selected && logic.ticketLoading)
const Center(
child: CircularProgressIndicator(color: Color(0xFF2F7BFF)),
child: CircularProgressIndicator(color: AppColors.blueSoft),
),
// 票据三态之二:拿票失败(断网/服务异常)→ 可重试,不假装在加载
if (selected && !logic.ticketLoading && logic.ticketError != null)
@@ -235,7 +237,7 @@ class _PlayerPageState extends State<PlayerPage> with WidgetsBindingObserver {
),
if (selected && logic.session.loading)
const Center(
child: CircularProgressIndicator(color: Color(0xFF2F7BFF)),
child: CircularProgressIndicator(color: AppColors.blueSoft),
),
if (selected && !ready && logic.session.error != null)
Center(
@@ -764,7 +766,7 @@ class _RailAction extends StatelessWidget {
visualDensity: VisualDensity.compact,
padding: EdgeInsets.zero,
constraints: const BoxConstraints.tightFor(width: 42, height: 36),
color: selected ? const Color(0xFF8FB4FF) : Colors.white,
color: selected ? AppColors.blueSoft : Colors.white,
icon: Icon(icon, size: 24),
),
Text(
@@ -804,16 +806,14 @@ class _BottomAction extends StatelessWidget {
children: [
Icon(
icon,
color: selected ? const Color(0xFF2F7BFF) : const Color(0xFFF3EEEA),
color: selected ? AppColors.blueSoft : const Color(0xFFF3EEEA),
),
const SizedBox(height: 2),
Text(
label,
style: TextStyle(
fontSize: 11,
color: selected
? const Color(0xFF2F7BFF)
: const Color(0xFFF3EEEA),
color: selected ? AppColors.blueSoft : const Color(0xFFF3EEEA),
),
),
],
@@ -6,6 +6,8 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import '../../../core/theme/app_colors.dart';
/// Keeps seeks within the playable range so dragging to the edge does not
/// trigger the player's completion callback before playback resumes.
Duration seekPositionForFraction(double fraction, Duration duration) {
@@ -118,7 +120,7 @@ class _SeekProgressBarState extends State<SeekProgressBar> {
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: scrubbing ? 4 : 3,
activeTrackColor: const Color(0xFF2F7BFF),
activeTrackColor: AppColors.blueSoft,
inactiveTrackColor: Colors.white30,
thumbColor: Colors.white,
thumbShape: RoundSliderThumbShape(