From f5d0709ff98cb9bb1766a2eb336078afa98be325 Mon Sep 17 00:00:00 2001 From: Feichtmeier Date: Sun, 1 Dec 2024 18:57:25 +0100 Subject: [PATCH] feat: rework the bottom bar for mobile --- lib/app/app_model.dart | 4 +- lib/app/view/app.dart | 3 +- lib/app/view/desktop_scaffold.dart | 2 +- lib/app/view/master_detail_page.dart | 3 +- lib/app/view/master_items.dart | 4 +- lib/app/view/mobile_bottom_bar.dart | 88 ++++-------------- lib/app/view/mobile_musicpod_app.dart | 29 +++--- lib/app/view/mobile_navigation_bar.dart | 89 +++++++++++++++++++ ...page_with_player.dart => mobile_page.dart} | 17 ++-- lib/app/view/splash_screen.dart | 52 ++++------- lib/app_config.dart | 2 +- lib/common/data/audio.dart | 6 +- lib/common/view/audio_card_vignette.dart | 10 ++- lib/common/view/audio_tile.dart | 12 +-- lib/common/view/audio_tile_option_button.dart | 3 +- lib/common/view/header_bar.dart | 10 +-- lib/common/view/icons.dart | 8 +- lib/common/view/search_input.dart | 3 +- lib/common/view/sliver_audio_page.dart | 8 +- lib/common/view/theme.dart | 45 +++++----- lib/external_path/external_path_service.dart | 4 +- lib/library/library_model.dart | 5 +- lib/local_audio/view/album_view.dart | 6 +- lib/local_audio/view/artist_page.dart | 10 ++- lib/local_audio/view/genre_page.dart | 6 +- lib/local_audio/view/local_audio_page.dart | 5 +- lib/main.dart | 2 +- lib/player/player_model.dart | 11 +++ lib/player/view/bottom_player.dart | 33 +++---- lib/player/view/full_height_player.dart | 13 +-- lib/player/view/full_height_player_image.dart | 4 +- .../view/full_height_player_top_controls.dart | 7 +- lib/player/view/player_main_controls.dart | 5 +- .../view/player_pause_timer_button.dart | 3 +- lib/playlists/view/playlist_page.dart | 2 + lib/podcasts/view/podcast_audio_tile.dart | 4 +- lib/podcasts/view/podcast_page.dart | 12 +-- lib/radio/view/radio_history_tile_image.dart | 4 +- lib/radio/view/station_page.dart | 5 +- lib/search/view/search_page.dart | 8 +- lib/settings/view/about_page.dart | 4 +- lib/settings/view/about_section.dart | 4 +- lib/settings/view/licenses_page.dart | 4 +- lib/settings/view/settings_action.dart | 4 +- lib/settings/view/settings_page.dart | 3 +- pubspec.yaml | 1 + 46 files changed, 320 insertions(+), 247 deletions(-) create mode 100644 lib/app/view/mobile_navigation_bar.dart rename lib/app/view/{mobile_page_with_player.dart => mobile_page.dart} (70%) diff --git a/lib/app/app_model.dart b/lib/app/app_model.dart index 8850167fb..9bd695bc8 100644 --- a/lib/app/app_model.dart +++ b/lib/app/app_model.dart @@ -3,8 +3,8 @@ import 'package:flutter/widgets.dart'; import 'package:github/github.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:safe_change_notifier/safe_change_notifier.dart'; -import 'package:yaru/theme.dart'; +import '../app_config.dart'; import '../constants.dart'; import '../expose/expose_service.dart'; import '../settings/settings_service.dart'; @@ -67,7 +67,7 @@ class AppModel extends SafeChangeNotifier { if (value == null || value == _fullWindowMode) return; _fullWindowMode = value; - if (isMobile) { + if (isMobilePlatform) { if (_fullWindowMode == true) { await SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); } else { diff --git a/lib/app/view/app.dart b/lib/app/view/app.dart index fdadfc110..1b72ded00 100644 --- a/lib/app/view/app.dart +++ b/lib/app/view/app.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:system_theme/system_theme.dart'; import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../common/view/theme.dart'; import 'desktop_musicpod_app.dart'; import 'mobile_musicpod_app.dart'; @@ -28,7 +29,7 @@ class MaterialMusicPodApp extends StatelessWidget { @override Widget build(BuildContext context) => SystemThemeBuilder( builder: (context, accent) { - return isMobile + return isMobilePlatform ? MobileMusicPodApp(accent: accent.accent) : DesktopMusicPodApp(accent: accent.accent); }, diff --git a/lib/app/view/desktop_scaffold.dart b/lib/app/view/desktop_scaffold.dart index 278ce416a..cd61c5d53 100644 --- a/lib/app/view/desktop_scaffold.dart +++ b/lib/app/view/desktop_scaffold.dart @@ -73,7 +73,7 @@ class _DesktopScaffoldState extends State { child: Column( children: [ const Expanded(child: MasterDetailPage()), - if (!playerToTheRight || isMobile) + if (!playerToTheRight || isMobilePlatform) const PlayerView(position: PlayerPosition.bottom), ], ), diff --git a/lib/app/view/master_detail_page.dart b/lib/app/view/master_detail_page.dart index b633991df..66dcb8947 100644 --- a/lib/app/view/master_detail_page.dart +++ b/lib/app/view/master_detail_page.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../common/view/back_gesture.dart'; import '../../common/view/global_keys.dart'; import '../../common/view/header_bar.dart'; @@ -49,7 +50,7 @@ class MasterDetailPage extends StatelessWidget with WatchItMixin { ); return Scaffold( - resizeToAvoidBottomInset: isMobile ? false : null, + resizeToAvoidBottomInset: isMobilePlatform ? false : null, key: masterScaffoldKey, endDrawer: Platform.isMacOS ? drawer : null, drawer: Platform.isMacOS ? null : drawer, diff --git a/lib/app/view/master_items.dart b/lib/app/view/master_items.dart index 900cf691f..f8963f325 100644 --- a/lib/app/view/master_items.dart +++ b/lib/app/view/master_items.dart @@ -1,7 +1,7 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; -import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../common/data/audio_type.dart'; import '../../common/view/icons.dart'; import '../../common/view/side_bar_fall_back_image.dart'; @@ -75,7 +75,7 @@ List createMasterItems({required LibraryModel libraryModel}) { ), pageId: kPodcastsPageId, ), - if (isMobile) + if (isMobilePlatform) MasterItem( titleBuilder: (context) => Text(context.l10n.settings), iconBuilder: (selected) => diff --git a/lib/app/view/mobile_bottom_bar.dart b/lib/app/view/mobile_bottom_bar.dart index 9afdeabb6..8cb8573a5 100644 --- a/lib/app/view/mobile_bottom_bar.dart +++ b/lib/app/view/mobile_bottom_bar.dart @@ -1,27 +1,17 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import '../../common/data/audio_type.dart'; -import '../../common/view/icons.dart'; -import '../../common/view/theme.dart'; -import '../../common/view/ui_constants.dart'; -import '../../constants.dart'; import '../../extensions/build_context_x.dart'; -import '../../l10n/l10n.dart'; -import '../../library/library_model.dart'; +import '../../player/player_model.dart'; import '../../player/view/bottom_player.dart'; import '../app_model.dart'; -import 'main_page_icon.dart'; +import 'mobile_navigation_bar.dart'; class MobileBottomBar extends StatelessWidget with WatchItMixin { - const MobileBottomBar({ - super.key, - }); + const MobileBottomBar({super.key}); @override Widget build(BuildContext context) { - final fullWindowMode = - watchPropertyValue((AppModel m) => m.fullWindowMode) ?? false; return SizedBox( width: context.mediaQuerySize.width, child: RepaintBoundary( @@ -30,9 +20,20 @@ class MobileBottomBar extends StatelessWidget with WatchItMixin { child: Column( mainAxisSize: MainAxisSize.min, children: [ - SizedBox(height: bottomPlayerHeight, child: const BottomPlayer()), - const SizedBox(height: kMediumSpace), - if (!fullWindowMode) const MobileNavigationBar(), + GestureDetector( + onVerticalDragUpdate: (details) { + di().bottomPlayerHeight = + context.mediaQuerySize.height - details.globalPosition.dy; + }, + onVerticalDragEnd: (details) { + if (details.primaryVelocity != null && + details.primaryVelocity! < 150) { + di().setFullWindowMode(true); + } + }, + child: const BottomPlayer(), + ), + const MobileNavigationBar(), ], ), ), @@ -40,58 +41,3 @@ class MobileBottomBar extends StatelessWidget with WatchItMixin { ); } } - -class MobileNavigationBar extends StatelessWidget with WatchItMixin { - const MobileNavigationBar({super.key}); - - @override - Widget build(BuildContext context) { - final l10n = context.l10n; - - final selectedPageId = - watchPropertyValue((LibraryModel m) => m.selectedPageId); - - final destinations = { - kLocalAudioPageId: IconButton( - isSelected: selectedPageId == kLocalAudioPageId, - selectedIcon: - const MainPageIcon(selected: true, audioType: AudioType.local), - icon: const MainPageIcon(selected: false, audioType: AudioType.local), - tooltip: l10n.local, - onPressed: () => di().push(pageId: kLocalAudioPageId), - ), - kRadioPageId: IconButton( - isSelected: selectedPageId == kRadioPageId, - selectedIcon: - const MainPageIcon(selected: true, audioType: AudioType.radio), - icon: const MainPageIcon(selected: false, audioType: AudioType.radio), - tooltip: l10n.radio, - onPressed: () => di().push(pageId: kRadioPageId), - ), - kPodcastsPageId: IconButton( - isSelected: selectedPageId == kPodcastsPageId, - selectedIcon: - const MainPageIcon(selected: true, audioType: AudioType.podcast), - icon: const MainPageIcon(selected: false, audioType: AudioType.podcast), - tooltip: l10n.podcasts, - onPressed: () => di().push(pageId: kPodcastsPageId), - ), - kSettingsPageId: IconButton( - isSelected: selectedPageId == kSettingsPageId, - selectedIcon: Icon(Iconz.settingsFilled), - icon: Icon(Iconz.settings), - tooltip: l10n.settings, - onPressed: () => di().push(pageId: kSettingsPageId), - ), - }; - - return SizedBox( - height: navigationBarHeight, - width: context.mediaQuerySize.width, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: destinations.values.toList(), - ), - ); - } -} diff --git a/lib/app/view/mobile_musicpod_app.dart b/lib/app/view/mobile_musicpod_app.dart index 2ec26b5be..a25333116 100644 --- a/lib/app/view/mobile_musicpod_app.dart +++ b/lib/app/view/mobile_musicpod_app.dart @@ -1,3 +1,11 @@ +import 'dart:ui'; + +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:phoenix_theme/phoenix_theme.dart'; +import 'package:watch_it/watch_it.dart'; + +import '../../app_config.dart'; import '../../common/view/theme.dart'; import '../../constants.dart'; import '../../external_path/external_path_service.dart'; @@ -6,14 +14,8 @@ import '../../library/library_model.dart'; import '../../radio/radio_model.dart'; import '../../settings/settings_model.dart'; import '../connectivity_model.dart'; -import 'dart:ui'; import 'master_items.dart'; -import 'mobile_page_with_player.dart'; -import 'package:collection/collection.dart'; -import 'package:flutter/material.dart'; -import 'package:phoenix_theme/phoenix_theme.dart'; -import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; +import 'mobile_page.dart'; import 'splash_screen.dart'; class MobileMusicPodApp extends StatefulWidget with WatchItStatefulWidgetMixin { @@ -54,8 +56,9 @@ class _MobileMusicPodAppState extends State { return MaterialApp( navigatorKey: libraryModel.masterNavigatorKey, navigatorObservers: [libraryModel], - initialRoute: - isMobile ? (libraryModel.selectedPageId ?? kLocalAudioPageId) : null, + initialRoute: isMobilePlatform + ? (libraryModel.selectedPageId ?? kLocalAudioPageId) + : null, onGenerateRoute: (settings) { final page = (masterItems.firstWhereOrNull( (e) => e.pageId == settings.name, @@ -67,11 +70,9 @@ class _MobileMusicPodAppState extends State { settings: settings, pageBuilder: (_, __, ___) => FutureBuilder( future: _initFuture, - builder: (context, snapshot) { - return snapshot.data == true - ? MobilePageWithPlayer(page: page) - : const SplashScreen(); - }, + builder: (context, snapshot) => snapshot.data == true + ? MobilePage(page: page) + : const SplashScreen(), ), transitionsBuilder: (_, a, __, c) => FadeTransition(opacity: a, child: c), diff --git a/lib/app/view/mobile_navigation_bar.dart b/lib/app/view/mobile_navigation_bar.dart new file mode 100644 index 000000000..8f1b1a266 --- /dev/null +++ b/lib/app/view/mobile_navigation_bar.dart @@ -0,0 +1,89 @@ +import '../../common/data/audio_type.dart'; +import '../../common/view/icons.dart'; +import '../../common/view/theme.dart'; +import '../../common/view/ui_constants.dart'; +import '../../constants.dart'; +import '../../l10n/l10n.dart'; +import '../../library/library_model.dart'; +import 'main_page_icon.dart'; +import 'package:flutter/material.dart'; +import 'package:watch_it/watch_it.dart'; + +class MobileNavigationBar extends StatelessWidget with WatchItMixin { + const MobileNavigationBar({super.key}); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + + final selectedPageId = + watchPropertyValue((LibraryModel m) => m.selectedPageId); + + return SizedBox( + height: navigationBarHeight, + child: Padding( + padding: const EdgeInsets.only(top: kMediumSpace), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + IconButton( + isSelected: selectedPageId == kLikedAudiosPageId, + selectedIcon: Icon(Iconz.heartFilled), + icon: Icon(Iconz.heart), + tooltip: l10n.local, + onPressed: () => + di().push(pageId: kLikedAudiosPageId), + ), + IconButton( + isSelected: selectedPageId == kLocalAudioPageId, + selectedIcon: const MainPageIcon( + selected: true, + audioType: AudioType.local, + ), + icon: const MainPageIcon( + selected: false, + audioType: AudioType.local, + ), + tooltip: l10n.local, + onPressed: () => + di().push(pageId: kLocalAudioPageId), + ), + IconButton( + isSelected: selectedPageId == kRadioPageId, + selectedIcon: const MainPageIcon( + selected: true, + audioType: AudioType.radio, + ), + icon: const MainPageIcon( + selected: false, + audioType: AudioType.radio, + ), + tooltip: l10n.radio, + onPressed: () => di().push(pageId: kRadioPageId), + ), + IconButton( + isSelected: selectedPageId == kPodcastsPageId, + selectedIcon: const MainPageIcon( + selected: true, + audioType: AudioType.podcast, + ), + icon: const MainPageIcon( + selected: false, + audioType: AudioType.podcast, + ), + tooltip: l10n.podcasts, + onPressed: () => di().push(pageId: kPodcastsPageId), + ), + IconButton( + isSelected: selectedPageId == kSettingsPageId, + selectedIcon: Icon(Iconz.settingsFilled), + icon: Icon(Iconz.settings), + tooltip: l10n.settings, + onPressed: () => di().push(pageId: kSettingsPageId), + ), + ], + ), + ), + ); + } +} diff --git a/lib/app/view/mobile_page_with_player.dart b/lib/app/view/mobile_page.dart similarity index 70% rename from lib/app/view/mobile_page_with_player.dart rename to lib/app/view/mobile_page.dart index 2c287b8ab..ba4782c0f 100644 --- a/lib/app/view/mobile_page_with_player.dart +++ b/lib/app/view/mobile_page.dart @@ -7,8 +7,8 @@ import '../../player/view/player_view.dart'; import '../app_model.dart'; import 'mobile_bottom_bar.dart'; -class MobilePageWithPlayer extends StatelessWidget with WatchItMixin { - const MobilePageWithPlayer({ +class MobilePage extends StatelessWidget with WatchItMixin { + const MobilePage({ super.key, required this.page, }); @@ -27,11 +27,14 @@ class MobilePageWithPlayer extends StatelessWidget with WatchItMixin { children: [ page, if (fullWindowMode) - const Scaffold( - extendBody: true, - extendBodyBehindAppBar: true, - body: FullHeightPlayer( - playerPosition: PlayerPosition.fullWindow, + const Hero( + tag: 'full_height_player', + child: Scaffold( + extendBody: true, + extendBodyBehindAppBar: true, + body: FullHeightPlayer( + playerPosition: PlayerPosition.fullWindow, + ), ), ) else diff --git a/lib/app/view/splash_screen.dart b/lib/app/view/splash_screen.dart index 0e0bae71e..5350892f2 100644 --- a/lib/app/view/splash_screen.dart +++ b/lib/app/view/splash_screen.dart @@ -1,47 +1,33 @@ import 'package:flutter/material.dart'; import '../../common/view/header_bar.dart'; -import '../../common/view/icons.dart'; import '../../common/view/progress.dart'; -import '../../extensions/build_context_x.dart'; class SplashScreen extends StatelessWidget { - const SplashScreen({ - super.key, - }); + const SplashScreen({super.key}); @override - Widget build(BuildContext context) { - return Scaffold( - appBar: const HeaderBar(adaptive: false, title: Text('')), - body: Center( - child: SingleChildScrollView( - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 250, - height: 250, - decoration: BoxDecoration( - color: context.colorScheme.primary, - borderRadius: BorderRadius.circular(30), + Widget build(BuildContext context) => Scaffold( + appBar: const HeaderBar(adaptive: false, title: Text('')), + body: Center( + child: SingleChildScrollView( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Image.asset( + 'assets/icon.png', + height: 250, + width: 250, ), - child: Icon( - Iconz.musicNote, - size: 150, - color: Colors.white, + const Padding( + padding: EdgeInsets.all(20), + child: Progress(), ), - ), - const Padding( - padding: EdgeInsets.all(20), - child: Progress(), - ), - ], + ], + ), ), ), ), - ), - ); - } + ); } diff --git a/lib/app_config.dart b/lib/app_config.dart index de7b23ce9..5fe6a7631 100644 --- a/lib/app_config.dart +++ b/lib/app_config.dart @@ -18,5 +18,5 @@ bool get allowVideoFullScreen => !Platform.isLinux; bool get isGtkApp => Platform.isLinux; -bool get useSystemBackGestures => +bool get isMobilePlatform => Platform.isAndroid || Platform.isIOS || Platform.isFuchsia; diff --git a/lib/common/data/audio.dart b/lib/common/data/audio.dart index 395ce5ab1..87a5fd4e5 100644 --- a/lib/common/data/audio.dart +++ b/lib/common/data/audio.dart @@ -365,13 +365,13 @@ class Audio { final artistName = artist; final id = albumName == null && artistName == null ? null - : _isMobile + : _isMobilePlatform ? '${artistName ?? ''}_${albumName ?? ''}' : '${artistName ?? ''}:${albumName ?? ''}'; - return _isMobile ? id?.replaceAll(' ', '_') : id; + return _isMobilePlatform ? id?.replaceAll(' ', '_') : id; } - bool get _isMobile => + bool get _isMobilePlatform => Platform.isAndroid || Platform.isIOS || Platform.isFuchsia; bool get hasPathAndId => diff --git a/lib/common/view/audio_card_vignette.dart b/lib/common/view/audio_card_vignette.dart index 48ced15e7..8c8cc75bf 100644 --- a/lib/common/view/audio_card_vignette.dart +++ b/lib/common/view/audio_card_vignette.dart @@ -1,7 +1,9 @@ -import '../../extensions/build_context_x.dart'; -import '../../l10n/l10n.dart'; import 'package:flutter/material.dart'; import 'package:yaru/yaru.dart'; + +import '../../app_config.dart'; +import '../../extensions/build_context_x.dart'; +import '../../l10n/l10n.dart'; import 'theme.dart'; class AudioCardVignette extends StatelessWidget { @@ -31,8 +33,8 @@ class AudioCardVignette extends StatelessWidget { color: colorScheme.inverseSurface, borderRadius: borderRadius, ), - width: audioCardDimension / (isMobile ? 3 : 4), - height: audioCardDimension / (isMobile ? 3 : 4), + width: audioCardDimension / (isMobilePlatform ? 3 : 4), + height: audioCardDimension / (isMobilePlatform ? 3 : 4), child: Icon( iconData, color: colorScheme.onInverseSurface, diff --git a/lib/common/view/audio_tile.dart b/lib/common/view/audio_tile.dart index 09fc8a1fb..0bbbb4ce7 100644 --- a/lib/common/view/audio_tile.dart +++ b/lib/common/view/audio_tile.dart @@ -1,8 +1,7 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; -import 'ui_constants.dart'; +import '../../app_config.dart'; import '../../extensions/build_context_x.dart'; import '../../extensions/duration_x.dart'; import '../../extensions/theme_data_x.dart'; @@ -17,6 +16,7 @@ import 'audio_tile_option_button.dart'; import 'like_icon.dart'; import 'tapable_text.dart'; import 'theme.dart'; +import 'ui_constants.dart'; class AudioTile extends StatefulWidget with WatchItStatefulWidgetMixin { const AudioTile({ @@ -149,13 +149,13 @@ class _AudioTileState extends State { pageId: widget.pageId, audioPageType: widget.audioPageType, selectedColor: selectedColor, - showDuration: !isMobile, - showLikeIcon: !isMobile, - alwaysShowOptionButton: isMobile, + showDuration: !isMobilePlatform, + showLikeIcon: !isMobilePlatform, + alwaysShowOptionButton: isMobilePlatform, ), ); - if (isMobile) return listTile; + if (isMobilePlatform) return listTile; return MouseRegion( key: ObjectKey(widget.audio), diff --git a/lib/common/view/audio_tile_option_button.dart b/lib/common/view/audio_tile_option_button.dart index b72ea6351..04df90e17 100644 --- a/lib/common/view/audio_tile_option_button.dart +++ b/lib/common/view/audio_tile_option_button.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../constants.dart'; import '../../extensions/build_context_x.dart'; import '../../l10n/l10n.dart'; @@ -46,7 +47,7 @@ class AudioTileOptionButton extends StatelessWidget { final l10n = context.l10n; final libraryModel = di(); - if (isMobile) { + if (isMobilePlatform) { return AudioTileBottomSheetButton( audios: audios, allowRemove: allowRemove, diff --git a/lib/common/view/header_bar.dart b/lib/common/view/header_bar.dart index 96217323c..b8105873e 100644 --- a/lib/common/view/header_bar.dart +++ b/lib/common/view/header_bar.dart @@ -44,8 +44,8 @@ class HeaderBar extends StatelessWidget @override Widget build(BuildContext context) { - final useSidebarButton = isMobile ? false : includeSidebarButton; - final useBackButton = isMobile ? true : includeBackButton; + final useSidebarButton = isMobilePlatform ? false : includeSidebarButton; + final useBackButton = isMobilePlatform ? true : includeBackButton; final canPop = watchPropertyValue((LibraryModel m) => m.canPop); Widget? leading; @@ -58,7 +58,7 @@ class HeaderBar extends StatelessWidget if (useBackButton && canPop) { leading = const NavBackButton(); } else { - leading = isMobile + leading = isMobilePlatform ? const SizedBox( width: 60, ) @@ -66,7 +66,7 @@ class HeaderBar extends StatelessWidget } } - if (isMobile) { + if (isMobilePlatform) { final fullWindowMode = watchPropertyValue((AppModel m) => m.fullWindowMode) == true; return AppBar( @@ -121,7 +121,7 @@ class HeaderBar extends StatelessWidget @override Size get preferredSize => Size( 0, - isMobile + isMobilePlatform ? (style == YaruTitleBarStyle.hidden ? 0 : kYaruTitleBarHeight) : kToolbarHeight, ); diff --git a/lib/common/view/icons.dart b/lib/common/view/icons.dart index b627e21d0..21ed659ae 100644 --- a/lib/common/view/icons.dart +++ b/lib/common/view/icons.dart @@ -130,28 +130,28 @@ class Iconz { static IconData get localAudio { if (appleStyled) { - if (isMobile) { + if (isMobilePlatform) { return CupertinoIcons.device_phone_portrait; } return CupertinoIcons.device_laptop; } return yaruStyled ? YaruIcons.drive_harddisk - : isMobile + : isMobilePlatform ? Icons.phone_android_outlined : Icons.computer_rounded; } static IconData get localAudioFilled { if (appleStyled) { - if (isMobile) { + if (isMobilePlatform) { return CupertinoIcons.device_phone_portrait; } return CupertinoIcons.device_laptop; } return yaruStyled ? YaruIcons.drive_harddisk_filled - : isMobile + : isMobilePlatform ? Icons.phone_android_rounded : Icons.computer_rounded; } diff --git a/lib/common/view/search_input.dart b/lib/common/view/search_input.dart index 0d929796c..011013ec4 100644 --- a/lib/common/view/search_input.dart +++ b/lib/common/view/search_input.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:yaru/yaru.dart'; import '../../app_config.dart'; import '../../extensions/build_context_x.dart'; @@ -60,7 +59,7 @@ class _SearchInputState extends State { Widget build(BuildContext context) { final theme = context.theme; return SizedBox( - height: yaruStyled || isMobile ? null : 38, + height: yaruStyled || isMobilePlatform ? null : 38, child: TextField( onTap: () { _controller.selection = TextSelection( diff --git a/lib/common/view/sliver_audio_page.dart b/lib/common/view/sliver_audio_page.dart index bab1e72d5..cd417cdcf 100644 --- a/lib/common/view/sliver_audio_page.dart +++ b/lib/common/view/sliver_audio_page.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../constants.dart'; import '../../library/library_model.dart'; import '../../search/search_model.dart'; @@ -84,7 +84,7 @@ class SliverAudioPage extends StatelessWidget { builder: (context, constraints) { final padding = getAdaptiveHorizontalPadding( constraints: constraints, - min: isMobile ? 5 : 15, + min: isMobilePlatform ? 5 : 15, ); if (audios == null) { @@ -133,7 +133,9 @@ class SliverAudioPage extends StatelessWidget { ) else SliverPadding( - padding: padding, + padding: padding.copyWith( + bottom: sliverPageBottomPadding, + ), sliver: SliverAudioTileList( audioPageType: audioPageType, audios: audios!, diff --git a/lib/common/view/theme.dart b/lib/common/view/theme.dart index 8607c60ab..f43c77b71 100644 --- a/lib/common/view/theme.dart +++ b/lib/common/view/theme.dart @@ -107,7 +107,7 @@ Color getAlphabetColor(String text, [Color fallBackColor = Colors.black]) { } double get searchBarWidth => - isMobile ? kMobileSearchBarWidth : kDesktopSearchBarWidth; + isMobilePlatform ? kMobileSearchBarWidth : kDesktopSearchBarWidth; InputDecoration createMaterialDecoration({ required ColorScheme colorScheme, @@ -125,7 +125,7 @@ InputDecoration createMaterialDecoration({ OutlineInputBorder( borderRadius: BorderRadius.circular(100), borderSide: BorderSide( - width: isMobile ? 2 : 1, + width: isMobilePlatform ? 2 : 1, color: colorScheme.outline, ), ); @@ -133,12 +133,12 @@ InputDecoration createMaterialDecoration({ prefixIcon: prefixIcon, suffixIcon: suffixIcon, suffixIconConstraints: BoxConstraints( - maxHeight: isMobile ? kToolbarHeight : kYaruTitleBarItemHeight, + maxHeight: isMobilePlatform ? kToolbarHeight : kYaruTitleBarItemHeight, ), hintText: hintText, fillColor: fillColor, filled: filled, - contentPadding: isMobile + contentPadding: isMobilePlatform ? const EdgeInsets.only(top: 16, bottom: 0, left: 15, right: 15) : contentPadding ?? const EdgeInsets.only(top: 10, bottom: 10, left: 15, right: 15), @@ -148,15 +148,15 @@ InputDecoration createMaterialDecoration({ focusedBorder: outlineInputBorder.copyWith( borderSide: BorderSide( color: colorScheme.primary, - width: isMobile ? 2 : 1, + width: isMobilePlatform ? 2 : 1, ), ), disabledBorder: outlineInputBorder, focusedErrorBorder: outlineInputBorder, - helperStyle: isMobile ? null : style, - hintStyle: isMobile ? null : style, - labelStyle: isMobile ? null : style, - isDense: isMobile ? false : isDense, + helperStyle: isMobilePlatform ? null : style, + hintStyle: isMobilePlatform ? null : style, + labelStyle: isMobilePlatform ? null : style, + isDense: isMobilePlatform ? false : isDense, ); } @@ -208,7 +208,7 @@ InputDecoration createYaruDecoration({ double get iconSize => yaruStyled ? kYaruIconSize - : isMobile + : isMobilePlatform ? 24.0 : kLargestSpace; @@ -221,19 +221,19 @@ double get progressStrokeWidth => 3.0; double get smallAvatarButtonRadius => (yaruStyled ? kYaruTitleBarItemHeight - : isMobile + : isMobilePlatform ? 42 : 38) / 2; double get bigAvatarButtonRadius => yaruStyled ? 22 - : isMobile + : isMobilePlatform ? 26 : 23; EdgeInsets get filterPanelPadding => - EdgeInsets.only(top: isMobile ? 10 : 0, bottom: 10); + EdgeInsets.only(top: isMobilePlatform ? 10 : 0, bottom: 10); EdgeInsets get bigPlayButtonPadding => EdgeInsets.symmetric(horizontal: yaruStyled ? 2.5 : 5); @@ -247,16 +247,16 @@ FontWeight get mediumTextWeight => FontWeight get largeTextWeight => yaruStyled ? FontWeight.w200 : FontWeight.w300; -double get chipHeight => isMobile ? 40 : 34.0; +double get chipHeight => isMobilePlatform ? 40 : 34.0; EdgeInsets get audioTilePadding => kAudioTilePadding; SliverGridDelegate get audioCardGridDelegate => - isMobile ? kMobileAudioCardGridDelegate : kAudioCardGridDelegate; + isMobilePlatform ? kMobileAudioCardGridDelegate : kAudioCardGridDelegate; EdgeInsets get appBarSingleActionSpacing => Platform.isMacOS ? const EdgeInsets.only(right: 5, left: 5) - : EdgeInsets.only(right: 10, left: isMobile ? 0 : kLargestSpace); + : EdgeInsets.only(right: 10, left: isMobilePlatform ? 0 : kLargestSpace); EdgeInsetsGeometry get radioHistoryListPadding => EdgeInsets.only(left: yaruStyled ? 0 : 5); @@ -273,17 +273,22 @@ EdgeInsets get countryPillPadding => yaruStyled ) : const EdgeInsets.only(top: 11, bottom: 11, left: 15, right: 15); -double get inputHeight => isMobile +double get inputHeight => isMobilePlatform ? 40 : yaruStyled ? kYaruTitleBarItemHeight : 36; -double get audioCardDimension => kAudioCardDimension - (isMobile ? 15 : 0); +double get audioCardDimension => + kAudioCardDimension - (isMobilePlatform ? 15 : 0); -double get bottomPlayerHeight => isMobile ? 76.0 : 90.0; +double get bottomPlayerDefaultHeight => isMobilePlatform ? 76.0 : 90.0; -double get navigationBarHeight => bottomPlayerHeight - 25; +double get navigationBarHeight => bottomPlayerDefaultHeight - 25; + +double? get sliverPageBottomPadding => isMobilePlatform + ? bottomPlayerDefaultHeight + navigationBarHeight + kLargestSpace + : null; NavigationBarThemeData navigationBarTheme({required ThemeData theme}) => theme.navigationBarTheme.copyWith( diff --git a/lib/external_path/external_path_service.dart b/lib/external_path/external_path_service.dart index 6ef451c53..11952f950 100644 --- a/lib/external_path/external_path_service.dart +++ b/lib/external_path/external_path_service.dart @@ -8,8 +8,8 @@ import 'package:gtk/gtk.dart'; import 'package:m3u_parser_nullsafe/m3u_parser_nullsafe.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:pls/pls.dart'; -import 'package:yaru/yaru.dart'; +import '../app_config.dart'; import '../common/data/audio.dart'; import '../common/data/audio_type.dart'; import '../common/logging.dart'; @@ -170,7 +170,7 @@ class ExternalPathService { } Future getPathOfDirectory() async { - if (isMobile && await _androidPermissionsGranted()) { + if (isMobilePlatform && await _androidPermissionsGranted()) { return FilePicker.platform.getDirectoryPath(); } diff --git a/lib/library/library_model.dart b/lib/library/library_model.dart index fde7ffaae..618c79f14 100644 --- a/lib/library/library_model.dart +++ b/lib/library/library_model.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:safe_change_notifier/safe_change_notifier.dart'; +import '../app/view/mobile_page.dart'; import '../app_config.dart'; import '../common/data/audio.dart'; import '../common/logging.dart'; @@ -201,8 +202,8 @@ class LibraryModel extends SafeChangeNotifier implements NavigatorObserver { } } else if (builder != null) { final materialPageRoute = MaterialPageRoute( - builder: (context) => useSystemBackGestures - ? builder(context) + builder: (context) => isMobilePlatform + ? MobilePage(page: builder(context)) : BackGesture(child: builder(context)), maintainState: maintainState, settings: RouteSettings( diff --git a/lib/local_audio/view/album_view.dart b/lib/local_audio/view/album_view.dart index f2131e2ce..9cabf814b 100644 --- a/lib/local_audio/view/album_view.dart +++ b/lib/local_audio/view/album_view.dart @@ -1,8 +1,8 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../common/view/audio_card.dart'; import '../../common/view/audio_card_bottom.dart'; import '../../common/view/audio_card_vignette.dart'; @@ -116,8 +116,8 @@ class AlbumCard extends StatelessWidget { ), if (pinned) Positioned( - left: isMobile ? 6 : 5, - bottom: kAudioCardBottomHeight + (isMobile ? 25 : 13), + left: isMobilePlatform ? 6 : 5, + bottom: kAudioCardBottomHeight + (isMobilePlatform ? 25 : 13), child: AudioCardVignette( iconData: Iconz.pinFilled, onTap: id == null diff --git a/lib/local_audio/view/artist_page.dart b/lib/local_audio/view/artist_page.dart index d2758f58b..63b352805 100644 --- a/lib/local_audio/view/artist_page.dart +++ b/lib/local_audio/view/artist_page.dart @@ -122,7 +122,10 @@ class ArtistPage extends StatelessWidget with WatchItMixin { if (useGridView) SliverPadding( padding: - getAdaptiveHorizontalPadding(constraints: constraints), + getAdaptiveHorizontalPadding(constraints: constraints) + .copyWith( + bottom: sliverPageBottomPadding, + ), sliver: AlbumsView( albums: albums, ), @@ -130,7 +133,10 @@ class ArtistPage extends StatelessWidget with WatchItMixin { else SliverPadding( padding: - getAdaptiveHorizontalPadding(constraints: constraints), + getAdaptiveHorizontalPadding(constraints: constraints) + .copyWith( + bottom: sliverPageBottomPadding, + ), sliver: SliverAudioTileList( audios: artistAudios!, pageId: pageId, diff --git a/lib/local_audio/view/genre_page.dart b/lib/local_audio/view/genre_page.dart index 4f20c066b..700a08fae 100644 --- a/lib/local_audio/view/genre_page.dart +++ b/lib/local_audio/view/genre_page.dart @@ -6,6 +6,7 @@ import '../../common/data/audio_type.dart'; import '../../common/view/adaptive_container.dart'; import '../../common/view/header_bar.dart'; import '../../common/view/icons.dart'; +import '../../common/view/theme.dart'; import '../../constants.dart'; import '../../l10n/l10n.dart'; import '../../library/library_model.dart'; @@ -77,7 +78,10 @@ class _GenrePageState extends State { return CustomScrollView( slivers: [ SliverPadding( - padding: getAdaptiveHorizontalPadding(constraints: constraints), + padding: getAdaptiveHorizontalPadding(constraints: constraints) + .copyWith( + bottom: sliverPageBottomPadding, + ), sliver: ArtistsView( artists: artistAudiosWithGenre, ), diff --git a/lib/local_audio/view/local_audio_page.dart b/lib/local_audio/view/local_audio_page.dart index c974e6fef..0932d238b 100644 --- a/lib/local_audio/view/local_audio_page.dart +++ b/lib/local_audio/view/local_audio_page.dart @@ -92,7 +92,10 @@ class _LocalAudioPageState extends State { title: const LocalAudioControlPanel(), ), SliverPadding( - padding: getAdaptiveHorizontalPadding(constraints: constraints), + padding: getAdaptiveHorizontalPadding(constraints: constraints) + .copyWith( + bottom: sliverPageBottomPadding, + ), sliver: LocalAudioBody( localAudioView: localAudioView, titles: audios, diff --git a/lib/main.dart b/lib/main.dart index 120a1c176..bb53b278e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,7 +10,7 @@ import 'app_config.dart'; import 'register.dart'; Future main(List args) async { - if (isMobile) { + if (isMobilePlatform) { WidgetsFlutterBinding.ensureInitialized(); } else { // Note: this includes the `WidgetsFlutterBinding.ensureInitialized()` call diff --git a/lib/player/player_model.dart b/lib/player/player_model.dart index 8065e0351..9b34ba2ce 100644 --- a/lib/player/player_model.dart +++ b/lib/player/player_model.dart @@ -5,6 +5,7 @@ import 'package:safe_change_notifier/safe_change_notifier.dart'; import '../common/data/audio.dart'; import '../common/data/mpv_meta_data.dart'; +import '../common/view/theme.dart'; import '../radio/online_art_service.dart'; import 'player_service.dart'; @@ -152,6 +153,16 @@ class PlayerModel extends SafeChangeNotifier { void setTimer(Duration duration) => _playerService.setPauseTimer(duration); + double _bottomPlayerHeight = bottomPlayerDefaultHeight; + double get bottomPlayerHeight => _bottomPlayerHeight; + set bottomPlayerHeight(double value) { + if (value == _bottomPlayerHeight || value < bottomPlayerDefaultHeight) { + return; + } + _bottomPlayerHeight = value; + notifyListeners(); + } + @override Future dispose() async { await _propertiesChangedSub?.cancel(); diff --git a/lib/player/view/bottom_player.dart b/lib/player/view/bottom_player.dart index e060386b5..c80cdcb76 100644 --- a/lib/player/view/bottom_player.dart +++ b/lib/player/view/bottom_player.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; import '../../app/app_model.dart'; import '../../app/connectivity_model.dart'; +import '../../app_config.dart'; import '../../common/data/audio_type.dart'; import '../../common/view/icons.dart'; import '../../common/view/like_icon.dart'; @@ -61,7 +61,7 @@ class BottomPlayer extends StatelessWidget with WatchItMixin { borderRadius: BorderRadius.circular(4), child: BottomPlayerImage( audio: audio, - size: bottomPlayerHeight - 24, + size: bottomPlayerDefaultHeight - 24, videoController: model.controller, isVideo: isVideo, isOnline: isOnline, @@ -106,7 +106,7 @@ class BottomPlayer extends StatelessWidget with WatchItMixin { children: [ if (audio?.audioType == AudioType.podcast) PlaybackRateButton(active: active), - if (!isMobile) const VolumeSliderPopup(), + if (!isMobilePlatform) const VolumeSliderPopup(), if (showQueueButton) const QueueButton(), IconButton( tooltip: context.l10n.fullWindow, @@ -129,34 +129,27 @@ class BottomPlayer extends StatelessWidget with WatchItMixin { ), ), ]; + final player = SizedBox( - height: bottomPlayerHeight, + height: watchPropertyValue((PlayerModel m) => m.bottomPlayerHeight), child: Column( - children: (isMobile ? children.reversed : children).toList(), + children: (isMobilePlatform ? children.reversed : children).toList(), ), ); - if (isMobile) { - return GestureDetector( - onVerticalDragEnd: (details) { - if (details.primaryVelocity != null && - details.primaryVelocity! < 150) { - appModel.setFullWindowMode(true); - } - }, - child: player, - ); - } - if (isVideo == true) { return player; } return Stack( children: [ - BlurredFullHeightPlayerImage( - size: Size(context.mediaQuerySize.width, bottomPlayerHeight), - ), + if (!isMobilePlatform) + BlurredFullHeightPlayerImage( + size: Size( + context.mediaQuerySize.width, + watchPropertyValue((PlayerModel m) => m.bottomPlayerHeight), + ), + ), player, ], ); diff --git a/lib/player/view/full_height_player.dart b/lib/player/view/full_height_player.dart index 5777f3e8e..07ffb6afe 100644 --- a/lib/player/view/full_height_player.dart +++ b/lib/player/view/full_height_player.dart @@ -1,11 +1,12 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; import '../../app/app_model.dart'; import '../../app/connectivity_model.dart'; +import '../../app_config.dart'; import '../../common/data/audio_type.dart'; import '../../common/view/header_bar.dart'; +import '../../common/view/theme.dart'; import '../../common/view/ui_constants.dart'; import '../../extensions/build_context_x.dart'; import '../../player/player_model.dart'; @@ -13,9 +14,9 @@ import '../../radio/view/radio_history_list.dart'; import 'blurred_full_height_player_image.dart'; import 'full_height_player_image.dart'; import 'full_height_player_top_controls.dart'; -import 'player_title_and_artist.dart'; import 'full_height_video_player.dart'; import 'player_main_controls.dart'; +import 'player_title_and_artist.dart'; import 'player_track.dart'; import 'player_view.dart'; import 'queue_button.dart'; @@ -53,7 +54,8 @@ class FullHeightPlayer extends StatelessWidget with WatchItMixin { mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ - if (!isMobile || context.isPortrait) const FullHeightPlayerImage(), + if (!isMobilePlatform || context.isPortrait) + const FullHeightPlayerImage(), const SizedBox( height: kLargestSpace, ), @@ -112,13 +114,14 @@ class FullHeightPlayer extends StatelessWidget with WatchItMixin { ); } - final body = isMobile + final body = isMobilePlatform ? GestureDetector( onVerticalDragEnd: (details) { if (details.primaryVelocity != null && details.primaryVelocity! > 150) { appModel.setFullWindowMode(false); } + di().bottomPlayerHeight = bottomPlayerDefaultHeight; }, child: Padding( padding: const EdgeInsets.only(top: 40), @@ -148,7 +151,7 @@ class FullHeightPlayer extends StatelessWidget with WatchItMixin { ) : Column( children: [ - if (!isMobile) headerBar, + if (!isMobilePlatform) headerBar, Expanded( child: body, ), diff --git a/lib/player/view/full_height_player_image.dart b/lib/player/view/full_height_player_image.dart index 3386c37f4..fb092a363 100644 --- a/lib/player/view/full_height_player_image.dart +++ b/lib/player/view/full_height_player_image.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../common/view/ui_constants.dart'; import '../../extensions/build_context_x.dart'; import '../../local_audio/view/local_cover.dart'; @@ -30,7 +30,7 @@ class FullHeightPlayerImage extends StatelessWidget with WatchItMixin { final size = context.isPortrait ? fullHeightPlayerImageSize - : isMobile + : isMobilePlatform ? fullHeightPlayerImageSize / 3 : fullHeightPlayerImageSize; final theHeight = height ?? size; diff --git a/lib/player/view/full_height_player_top_controls.dart b/lib/player/view/full_height_player_top_controls.dart index 93c818b30..391d373a6 100644 --- a/lib/player/view/full_height_player_top_controls.dart +++ b/lib/player/view/full_height_player_top_controls.dart @@ -2,15 +2,16 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/theme.dart'; import '../../app/app_model.dart'; import '../../app/connectivity_model.dart'; +import '../../app_config.dart'; import '../../common/data/audio_type.dart'; import '../../common/view/icons.dart'; import '../../common/view/like_icon.dart'; import '../../common/view/share_button.dart'; import '../../common/view/snackbars.dart'; +import '../../common/view/theme.dart'; import '../../common/view/ui_constants.dart'; import '../../extensions/build_context_x.dart'; import '../../l10n/l10n.dart'; @@ -91,7 +92,7 @@ class FullHeightPlayerTopControls extends StatelessWidget with WatchItMixin { active: active, color: iconColor, ), - if (!isMobile) VolumeSliderPopup(color: iconColor), + if (!isMobilePlatform) VolumeSliderPopup(color: iconColor), IconButton( tooltip: playerPosition == PlayerPosition.fullWindow ? context.l10n.leaveFullWindow @@ -107,6 +108,8 @@ class FullHeightPlayerTopControls extends StatelessWidget with WatchItMixin { playerPosition == PlayerPosition.fullWindow ? false : true, ); + di().bottomPlayerHeight = bottomPlayerDefaultHeight; + appModel.setShowWindowControls( (fullScreen == true && playerToTheRight) ? false : true, ); diff --git a/lib/player/view/player_main_controls.dart b/lib/player/view/player_main_controls.dart index 082cd2881..48274d614 100644 --- a/lib/player/view/player_main_controls.dart +++ b/lib/player/view/player_main_controls.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; import '../../app/connectivity_model.dart'; +import '../../app_config.dart'; import '../../common/data/audio_type.dart'; import '../../common/view/icons.dart'; import '../../common/view/theme.dart'; @@ -49,7 +49,8 @@ class PlayerMainControls extends StatelessWidget with WatchItMixin { active: active, ); - final radius = isMobile ? bigAvatarButtonRadius : smallAvatarButtonRadius; + final radius = + isMobilePlatform ? bigAvatarButtonRadius : smallAvatarButtonRadius; final playButton = avatarPlayButton ? CircleAvatar( radius: radius, diff --git a/lib/player/view/player_pause_timer_button.dart b/lib/player/view/player_pause_timer_button.dart index 02e087b15..6e8450421 100644 --- a/lib/player/view/player_pause_timer_button.dart +++ b/lib/player/view/player_pause_timer_button.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../common/view/common_widgets.dart'; import '../../common/view/icons.dart'; import '../../common/view/modals.dart'; @@ -22,7 +23,7 @@ class PlayerPauseTimerButton extends StatelessWidget { onPressed: () => showModal( context: context, mode: ModalMode.platformModalMode, - content: isMobile ? const _BottomSheet() : const _Dialog(), + content: isMobilePlatform ? const _BottomSheet() : const _Dialog(), ), icon: Icon(Iconz.sleep), ); diff --git a/lib/playlists/view/playlist_page.dart b/lib/playlists/view/playlist_page.dart index 1edce80f5..3fffd6002 100644 --- a/lib/playlists/view/playlist_page.dart +++ b/lib/playlists/view/playlist_page.dart @@ -268,6 +268,8 @@ class _PlaylistPageBody extends StatelessWidget with WatchItMixin { padding: getAdaptiveHorizontalPadding( constraints: constraints, min: 40, + ).copyWith( + bottom: sliverPageBottomPadding, ), sliver: SliverReorderableList( itemCount: audios.length, diff --git a/lib/podcasts/view/podcast_audio_tile.dart b/lib/podcasts/view/podcast_audio_tile.dart index cbe156e12..745d3bb37 100644 --- a/lib/podcasts/view/podcast_audio_tile.dart +++ b/lib/podcasts/view/podcast_audio_tile.dart @@ -76,7 +76,7 @@ class PodcastAudioTile extends StatelessWidget { startPlaylist: startPlaylist, removeUpdate: removeUpdate, ), - SizedBox(width: isMobile ? 15 : 25), + SizedBox(width: isMobilePlatform ? 15 : 25), Expanded( child: _Center( selected: selected, @@ -92,7 +92,7 @@ class PodcastAudioTile extends StatelessWidget { child: Align( alignment: Alignment.centerLeft, child: Padding( - padding: isMobile + padding: isMobilePlatform ? const EdgeInsets.symmetric(horizontal: 10) : EdgeInsets.only( left: (smallAvatarButtonRadius * 2) + 30, diff --git a/lib/podcasts/view/podcast_page.dart b/lib/podcasts/view/podcast_page.dart index 52ea994b4..61837f650 100644 --- a/lib/podcasts/view/podcast_page.dart +++ b/lib/podcasts/view/podcast_page.dart @@ -1,8 +1,8 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../common/data/audio.dart'; import '../../common/data/audio_type.dart'; import '../../common/view/adaptive_container.dart'; @@ -23,6 +23,7 @@ import '../../extensions/build_context_x.dart'; import '../../l10n/l10n.dart'; import '../../library/library_model.dart'; import '../../player/player_model.dart'; +import '../../player/view/player_pause_timer_button.dart'; import '../../search/search_model.dart'; import '../../search/search_type.dart'; import '../../settings/settings_model.dart'; @@ -31,7 +32,6 @@ import 'podcast_refresh_button.dart'; import 'podcast_reorder_button.dart'; import 'podcast_replay_button.dart'; import 'podcast_sub_button.dart'; -import '../../player/view/player_pause_timer_button.dart'; import 'sliver_podcast_page_list.dart'; class PodcastPage extends StatefulWidget with WatchItStatefulWidgetMixin { @@ -165,7 +165,7 @@ class _PodcastPageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: space( children: [ - if (!isMobile) + if (!isMobilePlatform) PodcastReplayButton(audios: episodesWithDownloads), const PlayerPauseTimerButton(), PodcastSubButton( @@ -178,7 +178,7 @@ class _PodcastPageState extends State { ), PodcastRefreshButton(pageId: widget.feedUrl), PodcastReorderButton(feedUrl: widget.feedUrl), - if (!isMobile) + if (!isMobilePlatform) AudioTileOptionButton( audios: episodesWithDownloads, playlistId: widget.feedUrl, @@ -196,9 +196,9 @@ class _PodcastPageState extends State { ), SliverPadding( padding: getAdaptiveHorizontalPadding( - min: isMobile ? 0 : 15, + min: isMobilePlatform ? 0 : 15, constraints: constraints, - ).copyWith(bottom: kLargestSpace), + ).copyWith(bottom: sliverPageBottomPadding ?? kLargestSpace), sliver: SliverPodcastPageList( audios: episodesWithDownloads, pageId: widget.feedUrl, diff --git a/lib/radio/view/radio_history_tile_image.dart b/lib/radio/view/radio_history_tile_image.dart index 7468c6850..2b7b46eaa 100644 --- a/lib/radio/view/radio_history_tile_image.dart +++ b/lib/radio/view/radio_history_tile_image.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../common/view/icons.dart'; import '../../common/view/modals.dart'; import '../../common/view/mpv_metadata_dialog.dart'; @@ -44,7 +44,7 @@ class RadioHistoryTileImage extends StatelessWidget with WatchItMixin { showModal( mode: ModalMode.platformModalMode, context: context, - content: isMobile + content: isMobilePlatform ? MpvMetadataDialog.bottomSheet( image: imageUrl, mpvMetaData: metadata, diff --git a/lib/radio/view/station_page.dart b/lib/radio/view/station_page.dart index e92991240..d0854ca7b 100644 --- a/lib/radio/view/station_page.dart +++ b/lib/radio/view/station_page.dart @@ -101,7 +101,10 @@ class StationPage extends StatelessWidget with WatchItMixin { ), ), SliverPadding( - padding: getAdaptiveHorizontalPadding(constraints: constraints), + padding: getAdaptiveHorizontalPadding(constraints: constraints) + .copyWith( + bottom: sliverPageBottomPadding, + ), sliver: SliverRadioHistoryList( filter: station.title, emptyMessage: const SizedBox.shrink(), diff --git a/lib/search/view/search_page.dart b/lib/search/view/search_page.dart index 5a5d2e76d..57d6a66f0 100644 --- a/lib/search/view/search_page.dart +++ b/lib/search/view/search_page.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/theme.dart'; import '../../app_config.dart'; import '../../common/data/audio_type.dart'; @@ -35,7 +34,7 @@ class SearchPage extends StatelessWidget with WatchItMixin { appBar: HeaderBar( adaptive: true, title: Padding( - padding: EdgeInsets.only(left: isMobile ? 5 : 0), + padding: EdgeInsets.only(left: isMobilePlatform ? 5 : 0), child: const SearchPageInput(), ), actions: [ @@ -95,7 +94,10 @@ class SearchPage extends StatelessWidget with WatchItMixin { ), SliverPadding( padding: - getAdaptiveHorizontalPadding(constraints: constraints), + getAdaptiveHorizontalPadding(constraints: constraints) + .copyWith( + bottom: sliverPageBottomPadding, + ), sliver: switch (audioType) { AudioType.radio => const SliverRadioSearchResults(), AudioType.podcast => const SliverPodcastSearchResults(), diff --git a/lib/settings/view/about_page.dart b/lib/settings/view/about_page.dart index 7d9951875..1e3fca0d1 100644 --- a/lib/settings/view/about_page.dart +++ b/lib/settings/view/about_page.dart @@ -5,7 +5,7 @@ import 'package:watch_it/watch_it.dart'; import 'package:yaru/yaru.dart'; import '../../app/app_model.dart'; - +import '../../app_config.dart'; import '../../common/view/header_bar.dart'; import '../../common/view/progress.dart'; import '../../common/view/safe_network_image.dart'; @@ -179,7 +179,7 @@ class _AboutPageState extends State { final title = Text('${context.l10n.about} $kAppTitle'); - if (isMobile) { + if (isMobilePlatform) { return Scaffold( appBar: HeaderBar( adaptive: false, diff --git a/lib/settings/view/about_section.dart b/lib/settings/view/about_section.dart index 9be5156c1..05989f866 100644 --- a/lib/settings/view/about_section.dart +++ b/lib/settings/view/about_section.dart @@ -100,7 +100,7 @@ class _AboutTileState extends State<_AboutTile> { ), ), trailing: OutlinedButton( - onPressed: () => isMobile + onPressed: () => isMobilePlatform ? di().push( pageId: 'about', builder: (p0) => const AboutPage(), @@ -122,7 +122,7 @@ class _LicenseTile extends StatelessWidget { text: '${context.l10n.license}: GPL3', ), trailing: OutlinedButton( - onPressed: () => isMobile + onPressed: () => isMobilePlatform ? di().push( pageId: 'licenses', builder: (p0) => const LicensePage(), diff --git a/lib/settings/view/licenses_page.dart b/lib/settings/view/licenses_page.dart index 2f5b2fe41..0e403b6e5 100644 --- a/lib/settings/view/licenses_page.dart +++ b/lib/settings/view/licenses_page.dart @@ -1,12 +1,14 @@ import 'package:flutter/material.dart'; import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; + class LicensesPage extends StatelessWidget { const LicensesPage({super.key}); @override Widget build(BuildContext context) { - if (isMobile) { + if (isMobilePlatform) { return const LicensePage(); } diff --git a/lib/settings/view/settings_action.dart b/lib/settings/view/settings_action.dart index b33ce8b33..1c24be348 100644 --- a/lib/settings/view/settings_action.dart +++ b/lib/settings/view/settings_action.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:watch_it/watch_it.dart'; -import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../common/view/common_widgets.dart'; import '../../common/view/icons.dart'; import '../../constants.dart'; @@ -33,7 +33,7 @@ class SettingsButton extends StatelessWidget { @override Widget build(BuildContext context) { - void onPressed() => isMobile + void onPressed() => isMobilePlatform ? di().push(pageId: kSettingsPageId) : showDialog( context: context, diff --git a/lib/settings/view/settings_page.dart b/lib/settings/view/settings_page.dart index e507cff2c..b88ad42dd 100644 --- a/lib/settings/view/settings_page.dart +++ b/lib/settings/view/settings_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:yaru/yaru.dart'; +import '../../app_config.dart'; import '../../common/view/header_bar.dart'; import '../../extensions/build_context_x.dart'; import '../../l10n/l10n.dart'; @@ -24,7 +25,7 @@ class SettingsPage extends StatelessWidget { AboutSection(), ], ); - if (isMobile) { + if (isMobilePlatform) { return Scaffold( appBar: HeaderBar( adaptive: false, diff --git a/pubspec.yaml b/pubspec.yaml index d1a1eb9fe..7710c7efe 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -113,6 +113,7 @@ flutter: - assets/images/media-optical.png - assets/images/tray_icon.ico - assets/images/tray_icon.png + - assets/icon.png - CHANGELOG.md dependency_overrides: