refactor: adjust video controls button sizes

This commit is contained in:
edde746
2025-11-05 20:16:12 +01:00
parent 57b691782c
commit 2571a6c38b
2 changed files with 72 additions and 34 deletions
@@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
/// A standardized button for video player controls with improved tap targets.
///
/// This widget ensures consistent tap target sizing across all video control
/// buttons without changing their visual appearance. The larger tap area makes
/// buttons easier to interact with, especially on mobile devices.
class VideoControlButton extends StatelessWidget {
/// The icon to display in the button.
final IconData icon;
/// Called when the button is tapped.
final VoidCallback? onPressed;
/// The color of the icon. Defaults to white, or amber if [isActive] is true.
final Color? color;
/// Optional tooltip text shown on hover or long press.
final String? tooltip;
/// Whether this button represents an active state (e.g., a feature is enabled).
/// When true, the icon color defaults to amber instead of white.
final bool isActive;
const VideoControlButton({
super.key,
required this.icon,
required this.onPressed,
this.color,
this.tooltip,
this.isActive = false,
});
@override
Widget build(BuildContext context) {
// Determine the effective color: explicit color > active amber > default white
final effectiveColor = color ?? (isActive ? Colors.amber : Colors.white);
return IconButton(
icon: Icon(icon, color: effectiveColor),
onPressed: onPressed,
tooltip: tooltip,
constraints: const BoxConstraints(minWidth: 40, minHeight: 56),
);
}
}
+26 -34
View File
@@ -23,6 +23,7 @@ import 'sheets/chapter_sheet.dart';
import 'sheets/subtitle_track_sheet.dart';
import 'sheets/version_sheet.dart';
import 'sheets/video_settings_sheet.dart';
import 'video_control_button.dart';
/// Custom video controls builder for Plex with chapter, audio, and subtitle support
Widget plexVideoControlsBuilder(
@@ -374,9 +375,11 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
initialData: widget.player.state.tracks,
builder: (context, snapshot) {
final tracks = snapshot.data;
return Row(
mainAxisSize: MainAxisSize.min,
children: [
return IntrinsicHeight(
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Unified settings button (speed, sleep timer, audio sync, subtitle sync)
ListenableBuilder(
listenable: SleepTimerService(),
@@ -386,11 +389,9 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
sleepTimer.isActive ||
_audioSyncOffset != 0 ||
_subtitleSyncOffset != 0;
return IconButton(
icon: Icon(
Icons.tune,
color: isActive ? Colors.amber : Colors.white,
),
return VideoControlButton(
icon: Icons.tune,
isActive: isActive,
onPressed: () async {
await VideoSettingsSheet.show(
context,
@@ -407,19 +408,18 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
},
),
if (_hasMultipleAudioTracks(tracks))
IconButton(
icon: const Icon(Icons.audiotrack, color: Colors.white),
VideoControlButton(
icon: Icons.audiotrack,
onPressed: () => AudioTrackSheet.show(context, widget.player),
),
if (_hasSubtitles(tracks))
IconButton(
icon: const Icon(Icons.subtitles, color: Colors.white),
onPressed: () =>
SubtitleTrackSheet.show(context, widget.player),
VideoControlButton(
icon: Icons.subtitles,
onPressed: () => SubtitleTrackSheet.show(context, widget.player),
),
if (_chapters.isNotEmpty)
IconButton(
icon: const Icon(Icons.video_library, color: Colors.white),
VideoControlButton(
icon: Icons.video_library,
onPressed: () => ChapterSheet.show(
context,
widget.player,
@@ -428,8 +428,8 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
),
),
if (widget.availableVersions.length > 1)
IconButton(
icon: const Icon(Icons.video_file, color: Colors.white),
VideoControlButton(
icon: Icons.video_file,
onPressed: () => VersionSheet.show(
context,
widget.availableVersions,
@@ -439,34 +439,26 @@ class _PlexVideoControlsState extends State<PlexVideoControls>
),
// BoxFit mode cycle button
if (widget.onCycleBoxFitMode != null)
IconButton(
icon: Icon(
_getBoxFitIcon(widget.boxFitMode),
color: Colors.white,
),
VideoControlButton(
icon: _getBoxFitIcon(widget.boxFitMode),
tooltip: _getBoxFitTooltip(widget.boxFitMode),
onPressed: widget.onCycleBoxFitMode,
),
// Rotation lock toggle (mobile only)
if (PlatformDetector.isMobile(context))
IconButton(
icon: Icon(
_isRotationLocked ? Icons.screen_lock_rotation : Icons.screen_rotation,
color: Colors.white,
),
VideoControlButton(
icon: _isRotationLocked ? Icons.screen_lock_rotation : Icons.screen_rotation,
tooltip: _isRotationLocked ? 'Unlock rotation' : 'Lock rotation',
onPressed: _toggleRotationLock,
),
// Fullscreen toggle (desktop only)
if (Platform.isWindows || Platform.isLinux || Platform.isMacOS)
IconButton(
icon: Icon(
_isFullscreen ? Icons.fullscreen_exit : Icons.fullscreen,
color: Colors.white,
),
VideoControlButton(
icon: _isFullscreen ? Icons.fullscreen_exit : Icons.fullscreen,
onPressed: _toggleFullscreen,
),
],
],
),
);
},
);