Skip to content

Commit

Permalink
Merge pull request #377 from lamarios/fix/fix_adding_to_playlist
Browse files Browse the repository at this point in the history
strengthen adding a video to playlist buttons from video modal sheet …
  • Loading branch information
lamarios authored Nov 16, 2023
2 parents cffacd6 + d1828b0 commit c3d5551
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 45 deletions.
61 changes: 27 additions & 34 deletions lib/videos/states/add_to_playlist.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ part 'add_to_playlist.g.dart';
const String likePlaylistName = '❤️';

class AddToPlaylistCubit extends Cubit<AddToPlaylistController> {

final log = Logger('AddToPlaylistcubit');

AddToPlaylistCubit(super.initialState) {
Expand All @@ -31,83 +30,76 @@ class AddToPlaylistCubit extends Cubit<AddToPlaylistController> {
}

Future<void> onReady() async {
await getAllPlaylists();
await countPlaylistsForVideo();
await checkVideoLikeStatus();
await getAllPlaylists();
await countPlaylistsForVideo();
await checkVideoLikeStatus();
}

getAllPlaylists() async {
var state = this.state.copyWith();
emit(state.copyWith(loading: true));
late List<Playlist> playlists;
if (state.isLoggedIn) {
state.playlists = await service.getUserPlaylists();
playlists = await service.getUserPlaylists();
}
state.loading = false;
emit(state);
emit(state.copyWith(playlists: playlists, loading: false));
}

Future<Playlist?> getPlaylist() async {
List<Playlist> playlists = await service.getUserPlaylists();
Playlist? pl = playlists.firstWhereOrNull((pl) => pl.title == likePlaylistName);
Future<Playlist?> likePlaylist() async {
Playlist? pl = state.playlists.firstWhereOrNull((pl) => pl.title == likePlaylistName);

return pl;
}

checkVideoLikeStatus() async {
var state = this.state.copyWith();
Playlist? p = await getPlaylist();
Playlist? p = await likePlaylist();
VideoInList? video = p?.videos.firstWhereOrNull((element) => element.videoId == state.videoId);

state.isVideoLiked = video != null;
bool isVideoLiked = video != null;

if (!isClosed) {
emit(state);
emit(state.copyWith(isVideoLiked: isVideoLiked));
log.fine('video is currently liked ? $state.isVideoLiked');
}
}

Future<Playlist?> createPlayList() async {
await service.createPlayList(likePlaylistName, "private");
return getPlaylist();
await onReady();
return likePlaylist();
}

countPlaylistsForVideo() async {
var state = this.state.copyWith();
List<Playlist> lists = await service.getUserPlaylists();

state.playListCount =
lists.where((list) => list.videos.indexWhere((video) => video.videoId == state.videoId) >= 0).length;
int playListCount =
state.playlists.where((list) => list.videos.indexWhere((video) => video.videoId == state.videoId) >= 0).length;
log.fine('playlist count ${state.playListCount}');
if (!isClosed) {
emit(state);
emit(state.copyWith(playListCount: playListCount));
}
}

Future<void> toggleLike() async {
var state = this.state.copyWith();
state.loading = true;
emit(state);
emit(state.copyWith(loading: true));

state = this.state.copyWith();
await checkVideoLikeStatus();
Playlist? p = await getPlaylist();
await onReady();
Playlist? p = await likePlaylist();
p ??= await createPlayList();

bool isVideoLiked = state.isVideoLiked;
if (p != null && state.videoId != null) {
if (state.isVideoLiked) {
if (isVideoLiked) {
log.fine('Video is liked, unliking it');
VideoInList? v = p.videos.firstWhereOrNull((element) => element.videoId == state.videoId!);
if (v?.indexId != null) {
await service.deleteUserPlaylistVideo(p.playlistId, v!.indexId!);
state.isVideoLiked = !state.isVideoLiked;
isVideoLiked = isVideoLiked;
}
} else {
log.fine('Video is not liked yet, we add it to the like playlist');
await service.addVideoToPlaylist(p.playlistId, state.videoId!);
state.isVideoLiked = !state.isVideoLiked;
isVideoLiked = isVideoLiked;
}
}
state.loading = false;
emit(state);
emit(state.copyWith(isVideoLiked: isVideoLiked, loading: false));
onReady();
}

Expand All @@ -129,5 +121,6 @@ class AddToPlaylistController {

AddToPlaylistController(this.videoId);

AddToPlaylistController._(this.playlists, this.playListCount, this.videoId, this.loading, this.isLoggedIn, this.isVideoLiked);
AddToPlaylistController._(
this.playlists, this.playListCount, this.videoId, this.loading, this.isLoggedIn, this.isVideoLiked);
}
73 changes: 62 additions & 11 deletions lib/videos/views/components/add_to_playlist_button.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:invidious/globals.dart';
import 'package:invidious/settings/models/errors/invidiousServiceError.dart';
import 'package:invidious/utils.dart';
import 'package:invidious/videos/states/add_to_playlist.dart';

import 'add_to_playlist_dialog.dart';
Expand All @@ -10,6 +14,8 @@ enum AddToPlayListButtonType {
modalSheet;
}

const buttonScaleOffset = 0.8;

class AddToPlayListButton extends StatelessWidget {
final String videoId;
final AddToPlayListButtonType type;
Expand All @@ -19,12 +25,20 @@ class AddToPlayListButton extends StatelessWidget {
{super.key, required this.videoId, this.type = AddToPlayListButtonType.appBar, this.afterAdd});

showAddToPlaylistDialog(BuildContext context) {
var locals = AppLocalizations.of(context)!;
var cubit = context.read<AddToPlaylistCubit>();
AddToPlaylistDialog.showAddToPlaylistDialog(context, playlists: cubit.state.playlists, videoId: videoId,
onAdd: (selectedPlaylistId) async {
await cubit.saveVideoToPlaylist(selectedPlaylistId);
if (afterAdd != null) {
afterAdd!();
try {
await cubit.saveVideoToPlaylist(selectedPlaylistId);
if (afterAdd != null) {
afterAdd!();
}
} catch (err) {
if (context.mounted) {
showAlertDialog(context, locals.errorAddingVideoToPlaylist,
[(err is InvidiousServiceError) ? Text(err.message) : Text(err.runtimeType.toString())]);
}
}
});
}
Expand All @@ -45,27 +59,55 @@ class AddToPlayListButton extends StatelessWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
IconButton.filledTonal(
onPressed: () => showAddToPlaylistDialog(context), icon: const Icon(Icons.playlist_add)),
AnimatedCrossFade(
crossFadeState: _.loading ? CrossFadeState.showSecond : CrossFadeState.showFirst,
firstChild: IconButton.filledTonal(
onPressed: () => showAddToPlaylistDialog(context), icon: const Icon(Icons.playlist_add)),
secondChild: FilledButton.tonal(
style: ButtonStyle(shape: MaterialStateProperty.all(const CircleBorder())),
onPressed: () {},
child: const SizedBox(
height: 10,
width: 10,
child: CircularProgressIndicator(
strokeWidth: 1,
))),
duration: animationDuration,
firstCurve: Curves.easeInOutQuad,
secondCurve: Curves.easeInOutQuad,
sizeCurve: Curves.easeInOutQuad,
),
Text(locals.addToPlaylist)
],
),
),
(AddToPlayListButtonType.appBar) => Row(
children: [
IconButton(
onPressed: cubit.toggleLike,
onPressed: _.loading ? () {} : cubit.toggleLike,
icon: _.isVideoLiked ? const Icon(Icons.favorite) : const Icon(Icons.favorite_border),
),
).animate(target: _.loading ? 0 : 1).fade(begin: 0.2, duration: animationDuration).scale(
begin: const Offset(buttonScaleOffset, buttonScaleOffset),
duration: animationDuration,
curve: Curves.easeInOutQuad),
Stack(
children: [
IconButton(
style: ButtonStyle(padding: MaterialStateProperty.all<EdgeInsets>(EdgeInsets.zero)),
onPressed: () => showAddToPlaylistDialog(context),
onPressed: _.loading ? () {} : () => showAddToPlaylistDialog(context),
icon: const Icon(
Icons.add,
),
),
)
.animate(target: _.loading ? 0 : 1)
.fade(
begin: 0.2,
duration: animationDuration,
)
.scale(
begin: const Offset(buttonScaleOffset, buttonScaleOffset),
duration: animationDuration,
curve: Curves.easeInOutQuad),
_.playListCount > 0
? Positioned(
top: 1,
Expand All @@ -76,10 +118,19 @@ class AddToPlayListButton extends StatelessWidget {
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(color: colors.secondaryContainer, shape: BoxShape.circle),
child: Text(
_.playListCount.toString(),
_.loading ? '-' : _.playListCount.toString(),
style: textTheme.labelSmall,
),
),
)
.animate(target: _.loading ? 0 : 1)
.fade(
begin: 0.2,
duration: animationDuration,
)
.scale(
begin: const Offset(buttonScaleOffset, buttonScaleOffset),
duration: animationDuration,
curve: Curves.easeInOutQuad),
),
)
: const SizedBox.shrink()
Expand Down

0 comments on commit c3d5551

Please sign in to comment.