Skip to content

Commit

Permalink
use animated theme, refactor recent tracks toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
Chaphasilor committed Sep 30, 2023
1 parent e32b9a8 commit c9f1902
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 52 deletions.
148 changes: 101 additions & 47 deletions lib/components/PlayerScreen/queue_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class _QueueListState extends State<QueueList> {
QueueItemSource? _source;

late List<Widget> _contents;
bool isRecentTracksExpanded = false;
BehaviorSubject<bool> isRecentTracksExpanded = BehaviorSubject.seeded(false);

@override
void initState() {
Expand Down Expand Up @@ -147,47 +147,25 @@ class _QueueListState extends State<QueueList> {
Widget build(BuildContext context) {
_contents = <Widget>[
// Previous Tracks
if (isRecentTracksExpanded)
PreviousTracksList(
previousTracksHeaderKey: widget.previousTracksHeaderKey),
//TODO replace this with a SliverPersistentHeader and add an `onTap` callback to the delegate
SliverToBoxAdapter(
key: widget.previousTracksHeaderKey,
child: GestureDetector(
onTap: () {
Vibrate.feedback(FeedbackType.selection);
setState(() => isRecentTracksExpanded = !isRecentTracksExpanded);
if (!isRecentTracksExpanded) {
Future.delayed(const Duration(milliseconds: 200),
() => scrollToCurrentTrack());
}
// else {
// Future.delayed(const Duration(milliseconds: 300), () => scrollToCurrentTrack());
// }
},
child: Padding(
padding: const EdgeInsets.only(
left: 14.0, right: 14.0, bottom: 12.0, top: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(top: 2.0),
child: Text(AppLocalizations.of(context)!.recentlyPlayed),
),
const SizedBox(width: 4.0),
Icon(
isRecentTracksExpanded
? TablerIcons.chevron_up
: TablerIcons.chevron_down,
size: 28.0,
color: Colors.white,
),
],
),
),
)),
StreamBuilder<bool>(
stream: isRecentTracksExpanded,
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!) {
return PreviousTracksList(
previousTracksHeaderKey: widget.previousTracksHeaderKey);
} else {
return const SliverToBoxAdapter();
}
}
),
SliverPersistentHeader(
key: widget.previousTracksHeaderKey,
delegate: PreviousTracksSectionHeader(
isRecentTracksExpanded: isRecentTracksExpanded,
previousTracksHeaderKey: widget.previousTracksHeaderKey,
onTap: () => isRecentTracksExpanded.add(!isRecentTracksExpanded.value),
)
),
CurrentTrack(
// key: UniqueKey(),
key: widget.currentTrackKey,
Expand Down Expand Up @@ -276,7 +254,8 @@ Future<dynamic> showQueueBottomSheet(BuildContext context) {
builder: (BuildContext context, WidgetRef ref, Widget? child) {
final imageTheme = ref.watch(playerScreenThemeProvider);

return Theme(
return AnimatedTheme(
duration: const Duration(milliseconds: 750),
data: ThemeData(
fontFamily: "LexendDeca",
colorScheme: imageTheme,
Expand Down Expand Up @@ -1323,15 +1302,15 @@ class NextUpSectionHeader extends SliverPersistentHeaderDelegate {
_queueService.clearNextUp();
Vibrate.feedback(FeedbackType.success);
},
child: const Row(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(top: 4.0),
child: Text("Clear Next Up"),
padding: const EdgeInsets.only(top: 4.0),
child: Text(AppLocalizations.of(context)!.clearNextUp),
),
Icon(
const Icon(
TablerIcons.x,
color: Colors.white,
size: 32.0,
Expand All @@ -1354,6 +1333,81 @@ class NextUpSectionHeader extends SliverPersistentHeaderDelegate {
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => false;
}

class PreviousTracksSectionHeader extends SliverPersistentHeaderDelegate {
// final bool controls;
final double height;
final VoidCallback? onTap;
final GlobalKey previousTracksHeaderKey;
final BehaviorSubject<bool> isRecentTracksExpanded;

PreviousTracksSectionHeader({
required this.previousTracksHeaderKey,
required this.isRecentTracksExpanded,
// this.controls = false,
this.onTap,
this.height = 50.0,
});

@override
Widget build(context, double shrinkOffset, bool overlapsContent) {

return Padding(
// color: Colors.black.withOpacity(0.5),
padding: const EdgeInsets.only(left: 14.0, right: 14.0, bottom: 12.0, top: 8.0),
child: GestureDetector(
onTap: () {
try {
if (onTap != null) {
onTap!();
Vibrate.feedback(FeedbackType.selection);
}
} catch (e) {
Vibrate.feedback(FeedbackType.error);
}
},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Text(AppLocalizations.of(context)!.previousTracks),
),
const SizedBox(width: 4.0),
StreamBuilder<bool>(
stream: isRecentTracksExpanded,
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!) {
return const Icon(
TablerIcons.chevron_up,
size: 28.0,
color: Colors.white,
);
} else {
return const Icon(
TablerIcons.chevron_down,
size: 28.0,
color: Colors.white,
);
}
}
),
],
),
),
);
}

@override
double get maxExtent => height;

@override
double get minExtent => height;

@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => false;
}

/// If offline, check if an album is downloaded. Always returns true if online.
/// Returns false if albumId is null.
bool _isAlbumDownloadedIfOffline(String? albumId) {
Expand Down
2 changes: 1 addition & 1 deletion lib/components/PlayerScreen/queue_list_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class _QueueListItemState extends State<QueueListItem>
alignment: Alignment.centerRight,
margin: const EdgeInsets.only(right: 8.0),
padding: const EdgeInsets.only(right: 6.0),
width: widget.allowReorder ? 72.0 : 40.0,
width: widget.allowReorder ? 72.0 : 42.0, //TODO make this responsive
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
Expand Down
3 changes: 2 additions & 1 deletion lib/components/now_playing_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class NowPlayingBar extends ConsumerWidget {
final audioHandler = GetIt.instance<MusicPlayerBackgroundTask>();
final queueService = GetIt.instance<QueueService>();

return Theme(
return AnimatedTheme(
duration: const Duration(milliseconds: 750),
data: ThemeData(
fontFamily: "LexendDeca",
colorScheme: imageTheme,
Expand Down
8 changes: 6 additions & 2 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -484,14 +484,18 @@
"@bufferDurationSubtitle": {},
"language": "Language",
"@language": {},
"recentlyPlayed": "Recently Played",
"@recentlyPlayed": {
"previousTracks": "Recently Played",
"@previousTracks": {
"description": "Description in the queue panel for the list of tracks that was previously played"
},
"nextUp": "Next Up",
"@nextUp": {
"description": "Description in the queue panel for the list of tracks were manually added to be played after the current track. This should be capitalized (if applicable) to be more recognizable throughout the UI"
},
"clearNextUp": "Clear Next Up",
"@clearNextUp": {
"description": "Label for the action that deletes all tracks added to Next Up"
},
"playingFrom": "Playing from",
"@playingFrom": {
"description": "Prefix shown before the name of the main queue source, like the album or playlist that was used to start playback. Example: \"Playing from {My Nice Playlist}\""
Expand Down
3 changes: 2 additions & 1 deletion lib/screens/player_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class PlayerScreen extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final imageTheme = ref.watch(playerScreenThemeProvider);

return Theme(
return AnimatedTheme(
duration: const Duration(milliseconds: 750),
data: ThemeData(
fontFamily: "LexendDeca",
colorScheme: imageTheme,
Expand Down
1 change: 1 addition & 0 deletions lib/services/playback_history_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ class PlaybackHistoryService {
if (previousTrackPlaybackData != null) {
_playbackHistoryServiceLogger.info("Stopping playback progress for ${previousItem?.item.title}");
await _jellyfinApiHelper.stopPlaybackProgress(previousTrackPlaybackData);
//TODO also mark the track as played in the user data: https://api.jellyfin.org/openapi/api.html#tag/Playstate/operation/MarkPlayedItem
}
if (newTrackplaybackData != null) {
_playbackHistoryServiceLogger.info("Starting playback progress for ${currentItem.item.title}");
Expand Down

0 comments on commit c9f1902

Please sign in to comment.