diff --git a/assets/icon/shuffle.svg b/assets/icon/shuffle.svg
new file mode 100644
index 0000000..f71a3ce
--- /dev/null
+++ b/assets/icon/shuffle.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/lib/features/library/ui/library_widgets/library_app_bar.dart b/lib/features/library/ui/library_widgets/library_app_bar.dart
index 378e072..bb39891 100644
--- a/lib/features/library/ui/library_widgets/library_app_bar.dart
+++ b/lib/features/library/ui/library_widgets/library_app_bar.dart
@@ -42,9 +42,20 @@ class LibraryAppBar extends StatelessWidget {
),
child: FlexibleSpaceBar(
centerTitle: true,
- title: state.showTitleInAppBar
- ? Text(state.title, style: context.textTheme.headlineSmall)
- : null,
+ title: AnimatedCrossFade(
+ crossFadeState: state.showTitleInAppBar
+ ? CrossFadeState.showSecond
+ : CrossFadeState.showFirst,
+ firstChild: const SizedBox.shrink(),
+ secondChild: Text(
+ state.title,
+ style: context.textTheme.titleMedium?.copyWith(
+ fontWeight: FontWeight.bold,
+ letterSpacing: 0.5,
+ ),
+ ),
+ duration: const Duration(milliseconds: 100),
+ ),
collapseMode: CollapseMode.pin,
background: AnimatedContainer(
duration: kThemeAnimationDuration,
diff --git a/lib/features/library/ui/library_widgets/page.dart b/lib/features/library/ui/library_widgets/page.dart
index 4aec7dd..6e1b96c 100644
--- a/lib/features/library/ui/library_widgets/page.dart
+++ b/lib/features/library/ui/library_widgets/page.dart
@@ -7,11 +7,13 @@ import 'package:varanasi_mobile_app/cubits/player/player_cubit.dart';
import 'package:varanasi_mobile_app/features/library/cubit/library_cubit.dart';
import 'package:varanasi_mobile_app/features/library/ui/library_widgets/library_app_bar.dart';
import 'package:varanasi_mobile_app/models/playable_item.dart';
+import 'package:varanasi_mobile_app/utils/extensions/extensions.dart';
import 'package:varanasi_mobile_app/utils/extensions/media_query.dart';
+import 'package:varanasi_mobile_app/widgets/add_to_library.dart';
import 'package:varanasi_mobile_app/widgets/download_button.dart';
import 'package:varanasi_mobile_app/widgets/media_list.dart';
import 'package:varanasi_mobile_app/widgets/play_pause_button.dart';
-import 'package:varanasi_mobile_app/widgets/typography.dart';
+import 'package:varanasi_mobile_app/widgets/player/full_screen_player/shuffle_mode_toggle.dart';
class LibraryContent extends StatefulHookWidget {
/// The source of the library content
@@ -107,20 +109,31 @@ class _LibraryContentState extends State {
LibraryAppBar(state: state, padding: padding),
SliverToBoxAdapter(
child: Padding(
- key: titleKey,
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 16,
).copyWith(right: 84),
- child: Row(
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
- Expanded(
- child: Typography(
- state.title,
- secondary: state.subtitle,
+ Text(
+ state.title,
+ style: context.textTheme.bodyMedium?.copyWith(
+ fontWeight: FontWeight.bold,
+ letterSpacing: 0.5,
),
),
- DownloadPlaylist(playlist: state.playlist),
+ Text(state.subtitle),
+ Row(
+ key: titleKey,
+ children: [
+ AddToLibrary(state.playlist),
+ DownloadPlaylist(playlist: state.playlist),
+ const Spacer(),
+ const ShuffleModeToggle(iconSize: 24),
+ ],
+ ),
],
),
),
@@ -166,6 +179,7 @@ class _LibraryContentState extends State {
);
},
isPlaying: isThisPlaylistPlaying,
+ size: 36,
),
)
],
diff --git a/lib/features/user-library/cubit/user_library_cubit.dart b/lib/features/user-library/cubit/user_library_cubit.dart
index dad21fd..7a5552d 100644
--- a/lib/features/user-library/cubit/user_library_cubit.dart
+++ b/lib/features/user-library/cubit/user_library_cubit.dart
@@ -47,4 +47,11 @@ class UserLibraryCubit extends AppCubit {
final library = _repository.getLibraries();
emit(UserLibraryLoaded(library: library));
}
+
+ Future removeFromLibrary(MediaPlaylist playlist) async {
+ _repository.deleteLibrary(playlist.toUserLibrary());
+ final library = _repository.getLibraries();
+ emit(UserLibraryLoaded(library: library));
+ AppSnackbar.show("Removed from library");
+ }
}
diff --git a/lib/features/user-library/cubit/user_library_state.dart b/lib/features/user-library/cubit/user_library_state.dart
index f587519..63381a9 100644
--- a/lib/features/user-library/cubit/user_library_state.dart
+++ b/lib/features/user-library/cubit/user_library_state.dart
@@ -32,4 +32,10 @@ class UserLibraryLoaded extends UserLibraryState {
(library) => library is Favorite,
orElse: () => const Favorite.empty(),
) as Favorite;
+
+ bool get isEmpty => library.isEmpty;
+
+ bool isAdded(MediaPlaylist playlist) {
+ return library.any((a) => playlist.id == a.id);
+ }
}
diff --git a/lib/gen/assets.gen.dart b/lib/gen/assets.gen.dart
index e1ca7d9..918cb58 100644
--- a/lib/gen/assets.gen.dart
+++ b/lib/gen/assets.gen.dart
@@ -39,6 +39,9 @@ class $AssetsIconGen {
$AssetsIconNavGen get nav => const $AssetsIconNavGen();
+ /// File path: assets/icon/shuffle.svg
+ SvgGenImage get shuffle => const SvgGenImage('assets/icon/shuffle.svg');
+
/// List of all assets
List get values => [
appIcon,
@@ -46,7 +49,8 @@ class $AssetsIconGen {
circularLoader,
download,
downloadFilled,
- downloading
+ downloading,
+ shuffle
];
}
diff --git a/lib/widgets/add_to_library.dart b/lib/widgets/add_to_library.dart
new file mode 100644
index 0000000..ff7d8f6
--- /dev/null
+++ b/lib/widgets/add_to_library.dart
@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:varanasi_mobile_app/features/user-library/cubit/user_library_cubit.dart';
+import 'package:varanasi_mobile_app/models/media_playlist.dart';
+
+class AddToLibrary extends StatelessWidget {
+ final MediaPlaylist playlist;
+ const AddToLibrary(this.playlist, {super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocBuilder(
+ builder: (context, state) {
+ if (state is! UserLibraryLoaded) return const SizedBox.shrink();
+ final isAdded = state.isAdded(playlist);
+ AnimatedIcons.add_event;
+ return IconButton(
+ onPressed: () {
+ final cubit = context.read();
+ if (isAdded) {
+ cubit.removeFromLibrary(playlist);
+ } else {
+ cubit.addToLibrary(playlist);
+ }
+ },
+ icon: isAdded
+ ? const Icon(Icons.check_circle_rounded)
+ : const Icon(Icons.add_circle_outline_rounded),
+ iconSize: 30,
+ );
+ },
+ );
+ }
+}
diff --git a/lib/widgets/download_button.dart b/lib/widgets/download_button.dart
index c6e5b99..9fea6fd 100644
--- a/lib/widgets/download_button.dart
+++ b/lib/widgets/download_button.dart
@@ -97,8 +97,8 @@ class DownloadPlaylist extends StatelessWidget {
downloading: downloading,
downloaded: downloaded,
progress: progress,
+ dimension: 26,
),
- iconSize: 24,
);
});
}
@@ -120,7 +120,7 @@ class DownloadStatus extends StatelessWidget {
final double dimension;
final bool hideStopIconOnIos;
- double get iconSize => dimension * 0.6;
+ double get iconSize => dimension * 0.8;
@override
Widget build(BuildContext context) {
diff --git a/lib/widgets/player/full_screen_player/full_screen_player.dart b/lib/widgets/player/full_screen_player/full_screen_player.dart
index c189d1c..7de0ad7 100644
--- a/lib/widgets/player/full_screen_player/full_screen_player.dart
+++ b/lib/widgets/player/full_screen_player/full_screen_player.dart
@@ -94,7 +94,7 @@ class _PlayerState extends State {
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
- ShuffleModeToggle(audioHandler: audioHandler),
+ const ShuffleModeToggle(),
SkipToPrevious(queueState: queueState),
PlayPauseMediaButton(
backgroundColor: Colors.white,
diff --git a/lib/widgets/player/full_screen_player/shuffle_mode_toggle.dart b/lib/widgets/player/full_screen_player/shuffle_mode_toggle.dart
index 07b51f5..0664df5 100644
--- a/lib/widgets/player/full_screen_player/shuffle_mode_toggle.dart
+++ b/lib/widgets/player/full_screen_player/shuffle_mode_toggle.dart
@@ -2,21 +2,25 @@ import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:varanasi_mobile_app/cubits/player/player_cubit.dart';
+import 'package:varanasi_mobile_app/gen/assets.gen.dart';
import 'package:varanasi_mobile_app/utils/extensions/theme.dart';
-import 'package:varanasi_mobile_app/utils/player/audio_handler_impl.dart';
class ShuffleModeToggle extends StatelessWidget {
const ShuffleModeToggle({
super.key,
- required this.audioHandler,
+ this.iconSize = 32,
});
- final AudioHandlerImpl audioHandler;
+ final double iconSize;
+
+ double get smallSize => iconSize * 0.18;
@override
Widget build(BuildContext context) {
+ final audioHandler = context.read().audioHandler;
return StreamBuilder(
stream: audioHandler.playbackState.map((event) => event.shuffleMode),
+ initialData: AudioServiceShuffleMode.none,
builder: (context, snapshot) {
final shuffleEnabled =
![null, AudioServiceShuffleMode.none].contains(snapshot.data);
@@ -35,14 +39,16 @@ class ShuffleModeToggle extends StatelessWidget {
icon: Badge(
alignment: Alignment.bottomCenter,
isLabelVisible: shuffleEnabled,
- backgroundColor: context.colorScheme.primary,
- child: const Padding(
- padding: EdgeInsets.symmetric(vertical: 4.0),
- child: Icon(Icons.shuffle),
+ smallSize: smallSize,
+ child: Assets.icon.shuffle.svg(
+ width: iconSize,
+ height: iconSize,
+ color:
+ shuffleEnabled ? context.colorScheme.primary : Colors.white,
),
),
color: shuffleEnabled ? context.colorScheme.primary : null,
- iconSize: 32,
+ iconSize: iconSize,
);
},
);