Files
sm-emby-share/lib/features/detail/android/android_hero_actions.dart
T
2026-07-14 11:11:36 +08:00

194 lines
5.6 KiB
Dart

import 'package:flutter/material.dart';
import 'android_detail_colors.dart';
import '../../../shared/widgets/app_loading_ring.dart';
class AndroidHeroActions extends StatelessWidget {
final String playLabel;
final String? playTrailingLabel;
final double? progressPercent;
final bool isLoading;
final String loadingLabel;
final bool canPlay;
final VoidCallback? onPlay;
final bool showReplay;
final VoidCallback? onReplay;
final bool isPlayed;
final VoidCallback onTogglePlayed;
final bool isFavorite;
final VoidCallback onToggleFavorite;
const AndroidHeroActions({
super.key,
required this.playLabel,
this.playTrailingLabel,
this.progressPercent,
this.isLoading = false,
this.loadingLabel = '启动中',
this.canPlay = true,
this.onPlay,
this.showReplay = false,
this.onReplay,
required this.isPlayed,
required this.onTogglePlayed,
required this.isFavorite,
required this.onToggleFavorite,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
children: [
if (canPlay)
Expanded(
child: _GoldPlayButton(
label: playLabel,
trailingLabel: playTrailingLabel,
progressPercent: progressPercent,
isLoading: isLoading,
loadingLabel: loadingLabel,
onPressed: onPlay,
),
),
if (canPlay) const SizedBox(width: 8),
if (!canPlay) const Spacer(),
_SquareButton(
icon: isPlayed ? Icons.check_circle : Icons.check_circle_outline,
active: isPlayed,
onTap: onTogglePlayed,
),
const SizedBox(width: 8),
_SquareButton(
icon: isFavorite ? Icons.favorite : Icons.favorite_border,
active: isFavorite,
onTap: onToggleFavorite,
),
if (showReplay) ...[
const SizedBox(width: 8),
_SquareButton(icon: Icons.replay, active: false, onTap: onReplay),
],
],
),
);
}
}
class _GoldPlayButton extends StatelessWidget {
final String label;
final String? trailingLabel;
final bool isLoading;
final String loadingLabel;
final double? progressPercent;
final VoidCallback? onPressed;
const _GoldPlayButton({
required this.label,
this.trailingLabel,
this.isLoading = false,
this.loadingLabel = '启动中',
this.progressPercent,
this.onPressed,
});
@override
Widget build(BuildContext context) {
final progress = progressPercent;
final normalizedProgress = progress != null && progress > 0
? progress.clamp(0.0, 100.0) / 100.0
: null;
final enabled = !isLoading && onPressed != null;
final radius = BorderRadius.circular(10);
final backgroundColor = enabled
? AndroidDetailColors.accent
: Colors.white.withValues(alpha: 0.12);
final foregroundColor = enabled
? Colors.black
: Colors.white.withValues(alpha: 0.38);
return SizedBox(
height: 48,
child: Material(
color: backgroundColor,
borderRadius: radius,
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: enabled ? onPressed : null,
child: Stack(
fit: StackFit.expand,
children: [
if (normalizedProgress != null)
FractionallySizedBox(
alignment: Alignment.centerLeft,
widthFactor: normalizedProgress,
child: ColoredBox(
color: AndroidDetailColors.accent.withValues(alpha: 0.25),
),
),
Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (isLoading)
AppLoadingRing(size: 16, color: foregroundColor)
else
Icon(Icons.play_arrow, color: foregroundColor, size: 20),
const SizedBox(width: 6),
Text(
isLoading
? loadingLabel
: trailingLabel != null
? '$label $trailingLabel'
: label,
style: TextStyle(
color: foregroundColor,
fontSize: 15,
fontWeight: FontWeight.w700,
),
),
],
),
),
],
),
),
),
);
}
}
class _SquareButton extends StatelessWidget {
final IconData icon;
final bool active;
final VoidCallback? onTap;
const _SquareButton({required this.icon, required this.active, this.onTap});
@override
Widget build(BuildContext context) {
final color = active
? AndroidDetailColors.accent
: Colors.white.withValues(alpha: 0.8);
return SizedBox(
width: 48,
height: 48,
child: Material(
color: Colors.white.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(10),
child: InkWell(
borderRadius: BorderRadius.circular(10),
onTap: onTap,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.white.withValues(alpha: 0.15)),
),
child: Center(child: Icon(icon, size: 20, color: color)),
),
),
),
);
}
}