From 3709163a49c5b7c90d41d6626cd87a85f2a1e9fa Mon Sep 17 00:00:00 2001 From: NBA2K1 <78034913+NBA2K1@users.noreply.github.com> Date: Sun, 18 May 2025 01:47:12 +0200 Subject: [PATCH] Reduce Code Duplication Extract `CustomMaterialPlayOrPauseButton` class from *mobile.dart* and `CustomMaterialDesktopPlayOrPauseButton` class from *desktop.dart* into *play_or_pause_button.dart* to eliminate code duplication and improve maintainability. --- lib/modules/anime/anime_player_view.dart | 4 +- lib/modules/anime/widgets/desktop.dart | 69 ----------------- lib/modules/anime/widgets/mobile.dart | 71 +---------------- .../anime/widgets/play_or_pause_button.dart | 76 +++++++++++++++++++ 4 files changed, 81 insertions(+), 139 deletions(-) create mode 100644 lib/modules/anime/widgets/play_or_pause_button.dart diff --git a/lib/modules/anime/anime_player_view.dart b/lib/modules/anime/anime_player_view.dart index 41bd93d2..a8ade022 100644 --- a/lib/modules/anime/anime_player_view.dart +++ b/lib/modules/anime/anime_player_view.dart @@ -15,6 +15,7 @@ import 'package:mangayomi/models/video.dart' as vid; import 'package:mangayomi/modules/anime/providers/anime_player_controller_provider.dart'; import 'package:mangayomi/modules/anime/widgets/aniskip_countdown_btn.dart'; import 'package:mangayomi/modules/anime/widgets/desktop.dart'; +import 'package:mangayomi/modules/anime/widgets/play_or_pause_button.dart'; import 'package:mangayomi/modules/manga/reader/widgets/btn_chapter_list_dialog.dart'; import 'package:mangayomi/modules/anime/widgets/mobile.dart'; import 'package:mangayomi/modules/anime/widgets/subtitle_view.dart'; @@ -870,8 +871,9 @@ class _AnimeStreamPageState extends riv.ConsumerState }, icon: const Icon(Icons.skip_previous, color: Colors.white), ), - CustomeMaterialDesktopPlayOrPauseButton( + CustomPlayOrPauseButton( controller: _controller, + isDesktop: _isDesktop, ), if (hasNextEpisode) IconButton( diff --git a/lib/modules/anime/widgets/desktop.dart b/lib/modules/anime/widgets/desktop.dart index ad4304b8..9518074d 100644 --- a/lib/modules/anime/widgets/desktop.dart +++ b/lib/modules/anime/widgets/desktop.dart @@ -500,75 +500,6 @@ class _DesktopControllerWidgetState extends State { } } -// BUTTON: PLAY/PAUSE - -/// A material design play/pause button. -class CustomeMaterialDesktopPlayOrPauseButton extends StatefulWidget { - final VideoController controller; - - const CustomeMaterialDesktopPlayOrPauseButton({ - super.key, - required this.controller, - }); - - @override - CustomeMaterialDesktopPlayOrPauseButtonState createState() => - CustomeMaterialDesktopPlayOrPauseButtonState(); -} - -class CustomeMaterialDesktopPlayOrPauseButtonState - extends State - with SingleTickerProviderStateMixin { - late final animation = AnimationController( - vsync: this, - value: widget.controller.player.state.playing ? 1 : 0, - duration: const Duration(milliseconds: 200), - ); - - StreamSubscription? subscription; - - @override - void setState(VoidCallback fn) { - if (mounted) { - super.setState(fn); - } - } - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - subscription ??= widget.controller.player.stream.playing.listen((event) { - if (event) { - animation.forward(); - } else { - animation.reverse(); - } - }); - } - - @override - void dispose() { - animation.dispose(); - subscription?.cancel(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return IconButton( - onPressed: widget.controller.player.playOrPause, - iconSize: 25, - color: Colors.white, - icon: AnimatedIcon( - progress: animation, - icon: AnimatedIcons.play_pause, - size: 25, - color: Colors.white, - ), - ); - } -} - // BUTTON: VOLUME /// MaterialDesktop design volume button & slider. diff --git a/lib/modules/anime/widgets/mobile.dart b/lib/modules/anime/widgets/mobile.dart index 21f9c1a5..ad242913 100644 --- a/lib/modules/anime/widgets/mobile.dart +++ b/lib/modules/anime/widgets/mobile.dart @@ -10,6 +10,7 @@ import 'package:mangayomi/modules/anime/widgets/indicator_builder.dart'; import 'package:mangayomi/modules/anime/widgets/subtitle_view.dart'; import 'package:mangayomi/modules/manga/reader/providers/push_router.dart'; import 'package:mangayomi/modules/more/settings/player/providers/player_state_provider.dart'; +import 'package:mangayomi/modules/anime/widgets/play_or_pause_button.dart'; import 'package:volume_controller/volume_controller.dart'; import 'package:screen_brightness/screen_brightness.dart'; import 'package:flutter/material.dart'; @@ -884,74 +885,6 @@ class _ForwardSeekIndicatorState extends State<_ForwardSeekIndicator> { } } -// BUTTON: PLAY/PAUSE - -/// A material design play/pause button. -class CustomMaterialPlayOrPauseButton extends StatefulWidget { - final VideoController controller; - - const CustomMaterialPlayOrPauseButton({super.key, required this.controller}); - - @override - CustomMaterialPlayOrPauseButtonState createState() => - CustomMaterialPlayOrPauseButtonState(); -} - -class CustomMaterialPlayOrPauseButtonState - extends State - with SingleTickerProviderStateMixin { - late final animation = AnimationController( - vsync: this, - value: widget.controller.player.state.playing ? 1 : 0, - duration: const Duration(milliseconds: 200), - ); - - StreamSubscription? subscription; - - @override - void setState(VoidCallback fn) { - if (mounted) { - super.setState(fn); - } - } - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - subscription ??= widget.controller.player.stream.playing.listen((event) { - if (event) { - animation.forward(); - } else { - animation.reverse(); - } - }); - } - - @override - void dispose() { - animation.dispose(); - subscription?.cancel(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return IconButton( - onPressed: widget.controller.player.playOrPause, - iconSize: 65, - color: Colors.white, - icon: IgnorePointer( - child: AnimatedIcon( - progress: animation, - icon: AnimatedIcons.play_pause, - size: 65, - color: Colors.white, - ), - ), - ); - } -} - List mobilePrimaryButtonBar( BuildContext context, GlobalKey key, @@ -985,7 +918,7 @@ List mobilePrimaryButtonBar( ), ), const Spacer(), - CustomMaterialPlayOrPauseButton(controller: controller), + CustomPlayOrPauseButton(controller: controller, isDesktop: false), const Spacer(), IconButton( onPressed: diff --git a/lib/modules/anime/widgets/play_or_pause_button.dart b/lib/modules/anime/widgets/play_or_pause_button.dart new file mode 100644 index 00000000..e6443edc --- /dev/null +++ b/lib/modules/anime/widgets/play_or_pause_button.dart @@ -0,0 +1,76 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:media_kit_video/media_kit_video.dart'; + +// BUTTON: PLAY/PAUSE + +/// A material design play/pause button. +class CustomPlayOrPauseButton extends StatefulWidget { + final VideoController controller; + final bool isDesktop; + + const CustomPlayOrPauseButton({ + super.key, + required this.controller, + required this.isDesktop, + }); + + @override + CustomPlayOrPauseButtonState createState() => CustomPlayOrPauseButtonState(); +} + +class CustomPlayOrPauseButtonState extends State + with SingleTickerProviderStateMixin { + late final animation = AnimationController( + vsync: this, + value: widget.controller.player.state.playing ? 1 : 0, + duration: const Duration(milliseconds: 200), + ); + + StreamSubscription? subscription; + + double get iconSize => widget.isDesktop ? 25 : 65; + + @override + void setState(VoidCallback fn) { + if (mounted) { + super.setState(fn); + } + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + subscription ??= widget.controller.player.stream.playing.listen((event) { + if (event) { + animation.forward(); + } else { + animation.reverse(); + } + }); + } + + @override + void dispose() { + animation.dispose(); + subscription?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return IconButton( + onPressed: widget.controller.player.playOrPause, + iconSize: iconSize, + color: Colors.white, + icon: IgnorePointer( + child: AnimatedIcon( + progress: animation, + icon: AnimatedIcons.play_pause, + size: iconSize, + color: Colors.white, + ), + ), + ); + } +}