diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 83caa526..1f8ea118 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -407,7 +407,7 @@ jobs: - name: Setup Flutter uses: subosito/flutter-action@v2 with: - channel: "stable" + channel: "master" flutter-version: "3.44.0" cache: true pub-cache: false @@ -649,7 +649,7 @@ jobs: - name: Setup Flutter uses: subosito/flutter-action@v2 with: - channel: "stable" + channel: "master" flutter-version: "3.44.0" cache: true pub-cache: false diff --git a/lib/widgets/media_card.dart b/lib/widgets/media_card.dart index 6e803c03..5be8ad52 100644 --- a/lib/widgets/media_card.dart +++ b/lib/widgets/media_card.dart @@ -228,7 +228,7 @@ class MediaCardState extends State with ContextMenuTapMixin with ContextMenuTapMixin + double _posterWidth() => MediaCardListLayout.posterWidth(density: density, usesWideAspectRatio: _usesWideAspectRatio()); - double _posterHeight(BuildContext context) => + double _posterHeight() => MediaCardListLayout.posterHeight(density: density, usesWideAspectRatio: _usesWideAspectRatio()); double get _titleFontSize => 13 + LibraryDensity.factor(density) * 3; // 13–16 @@ -461,7 +461,7 @@ class _MediaCardList extends StatelessWidget { return parts.join(' • '); } - String? _buildSubtitleText(BuildContext context) { + String? _buildSubtitleText() { if (item is MediaPlaylist) { return null; } else if (item is MediaItem) { @@ -523,7 +523,7 @@ class _MediaCardList extends StatelessWidget { @override Widget build(BuildContext context) { final metadataLine = _buildMetadataLine(); - final subtitle = _buildSubtitleText(context); + final subtitle = _buildSubtitleText(); return InkWell( mouseCursor: SystemMouseCursors.click, @@ -540,8 +540,8 @@ class _MediaCardList extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - width: _posterWidth(context), - height: _posterHeight(context), + width: _posterWidth(), + height: _posterHeight(), child: Stack( children: [ ClipRRect( diff --git a/lib/widgets/rating_bottom_sheet.dart b/lib/widgets/rating_bottom_sheet.dart index f39b250b..f3ea8159 100644 --- a/lib/widgets/rating_bottom_sheet.dart +++ b/lib/widgets/rating_bottom_sheet.dart @@ -112,7 +112,6 @@ class _RatingBottomSheetState extends State { children: [ if (widget.serverClient != null) _buildServerRow( - context, widget.serverClient!, _serverFocusNode, autofocus: focusIndex == 0, @@ -121,7 +120,6 @@ class _RatingBottomSheetState extends State { ), for (final source in trackerSources) _buildTrackerRow( - context, source, _trackerFocusNode(source.service), autofocus: focusIndex == 0, @@ -149,7 +147,6 @@ class _RatingBottomSheetState extends State { } Widget _buildServerRow( - BuildContext context, MediaServerClient client, FocusNode focusNode, { required bool autofocus, @@ -215,7 +212,6 @@ class _RatingBottomSheetState extends State { } Widget _buildTrackerRow( - BuildContext context, _TrackerRatingSource source, FocusNode focusNode, { required bool autofocus, diff --git a/lib/widgets/server_activities_button.dart b/lib/widgets/server_activities_button.dart index b69f410a..1ec43a93 100644 --- a/lib/widgets/server_activities_button.dart +++ b/lib/widgets/server_activities_button.dart @@ -80,7 +80,7 @@ class _ServerActivitiesButtonState extends State { _panelNotifier.value = _PanelData.loading; _overlayEntry = OverlayEntry( - builder: (ctx) => _buildOverlay(ctx, right: right, top: top), + builder: (_) => _buildOverlay(right: right, top: top), ); Overlay.of(context).insert(_overlayEntry!); _fetchActivities(); @@ -146,7 +146,7 @@ class _ServerActivitiesButtonState extends State { unawaited(_fetchActivities()); } - Widget _buildOverlay(BuildContext overlayContext, {required double right, required double top}) { + Widget _buildOverlay({required double right, required double top}) { return Stack( children: [ Positioned.fill( diff --git a/lib/widgets/tv_browse_rail.dart b/lib/widgets/tv_browse_rail.dart index 778c2c0e..7b477490 100644 --- a/lib/widgets/tv_browse_rail.dart +++ b/lib/widgets/tv_browse_rail.dart @@ -606,16 +606,16 @@ class TvBrowseRailState extends State { child: Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - SizedBox(width: _selectorWidth(context), child: _buildShelfSelector(context, hub)), + SizedBox(width: _selectorWidth(context), child: _buildShelfSelector(context)), SizedBox(width: selectorGap), - Expanded(child: _buildActiveRail(context, hub, hasFocus)), + Expanded(child: _buildActiveRail(hub, hasFocus)), ], ), ), ); } - Widget _buildShelfSelector(BuildContext context, MediaHub activeHub) { + Widget _buildShelfSelector(BuildContext context) { final scale = _scale(context); final visibleIndices = _visibleShelfIndices(); final isScrollable = widget.hubs.length > visibleIndices.length; @@ -803,7 +803,7 @@ class TvBrowseRailState extends State { ); } - Widget _buildActiveRail(BuildContext context, MediaHub hub, bool hasFocus) { + Widget _buildActiveRail(MediaHub hub, bool hasFocus) { return SettingsBuilder( prefs: const [SettingsService.libraryDensity, SettingsService.episodePosterMode], builder: (context) => LayoutBuilder( diff --git a/lib/widgets/tv_spotlight_background.dart b/lib/widgets/tv_spotlight_background.dart index bbe1a020..52c22d9a 100644 --- a/lib/widgets/tv_spotlight_background.dart +++ b/lib/widgets/tv_spotlight_background.dart @@ -191,7 +191,7 @@ class TvSpotlightBackground extends StatelessWidget { ], if (showPrimaryAction || actions != null) ...[ SizedBox(height: (compact ? 18 : 26) * scale), - actions ?? _buildPrimaryAction(context, colorScheme, media), + actions ?? _buildPrimaryAction(context, media), ], ], ); @@ -285,7 +285,7 @@ class TvSpotlightBackground extends StatelessWidget { double _summaryFontSize(double scale) => (compact ? 18 : 20) * scale; - Widget _buildPrimaryAction(BuildContext context, ColorScheme colorScheme, MediaItem media) { + Widget _buildPrimaryAction(BuildContext context, MediaItem media) { final scale = _scale(context); final hasProgress = media.hasActiveProgress; final minutesLeft = hasProgress && media.durationMs != null && media.viewOffsetMs != null diff --git a/lib/widgets/video_controls/widgets/content_strip.dart b/lib/widgets/video_controls/widgets/content_strip.dart index 3d9eb295..6f02776d 100644 --- a/lib/widgets/video_controls/widgets/content_strip.dart +++ b/lib/widgets/video_controls/widgets/content_strip.dart @@ -169,7 +169,7 @@ class ContentStripState extends State { }); } - KeyEventResult _handleFocusItemKeyEvent(FocusNode node, KeyEvent event, int index, int totalItems, _StripTab page) { + KeyEventResult _handleFocusItemKeyEvent(KeyEvent event, int index, int totalItems, _StripTab page) { if (!event.isActionable) return KeyEventResult.ignored; final key = event.logicalKey; @@ -359,7 +359,6 @@ class ContentStripState extends State { void onTap() => unawaited(_handleChapterTap(chapter.startTime)); final item = _buildStripItem( - context: context, isCurrent: isCurrent, isTablet: isTablet, thumbnail: chapter.thumb != null @@ -385,8 +384,8 @@ class ContentStripState extends State { child: FocusableWrapper( focusNode: _chapterFocusNodes[index], onSelect: onTap, - onKeyEvent: (node, event) => - _handleFocusItemKeyEvent(node, event, index, widget.chapters.length, _StripTab.chapters), + onKeyEvent: (_, event) => + _handleFocusItemKeyEvent(event, index, widget.chapters.length, _StripTab.chapters), onFocusChange: (hasFocus) { if (hasFocus) widget.onFocusActivity?.call(); }, @@ -441,7 +440,6 @@ class ContentStripState extends State { void onTap() => widget.onQueueItemSelected?.call(item); final stripItem = _buildStripItem( - context: context, isCurrent: isCurrent, isTablet: isTablet, thumbnail: item.thumbPath != null @@ -466,8 +464,7 @@ class ContentStripState extends State { child: FocusableWrapper( focusNode: _queueFocusNodes[index], onSelect: onTap, - onKeyEvent: (node, event) => - _handleFocusItemKeyEvent(node, event, index, items.length, _StripTab.queue), + onKeyEvent: (_, event) => _handleFocusItemKeyEvent(event, index, items.length, _StripTab.queue), onFocusChange: (hasFocus) { if (hasFocus) widget.onFocusActivity?.call(); }, @@ -499,7 +496,6 @@ class ContentStripState extends State { } Widget _buildStripItem({ - required BuildContext context, required bool isCurrent, required Widget? thumbnail, required String title, diff --git a/lib/widgets/video_controls/widgets/live_timeline_bar.dart b/lib/widgets/video_controls/widgets/live_timeline_bar.dart index 92d4596b..d7aa6633 100644 --- a/lib/widgets/video_controls/widgets/live_timeline_bar.dart +++ b/lib/widgets/video_controls/widgets/live_timeline_bar.dart @@ -138,9 +138,9 @@ class _LiveTimelineBarState extends State { return ClickableCursor( enabled: widget.enabled, child: GestureDetector( - onHorizontalDragStart: widget.enabled ? _onDragStart : null, + onHorizontalDragStart: widget.enabled ? (_) => _onDragStart() : null, onHorizontalDragUpdate: widget.enabled ? (details) => _onDragUpdate(details, _widthOf(context)) : null, - onHorizontalDragEnd: widget.enabled ? _onDragEnd : null, + onHorizontalDragEnd: widget.enabled ? (_) => _onDragEnd() : null, onTapUp: widget.enabled ? (details) => _onTap(details, _widthOf(context)) : null, child: SizedBox( width: double.infinity, @@ -154,7 +154,7 @@ class _LiveTimelineBarState extends State { ); } - void _onDragStart(DragStartDetails details) { + void _onDragStart() { setState(() { _isDragging = true; _dragPositionEpoch = _currentEpoch(widget.player.state.position); @@ -169,7 +169,7 @@ class _LiveTimelineBarState extends State { }); } - void _onDragEnd(DragEndDetails details) { + void _onDragEnd() { final target = _dragPositionEpoch; setState(() => _isDragging = false); widget.onSeekEnd?.call(target); diff --git a/lib/widgets/video_controls/widgets/track_chapter_controls.dart b/lib/widgets/video_controls/widgets/track_chapter_controls.dart index c65fa678..4a8a061c 100644 --- a/lib/widgets/video_controls/widgets/track_chapter_controls.dart +++ b/lib/widgets/video_controls/widgets/track_chapter_controls.dart @@ -153,7 +153,6 @@ class TrackChapterControls extends StatelessWidget { required IconData icon, required String semanticLabel, required VoidCallback? onPressed, - required Tracks? tracks, required bool isMobile, required bool isDesktop, String? tooltip, @@ -166,8 +165,7 @@ class TrackChapterControls extends StatelessWidget { isActive: isActive, focusNode: focusNodes != null && focusNodes!.length > buttonIndex ? focusNodes![buttonIndex] : null, onKeyEvent: focusNodes != null - ? (node, event) => - _handleButtonKeyEvent(node, event, buttonIndex, _getButtonCount(tracks, isMobile, isDesktop)) + ? (node, event) => _handleButtonKeyEvent(node, event, buttonIndex, _getButtonCount(isMobile, isDesktop)) : null, onFocusChange: onFocusChange, onPressed: onPressed, @@ -203,7 +201,6 @@ class TrackChapterControls extends StatelessWidget { isActive: isActive, tooltip: t.videoControls.settingsButton, semanticLabel: t.videoControls.settingsButton, - tracks: tracks, isMobile: isMobile, isDesktop: isDesktop, onPressed: () { @@ -259,7 +256,6 @@ class TrackChapterControls extends StatelessWidget { icon: icon, tooltip: t.videoControls.tracksButton, semanticLabel: t.videoControls.tracksButton, - tracks: tracks, isMobile: isMobile, isDesktop: isDesktop, onPressed: () { @@ -298,7 +294,6 @@ class TrackChapterControls extends StatelessWidget { icon: Symbols.bookmarks_rounded, tooltip: t.videoControls.chaptersButton, semanticLabel: t.videoControls.chaptersButton, - tracks: tracks, isMobile: isMobile, isDesktop: isDesktop, onPressed: () { @@ -329,7 +324,6 @@ class TrackChapterControls extends StatelessWidget { icon: Symbols.queue_rounded, tooltip: t.videoControls.queue, semanticLabel: t.videoControls.queue, - tracks: tracks, isMobile: isMobile, isDesktop: isDesktop, onPressed: () { @@ -352,7 +346,6 @@ class TrackChapterControls extends StatelessWidget { icon: Symbols.picture_in_picture_alt, tooltip: t.videoControls.pipButton, semanticLabel: t.videoControls.pipButton, - tracks: tracks, isMobile: isMobile, isDesktop: isDesktop, onPressed: onTogglePIPMode, @@ -370,7 +363,6 @@ class TrackChapterControls extends StatelessWidget { icon: _getBoxFitIcon(boxFitMode), tooltip: _getBoxFitTooltip(boxFitMode), semanticLabel: t.videoControls.aspectRatioButton, - tracks: tracks, isMobile: isMobile, isDesktop: isDesktop, onPressed: onCycleBoxFitMode, @@ -388,7 +380,6 @@ class TrackChapterControls extends StatelessWidget { icon: isRotationLocked ? Symbols.screen_lock_rotation_rounded : Symbols.screen_rotation_rounded, tooltip: isRotationLocked ? t.videoControls.unlockRotation : t.videoControls.lockRotation, semanticLabel: t.videoControls.rotationLockButton, - tracks: tracks, isMobile: isMobile, isDesktop: isDesktop, onPressed: onToggleRotationLock, @@ -406,7 +397,6 @@ class TrackChapterControls extends StatelessWidget { icon: Symbols.lock_rounded, tooltip: t.videoControls.lockScreen, semanticLabel: t.videoControls.screenLockButton, - tracks: tracks, isMobile: isMobile, isDesktop: isDesktop, onPressed: onToggleScreenLock, @@ -425,7 +415,6 @@ class TrackChapterControls extends StatelessWidget { tooltip: t.videoControls.alwaysOnTopButton, semanticLabel: t.videoControls.alwaysOnTopButton, isActive: isAlwaysOnTop, - tracks: tracks, isMobile: isMobile, isDesktop: isDesktop, onPressed: onToggleAlwaysOnTop, @@ -443,7 +432,6 @@ class TrackChapterControls extends StatelessWidget { icon: isFullscreen ? Symbols.fullscreen_exit_rounded : Symbols.fullscreen_rounded, tooltip: isFullscreen ? t.videoControls.exitFullscreenButton : t.videoControls.fullscreenButton, semanticLabel: isFullscreen ? t.videoControls.exitFullscreenButton : t.videoControls.fullscreenButton, - tracks: tracks, isMobile: isMobile, isDesktop: isDesktop, onPressed: onToggleFullscreen, @@ -459,7 +447,7 @@ class TrackChapterControls extends StatelessWidget { } /// Calculate total button count for navigation - int _getButtonCount(Tracks? tracks, bool isMobile, bool isDesktop) { + int _getButtonCount(bool isMobile, bool isDesktop) { int count = 1; // Settings button always shown count++; // Audio & subtitles button always shown if (chapters.isNotEmpty && !hideChaptersAndQueue) count++; diff --git a/lib/widgets/video_controls/widgets/volume_control.dart b/lib/widgets/video_controls/widgets/volume_control.dart index 71d5b47b..02c66ead 100644 --- a/lib/widgets/video_controls/widgets/volume_control.dart +++ b/lib/widgets/video_controls/widgets/volume_control.dart @@ -10,7 +10,6 @@ import '../../../mpv/mpv.dart'; import '../../../services/settings_service.dart'; import '../../../i18n/strings.g.dart'; import '../../../focus/focusable_wrapper.dart'; -import '../../../focus/input_mode_tracker.dart'; /// A volume control widget that displays a mute/unmute button and volume slider. /// @@ -138,8 +137,6 @@ class _VolumeControlState extends State { builder: (context, snapshot) { final volume = snapshot.data ?? 100.0; final isMuted = volume == 0; - final isKeyboardMode = InputModeTracker.isKeyboardMode(context); - final muteButton = Semantics( label: isMuted ? t.videoControls.unmuteButton : t.videoControls.muteButton, button: true, @@ -180,7 +177,7 @@ class _VolumeControlState extends State { else muteButton, const SizedBox(width: 8), - _buildVolumeSlider(volume, isKeyboardMode, maxVolume), + _buildVolumeSlider(volume, maxVolume), ], ); }, @@ -189,7 +186,7 @@ class _VolumeControlState extends State { ); } - Widget _buildVolumeSlider(double volume, bool isKeyboardMode, int maxVolume) { + Widget _buildVolumeSlider(double volume, int maxVolume) { final maxVolumeDouble = maxVolume.toDouble(); // Calculate 100% marker position as fraction of slider width