From a8330ef2e1112012bbae19ee6a5c27a26c5fb719 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Thu, 24 Nov 2022 12:12:55 +0600 Subject: [PATCH] fix(mobile): SafeArea bugs and back button color --- lib/components/Home/Genres.dart | 3 +- lib/components/Library/UserLibrary.dart | 38 +- lib/components/Player/PlayerOverlay.dart | 6 +- lib/components/Search/Search.dart | 527 +++++++++--------- .../Shared/TrackCollectionView.dart | 9 +- lib/main.dart | 16 +- 6 files changed, 305 insertions(+), 294 deletions(-) diff --git a/lib/components/Home/Genres.dart b/lib/components/Home/Genres.dart index 0b0677f08..e555aa764 100644 --- a/lib/components/Home/Genres.dart +++ b/lib/components/Home/Genres.dart @@ -11,6 +11,7 @@ import 'package:spotube/components/Shared/Waypoint.dart'; import 'package:spotube/provider/SpotifyDI.dart'; import 'package:spotube/provider/SpotifyRequests.dart'; import 'package:spotube/provider/UserPreferences.dart'; +import 'package:spotube/utils/platform.dart'; class Genres extends HookConsumerWidget { const Genres({Key? key}) : super(key: key); @@ -43,7 +44,7 @@ class Genres extends HookConsumerWidget { ]; return PlatformScaffold( - appBar: PageWindowTitleBar(), + appBar: kIsDesktop ? PageWindowTitleBar() : null, body: ListView.builder( itemCount: categories.length, itemBuilder: (context, index) { diff --git a/lib/components/Library/UserLibrary.dart b/lib/components/Library/UserLibrary.dart index 2a5bffa5c..e426b00eb 100644 --- a/lib/components/Library/UserLibrary.dart +++ b/lib/components/Library/UserLibrary.dart @@ -23,26 +23,28 @@ class UserLibrary extends HookConsumerWidget { const UserAlbums(), ][index.value]; - return PlatformScaffold( - appBar: PageWindowTitleBar( - titleWidth: 347, - centerTitle: true, - center: PlatformTabBar( - androidIsScrollable: true, - selectedIndex: index.value, - onSelectedIndexChanged: (value) => index.value = value, - isNavigational: - PlatformProperty.byPlatformGroup(mobile: false, desktop: true), - tabs: [ - PlatformTab(label: 'Playlists', icon: const SizedBox.shrink()), - PlatformTab(label: 'Tracks', icon: const SizedBox.shrink()), - PlatformTab(label: 'Downloads', icon: const SizedBox.shrink()), - PlatformTab(label: 'Artists', icon: const SizedBox.shrink()), - PlatformTab(label: 'Albums', icon: const SizedBox.shrink()), - ], + return SafeArea( + child: PlatformScaffold( + appBar: PageWindowTitleBar( + titleWidth: 347, + centerTitle: true, + center: PlatformTabBar( + androidIsScrollable: true, + selectedIndex: index.value, + onSelectedIndexChanged: (value) => index.value = value, + isNavigational: + PlatformProperty.byPlatformGroup(mobile: false, desktop: true), + tabs: [ + PlatformTab(label: 'Playlists', icon: const SizedBox.shrink()), + PlatformTab(label: 'Tracks', icon: const SizedBox.shrink()), + PlatformTab(label: 'Downloads', icon: const SizedBox.shrink()), + PlatformTab(label: 'Artists', icon: const SizedBox.shrink()), + PlatformTab(label: 'Albums', icon: const SizedBox.shrink()), + ], + ), ), + body: body, ), - body: body, ); } } diff --git a/lib/components/Player/PlayerOverlay.dart b/lib/components/Player/PlayerOverlay.dart index aaa3d67f5..a7726f688 100644 --- a/lib/components/Player/PlayerOverlay.dart +++ b/lib/components/Player/PlayerOverlay.dart @@ -81,7 +81,7 @@ class PlayerOverlay extends HookConsumerWidget { ), Row( children: [ - PlatformIconButton( + IconButton( icon: Icon( Icons.skip_previous_rounded, color: paletteColor.bodyTextColor, @@ -91,7 +91,7 @@ class PlayerOverlay extends HookConsumerWidget { }), Consumer( builder: (context, ref, _) { - return PlatformIconButton( + return IconButton( icon: Icon( ref.read(playbackProvider).isPlaying ? Icons.pause_rounded @@ -105,7 +105,7 @@ class PlayerOverlay extends HookConsumerWidget { ); }, ), - PlatformIconButton( + IconButton( icon: Icon( Icons.skip_next_rounded, color: paletteColor.bodyTextColor, diff --git a/lib/components/Search/Search.dart b/lib/components/Search/Search.dart index e5e12db27..b25847508 100644 --- a/lib/components/Search/Search.dart +++ b/lib/components/Search/Search.dart @@ -73,292 +73,299 @@ class Search extends HookConsumerWidget { } } - return PlatformScaffold( - appBar: !kIsMacOS ? PageWindowTitleBar() : null, - body: auth.isAnonymous - ? const AnonymousFallback() - : Column( - children: [ - Container( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 10, + return SafeArea( + child: PlatformScaffold( + appBar: kIsDesktop && !kIsMacOS ? PageWindowTitleBar() : null, + body: auth.isAnonymous + ? const AnonymousFallback() + : Column( + children: [ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 10, + ), + child: PlatformTextField( + onChanged: (value) { + ref.read(searchTermStateProvider.notifier).state = + value; + }, + prefixIcon: Icons.search_rounded, + prefixIconColor: PlatformProperty.only( + ios: + PlatformTheme.of(context).textTheme?.caption?.color, + other: null, + ).resolve(platform!), + placeholder: "Search...", + onSubmitted: (value) { + onSearch(); + }, + ), ), - child: PlatformTextField( - onChanged: (value) { - ref.read(searchTermStateProvider.notifier).state = value; - }, - prefixIcon: Icons.search_rounded, - prefixIconColor: PlatformProperty.only( - ios: PlatformTheme.of(context).textTheme?.caption?.color, - other: null, - ).resolve(platform!), - placeholder: "Search...", - onSubmitted: (value) { - onSearch(); - }, - ), - ), - HookBuilder( - builder: (context) { - Playback playback = ref.watch(playbackProvider); - List albums = []; - List artists = []; - List tracks = []; - List playlists = []; - final pages = [ - ...searchTrack.pages, - ...searchAlbum.pages, - ...searchPlaylist.pages, - ...searchArtist.pages, - ].expand((page) => page ?? []).toList(); - for (MapEntry page in pages.asMap().entries) { - for (var item in page.value.items ?? []) { - if (item is AlbumSimple) { - albums.add(item); - } else if (item is PlaylistSimple) { - playlists.add(item); - } else if (item is Artist) { - artists.add(item); - } else if (item is Track) { - tracks.add(item); + HookBuilder( + builder: (context) { + Playback playback = ref.watch(playbackProvider); + List albums = []; + List artists = []; + List tracks = []; + List playlists = []; + final pages = [ + ...searchTrack.pages, + ...searchAlbum.pages, + ...searchPlaylist.pages, + ...searchArtist.pages, + ].expand((page) => page ?? []).toList(); + for (MapEntry page in pages.asMap().entries) { + for (var item in page.value.items ?? []) { + if (item is AlbumSimple) { + albums.add(item); + } else if (item is PlaylistSimple) { + playlists.add(item); + } else if (item is Artist) { + artists.add(item); + } else if (item is Track) { + tracks.add(item); + } } } - } - return Expanded( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, - horizontal: 20, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (tracks.isNotEmpty) - PlatformText.headline("Songs"), - if (searchTrack.isLoading && - !searchTrack.isFetchingNextPage) - const PlatformCircularProgressIndicator() - else if (searchTrack.hasError) - PlatformText(searchTrack - .error?[searchTrack.pageParams.last]) - else - ...tracks.asMap().entries.map((track) { - String duration = - "${track.value.duration?.inMinutes.remainder(60)}:${PrimitiveUtils.zeroPadNumStr(track.value.duration?.inSeconds.remainder(60) ?? 0)}"; - return TrackTile( - playback, - track: track, - duration: duration, - isActive: - playback.track?.id == track.value.id, - onTrackPlayButtonPressed: - (currentTrack) async { - var isPlaylistPlaying = - playback.playlist?.id != null && - playback.playlist?.id == - currentTrack.id; - if (!isPlaylistPlaying) { - playback.playPlaylist( - CurrentPlaylist( - tracks: [currentTrack], - id: currentTrack.id!, - name: currentTrack.name!, - thumbnail: TypeConversionUtils - .image_X_UrlString( - currentTrack.album?.images, - placeholder: - ImagePlaceholder.albumArt, + return Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 20, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (tracks.isNotEmpty) + PlatformText.headline("Songs"), + if (searchTrack.isLoading && + !searchTrack.isFetchingNextPage) + const PlatformCircularProgressIndicator() + else if (searchTrack.hasError) + PlatformText(searchTrack + .error?[searchTrack.pageParams.last]) + else + ...tracks.asMap().entries.map((track) { + String duration = + "${track.value.duration?.inMinutes.remainder(60)}:${PrimitiveUtils.zeroPadNumStr(track.value.duration?.inSeconds.remainder(60) ?? 0)}"; + return TrackTile( + playback, + track: track, + duration: duration, + isActive: + playback.track?.id == track.value.id, + onTrackPlayButtonPressed: + (currentTrack) async { + var isPlaylistPlaying = + playback.playlist?.id != null && + playback.playlist?.id == + currentTrack.id; + if (!isPlaylistPlaying) { + playback.playPlaylist( + CurrentPlaylist( + tracks: [currentTrack], + id: currentTrack.id!, + name: currentTrack.name!, + thumbnail: TypeConversionUtils + .image_X_UrlString( + currentTrack.album?.images, + placeholder: + ImagePlaceholder.albumArt, + ), ), - ), - ); - } else if (isPlaylistPlaying && - currentTrack.id != null && - currentTrack.id != - playback.track?.id) { - playback.play(currentTrack); - } - }, - ); - }), - if (searchTrack.hasNextPage && tracks.isNotEmpty) - Center( - child: PlatformTextButton( - onPressed: searchTrack.isFetchingNextPage - ? null - : () => searchTrack.fetchNextPage(), - child: searchTrack.isFetchingNextPage - ? const PlatformCircularProgressIndicator() - : const PlatformText("Load more"), - ), - ), - if (playlists.isNotEmpty) - PlatformText.headline("Playlists"), - const SizedBox(height: 10), - if (searchPlaylist.isLoading && - !searchPlaylist.isFetchingNextPage) - const PlatformCircularProgressIndicator() - else if (searchPlaylist.hasError) - PlatformText(searchPlaylist - .error?[searchPlaylist.pageParams.last]) - else - ScrollConfiguration( - behavior: - ScrollConfiguration.of(context).copyWith( - dragDevices: { - PointerDeviceKind.touch, - PointerDeviceKind.mouse, - }, + ); + } else if (isPlaylistPlaying && + currentTrack.id != null && + currentTrack.id != + playback.track?.id) { + playback.play(currentTrack); + } + }, + ); + }), + if (searchTrack.hasNextPage && + tracks.isNotEmpty) + Center( + child: PlatformTextButton( + onPressed: searchTrack.isFetchingNextPage + ? null + : () => searchTrack.fetchNextPage(), + child: searchTrack.isFetchingNextPage + ? const PlatformCircularProgressIndicator() + : const PlatformText("Load more"), + ), ), - child: Scrollbar( - scrollbarOrientation: - breakpoint > Breakpoints.md - ? ScrollbarOrientation.bottom - : ScrollbarOrientation.top, - controller: playlistController, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, + if (playlists.isNotEmpty) + PlatformText.headline("Playlists"), + const SizedBox(height: 10), + if (searchPlaylist.isLoading && + !searchPlaylist.isFetchingNextPage) + const PlatformCircularProgressIndicator() + else if (searchPlaylist.hasError) + PlatformText(searchPlaylist + .error?[searchPlaylist.pageParams.last]) + else + ScrollConfiguration( + behavior: ScrollConfiguration.of(context) + .copyWith( + dragDevices: { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + }, + ), + child: Scrollbar( + scrollbarOrientation: + breakpoint > Breakpoints.md + ? ScrollbarOrientation.bottom + : ScrollbarOrientation.top, controller: playlistController, - child: Row( - children: [ - ...playlists.mapIndexed( - (i, playlist) { - if (i == playlists.length - 1 && - searchPlaylist.hasNextPage) { - return Waypoint( - onEnter: () { + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + controller: playlistController, + child: Row( + children: [ + ...playlists.mapIndexed( + (i, playlist) { + if (i == playlists.length - 1 && searchPlaylist - .fetchNextPage(); - }, - child: - const ShimmerPlaybuttonCard( - count: 1), + .hasNextPage) { + return Waypoint( + onEnter: () { + searchPlaylist + .fetchNextPage(); + }, + child: + const ShimmerPlaybuttonCard( + count: 1), + ); + } + return PlaylistCard(playlist); + }, + ), + ], + ), + ), + ), + ), + const SizedBox(height: 20), + if (artists.isNotEmpty) + PlatformText.headline("Artists"), + const SizedBox(height: 10), + if (searchArtist.isLoading && + !searchArtist.isFetchingNextPage) + const PlatformCircularProgressIndicator() + else if (searchArtist.hasError) + PlatformText(searchArtist + .error?[searchArtist.pageParams.last]) + else + ScrollConfiguration( + behavior: ScrollConfiguration.of(context) + .copyWith( + dragDevices: { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + }, + ), + child: Scrollbar( + controller: artistController, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + controller: artistController, + child: Row( + children: [ + ...artists.mapIndexed( + (i, artist) { + if (i == artists.length - 1 && + searchArtist.hasNextPage) { + return Waypoint( + onEnter: () { + searchArtist + .fetchNextPage(); + }, + child: + const ShimmerPlaybuttonCard( + count: 1), + ); + } + return Container( + margin: const EdgeInsets + .symmetric( + horizontal: 15), + child: ArtistCard(artist), ); - } - return PlaylistCard(playlist); - }, - ), - ], + }, + ), + ], + ), ), ), ), - ), - const SizedBox(height: 20), - if (artists.isNotEmpty) - PlatformText.headline("Artists"), - const SizedBox(height: 10), - if (searchArtist.isLoading && - !searchArtist.isFetchingNextPage) - const PlatformCircularProgressIndicator() - else if (searchArtist.hasError) - PlatformText(searchArtist - .error?[searchArtist.pageParams.last]) - else - ScrollConfiguration( - behavior: - ScrollConfiguration.of(context).copyWith( - dragDevices: { - PointerDeviceKind.touch, - PointerDeviceKind.mouse, - }, + const SizedBox(height: 20), + if (albums.isNotEmpty) + PlatformText( + "Albums", + style: + Theme.of(context).textTheme.headline5, ), - child: Scrollbar( - controller: artistController, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - controller: artistController, - child: Row( - children: [ - ...artists.mapIndexed( - (i, artist) { - if (i == artists.length - 1 && - searchArtist.hasNextPage) { + const SizedBox(height: 10), + if (searchAlbum.isLoading && + !searchAlbum.isFetchingNextPage) + const PlatformCircularProgressIndicator() + else if (searchAlbum.hasError) + PlatformText(searchAlbum + .error?[searchAlbum.pageParams.last]) + else + ScrollConfiguration( + behavior: ScrollConfiguration.of(context) + .copyWith( + dragDevices: { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + }, + ), + child: Scrollbar( + controller: albumController, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + controller: albumController, + child: Row( + children: [ + ...albums.mapIndexed((i, album) { + if (i == albums.length - 1 && + searchAlbum.hasNextPage) { return Waypoint( onEnter: () { - searchArtist - .fetchNextPage(); + searchAlbum.fetchNextPage(); }, child: const ShimmerPlaybuttonCard( count: 1), ); } - return Container( - margin: - const EdgeInsets.symmetric( - horizontal: 15), - child: ArtistCard(artist), + return AlbumCard( + TypeConversionUtils + .simpleAlbum_X_Album( + album, + ), ); - }, - ), - ], + }), + ], + ), ), ), ), - ), - const SizedBox(height: 20), - if (albums.isNotEmpty) - PlatformText( - "Albums", - style: Theme.of(context).textTheme.headline5, - ), - const SizedBox(height: 10), - if (searchAlbum.isLoading && - !searchAlbum.isFetchingNextPage) - const PlatformCircularProgressIndicator() - else if (searchAlbum.hasError) - PlatformText(searchAlbum - .error?[searchAlbum.pageParams.last]) - else - ScrollConfiguration( - behavior: - ScrollConfiguration.of(context).copyWith( - dragDevices: { - PointerDeviceKind.touch, - PointerDeviceKind.mouse, - }, - ), - child: Scrollbar( - controller: albumController, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - controller: albumController, - child: Row( - children: [ - ...albums.mapIndexed((i, album) { - if (i == albums.length - 1 && - searchAlbum.hasNextPage) { - return Waypoint( - onEnter: () { - searchAlbum.fetchNextPage(); - }, - child: - const ShimmerPlaybuttonCard( - count: 1), - ); - } - return AlbumCard( - TypeConversionUtils - .simpleAlbum_X_Album( - album, - ), - ); - }), - ], - ), - ), - ), - ), - ], + ], + ), ), ), - ), - ); - }, - ) - ], - ), + ); + }, + ) + ], + ), + ), ); } } diff --git a/lib/components/Shared/TrackCollectionView.dart b/lib/components/Shared/TrackCollectionView.dart index c4bbb6082..d10253726 100644 --- a/lib/components/Shared/TrackCollectionView.dart +++ b/lib/components/Shared/TrackCollectionView.dart @@ -114,11 +114,7 @@ class TrackCollectionView extends HookConsumerWidget { ? PageWindowTitleBar( backgroundColor: color?.color, foregroundColor: color?.titleTextColor, - leading: Row( - children: [ - PlatformBackButton(color: color?.titleTextColor) - ], - ), + leading: PlatformBackButton(color: color?.titleTextColor), ) : null, body: CustomScrollView( @@ -130,6 +126,9 @@ class TrackCollectionView extends HookConsumerWidget { pinned: true, expandedHeight: 400, automaticallyImplyLeading: kIsMobile, + leading: kIsMobile + ? PlatformBackButton(color: color?.titleTextColor) + : null, iconTheme: IconThemeData(color: color?.titleTextColor), primary: true, backgroundColor: color?.color, diff --git a/lib/main.dart b/lib/main.dart index 9a421cd9b..aa1e687d1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -235,13 +235,15 @@ class SpotubeState extends ConsumerState with WidgetsBindingObserver { macosTheme: macosTheme, macosDarkTheme: macosDarkTheme, themeMode: themeMode, - windowButtonConfig: PlatformWindowButtonConfig( - isMaximized: () => appWindow.isMaximized, - onClose: appWindow.close, - onRestore: appWindow.restore, - onMaximize: appWindow.maximize, - onMinimize: appWindow.minimize, - ), + windowButtonConfig: kIsDesktop + ? PlatformWindowButtonConfig( + isMaximized: () => appWindow.isMaximized, + onClose: appWindow.close, + onRestore: appWindow.restore, + onMaximize: appWindow.maximize, + onMinimize: appWindow.minimize, + ) + : null, shortcuts: PlatformProperty.all({ ...WidgetsApp.defaultShortcuts.map((key, value) { return MapEntry(