Skip to content

Commit

Permalink
Add sync button to playlist screen
Browse files Browse the repository at this point in the history
  • Loading branch information
shayaantx committed Nov 8, 2023
1 parent a1ec325 commit f6527e2
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 1 deletion.
5 changes: 4 additions & 1 deletion lib/components/AlbumScreen/album_screen_content.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:finamp/components/AlbumScreen/sync_playlist.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Expand Down Expand Up @@ -77,7 +78,9 @@ class _AlbumScreenContentState extends State<AlbumScreenContent> {
!FinampSettingsHelper.finampSettings.isOffline)
PlaylistNameEditButton(playlist: widget.parent),
FavoriteButton(item: widget.parent),
DownloadButton(parent: widget.parent, items: widget.children)
DownloadButton(parent: widget.parent, items: widget.children),
if (widget.parent.type == "Playlist" && !FinampSettingsHelper.finampSettings.isOffline)
SyncPlaylistButton(parent: widget.parent, items: widget.children)
],
),
if (widget.children.length > 1 &&
Expand Down
86 changes: 86 additions & 0 deletions lib/components/AlbumScreen/sync_playlist.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import 'dart:collection';

import 'package:finamp/models/finamp_models.dart';
import 'package:finamp/models/jellyfin_models.dart';
import 'package:finamp/services/downloads_helper.dart';
import 'package:finamp/services/jellyfin_api_helper.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:logging/logging.dart';

import '../../services/finamp_settings_helper.dart';
import '../../services/finamp_user_helper.dart';

class SyncPlaylistButton extends StatefulWidget {
const SyncPlaylistButton({
Key? key,
required this.parent,
required this.items,
}) : super(key: key);

final BaseItemDto parent;
final List<BaseItemDto> items;
@override
State<SyncPlaylistButton> createState() =>
_SyncPlaylistButtonState();
}
class _SyncPlaylistButtonState
extends State<SyncPlaylistButton> {
final _syncLogger = Logger("SyncPlaylistButton");
final DownloadsHelper downloadsHelper = GetIt.instance<DownloadsHelper>();
final JellyfinApiHelper jellyfinApiHelper = GetIt.instance<JellyfinApiHelper>();
final FinampUserHelper _finampUserHelper = GetIt.instance<FinampUserHelper>();

void syncPlaylist() async {
_syncLogger.info("Syncing playlist");

List<DownloadedSong> downloadedSongs = downloadsHelper.downloadedItems.toList();
Map<String, DownloadedSong> downloadedSongsCache = HashMap();
Map<String, BaseItemDto> playlistItems = HashMap();
String playlistParentId = widget.parent.id;
for (BaseItemDto item in widget.items) {
// songs actively in playlist
playlistItems.putIfAbsent(item.id, () => item);
}

for (DownloadedSong downloadedSong in downloadedSongs) {
if (downloadedSong.mediaSourceInfo.id != null &&
downloadedSong.requiredBy.contains(playlistParentId)) {
// songs actively downloaded
downloadedSongsCache.putIfAbsent(downloadedSong.mediaSourceInfo.id!, () => downloadedSong);
}
}

Set<String> playlistIds = playlistItems.keys.toSet();
Set<String> downloadedIds = downloadedSongsCache.keys.toSet();
Set<String> idsToAdd = playlistIds.difference(downloadedIds);
Set<String> idsToRemove = downloadedIds.difference(playlistIds);
Set<String> unchangedIds = playlistIds.intersection(downloadedIds);

_syncLogger.info("Items to be added $idsToAdd");
_syncLogger.info("Items to be removed $idsToRemove");
_syncLogger.info("Items with no change $unchangedIds");
await downloadsHelper.deleteDownloads(jellyfinItemIds: idsToRemove.toList());
await downloadsHelper.removeChildFromParent(parentId: playlistParentId, childIds: idsToRemove.toList());

DownloadLocation location = FinampSettingsHelper.finampSettings.downloadLocationsMap.values.first;
for (String itemToAdd in idsToAdd) {
BaseItemDto? item = playlistItems.remove(itemToAdd);
if (item != null) {
await downloadsHelper.addDownloads(
items: [item],
parent: widget.parent,
useHumanReadableNames: location.useHumanReadableNames,
downloadLocation: location,
viewId: _finampUserHelper.currentUser!.currentViewId!,
);
}
}
}

@override
Widget build(BuildContext context) {
return IconButton(
onPressed: () => syncPlaylist(), icon: const Icon(Icons.sync));
}
}
7 changes: 7 additions & 0 deletions lib/services/downloads_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ class DownloadsHelper {
}
}

Future<void> removeChildFromParent({required String parentId, required List<String> childIds}) async {
var album = _downloadedParentsBox.get(parentId);
for (String childId in childIds) {
album?.downloadedChildren.removeWhere((key, value) => key == childId);
}
}

/// Deletes download tasks for items with ids in jellyfinItemIds from storage
/// and removes the Hive entries for that download task. If deletedFor is
/// specified, also do checks to delete the parent album. The only time
Expand Down

0 comments on commit f6527e2

Please sign in to comment.