feat(flutter): 应用克莱因蓝主题与印尼语适配
This commit is contained in:
1 parent
e1147cfcba
commit
10d448c8ba
31 files changed
+891
-521
No files matched your search
@@ -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),
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in new issue
Block a user