mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
Safearea fix for Home widgets
This commit is contained in:
parent
42257d9615
commit
e2bba4ac94
@ -94,82 +94,79 @@ class Home extends HookConsumerWidget {
|
||||
return null;
|
||||
}, [backgroundColor]);
|
||||
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
body: Column(
|
||||
children: [
|
||||
if (_selectedIndex.value != 3)
|
||||
kIsMobile
|
||||
? titleBarContents
|
||||
: WindowTitleBarBox(child: titleBarContents),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Sidebar(
|
||||
selectedIndex: _selectedIndex.value,
|
||||
onSelectedIndexChanged: _onSelectedIndexChanged,
|
||||
),
|
||||
// contents of the spotify
|
||||
if (_selectedIndex.value == 0)
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 8.0,
|
||||
top: 8.0,
|
||||
left: 8.0,
|
||||
),
|
||||
child: HookBuilder(builder: (context) {
|
||||
final pagingController = usePaginatedFutureProvider<
|
||||
Page<Category>, int, Category>(
|
||||
(pageKey) => categoriesQuery(pageKey),
|
||||
ref: ref,
|
||||
firstPageKey: 0,
|
||||
onData: (categories, pagingController, pageKey) {
|
||||
final items = categories.items?.toList();
|
||||
if (pageKey == 0) {
|
||||
Category category = Category();
|
||||
category.id = "user-featured-playlists";
|
||||
category.name = "Featured";
|
||||
items?.insert(0, category);
|
||||
}
|
||||
if (categories.isLast && items != null) {
|
||||
pagingController.appendLastPage(items);
|
||||
} else if (categories.items != null) {
|
||||
pagingController.appendPage(
|
||||
items!, categories.nextOffset);
|
||||
}
|
||||
},
|
||||
);
|
||||
return PagedListView(
|
||||
pagingController: pagingController,
|
||||
builderDelegate:
|
||||
PagedChildBuilderDelegate<Category>(
|
||||
firstPageProgressIndicatorBuilder: (_) =>
|
||||
const ShimmerCategories(),
|
||||
newPageProgressIndicatorBuilder: (_) =>
|
||||
const ShimmerCategories(),
|
||||
itemBuilder: (context, item, index) {
|
||||
return CategoryCard(item);
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
return Scaffold(
|
||||
body: Column(
|
||||
children: [
|
||||
if (_selectedIndex.value != 3)
|
||||
kIsMobile
|
||||
? titleBarContents
|
||||
: WindowTitleBarBox(child: titleBarContents),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Sidebar(
|
||||
selectedIndex: _selectedIndex.value,
|
||||
onSelectedIndexChanged: _onSelectedIndexChanged,
|
||||
),
|
||||
// contents of the spotify
|
||||
if (_selectedIndex.value == 0)
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 8.0,
|
||||
top: 8.0,
|
||||
left: 8.0,
|
||||
),
|
||||
child: HookBuilder(builder: (context) {
|
||||
final pagingController = usePaginatedFutureProvider<
|
||||
Page<Category>, int, Category>(
|
||||
(pageKey) => categoriesQuery(pageKey),
|
||||
ref: ref,
|
||||
firstPageKey: 0,
|
||||
onData: (categories, pagingController, pageKey) {
|
||||
final items = categories.items?.toList();
|
||||
if (pageKey == 0) {
|
||||
Category category = Category();
|
||||
category.id = "user-featured-playlists";
|
||||
category.name = "Featured";
|
||||
items?.insert(0, category);
|
||||
}
|
||||
if (categories.isLast && items != null) {
|
||||
pagingController.appendLastPage(items);
|
||||
} else if (categories.items != null) {
|
||||
pagingController.appendPage(
|
||||
items!, categories.nextOffset);
|
||||
}
|
||||
},
|
||||
);
|
||||
return PagedListView(
|
||||
pagingController: pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<Category>(
|
||||
firstPageProgressIndicatorBuilder: (_) =>
|
||||
const ShimmerCategories(),
|
||||
newPageProgressIndicatorBuilder: (_) =>
|
||||
const ShimmerCategories(),
|
||||
itemBuilder: (context, item, index) {
|
||||
return CategoryCard(item);
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
if (_selectedIndex.value == 1) const Search(),
|
||||
if (_selectedIndex.value == 2) const UserLibrary(),
|
||||
if (_selectedIndex.value == 3) const SyncedLyrics(),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (_selectedIndex.value == 1) const Search(),
|
||||
if (_selectedIndex.value == 2) const UserLibrary(),
|
||||
if (_selectedIndex.value == 3) const SyncedLyrics(),
|
||||
],
|
||||
),
|
||||
// player itself
|
||||
Player(),
|
||||
SpotubeNavigationBar(
|
||||
selectedIndex: _selectedIndex.value,
|
||||
onSelectedIndexChanged: _onSelectedIndexChanged,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// player itself
|
||||
Player(),
|
||||
SpotubeNavigationBar(
|
||||
selectedIndex: _selectedIndex.value,
|
||||
onSelectedIndexChanged: _onSelectedIndexChanged,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -15,24 +15,27 @@ class UserLibrary extends ConsumerWidget {
|
||||
return Expanded(
|
||||
child: DefaultTabController(
|
||||
length: 3,
|
||||
child: Scaffold(
|
||||
appBar: TabBar(
|
||||
indicator: const BoxDecoration(color: Colors.transparent),
|
||||
labelColor: Theme.of(context).primaryColor,
|
||||
unselectedLabelColor: Theme.of(context).textTheme.bodyText1?.color,
|
||||
tabs: const [
|
||||
Tab(text: "Playlist"),
|
||||
Tab(text: "Artists"),
|
||||
Tab(text: "Album"),
|
||||
],
|
||||
child: SafeArea(
|
||||
child: Scaffold(
|
||||
appBar: TabBar(
|
||||
indicator: const BoxDecoration(color: Colors.transparent),
|
||||
labelColor: Theme.of(context).primaryColor,
|
||||
unselectedLabelColor:
|
||||
Theme.of(context).textTheme.bodyText1?.color,
|
||||
tabs: const [
|
||||
Tab(text: "Playlist"),
|
||||
Tab(text: "Artists"),
|
||||
Tab(text: "Album"),
|
||||
],
|
||||
),
|
||||
body: auth.isLoggedIn
|
||||
? TabBarView(children: [
|
||||
const UserPlaylists(),
|
||||
UserArtists(),
|
||||
const UserAlbums(),
|
||||
])
|
||||
: const AnonymousFallback(),
|
||||
),
|
||||
body: auth.isLoggedIn
|
||||
? TabBarView(children: [
|
||||
const UserPlaylists(),
|
||||
UserArtists(),
|
||||
const UserAlbums(),
|
||||
])
|
||||
: const AnonymousFallback(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -52,7 +52,7 @@ class Lyrics extends HookConsumerWidget {
|
||||
return Text(
|
||||
lyrics == null && playback.track == null
|
||||
? "No Track being played currently"
|
||||
: lyrics!,
|
||||
: lyrics ?? "",
|
||||
style: textTheme.headline6
|
||||
?.copyWith(color: textTheme.headline1?.color),
|
||||
);
|
||||
|
@ -14,6 +14,7 @@ import 'package:spotube/helpers/artist-to-string.dart';
|
||||
import 'package:spotube/helpers/image-to-url-string.dart';
|
||||
import 'package:spotube/hooks/useAutoScrollController.dart';
|
||||
import 'package:spotube/hooks/useBreakpoints.dart';
|
||||
import 'package:spotube/hooks/useCustomStatusBarColor.dart';
|
||||
import 'package:spotube/hooks/usePaletteColor.dart';
|
||||
import 'package:spotube/hooks/useSyncedLyrics.dart';
|
||||
import 'package:spotube/provider/Playback.dart';
|
||||
@ -110,6 +111,12 @@ class SyncedLyrics extends HookConsumerWidget {
|
||||
: textTheme.headline4?.copyWith(fontSize: 25))
|
||||
?.copyWith(color: palette.titleTextColor);
|
||||
|
||||
useCustomStatusBarColor(
|
||||
palette.color,
|
||||
true,
|
||||
noSetBGColor: true,
|
||||
);
|
||||
|
||||
return Expanded(
|
||||
child: Container(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
@ -126,83 +133,85 @@ class SyncedLyrics extends HookConsumerWidget {
|
||||
filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15),
|
||||
child: Container(
|
||||
color: palette.color.withOpacity(.7),
|
||||
child: failed.value
|
||||
? Lyrics(titleBarForegroundColor: palette.bodyTextColor)
|
||||
: Column(
|
||||
children: [
|
||||
PageWindowTitleBar(
|
||||
foregroundColor: palette.bodyTextColor,
|
||||
),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
height: breakpoint >= Breakpoints.md ? 50 : 30,
|
||||
child: playback.track?.name != null &&
|
||||
playback.track!.name!.length > 29
|
||||
? SpotubeMarqueeText(
|
||||
text: playback.track?.name ?? "Not Playing",
|
||||
style: headlineTextStyle,
|
||||
)
|
||||
: Text(
|
||||
playback.track?.name ?? "Not Playing",
|
||||
style: headlineTextStyle,
|
||||
),
|
||||
)),
|
||||
Center(
|
||||
child: Text(
|
||||
artistsToString<Artist>(
|
||||
playback.track?.artists ?? []),
|
||||
style: breakpoint >= Breakpoints.md
|
||||
? textTheme.headline5
|
||||
: textTheme.headline6,
|
||||
child: SafeArea(
|
||||
child: failed.value
|
||||
? Lyrics(titleBarForegroundColor: palette.bodyTextColor)
|
||||
: Column(
|
||||
children: [
|
||||
PageWindowTitleBar(
|
||||
foregroundColor: palette.bodyTextColor,
|
||||
),
|
||||
),
|
||||
if (lyricValue != null && lyricValue.lyrics.isNotEmpty)
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
controller: controller,
|
||||
itemCount: lyricValue.lyrics.length,
|
||||
itemBuilder: (context, index) {
|
||||
final lyricSlice = lyricValue.lyrics[index];
|
||||
final isActive =
|
||||
lyricSlice.time.inSeconds == currentTime;
|
||||
if (isActive) {
|
||||
controller.scrollToIndex(
|
||||
index,
|
||||
preferPosition: AutoScrollPosition.middle,
|
||||
);
|
||||
}
|
||||
return AutoScrollTag(
|
||||
key: ValueKey(index),
|
||||
index: index,
|
||||
controller: controller,
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
lyricSlice.text,
|
||||
style: TextStyle(
|
||||
// indicating the active state of that lyric slice
|
||||
color: isActive
|
||||
? Theme.of(context).primaryColor
|
||||
: palette.bodyTextColor,
|
||||
fontWeight:
|
||||
isActive ? FontWeight.bold : null,
|
||||
fontSize: 30,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
height: breakpoint >= Breakpoints.md ? 50 : 30,
|
||||
child: playback.track?.name != null &&
|
||||
playback.track!.name!.length > 29
|
||||
? SpotubeMarqueeText(
|
||||
text: playback.track?.name ?? "Not Playing",
|
||||
style: headlineTextStyle,
|
||||
)
|
||||
: Text(
|
||||
playback.track?.name ?? "Not Playing",
|
||||
style: headlineTextStyle,
|
||||
),
|
||||
);
|
||||
},
|
||||
)),
|
||||
Center(
|
||||
child: Text(
|
||||
artistsToString<Artist>(
|
||||
playback.track?.artists ?? []),
|
||||
style: breakpoint >= Breakpoints.md
|
||||
? textTheme.headline5
|
||||
: textTheme.headline6,
|
||||
),
|
||||
),
|
||||
if (playback.track != null &&
|
||||
(lyricValue == null ||
|
||||
lyricValue.lyrics.isEmpty == true))
|
||||
const Expanded(child: ShimmerLyrics()),
|
||||
],
|
||||
),
|
||||
if (lyricValue != null && lyricValue.lyrics.isNotEmpty)
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
controller: controller,
|
||||
itemCount: lyricValue.lyrics.length,
|
||||
itemBuilder: (context, index) {
|
||||
final lyricSlice = lyricValue.lyrics[index];
|
||||
final isActive =
|
||||
lyricSlice.time.inSeconds == currentTime;
|
||||
if (isActive) {
|
||||
controller.scrollToIndex(
|
||||
index,
|
||||
preferPosition: AutoScrollPosition.middle,
|
||||
);
|
||||
}
|
||||
return AutoScrollTag(
|
||||
key: ValueKey(index),
|
||||
index: index,
|
||||
controller: controller,
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
lyricSlice.text,
|
||||
style: TextStyle(
|
||||
// indicating the active state of that lyric slice
|
||||
color: isActive
|
||||
? Theme.of(context).primaryColor
|
||||
: palette.bodyTextColor,
|
||||
fontWeight:
|
||||
isActive ? FontWeight.bold : null,
|
||||
fontSize: 30,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
if (playback.track != null &&
|
||||
(lyricValue == null ||
|
||||
lyricValue.lyrics.isEmpty == true))
|
||||
const Expanded(child: ShimmerLyrics()),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -120,13 +120,22 @@ class PlayerView extends HookConsumerWidget {
|
||||
)..repeat();
|
||||
return RotationTransition(
|
||||
turns: Tween(begin: 0.0, end: 1.0).animate(controller),
|
||||
child: CircleAvatar(
|
||||
backgroundImage: CachedNetworkImageProvider(
|
||||
albumArt,
|
||||
cacheKey: albumArt,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: paletteColor.titleTextColor,
|
||||
width: 2,
|
||||
),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: CircleAvatar(
|
||||
backgroundImage: CachedNetworkImageProvider(
|
||||
albumArt,
|
||||
cacheKey: albumArt,
|
||||
),
|
||||
radius: MediaQuery.of(context).size.width *
|
||||
(breakpoint.isSm ? 0.4 : 0.3),
|
||||
),
|
||||
radius: MediaQuery.of(context).size.width *
|
||||
(breakpoint.isSm ? 0.4 : 0.3),
|
||||
),
|
||||
);
|
||||
}),
|
||||
|
@ -37,183 +37,188 @@ class Search extends HookConsumerWidget {
|
||||
}
|
||||
final searchSnapshot = ref.watch(searchQuery(searchTerm));
|
||||
|
||||
return Expanded(
|
||||
child: Container(
|
||||
color: Theme.of(context).backgroundColor,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: controller,
|
||||
decoration: const InputDecoration(hintText: "Search..."),
|
||||
onSubmitted: (value) {
|
||||
return SafeArea(
|
||||
child: Expanded(
|
||||
child: Container(
|
||||
color: Theme.of(context).backgroundColor,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: controller,
|
||||
decoration:
|
||||
const InputDecoration(hintText: "Search..."),
|
||||
onSubmitted: (value) {
|
||||
ref.read(searchTermStateProvider.notifier).state =
|
||||
controller.value.text;
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
MaterialButton(
|
||||
elevation: 3,
|
||||
splashColor: Theme.of(context).primaryColor,
|
||||
padding: const EdgeInsets.symmetric(vertical: 21),
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white,
|
||||
child: const Icon(Icons.search_rounded),
|
||||
onPressed: () {
|
||||
ref.read(searchTermStateProvider.notifier).state =
|
||||
controller.value.text;
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
MaterialButton(
|
||||
elevation: 3,
|
||||
splashColor: Theme.of(context).primaryColor,
|
||||
padding: const EdgeInsets.symmetric(vertical: 21),
|
||||
color: Theme.of(context).primaryColor,
|
||||
textColor: Colors.white,
|
||||
child: const Icon(Icons.search_rounded),
|
||||
onPressed: () {
|
||||
ref.read(searchTermStateProvider.notifier).state =
|
||||
controller.value.text;
|
||||
},
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
searchSnapshot.when(
|
||||
data: (data) {
|
||||
Playback playback = ref.watch(playbackProvider);
|
||||
List<AlbumSimple> albums = [];
|
||||
List<Artist> artists = [];
|
||||
List<Track> tracks = [];
|
||||
List<PlaylistSimple> playlists = [];
|
||||
for (MapEntry<int, Page> page in data.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);
|
||||
searchSnapshot.when(
|
||||
data: (data) {
|
||||
Playback playback = ref.watch(playbackProvider);
|
||||
List<AlbumSimple> albums = [];
|
||||
List<Artist> artists = [];
|
||||
List<Track> tracks = [];
|
||||
List<PlaylistSimple> playlists = [];
|
||||
for (MapEntry<int, Page> page in data.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)
|
||||
Text(
|
||||
"Songs",
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
...tracks.asMap().entries.map((track) {
|
||||
String duration =
|
||||
"${track.value.duration?.inMinutes.remainder(60)}:${zeroPadNumStr(track.value.duration?.inSeconds.remainder(60) ?? 0)}";
|
||||
return TrackTile(
|
||||
playback,
|
||||
track: track,
|
||||
duration: duration,
|
||||
thumbnailUrl:
|
||||
imageToUrlString(track.value.album?.images),
|
||||
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: imageToUrlString(
|
||||
currentTrack.album?.images),
|
||||
),
|
||||
);
|
||||
} else if (isPlaylistPlaying &&
|
||||
currentTrack.id != null &&
|
||||
currentTrack.id != playback.track?.id) {
|
||||
playback.play(currentTrack);
|
||||
}
|
||||
},
|
||||
);
|
||||
}),
|
||||
if (albums.isNotEmpty)
|
||||
Text(
|
||||
"Albums",
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Scrollbar(
|
||||
controller: albumController,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
controller: albumController,
|
||||
child: Row(
|
||||
children: albums.map((album) {
|
||||
return AlbumCard(simpleAlbumToAlbum(album));
|
||||
}).toList(),
|
||||
return Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8, horizontal: 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (tracks.isNotEmpty)
|
||||
Text(
|
||||
"Songs",
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
if (artists.isNotEmpty)
|
||||
Text(
|
||||
"Artists",
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Scrollbar(
|
||||
controller: artistController,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
controller: artistController,
|
||||
child: Row(
|
||||
children: artists
|
||||
.map(
|
||||
(artist) => Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 15),
|
||||
child: ArtistCard(artist),
|
||||
...tracks.asMap().entries.map((track) {
|
||||
String duration =
|
||||
"${track.value.duration?.inMinutes.remainder(60)}:${zeroPadNumStr(track.value.duration?.inSeconds.remainder(60) ?? 0)}";
|
||||
return TrackTile(
|
||||
playback,
|
||||
track: track,
|
||||
duration: duration,
|
||||
thumbnailUrl:
|
||||
imageToUrlString(track.value.album?.images),
|
||||
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: imageToUrlString(
|
||||
currentTrack.album?.images),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
} else if (isPlaylistPlaying &&
|
||||
currentTrack.id != null &&
|
||||
currentTrack.id != playback.track?.id) {
|
||||
playback.play(currentTrack);
|
||||
}
|
||||
},
|
||||
);
|
||||
}),
|
||||
if (albums.isNotEmpty)
|
||||
Text(
|
||||
"Albums",
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Scrollbar(
|
||||
controller: albumController,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
controller: albumController,
|
||||
child: Row(
|
||||
children: albums.map((album) {
|
||||
return AlbumCard(simpleAlbumToAlbum(album));
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
if (playlists.isNotEmpty)
|
||||
Text(
|
||||
"Playlists",
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
const SizedBox(height: 20),
|
||||
if (artists.isNotEmpty)
|
||||
Text(
|
||||
"Artists",
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Scrollbar(
|
||||
controller: artistController,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
controller: artistController,
|
||||
child: Row(
|
||||
children: artists
|
||||
.map(
|
||||
(artist) => Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 15),
|
||||
child: ArtistCard(artist),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Scrollbar(
|
||||
scrollbarOrientation: breakpoint > Breakpoints.md
|
||||
? ScrollbarOrientation.bottom
|
||||
: ScrollbarOrientation.top,
|
||||
controller: playlistController,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
const SizedBox(height: 20),
|
||||
if (playlists.isNotEmpty)
|
||||
Text(
|
||||
"Playlists",
|
||||
style: Theme.of(context).textTheme.headline5,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Scrollbar(
|
||||
scrollbarOrientation: breakpoint > Breakpoints.md
|
||||
? ScrollbarOrientation.bottom
|
||||
: ScrollbarOrientation.top,
|
||||
controller: playlistController,
|
||||
child: Row(
|
||||
children: playlists
|
||||
.map(
|
||||
(playlist) => PlaylistCard(playlist),
|
||||
)
|
||||
.toList(),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
controller: playlistController,
|
||||
child: Row(
|
||||
children: playlists
|
||||
.map(
|
||||
(playlist) => PlaylistCard(playlist),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
error: (error, __) => Text("Error $error"),
|
||||
loading: () => const CircularProgressIndicator(),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
error: (error, __) => Text("Error $error"),
|
||||
loading: () => const CircularProgressIndicator(),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user