From 13c374cb5e76a4a39023a98af1ee4de15371c8ce Mon Sep 17 00:00:00 2001 From: MSOB7YY Date: Thu, 29 Feb 2024 12:51:46 +0200 Subject: [PATCH] chore: fixes/tweaks --- lib/controller/ffmpeg_controller.dart | 11 ++- lib/packages/lyrics_lrc_parsed_view.dart | 2 +- lib/packages/miniplayer.dart | 8 +- lib/packages/miniplayer_base.dart | 2 +- lib/ui/dialogs/general_popup_dialog.dart | 8 +- lib/ui/widgets/custom_widgets.dart | 81 +++++++++++++++++++ lib/ui/widgets/inner_drawer.dart | 35 ++++++-- .../settings/backup_restore_settings.dart | 4 +- .../settings/customization_settings.dart | 2 +- lib/ui/widgets/video_widget.dart | 30 ++----- 10 files changed, 141 insertions(+), 42 deletions(-) diff --git a/lib/controller/ffmpeg_controller.dart b/lib/controller/ffmpeg_controller.dart index 43e94cae..6b88c1ec 100644 --- a/lib/controller/ffmpeg_controller.dart +++ b/lib/controller/ffmpeg_controller.dart @@ -48,7 +48,16 @@ class NamidaFFMPEG { map["PATH"] = path; final miBackup = MediaInfo.fromMap(map); final format = miBackup.format; - final tags = information?.getTags() ?? (map['streams'] as List?)?.firstWhereEff((e) => e['tags'].isNotEmpty)?['tags']; + Map? tags = information?.getTags(); + if (tags == null) { + try { + final mainTags = (map['streams'] as List?)?.firstWhereEff((e) { + final t = e['tags']; + return t is List && t.isNotEmpty; + }); + tags = mainTags?['tags']; + } catch (_) {} + } final mi = MediaInfo( path: path, streams: miBackup.streams, diff --git a/lib/packages/lyrics_lrc_parsed_view.dart b/lib/packages/lyrics_lrc_parsed_view.dart index 45ece080..1610b979 100644 --- a/lib/packages/lyrics_lrc_parsed_view.dart +++ b/lib/packages/lyrics_lrc_parsed_view.dart @@ -196,7 +196,7 @@ class LyricsLRCParsedViewState extends State { // NamidaOpacity causes rebuilds Opacity( opacity: widget.cp, - child: ClipRRect( + child: BorderRadiusClip( borderRadius: fullscreen ? BorderRadius.zero : BorderRadius.circular(16.0.multipliedRadius), child: NamidaBgBlur( blur: fullscreen ? 0.0 : 14.0, diff --git a/lib/packages/miniplayer.dart b/lib/packages/miniplayer.dart index 3253bee9..a103307c 100644 --- a/lib/packages/miniplayer.dart +++ b/lib/packages/miniplayer.dart @@ -622,9 +622,9 @@ class _AnimatingTrackImage extends StatelessWidget { AnimatedSwitcher( duration: const Duration(milliseconds: 300), child: videoInfo != null && videoInfo.isInitialized - ? ClipRRect( + ? BorderRadiusClip( borderRadius: BorderRadius.circular((6.0 + 10.0 * cp).multipliedRadius), - child: GestureDetector( + child: DoubleTapDetector( onDoubleTap: () => VideoController.inst.toggleFullScreenVideoView(isLocal: true), child: NamidaAspectRatio( aspectRatio: videoInfo.aspectRatio, @@ -780,9 +780,9 @@ class _AnimatingYoutubeIDImage extends StatelessWidget { child: AnimatedSwitcher( duration: const Duration(milliseconds: 300), child: videoInfo != null && videoInfo.isInitialized - ? ClipRRect( + ? BorderRadiusClip( borderRadius: BorderRadius.circular((6.0 + 10.0 * cp).multipliedRadius), - child: GestureDetector( + child: DoubleTapDetector( onDoubleTap: () => VideoController.inst.toggleFullScreenVideoView(isLocal: true), child: NamidaAspectRatio( aspectRatio: videoInfo.aspectRatio, diff --git a/lib/packages/miniplayer_base.dart b/lib/packages/miniplayer_base.dart index f1044be4..fabdebf5 100644 --- a/lib/packages/miniplayer_base.dart +++ b/lib/packages/miniplayer_base.dart @@ -173,7 +173,7 @@ class _NamidaMiniPlayerBaseState extends State> { children: [ SizedBox( height: MiniPlayerController.inst.maxOffset - 100.0 - MiniPlayerController.inst.topInset - 12.0, - child: ClipRRect( + child: BorderRadiusClip( borderRadius: BorderRadius.only( topLeft: Radius.circular(32.0.multipliedRadius), topRight: Radius.circular(32.0.multipliedRadius), diff --git a/lib/ui/dialogs/general_popup_dialog.dart b/lib/ui/dialogs/general_popup_dialog.dart index 9229e757..8f0e3f7b 100644 --- a/lib/ui/dialogs/general_popup_dialog.dart +++ b/lib/ui/dialogs/general_popup_dialog.dart @@ -64,8 +64,11 @@ Future showGeneralPopupDialog( String? heroTag, String? additionalHero, }) async { + final isSingle = tracks.length == 1; + forceSingleArtwork ??= isSingle; + final tracksExisting = []; - if (errorPlayingTrack != null) { + if (isSingle || errorPlayingTrack != null) { // -- fill using real-time checks if there was an error. tracks.loop((t, index) { if (File(t.path).existsSync()) tracksExisting.add(t); @@ -77,9 +80,6 @@ Future showGeneralPopupDialog( }); } - final isSingle = tracks.length == 1; - forceSingleArtwork ??= isSingle; - final trackToExtractColorFrom = tracks.isEmpty ? null : forceSingleArtwork diff --git a/lib/ui/widgets/custom_widgets.dart b/lib/ui/widgets/custom_widgets.dart index a6875371..43a99c94 100644 --- a/lib/ui/widgets/custom_widgets.dart +++ b/lib/ui/widgets/custom_widgets.dart @@ -3704,6 +3704,41 @@ class TapDetector extends StatelessWidget { } } +class DoubleTapDetector extends StatelessWidget { + final VoidCallback? onDoubleTap; + final void Function(DoubleTapGestureRecognizer instance)? initializer; + final Widget? child; + final HitTestBehavior? behavior; + + const DoubleTapDetector({ + super.key, + required this.onDoubleTap, + this.initializer, + this.child, + this.behavior, + }); + + @override + Widget build(BuildContext context) { + final Map gestures = {}; + gestures[DoubleTapGestureRecognizer] = GestureRecognizerFactoryWithHandlers( + () => DoubleTapGestureRecognizer(debugOwner: this), + initializer ?? + (DoubleTapGestureRecognizer instance) { + instance + ..onDoubleTap = onDoubleTap + ..gestureSettings = MediaQuery.maybeGestureSettingsOf(context); + }, + ); + + return RawGestureDetector( + behavior: behavior, + gestures: gestures, + child: child, + ); + } +} + class LongPressDetector extends StatelessWidget { final VoidCallback? onLongPress; final void Function(LongPressGestureRecognizer instance)? initializer; @@ -3776,3 +3811,49 @@ class ScaleDetector extends StatelessWidget { ); } } + +class DecorationClipper extends CustomClipper { + const DecorationClipper({ + this.textDirection = TextDirection.ltr, + required this.decoration, + }); + + final TextDirection textDirection; + final Decoration decoration; + + @override + Path getClip(Size size) { + return decoration.getClipPath(Offset.zero & size, textDirection); + } + + @override + bool shouldReclip(DecorationClipper oldClipper) { + return oldClipper.decoration != decoration || oldClipper.textDirection != textDirection; + } +} + +class BorderRadiusClip extends StatelessWidget { + final TextDirection textDirection; + final BorderRadius borderRadius; + final Widget child; + + const BorderRadiusClip({ + super.key, + this.textDirection = TextDirection.ltr, + required this.borderRadius, + required this.child, + }); + + @override + Widget build(BuildContext context) { + return ClipPath( + clipper: DecorationClipper( + textDirection: textDirection, + decoration: BoxDecoration( + borderRadius: borderRadius, + ), + ), + child: child, + ); + } +} diff --git a/lib/ui/widgets/inner_drawer.dart b/lib/ui/widgets/inner_drawer.dart index 452a14cd..3124bd1b 100644 --- a/lib/ui/widgets/inner_drawer.dart +++ b/lib/ui/widgets/inner_drawer.dart @@ -79,6 +79,15 @@ class NamidaInnerDrawerState extends State with SingleTickerP @override Widget build(BuildContext context) { + const scaffoldShadows = [ + BoxShadow( + color: Color(0x20202020), + blurRadius: 4.0, + spreadRadius: 2.0, + offset: Offset(-2.0, 0), + ), + ]; + return AnimatedBuilderMulti( animation: controller, children: [ @@ -95,7 +104,7 @@ class NamidaInnerDrawerState extends State with SingleTickerP child: IgnorePointer( ignoring: controller.value == controller.lowerBound, child: ColoredBox( - color: Colors.black.withOpacity(controller.value), + color: Colors.black.withOpacity(controller.value * 1.2), ), ), ), @@ -132,7 +141,7 @@ class NamidaInnerDrawerState extends State with SingleTickerP Positioned.fill( child: IgnorePointer( child: ColoredBox( - color: Colors.black.withOpacity(controller.upperBound - controller.value), + color: Colors.black.withOpacity((controller.upperBound - controller.value) * 1.8), ), ), ), @@ -142,11 +151,25 @@ class NamidaInnerDrawerState extends State with SingleTickerP Transform.translate( offset: Offset(context.width * controller.value, 0), child: widget.borderRadius > 0 - ? ClipRRect( - borderRadius: BorderRadius.circular(widget.borderRadius * controller.value), - child: child, + ? DecoratedBox( + decoration: const BoxDecoration( + boxShadow: scaffoldShadows, + ), + child: ClipPath( + clipper: DecorationClipper( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(widget.borderRadius * controller.value), + ), + ), + child: child, + ), ) - : child, + : DecoratedBox( + decoration: const BoxDecoration( + boxShadow: scaffoldShadows, + ), + child: child, + ), ), ], ); diff --git a/lib/ui/widgets/settings/backup_restore_settings.dart b/lib/ui/widgets/settings/backup_restore_settings.dart index ab52975f..1891cfc4 100644 --- a/lib/ui/widgets/settings/backup_restore_settings.dart +++ b/lib/ui/widgets/settings/backup_restore_settings.dart @@ -551,7 +551,7 @@ class BackupAndRestore extends SettingSubpageProvider { title: lang.IMPORT_YOUTUBE_HISTORY, leading: StackedIcon( baseIcon: Broken.import_2, - smallChild: ClipRRect( + smallChild: BorderRadiusClip( borderRadius: BorderRadius.circular(12.0.multipliedRadius), child: Image.asset( 'assets/icons/youtube.png', @@ -707,7 +707,7 @@ class BackupAndRestore extends SettingSubpageProvider { title: lang.IMPORT_LAST_FM_HISTORY, leading: StackedIcon( baseIcon: Broken.import_2, - smallChild: ClipRRect( + smallChild: BorderRadiusClip( borderRadius: BorderRadius.circular(12.0.multipliedRadius), child: Image.asset( 'assets/icons/lastfm.png', diff --git a/lib/ui/widgets/settings/customization_settings.dart b/lib/ui/widgets/settings/customization_settings.dart index 3bb98a2e..a74a7554 100644 --- a/lib/ui/widgets/settings/customization_settings.dart +++ b/lib/ui/widgets/settings/customization_settings.dart @@ -797,7 +797,7 @@ class CustomizationSettings extends SettingSubpageProvider { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - GestureDetector( + DoubleTapDetector( onDoubleTap: () { settings.save(didSupportNamida: true); }, diff --git a/lib/ui/widgets/video_widget.dart b/lib/ui/widgets/video_widget.dart index b7c19683..8ab08b07 100644 --- a/lib/ui/widgets/video_widget.dart +++ b/lib/ui/widgets/video_widget.dart @@ -440,11 +440,6 @@ class NamidaVideoControlsState extends State with TickerPro bool _isDraggingSeekBar = false; - bool get _showLoadingIndicator { - final isLoading = Player.inst.isBuffering || Player.inst.isLoading; - return isLoading && !Player.inst.isPlaying; - } - RxDouble get _currentBrigthnessDim => VideoController.inst.currentBrigthnessDim; Widget _getVerticalSliderWidget(String key, double? perc, IconData icon, ui.FlutterView view) { @@ -813,7 +808,7 @@ class NamidaVideoControlsState extends State with TickerPro ], child: Padding( padding: const EdgeInsets.all(4.0), - child: ClipRRect( + child: BorderRadiusClip( borderRadius: BorderRadius.circular(6.0.multipliedRadius), child: NamidaBgBlur( blur: 3.0, @@ -895,7 +890,7 @@ class NamidaVideoControlsState extends State with TickerPro ], child: Padding( padding: const EdgeInsets.all(4.0), - child: ClipRRect( + child: BorderRadiusClip( borderRadius: BorderRadius.circular(6.0.multipliedRadius), child: NamidaBgBlur( blur: 3.0, @@ -1051,7 +1046,7 @@ class NamidaVideoControlsState extends State with TickerPro ], child: Padding( padding: const EdgeInsets.all(4.0), - child: ClipRRect( + child: BorderRadiusClip( borderRadius: BorderRadius.circular(6.0.multipliedRadius), child: NamidaBgBlur( blur: 3.0, @@ -1157,7 +1152,7 @@ class NamidaVideoControlsState extends State with TickerPro ), Row( children: [ - ClipRRect( + BorderRadiusClip( borderRadius: borr8, child: NamidaBgBlur( blur: 3.0, @@ -1215,7 +1210,7 @@ class NamidaVideoControlsState extends State with TickerPro () { final queueL = (widget.isLocal ? Player.inst.currentQueue : Player.inst.currentQueueYoutube).length; if (queueL <= 1) return const SizedBox(); - return ClipRRect( + return BorderRadiusClip( borderRadius: borr8, child: NamidaBgBlur( blur: 3.0, @@ -1240,7 +1235,7 @@ class NamidaVideoControlsState extends State with TickerPro ], const Spacer(), const SizedBox(width: 4.0), - ClipRRect( + BorderRadiusClip( borderRadius: borr8, child: NamidaBgBlur( blur: 3.0, @@ -1357,15 +1352,6 @@ class NamidaVideoControlsState extends State with TickerPro color: Colors.black.withOpacity(0.3), child: Obx( () { - if (_showLoadingIndicator) { - return Padding( - padding: const EdgeInsets.all(14.0), - child: ThreeArchedCircle( - color: itemsColor, - size: 40.0, - ), - ); - } final currentPosition = Player.inst.nowPlayingPosition; final currentTotalDur = Player.inst.currentItemDuration?.inMilliseconds ?? 0; final reachedLastPosition = currentPosition != 0 && (currentPosition - currentTotalDur).abs() < 100; // 100ms allowance @@ -1465,10 +1451,10 @@ class NamidaVideoControlsState extends State with TickerPro ), ), Obx( - () => _showLoadingIndicator + () => Player.inst.isBuffering || Player.inst.isLoading ? ThreeArchedCircle( color: itemsColor, - size: 40.0, + size: 52.0, ) : const SizedBox(), ),