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;
|
return null;
|
||||||
}, [backgroundColor]);
|
}, [backgroundColor]);
|
||||||
|
|
||||||
return SafeArea(
|
return Scaffold(
|
||||||
child: Scaffold(
|
body: Column(
|
||||||
body: Column(
|
children: [
|
||||||
children: [
|
if (_selectedIndex.value != 3)
|
||||||
if (_selectedIndex.value != 3)
|
kIsMobile
|
||||||
kIsMobile
|
? titleBarContents
|
||||||
? titleBarContents
|
: WindowTitleBarBox(child: titleBarContents),
|
||||||
: WindowTitleBarBox(child: titleBarContents),
|
Expanded(
|
||||||
Expanded(
|
child: Row(
|
||||||
child: Row(
|
children: [
|
||||||
children: [
|
Sidebar(
|
||||||
Sidebar(
|
selectedIndex: _selectedIndex.value,
|
||||||
selectedIndex: _selectedIndex.value,
|
onSelectedIndexChanged: _onSelectedIndexChanged,
|
||||||
onSelectedIndexChanged: _onSelectedIndexChanged,
|
),
|
||||||
),
|
// contents of the spotify
|
||||||
// contents of the spotify
|
if (_selectedIndex.value == 0)
|
||||||
if (_selectedIndex.value == 0)
|
Expanded(
|
||||||
Expanded(
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.only(
|
||||||
padding: const EdgeInsets.only(
|
bottom: 8.0,
|
||||||
bottom: 8.0,
|
top: 8.0,
|
||||||
top: 8.0,
|
left: 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);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
|
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 == 1) const Search(),
|
||||||
if (_selectedIndex.value == 3) const SyncedLyrics(),
|
if (_selectedIndex.value == 2) const UserLibrary(),
|
||||||
],
|
if (_selectedIndex.value == 3) const SyncedLyrics(),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
// player itself
|
),
|
||||||
Player(),
|
// player itself
|
||||||
SpotubeNavigationBar(
|
Player(),
|
||||||
selectedIndex: _selectedIndex.value,
|
SpotubeNavigationBar(
|
||||||
onSelectedIndexChanged: _onSelectedIndexChanged,
|
selectedIndex: _selectedIndex.value,
|
||||||
),
|
onSelectedIndexChanged: _onSelectedIndexChanged,
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -15,24 +15,27 @@ class UserLibrary extends ConsumerWidget {
|
|||||||
return Expanded(
|
return Expanded(
|
||||||
child: DefaultTabController(
|
child: DefaultTabController(
|
||||||
length: 3,
|
length: 3,
|
||||||
child: Scaffold(
|
child: SafeArea(
|
||||||
appBar: TabBar(
|
child: Scaffold(
|
||||||
indicator: const BoxDecoration(color: Colors.transparent),
|
appBar: TabBar(
|
||||||
labelColor: Theme.of(context).primaryColor,
|
indicator: const BoxDecoration(color: Colors.transparent),
|
||||||
unselectedLabelColor: Theme.of(context).textTheme.bodyText1?.color,
|
labelColor: Theme.of(context).primaryColor,
|
||||||
tabs: const [
|
unselectedLabelColor:
|
||||||
Tab(text: "Playlist"),
|
Theme.of(context).textTheme.bodyText1?.color,
|
||||||
Tab(text: "Artists"),
|
tabs: const [
|
||||||
Tab(text: "Album"),
|
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(
|
return Text(
|
||||||
lyrics == null && playback.track == null
|
lyrics == null && playback.track == null
|
||||||
? "No Track being played currently"
|
? "No Track being played currently"
|
||||||
: lyrics!,
|
: lyrics ?? "",
|
||||||
style: textTheme.headline6
|
style: textTheme.headline6
|
||||||
?.copyWith(color: textTheme.headline1?.color),
|
?.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/helpers/image-to-url-string.dart';
|
||||||
import 'package:spotube/hooks/useAutoScrollController.dart';
|
import 'package:spotube/hooks/useAutoScrollController.dart';
|
||||||
import 'package:spotube/hooks/useBreakpoints.dart';
|
import 'package:spotube/hooks/useBreakpoints.dart';
|
||||||
|
import 'package:spotube/hooks/useCustomStatusBarColor.dart';
|
||||||
import 'package:spotube/hooks/usePaletteColor.dart';
|
import 'package:spotube/hooks/usePaletteColor.dart';
|
||||||
import 'package:spotube/hooks/useSyncedLyrics.dart';
|
import 'package:spotube/hooks/useSyncedLyrics.dart';
|
||||||
import 'package:spotube/provider/Playback.dart';
|
import 'package:spotube/provider/Playback.dart';
|
||||||
@ -110,6 +111,12 @@ class SyncedLyrics extends HookConsumerWidget {
|
|||||||
: textTheme.headline4?.copyWith(fontSize: 25))
|
: textTheme.headline4?.copyWith(fontSize: 25))
|
||||||
?.copyWith(color: palette.titleTextColor);
|
?.copyWith(color: palette.titleTextColor);
|
||||||
|
|
||||||
|
useCustomStatusBarColor(
|
||||||
|
palette.color,
|
||||||
|
true,
|
||||||
|
noSetBGColor: true,
|
||||||
|
);
|
||||||
|
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
@ -126,83 +133,85 @@ class SyncedLyrics extends HookConsumerWidget {
|
|||||||
filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15),
|
filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15),
|
||||||
child: Container(
|
child: Container(
|
||||||
color: palette.color.withOpacity(.7),
|
color: palette.color.withOpacity(.7),
|
||||||
child: failed.value
|
child: SafeArea(
|
||||||
? Lyrics(titleBarForegroundColor: palette.bodyTextColor)
|
child: failed.value
|
||||||
: Column(
|
? Lyrics(titleBarForegroundColor: palette.bodyTextColor)
|
||||||
children: [
|
: Column(
|
||||||
PageWindowTitleBar(
|
children: [
|
||||||
foregroundColor: palette.bodyTextColor,
|
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,
|
|
||||||
),
|
),
|
||||||
),
|
Center(
|
||||||
if (lyricValue != null && lyricValue.lyrics.isNotEmpty)
|
child: SizedBox(
|
||||||
Expanded(
|
height: breakpoint >= Breakpoints.md ? 50 : 30,
|
||||||
child: ListView.builder(
|
child: playback.track?.name != null &&
|
||||||
controller: controller,
|
playback.track!.name!.length > 29
|
||||||
itemCount: lyricValue.lyrics.length,
|
? SpotubeMarqueeText(
|
||||||
itemBuilder: (context, index) {
|
text: playback.track?.name ?? "Not Playing",
|
||||||
final lyricSlice = lyricValue.lyrics[index];
|
style: headlineTextStyle,
|
||||||
final isActive =
|
)
|
||||||
lyricSlice.time.inSeconds == currentTime;
|
: Text(
|
||||||
if (isActive) {
|
playback.track?.name ?? "Not Playing",
|
||||||
controller.scrollToIndex(
|
style: headlineTextStyle,
|
||||||
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: Text(
|
||||||
|
artistsToString<Artist>(
|
||||||
|
playback.track?.artists ?? []),
|
||||||
|
style: breakpoint >= Breakpoints.md
|
||||||
|
? textTheme.headline5
|
||||||
|
: textTheme.headline6,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (playback.track != null &&
|
if (lyricValue != null && lyricValue.lyrics.isNotEmpty)
|
||||||
(lyricValue == null ||
|
Expanded(
|
||||||
lyricValue.lyrics.isEmpty == true))
|
child: ListView.builder(
|
||||||
const Expanded(child: ShimmerLyrics()),
|
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();
|
)..repeat();
|
||||||
return RotationTransition(
|
return RotationTransition(
|
||||||
turns: Tween(begin: 0.0, end: 1.0).animate(controller),
|
turns: Tween(begin: 0.0, end: 1.0).animate(controller),
|
||||||
child: CircleAvatar(
|
child: Container(
|
||||||
backgroundImage: CachedNetworkImageProvider(
|
decoration: BoxDecoration(
|
||||||
albumArt,
|
border: Border.all(
|
||||||
cacheKey: albumArt,
|
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));
|
final searchSnapshot = ref.watch(searchQuery(searchTerm));
|
||||||
|
|
||||||
return Expanded(
|
return SafeArea(
|
||||||
child: Container(
|
child: Expanded(
|
||||||
color: Theme.of(context).backgroundColor,
|
child: Container(
|
||||||
child: Column(
|
color: Theme.of(context).backgroundColor,
|
||||||
children: [
|
child: Column(
|
||||||
Padding(
|
children: [
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
Padding(
|
||||||
child: Row(
|
padding:
|
||||||
children: [
|
const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||||
Expanded(
|
child: Row(
|
||||||
child: TextField(
|
children: [
|
||||||
controller: controller,
|
Expanded(
|
||||||
decoration: const InputDecoration(hintText: "Search..."),
|
child: TextField(
|
||||||
onSubmitted: (value) {
|
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 =
|
ref.read(searchTermStateProvider.notifier).state =
|
||||||
controller.value.text;
|
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(
|
||||||
searchSnapshot.when(
|
data: (data) {
|
||||||
data: (data) {
|
Playback playback = ref.watch(playbackProvider);
|
||||||
Playback playback = ref.watch(playbackProvider);
|
List<AlbumSimple> albums = [];
|
||||||
List<AlbumSimple> albums = [];
|
List<Artist> artists = [];
|
||||||
List<Artist> artists = [];
|
List<Track> tracks = [];
|
||||||
List<Track> tracks = [];
|
List<PlaylistSimple> playlists = [];
|
||||||
List<PlaylistSimple> playlists = [];
|
for (MapEntry<int, Page> page in data.asMap().entries) {
|
||||||
for (MapEntry<int, Page> page in data.asMap().entries) {
|
for (var item in page.value.items ?? []) {
|
||||||
for (var item in page.value.items ?? []) {
|
if (item is AlbumSimple) {
|
||||||
if (item is AlbumSimple) {
|
albums.add(item);
|
||||||
albums.add(item);
|
} else if (item is PlaylistSimple) {
|
||||||
} else if (item is PlaylistSimple) {
|
playlists.add(item);
|
||||||
playlists.add(item);
|
} else if (item is Artist) {
|
||||||
} else if (item is Artist) {
|
artists.add(item);
|
||||||
artists.add(item);
|
} else if (item is Track) {
|
||||||
} else if (item is Track) {
|
tracks.add(item);
|
||||||
tracks.add(item);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return Expanded(
|
||||||
return Expanded(
|
child: SingleChildScrollView(
|
||||||
child: SingleChildScrollView(
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.symmetric(
|
||||||
padding: const EdgeInsets.symmetric(
|
vertical: 8, horizontal: 20),
|
||||||
vertical: 8, horizontal: 20),
|
child: Column(
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
if (tracks.isNotEmpty)
|
||||||
if (tracks.isNotEmpty)
|
Text(
|
||||||
Text(
|
"Songs",
|
||||||
"Songs",
|
style: Theme.of(context).textTheme.headline5,
|
||||||
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(),
|
|
||||||
),
|
),
|
||||||
),
|
...tracks.asMap().entries.map((track) {
|
||||||
),
|
String duration =
|
||||||
const SizedBox(height: 20),
|
"${track.value.duration?.inMinutes.remainder(60)}:${zeroPadNumStr(track.value.duration?.inSeconds.remainder(60) ?? 0)}";
|
||||||
if (artists.isNotEmpty)
|
return TrackTile(
|
||||||
Text(
|
playback,
|
||||||
"Artists",
|
track: track,
|
||||||
style: Theme.of(context).textTheme.headline5,
|
duration: duration,
|
||||||
),
|
thumbnailUrl:
|
||||||
const SizedBox(height: 10),
|
imageToUrlString(track.value.album?.images),
|
||||||
Scrollbar(
|
isActive: playback.track?.id == track.value.id,
|
||||||
controller: artistController,
|
onTrackPlayButtonPressed: (currentTrack) async {
|
||||||
child: SingleChildScrollView(
|
var isPlaylistPlaying =
|
||||||
scrollDirection: Axis.horizontal,
|
playback.playlist?.id != null &&
|
||||||
controller: artistController,
|
playback.playlist?.id ==
|
||||||
child: Row(
|
currentTrack.id;
|
||||||
children: artists
|
if (!isPlaylistPlaying) {
|
||||||
.map(
|
playback.playPlaylist(
|
||||||
(artist) => Container(
|
CurrentPlaylist(
|
||||||
margin: const EdgeInsets.symmetric(
|
tracks: [currentTrack],
|
||||||
horizontal: 15),
|
id: currentTrack.id!,
|
||||||
child: ArtistCard(artist),
|
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),
|
||||||
const SizedBox(height: 20),
|
if (artists.isNotEmpty)
|
||||||
if (playlists.isNotEmpty)
|
Text(
|
||||||
Text(
|
"Artists",
|
||||||
"Playlists",
|
style: Theme.of(context).textTheme.headline5,
|
||||||
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),
|
const SizedBox(height: 20),
|
||||||
Scrollbar(
|
if (playlists.isNotEmpty)
|
||||||
scrollbarOrientation: breakpoint > Breakpoints.md
|
Text(
|
||||||
? ScrollbarOrientation.bottom
|
"Playlists",
|
||||||
: ScrollbarOrientation.top,
|
style: Theme.of(context).textTheme.headline5,
|
||||||
controller: playlistController,
|
),
|
||||||
child: SingleChildScrollView(
|
const SizedBox(height: 10),
|
||||||
scrollDirection: Axis.horizontal,
|
Scrollbar(
|
||||||
|
scrollbarOrientation: breakpoint > Breakpoints.md
|
||||||
|
? ScrollbarOrientation.bottom
|
||||||
|
: ScrollbarOrientation.top,
|
||||||
controller: playlistController,
|
controller: playlistController,
|
||||||
child: Row(
|
child: SingleChildScrollView(
|
||||||
children: playlists
|
scrollDirection: Axis.horizontal,
|
||||||
.map(
|
controller: playlistController,
|
||||||
(playlist) => PlaylistCard(playlist),
|
child: Row(
|
||||||
)
|
children: playlists
|
||||||
.toList(),
|
.map(
|
||||||
|
(playlist) => PlaylistCard(playlist),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
error: (error, __) => Text("Error $error"),
|
||||||
error: (error, __) => Text("Error $error"),
|
loading: () => const CircularProgressIndicator(),
|
||||||
loading: () => const CircularProgressIndicator(),
|
)
|
||||||
)
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user