feat(flutter): 重设计播放页与操作面板
This commit is contained in:
1 parent
148fbc3c93
commit
9a4269b847
24 files changed
+2395
-1101
No files matched your search
@@ -0,0 +1,162 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
part of 'player_view.dart';
|
||||
|
||||
extension _PlayerViewActions on _PlayerPageState {
|
||||
Future<void> _openSpeedSheet(BuildContext context) async {
|
||||
final selected = await showModalBottomSheet<double>(
|
||||
context: context,
|
||||
backgroundColor: Colors.transparent,
|
||||
showDragHandle: false,
|
||||
builder: (_) => PlayerSpeedSheet(selected: _playbackSpeed),
|
||||
);
|
||||
if (selected == null || !mounted) return;
|
||||
_updatePlaybackSpeed(selected);
|
||||
await logic.setPlaybackSpeed(selected);
|
||||
}
|
||||
|
||||
Future<void> _openQualitySheet(BuildContext context) async {
|
||||
await showModalBottomSheet<void>(
|
||||
context: context,
|
||||
backgroundColor: AppColors.card,
|
||||
showDragHandle: true,
|
||||
builder: (_) => QualitySheet(qualities: logic.qualities),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _openMore(
|
||||
BuildContext context,
|
||||
Drama drama,
|
||||
Episode episode,
|
||||
) async {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
await showModalBottomSheet<void>(
|
||||
context: context,
|
||||
backgroundColor: Colors.transparent,
|
||||
showDragHandle: false,
|
||||
isScrollControlled: true,
|
||||
builder: (_) => PlayerMoreSheet(
|
||||
l10n: l10n,
|
||||
state: PlayerMoreState(
|
||||
speed: _playbackSpeed,
|
||||
qualities: logic.qualities,
|
||||
textScale: _textScale,
|
||||
pipAvailable: logic.pictureInPicture.isPlatformSupported,
|
||||
),
|
||||
actions: PlayerMoreActions(
|
||||
onSpeed: () => unawaited(_openSpeedSheet(context)),
|
||||
onQuality: () => unawaited(_openQualitySheet(context)),
|
||||
onDownload: () => requestEpisodeDownload(context, episode.id),
|
||||
onTextSize: () => unawaited(_openTextSizeSheet(context)),
|
||||
onReport: () => unawaited(_reportDrama(context, drama, l10n)),
|
||||
onPip: logic.pictureInPicture.isPlatformSupported
|
||||
? () => unawaited(logic.enterPip(context))
|
||||
: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _openTextSizeSheet(BuildContext context) async {
|
||||
final selected = await showModalBottomSheet<double>(
|
||||
context: context,
|
||||
backgroundColor: Colors.transparent,
|
||||
showDragHandle: false,
|
||||
builder: (_) => PlayerTextSizeSheet(selected: _textScale),
|
||||
);
|
||||
if (selected == null || !mounted) return;
|
||||
_updateTextScale(selected);
|
||||
}
|
||||
|
||||
Future<void> _openUnlockSheet(
|
||||
BuildContext context,
|
||||
int index,
|
||||
Episode episode,
|
||||
) async {
|
||||
final wallet = logic.wallet;
|
||||
if (wallet == null) return;
|
||||
await showModalBottomSheet<bool>(
|
||||
context: context,
|
||||
backgroundColor: Colors.transparent,
|
||||
showDragHandle: false,
|
||||
isScrollControlled: true,
|
||||
builder: (_) => PlayerUnlockSheet(
|
||||
l10n: AppLocalizations.of(context)!,
|
||||
episodeNumber: episode.number,
|
||||
coinCost: logic.blockedTicket?.unlockCoin ?? 0,
|
||||
balance: wallet.snapshot == null ? null : wallet.balance,
|
||||
onUnlock: () => _unlockEpisode(context, index),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> _unlockEpisode(BuildContext context, int index) async {
|
||||
if (!await ensureSignedIn(context) || !context.mounted) return false;
|
||||
final ok = await logic.unlockEpisode(index);
|
||||
if (ok || !context.mounted) return ok;
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(errorText(l10n, logic.unlockError, l10n.unlockFailed)),
|
||||
),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> _reportDrama(
|
||||
BuildContext context,
|
||||
Drama drama,
|
||||
AppLocalizations l10n,
|
||||
) async {
|
||||
if (!await ensureSignedIn(context) || !context.mounted) return;
|
||||
final draft = await showReportDialog(context, title: l10n.reportDrama);
|
||||
if (draft == null || !context.mounted) return;
|
||||
unawaited(context.read<Haptics>().lightImpact());
|
||||
final result = await context.read<InteractionController>().reportDrama(
|
||||
drama.id,
|
||||
reason: draft.reason,
|
||||
description: draft.description,
|
||||
);
|
||||
if (!context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
result.isSuccess
|
||||
? l10n.reportSubmitted
|
||||
: result.errorMessage ?? l10n.reportFailed,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _toggleLike(
|
||||
BuildContext context,
|
||||
InteractionController interactions,
|
||||
Drama drama,
|
||||
) async {
|
||||
if (!await ensureSignedIn(context) || !context.mounted) return;
|
||||
unawaited(context.read<Haptics>().lightImpact());
|
||||
final result = await interactions.toggleDramaLike(drama.id);
|
||||
if (result.isSuccess || !context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
result.errorMessage ?? AppLocalizations.of(context)!.likeFailed,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _toggleSave(BuildContext context, Drama drama) async {
|
||||
final favorites = context.read<FavoriteController>();
|
||||
if (!await ensureSignedIn(context) || !context.mounted) return;
|
||||
unawaited(context.read<Haptics>().lightImpact());
|
||||
final ok = await favorites.toggle(drama.id, card: drama);
|
||||
if (ok || !context.mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!.favoriteToggleFailed),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user