feat(app): 完成 P0 钱包解锁、下载落盘与手机号登录
This commit is contained in:
1 parent
de941c841c
commit
136ee74618
47 files changed
+3264
-70
No files matched your search
@@ -7,6 +7,7 @@ import 'package:provider/provider.dart';
|
||||
|
||||
import '../../core/data/models/download_license.dart';
|
||||
import '../../core/data/models/download_policy.dart';
|
||||
import '../../core/data/models/drama.dart';
|
||||
import '../../core/data/services/auth_controller.dart';
|
||||
import '../../core/data/services/download_controller.dart';
|
||||
import '../../core/formatting/error_text.dart';
|
||||
@@ -18,6 +19,7 @@ import '../../core/theme/app_theme.dart';
|
||||
import '../../core/widgets/auth_gate.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import '../player/player_view.dart';
|
||||
import 'downloads_binding.dart';
|
||||
|
||||
/// 下载授权与状态管理页;本批不落盘,只管理服务端授权。
|
||||
@@ -135,7 +137,12 @@ class _DownloadsBody extends StatelessWidget {
|
||||
for (final license in downloads.licenses) ...[
|
||||
_LicenseTile(
|
||||
license: license,
|
||||
downloads: downloads,
|
||||
onRemove: () => _remove(context, license.episodeId),
|
||||
onPlay: () => _playOffline(context, license),
|
||||
onDownload: () => unawaited(
|
||||
downloads.startDownload(license.episodeId, license: license),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
@@ -144,6 +151,32 @@ class _DownloadsBody extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
void _playOffline(BuildContext context, DownloadLicense license) {
|
||||
final drama = Drama(
|
||||
id: license.dramaId,
|
||||
title: license.dramaTitle,
|
||||
synopsis: '',
|
||||
posterUrl: '',
|
||||
episodes: [
|
||||
Episode(
|
||||
id: license.episodeId,
|
||||
number: license.episodeNo,
|
||||
title: 'Episode ${license.episodeNo}',
|
||||
isFree: true,
|
||||
),
|
||||
],
|
||||
);
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => PlayerPage(
|
||||
drama: drama,
|
||||
initialIndex: 0,
|
||||
downloads: downloads,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _remove(BuildContext context, String episodeId) async {
|
||||
unawaited(context.read<Haptics>().mediumImpact());
|
||||
final ok = await downloads.remove(episodeId);
|
||||
@@ -302,14 +335,35 @@ class _PolicyPanel extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _LicenseTile extends StatelessWidget {
|
||||
const _LicenseTile({required this.license, required this.onRemove});
|
||||
const _LicenseTile({
|
||||
required this.license,
|
||||
required this.downloads,
|
||||
required this.onRemove,
|
||||
required this.onPlay,
|
||||
required this.onDownload,
|
||||
});
|
||||
|
||||
final DownloadLicense license;
|
||||
final DownloadController downloads;
|
||||
final VoidCallback onRemove;
|
||||
final VoidCallback onPlay;
|
||||
final VoidCallback onDownload;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final downloaded = downloads.isDownloaded(license.episodeId);
|
||||
final downloading = downloads.isDownloading(license.episodeId);
|
||||
final progress = downloaded
|
||||
? 1.0
|
||||
: downloading
|
||||
? downloads.progressFor(license.episodeId)
|
||||
: license.progressPercent / 100;
|
||||
final taskStatus = downloaded
|
||||
? 'COMPLETED'
|
||||
: downloading
|
||||
? 'DOWNLOADING'
|
||||
: license.taskStatus;
|
||||
return Container(
|
||||
key: ValueKey('download-license-${license.episodeId}'),
|
||||
padding: const EdgeInsets.all(12),
|
||||
@@ -335,6 +389,20 @@ class _LicenseTile extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Text(l10n.episodeLabel(license.episodeNo)),
|
||||
if (downloaded)
|
||||
IconButton(
|
||||
key: ValueKey('download-play-${license.episodeId}'),
|
||||
tooltip: l10n.play,
|
||||
onPressed: onPlay,
|
||||
icon: const Icon(Icons.play_circle_outline_rounded),
|
||||
)
|
||||
else if (!downloading)
|
||||
IconButton(
|
||||
key: ValueKey('download-start-${license.episodeId}'),
|
||||
tooltip: l10n.downloads,
|
||||
onPressed: onDownload,
|
||||
icon: const Icon(Icons.download_rounded),
|
||||
),
|
||||
IconButton(
|
||||
key: ValueKey('download-remove-${license.episodeId}'),
|
||||
tooltip: l10n.remove,
|
||||
@@ -352,7 +420,7 @@ class _LicenseTile extends StatelessWidget {
|
||||
style: const TextStyle(color: AppColors.blueSoft, fontSize: 12),
|
||||
),
|
||||
Text(
|
||||
l10n.downloadTaskStatus(license.taskStatus),
|
||||
l10n.downloadTaskStatus(taskStatus),
|
||||
style: const TextStyle(color: AppColors.muted, fontSize: 12),
|
||||
),
|
||||
Text(
|
||||
@@ -371,7 +439,7 @@ class _LicenseTile extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(AppDimens.progressRadius),
|
||||
child: LinearProgressIndicator(
|
||||
minHeight: AppDimens.progressHeight,
|
||||
value: (license.progressPercent / 100).clamp(0.0, 1.0),
|
||||
value: progress.clamp(0.0, 1.0),
|
||||
backgroundColor: Colors.white24,
|
||||
valueColor: const AlwaysStoppedAnimation(AppColors.blueSoft),
|
||||
),
|
||||
|
||||
Reference in new issue
Block a user