diff --git a/app/src/main/java/ru/vtosters/hooks/music/MusicBottomSheetHook.java b/app/src/main/java/ru/vtosters/hooks/music/MusicBottomSheetHook.java index ad050c7b1..4aaa8299e 100644 --- a/app/src/main/java/ru/vtosters/hooks/music/MusicBottomSheetHook.java +++ b/app/src/main/java/ru/vtosters/hooks/music/MusicBottomSheetHook.java @@ -9,6 +9,7 @@ import com.vk.music.common.MusicPlaybackLaunchContext; import com.vtosters.lite.R; import ru.vtosters.lite.downloaders.AudioDownloader; import ru.vtosters.lite.music.cache.MusicCacheImpl; +import ru.vtosters.lite.music.cache.delegate.PlaylistCacheDbDelegate; import ru.vtosters.lite.utils.AndroidUtils; import ru.vtosters.lite.utils.music.VKXUtils; @@ -19,18 +20,29 @@ import static ru.vtosters.hooks.other.Preferences.milkshake; import static ru.vtosters.lite.utils.NetworkUtils.isNetworkConnected; public class MusicBottomSheetHook { - public static ArrayList hook(final ArrayList actions, final MusicTrack musicTrack) { + public static ArrayList hook(ArrayList actions, MusicTrack musicTrack) { if (musicTrack.F1()) return actions; - final var trackId = asId(musicTrack); + + String trackId = asId(musicTrack); + if (isVkxInstalled()) actions.add(getPlayInVKXAction()); + if (isIntegrationEnabled()) { - if (VKXUtils.isVkxCached(trackId)) actions.add(getRemoveCacheTrackVkxAction()); - else if (isNetworkConnected()) actions.add(addToCacheTrackVkxAction()); + if (VKXUtils.isVkxCached(trackId)) { + actions.add(getRemoveCacheTrackVkxAction()); + } else if (isNetworkConnected()) { + actions.add(addToCacheTrackVkxAction()); + } } else { - if (MusicCacheImpl.isCachedTrack(trackId)) actions.add(getRemoveCacheTrackAction()); - else if (isNetworkConnected()) actions.add(addToCacheTrackAction()); + if (MusicCacheImpl.isCachedTrack(trackId)) { + actions.add(getRemoveCacheTrackAction()); + } else if (isNetworkConnected()) { + actions.add(addToCacheTrackAction()); + } } + if (isNetworkConnected()) actions.add(downloadAsMp3Action()); + return actions; } @@ -72,8 +84,12 @@ public class MusicBottomSheetHook { } else if (isNetworkConnected()) { actions.add(addToCacheTrackVkxAction()); } - } else if (isNetworkConnected()) { - actions.add(addToCacheTrackAction()); + } else { + if (PlaylistCacheDbDelegate.isCachedPlaylist(AndroidUtils.getGlobalContext(), playlist.v1())) { + actions.add(getRemoveCacheTrackAction()); + } else if (isNetworkConnected()) { + actions.add(addToCacheTrackAction()); + } } if (isNetworkConnected()) actions.add(downloadAsMp3Action()); @@ -134,20 +150,24 @@ public class MusicBottomSheetHook { } public static boolean injectOnClick(int actionId, Playlist playlist) { // playlist inj - if (actionId == R.id.play_in_vkx) + if (actionId == R.id.play_in_vkx) { return tryPlayInVKX(null, null, playlist); - - if (actionId == R.id.add_to_cache) { + } + + if (actionId == R.id.remove_from_cache) { + PlaylistCacheDbDelegate.deletePlaylist(AndroidUtils.getGlobalContext(), playlist.v1()); + return true; + } else if (actionId == R.id.add_to_cache) { AudioDownloader.cachePlaylist(playlist); return true; } - + if (actionId == R.id.remove_from_cache_vkx) { getInstance().runOnService(service -> { try { service.deletePlaylistFromCache(playlist.a, playlist.b); } catch (RemoteException e) { - e.printStackTrace(); + e.fillInStackTrace(); } }); return true; @@ -156,7 +176,7 @@ public class MusicBottomSheetHook { try { service.addPlaylistToCache(playlist.a, playlist.b, (playlist.Q != null) ? playlist.Q : ""); } catch (RemoteException e) { - e.printStackTrace(); + e.fillInStackTrace(); } }); return true; @@ -168,7 +188,7 @@ public class MusicBottomSheetHook { try { service.downloadPlaylist(playlist.a, playlist.b, (playlist.Q != null) ? playlist.Q : ""); } catch (RemoteException e) { - e.printStackTrace(); + e.fillInStackTrace(); } }); } else { @@ -258,4 +278,4 @@ public class MusicBottomSheetHook { false ); } -} +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/hooks/music/injectors/CatalogJsonInjector.java b/app/src/main/java/ru/vtosters/hooks/music/injectors/CatalogJsonInjector.java index eefacc01d..bc936430d 100644 --- a/app/src/main/java/ru/vtosters/hooks/music/injectors/CatalogJsonInjector.java +++ b/app/src/main/java/ru/vtosters/hooks/music/injectors/CatalogJsonInjector.java @@ -94,7 +94,6 @@ public class CatalogJsonInjector { PlaylistHelper.addCachedPlaylists(json.optJSONArray("playlists"), noPlaylists); - if (!useOldAppVer && !noPlaylists) { var newBlocks = new JSONArray(); @@ -117,12 +116,15 @@ public class CatalogJsonInjector { if (type.equals("music_playlists") && j.has("playlists_ids")) { var newarr = new JSONArray(); - var playlists_ids = j.optJSONArray("playlists_ids"); + var playlists_ids = j.getJSONArray("playlists_ids"); + var savedPlaylists = PlaylistHelper.getCachedPlaylistsIds(); - newarr.put(getUserId() + "_-1"); + for (int n = 0; n < savedPlaylists.length(); n++) { + newarr.put(savedPlaylists.getString(n)); + } for (int n = 0; n < playlists_ids.length(); n++) { - newarr.put(playlists_ids.optString(n)); + newarr.put(playlists_ids.getString(n)); } Log.d("catalogInjector", "added to pl ids"); diff --git a/app/src/main/java/ru/vtosters/hooks/music/injectors/PlaylistInjector.java b/app/src/main/java/ru/vtosters/hooks/music/injectors/PlaylistInjector.java index ac14a34a0..537166b6a 100644 --- a/app/src/main/java/ru/vtosters/hooks/music/injectors/PlaylistInjector.java +++ b/app/src/main/java/ru/vtosters/hooks/music/injectors/PlaylistInjector.java @@ -18,6 +18,7 @@ import ru.vtosters.lite.music.cache.helpers.TracklistHelper; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -70,7 +71,7 @@ public class PlaylistInjector { response.c = tracks; } catch (RemoteException | JSONException e) { - e.printStackTrace(); + e.fillInStackTrace(); response.c = new ArrayList<>(); } observableEmitter.b(response); @@ -79,18 +80,20 @@ public class PlaylistInjector { return; } - if (isVirtualPlaylist) { - response.c = (ArrayList) TracklistHelper.getMyCachedMusicTracks(); + response.c = (ArrayList) MusicCacheImpl.getPlaylistSongs(ownerId, id); + + Log.d("Playlist", "Open playlist " + ownerId + "_" + id); + + if (Objects.equals(id, "-1")) { response.b = PlaylistHelper.createCachedPlaylistMetadata(); } else { - response.c = (ArrayList) MusicCacheImpl.getPlaylistSongs(requestArgs.get("id"), requestArgs.get("owner_id")); - response.b = MusicCacheImpl.getPlaylist(requestArgs.get("id"), requestArgs.get("owner_id")); + response.b = MusicCacheImpl.getPlaylist(id, ownerId); } observableEmitter.b(response); }); } catch (Exception e) { - e.printStackTrace(); + e.fillInStackTrace(); } return null; } diff --git a/app/src/main/java/ru/vtosters/hooks/music/injectors/TracklistInjector.java b/app/src/main/java/ru/vtosters/hooks/music/injectors/TracklistInjector.java index 4c2ee31fd..7e1ad50ca 100644 --- a/app/src/main/java/ru/vtosters/hooks/music/injectors/TracklistInjector.java +++ b/app/src/main/java/ru/vtosters/hooks/music/injectors/TracklistInjector.java @@ -12,6 +12,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import ru.vtosters.lite.music.cache.MusicCacheImpl; +import ru.vtosters.lite.music.cache.delegate.PlaylistCacheDbDelegate; import ru.vtosters.lite.music.cache.helpers.PlaylistHelper; import ru.vtosters.lite.music.cache.helpers.TracklistHelper; import ru.vtosters.lite.utils.AccountManagerUtils; @@ -61,7 +62,9 @@ public class TracklistInjector { if (MusicCacheImpl.isEmpty()) { observableEmitter.b(parser.c(getEmptyCatalog())); } else { - observableEmitter.b(parser.c(createVirtualCatalog(TracklistHelper.getTracks()))); + observableEmitter.b(parser.c(createVirtualCatalog( + PlaylistCacheDbDelegate.getTracksInPlaylist(AndroidUtils.getGlobalContext(), + AccountManagerUtils.getUserId() + "_-1")))); } } }); diff --git a/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java b/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java index cfdaaf641..2f2bd8e46 100644 --- a/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java +++ b/app/src/main/java/ru/vtosters/lite/downloaders/AudioDownloader.java @@ -1,6 +1,7 @@ package ru.vtosters.lite.downloaders; import android.os.Environment; +import android.util.Log; import bruhcollective.itaysonlab.libvkx.client.LibVKXClient; import com.vk.core.util.ToastUtils; import com.vk.dto.music.MusicTrack; @@ -9,6 +10,7 @@ import com.vtosters.lite.R; import ru.vtosters.hooks.music.MusicCacheFilesHook; import ru.vtosters.hooks.other.Preferences; import ru.vtosters.lite.music.cache.MusicCacheImpl; +import ru.vtosters.lite.music.cache.delegate.PlaylistCacheDbDelegate; import ru.vtosters.lite.music.callback.MusicCallbackBuilder; import ru.vtosters.lite.music.converter.playlist.PlaylistConverter; import ru.vtosters.lite.music.downloader.AudioGet; @@ -80,9 +82,14 @@ public class AudioDownloader { var notificationId = playlist.g.hashCode(); var notification = MusicNotificationBuilder.buildPlaylistDownloadNotification(playlist.g, notificationId); + PlaylistCacheDbDelegate.addPlaylist(AndroidUtils.getGlobalContext(), playlist); + + Log.d("Playlist", "adding to cache " + playlist.a); + PlaylistDownloader.cachePlaylist( tracks, - MusicCallbackBuilder.buildPlaylistCallback(tracks.size(), notification, notificationId) + MusicCallbackBuilder.buildPlaylistCallback(tracks.size(), notification, notificationId), + playlist.v1() ); } @@ -94,7 +101,8 @@ public class AudioDownloader { PlaylistDownloader.cachePlaylist( tracks, - MusicCallbackBuilder.buildPlaylistCallback(tracks.size(), notification, notificationId) + MusicCallbackBuilder.buildPlaylistCallback(tracks.size(), notification, notificationId), + AccountManagerUtils.getUserId() + "_-1" ); } @@ -130,6 +138,7 @@ public class AudioDownloader { if (cache) { TrackDownloader.cacheTrack(track, MusicCallbackBuilder.buildOneTrackCallback(tempId, notification)); + PlaylistCacheDbDelegate.addTrackToPlaylist(AndroidUtils.getGlobalContext(), AccountManagerUtils.getUserId() + "_-1", track.y1()); // TODO Move to download success } else { TrackDownloader.downloadTrack(track, downloadPath, MusicCallbackBuilder.buildOneTrackCallback(tempId, notification)); } diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheImpl.java b/app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheImpl.java index 617844e59..b9f5b8de9 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheImpl.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheImpl.java @@ -7,11 +7,13 @@ import bruhcollective.itaysonlab.libvkx.client.LibVKXClient; import bruhcollective.itaysonlab.libvkx.client.LibVKXClientImpl; import com.vk.dto.music.MusicTrack; import com.vk.dto.music.Playlist; +import ru.vtosters.lite.music.cache.delegate.MusicCacheDbDelegate; +import ru.vtosters.lite.music.cache.delegate.PlaylistCacheDbDelegate; import ru.vtosters.lite.music.downloader.M3UDownloader; +import ru.vtosters.lite.utils.AccountManagerUtils; import ru.vtosters.lite.utils.AndroidUtils; import ru.vtosters.lite.utils.music.MusicCacheStorageUtils; -import java.util.ArrayList; import java.util.List; public class MusicCacheImpl { @@ -34,40 +36,28 @@ public class MusicCacheImpl { MusicCacheStorageUtils.removeTrackDirById(trackId); } - public static List getAllTracks() { - return MusicCacheDbDelegate.getAllTracks(AndroidUtils.getGlobalContext()); + public static List getAllOwnTracks() { + return PlaylistCacheDbDelegate.getTracksInPlaylist(AndroidUtils.getGlobalContext(), AccountManagerUtils.getUserId() + "_-1"); } - public static List getAlbumById(String albumId) { - return MusicCacheDbDelegate.getAlbumById(AndroidUtils.getGlobalContext(), albumId); - } - - public static List getFirstAlbumTrack(String albumId) { - return MusicCacheDbDelegate.getFirstAlbumTrack(AndroidUtils.getGlobalContext(), albumId); - } - - public static List getPlaylist() { - return MusicCacheDbDelegate.getPlaylist(AndroidUtils.getGlobalContext()); - } - - public static List getPlaylistSongs(String playlist_id, String owner_id) { - return null; // get songs from playlist + public static List getPlaylistSongs(String owner_id, String playlist_id) { + return PlaylistCacheDbDelegate.getTracksInPlaylist(AndroidUtils.getGlobalContext(), owner_id + "_" + playlist_id); // get songs from playlist } public static Playlist getPlaylist(String playlist_id, String owner_id) { - return getPlaylist(""); // get playlist from db + return getPlaylistById(owner_id + "_" + playlist_id); // get playlist from db } public static List getPlaylists() { - return new ArrayList<>(); // get all cached playlists + return PlaylistCacheDbDelegate.getAllPlaylists(AndroidUtils.getGlobalContext()); // get all cached playlists } - public static Playlist getPlaylist(String query) { - return null; // get playlist from db + public static Playlist getPlaylistById(String query) { + return PlaylistCacheDbDelegate.getPlaylistById(AndroidUtils.getGlobalContext(), query); // get playlist from db } public static boolean hasPlaylist() { - return false; // has playlists or not + return PlaylistCacheDbDelegate.getPlaylistsCount(AndroidUtils.getGlobalContext()) != 0; // has playlists or not } public static long getTracksCount() { @@ -80,7 +70,7 @@ public class MusicCacheImpl { try { return (long) service.getCache().size(); } catch (RemoteException e) { - e.printStackTrace(); + e.fillInStackTrace(); return defaultValue(); } } diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/db/MusicCacheDb.java b/app/src/main/java/ru/vtosters/lite/music/cache/db/MusicCacheDb.java index e13e2c1ce..bbdaf4fe3 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/db/MusicCacheDb.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/db/MusicCacheDb.java @@ -166,18 +166,21 @@ public class MusicCacheDb extends SQLiteOpenHelper implements AutoCloseable { // return DatabaseUtils.queryNumEntries(getReadableDatabase(), Constants.TABLE_NAME); } + public MusicTrack getTrackById(String trackId) { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.query(Constants.TABLE_NAME, null, Constants.COLUMN_TRACK_ID + " = ?", new String[]{trackId}, null, null, null); + MusicTrack track = null; + if (cursor.moveToFirst()) { + track = fromCursor(cursor); + } + cursor.close(); + return track; + } + public List getAllTracks() { return getTracksWithCursor(getReadableDatabase().query(Constants.TABLE_NAME, null, null, null, null, null, null)); } - public List getAlbum(String albumId) { - return getAlbumTracks(albumId, null); - } - - public List getFirstAlbumTrack(String albumId) { - return getAlbumTracks(albumId, "0,1"); - } - private List getAlbumTracks(String albumId, @Nullable String limit) { return getTracksWithCursor(getReadableDatabase().query( Constants.TABLE_NAME, diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/db/PlaylistCacheDb.java b/app/src/main/java/ru/vtosters/lite/music/cache/db/PlaylistCacheDb.java new file mode 100644 index 000000000..20120b53f --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/music/cache/db/PlaylistCacheDb.java @@ -0,0 +1,198 @@ +package ru.vtosters.lite.music.cache.db; + +import android.annotation.SuppressLint; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; +import com.vk.dto.music.MusicTrack; +import com.vk.dto.music.Playlist; +import org.json.JSONException; +import org.json.JSONObject; +import ru.vtosters.lite.music.cache.helpers.PlaylistHelper; +import ru.vtosters.lite.music.cache.helpers.TracklistHelper; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; + +public class PlaylistCacheDb extends SQLiteOpenHelper implements AutoCloseable { + public PlaylistCacheDb(Context context) { + super(context, Constants.DB_NAME, null, Constants.DV_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL(Constants.CREATE_QUERY); + db.execSQL(Constants.CREATE_PLAYLIST_TRACKS_QUERY); + } + + private static Playlist fromCursor(Cursor cur) throws JSONException { + @SuppressLint("Range") + JSONObject playlist = PlaylistHelper.generatePlaylist( + cur.getInt(cur.getColumnIndex(Constants.COLUMN_ID)), + cur.getInt(cur.getColumnIndex(Constants.COLUMN_OWNER_ID)), + Boolean.parseBoolean(cur.getString(cur.getColumnIndex(Constants.COLUMN_IS_EXPLICIT))), + cur.getString(cur.getColumnIndex(Constants.COLUMN_TITLE)), + cur.getString(cur.getColumnIndex(Constants.COLUMN_DESCRIPTION)), + new JSONObject(cur.getString(cur.getColumnIndex(Constants.COLUMN_PHOTO))) + ); + + Log.d("Playlist", "generated " + Playlist.U.a(playlist).v1()); + + return Playlist.U.a(playlist); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL(Constants.DROP_QUERY); + onCreate(db); + } + + public void addPlaylist(int id, int ownerId, boolean isExplicit, String title, String description, JSONObject photo) { + ContentValues values = new ContentValues(); + values.put(Constants.COLUMN_ID, id); + values.put(Constants.COLUMN_OWNER_ID, ownerId); + values.put(Constants.COLUMN_IS_EXPLICIT, isExplicit); + values.put(Constants.COLUMN_TITLE, title); + values.put(Constants.COLUMN_DESCRIPTION, description); + values.put(Constants.COLUMN_PHOTO, String.valueOf(photo)); + + getWritableDatabase().insert(Constants.TABLE_NAME, null, values); + } + + public void deletePlaylist(int id, int ownerId) { + getWritableDatabase().delete(Constants.TABLE_NAME, Constants.COLUMN_ID + " = ? AND " + Constants.COLUMN_OWNER_ID + " = ?", new String[]{String.valueOf(id), String.valueOf(ownerId)}); + } + + public boolean isCachedPlaylist(int id, int ownerId) { + Cursor cursor = getReadableDatabase().query(Constants.TABLE_NAME, new String[]{Constants.COLUMN_ID}, Constants.COLUMN_ID + " = ? AND " + Constants.COLUMN_OWNER_ID + " = ?", new String[]{String.valueOf(id), String.valueOf(ownerId)}, null, null, null); + boolean exists = cursor.getCount() > 0; + cursor.close(); + return exists; + } + + public long getPlaylistsCount() { + return DatabaseUtils.queryNumEntries(getReadableDatabase(), Constants.TABLE_NAME); + } + + public List getAllPlaylists() { + Cursor cursor = getReadableDatabase().query(Constants.TABLE_NAME, null, null, null, null, null, null); + List playlists = getPlaylistsWithCursor(cursor); + cursor.close(); + return playlists; + } + + public Playlist getPlaylistById(int id, int ownerId) { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.query(Constants.TABLE_NAME, null, Constants.COLUMN_ID + " = ? AND " + Constants.COLUMN_OWNER_ID + " = ?", new String[]{String.valueOf(id), String.valueOf(ownerId)}, null, null, null); + Playlist playlist = null; + if (cursor.moveToFirst()) { + try { + playlist = fromCursor(cursor); + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + cursor.close(); + return playlist; + } + + private List getPlaylistsWithCursor(Cursor cur) { + List playlists = new ArrayList<>(); + while (cur.moveToNext()) { + try { + playlists.add(fromCursor(cur)); + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + return playlists; + } + + public void addTrackToPlaylist(String playlistId, String trackId) { + ContentValues values = new ContentValues(); + values.put(Constants.COLUMN_PLAYLIST_ID, playlistId); + values.put(Constants.COLUMN_TRACK_ID, trackId); + getWritableDatabase().insert(Constants.TABLE_PLAYLIST_TRACKS, null, values); + } + + public void removeTrackFromPlaylist(String playlistId, String trackId) { + getWritableDatabase().delete(Constants.TABLE_PLAYLIST_TRACKS, Constants.COLUMN_PLAYLIST_ID + " = ? AND " + Constants.COLUMN_TRACK_ID + " = ?", new String[]{playlistId, trackId}); + } + + public List getTracksInPlaylist(String playlistId) { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.query( + Constants.TABLE_PLAYLIST_TRACKS, + new String[]{Constants.COLUMN_TRACK_ID}, + Constants.COLUMN_PLAYLIST_ID + " = ?", + new String[]{playlistId}, + null, null, null + ); + + List tracks = new ArrayList<>(); + while (cursor.moveToNext()) { + @SuppressLint("Range") + String trackId = cursor.getString(cursor.getColumnIndex(Constants.COLUMN_TRACK_ID)); + MusicTrack track = TracklistHelper.getTrack(trackId); + + Log.d("Playlist", "add " + trackId + " to playlist " + playlistId); + + if (track != null) { + tracks.add(track); + } + } + + cursor.close(); + return tracks; + } + + @Override + public void onConfigure(SQLiteDatabase db) { + super.onConfigure(db); + db.setForeignKeyConstraintsEnabled(true); + } + + @Retention(RetentionPolicy.SOURCE) + public @interface Constants { + int DV_VERSION = 0x2; + String DB_NAME = "vt_lite_cache_playlists.db"; + String TABLE_NAME = "playlists"; + + //columns + String COLUMN_ID = "id"; + String COLUMN_OWNER_ID = "owner_id"; + String COLUMN_IS_EXPLICIT = "is_explicit"; + String COLUMN_TITLE = "title"; + String COLUMN_DESCRIPTION = "description"; + String COLUMN_PHOTO = "photo"; + + // tracks + String COLUMN_TRACK_ID = "track_id"; + String TABLE_PLAYLIST_TRACKS = "playlist_tracks"; + String COLUMN_PLAYLIST_ID = "playlist_id"; + + //queries + String CREATE_QUERY = "create table " + TABLE_NAME + + "(" + + COLUMN_ID + " INTEGER PRIMARY KEY autoincrement," + + COLUMN_OWNER_ID + " INTEGER not null," + + COLUMN_IS_EXPLICIT + " TEXT not null," + + COLUMN_TITLE + " TEXT not null," + + COLUMN_DESCRIPTION + " TEXT not null," + + COLUMN_PHOTO + " TEXT not null" + + ")"; + + String CREATE_PLAYLIST_TRACKS_QUERY = "create table " + TABLE_PLAYLIST_TRACKS + "(" + + COLUMN_PLAYLIST_ID + " TEXT not null," + + COLUMN_TRACK_ID + " TEXT not null" + + ")"; + + String DROP_QUERY = "drop table if exists " + TABLE_NAME; + } +} diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheDbDelegate.java b/app/src/main/java/ru/vtosters/lite/music/cache/delegate/MusicCacheDbDelegate.java similarity index 73% rename from app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheDbDelegate.java rename to app/src/main/java/ru/vtosters/lite/music/cache/delegate/MusicCacheDbDelegate.java index 3dba6e124..8d65bb312 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/MusicCacheDbDelegate.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/delegate/MusicCacheDbDelegate.java @@ -1,4 +1,4 @@ -package ru.vtosters.lite.music.cache; +package ru.vtosters.lite.music.cache.delegate; import android.content.Context; import com.vk.dto.music.MusicTrack; @@ -43,27 +43,9 @@ public class MusicCacheDbDelegate { } } - public static List getAllTracks(Context context) { + public static MusicTrack getTrackById(Context context, String trackId) { try (var db = connectToDb(context)) { - return db.getAllTracks(); - } - } - - public static List getAlbumById(Context context, String albumId) { - try (var db = connectToDb(context)) { - return db.getAlbum(albumId); - } - } - - public static List getFirstAlbumTrack(Context context, String albumId) { - try (var db = connectToDb(context)) { - return db.getFirstAlbumTrack(albumId); - } - } - - public static List getPlaylist(Context context) { - try (var db = connectToDb(context)) { - return db.getPlaylist(); + return db.getTrackById(trackId); } } diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/delegate/PlaylistCacheDbDelegate.java b/app/src/main/java/ru/vtosters/lite/music/cache/delegate/PlaylistCacheDbDelegate.java new file mode 100644 index 000000000..a82d36de8 --- /dev/null +++ b/app/src/main/java/ru/vtosters/lite/music/cache/delegate/PlaylistCacheDbDelegate.java @@ -0,0 +1,95 @@ +package ru.vtosters.lite.music.cache.delegate; + +import android.content.Context; +import com.vk.dto.music.MusicTrack; +import com.vk.dto.music.Playlist; +import org.json.JSONObject; +import ru.vtosters.lite.music.cache.db.PlaylistCacheDb; + +import java.util.List; + +public class PlaylistCacheDbDelegate { + static synchronized private PlaylistCacheDb connectToDb(Context context) { + synchronized (PlaylistCacheDb.class) { + return new PlaylistCacheDb(context); + } + } + + public static void addPlaylist(Context context, Playlist playlist) { + try (var db = connectToDb(context)) { + db.addPlaylist(playlist.a, playlist.b, playlist.C, playlist.g, playlist.B, getThumb(playlist)); + } + } + + public static void deletePlaylist(Context context, String id) { + try (var db = connectToDb(context)) { + String[] parts = id.split("_"); + int playlistId = Integer.parseInt(parts[1]); + int ownerId = Integer.parseInt(parts[0]); + + db.deletePlaylist(playlistId, ownerId); + } + } + + public static boolean isCachedPlaylist(Context context, String id) { + try (var db = connectToDb(context)) { + String[] parts = id.split("_"); + int playlistId = Integer.parseInt(parts[1]); + int ownerId = Integer.parseInt(parts[0]); + + return db.isCachedPlaylist(playlistId, ownerId); + } + } + + public static long getPlaylistsCount(Context context) { + try (var db = connectToDb(context)) { + return db.getPlaylistsCount(); + } + } + + public static List getAllPlaylists(Context context) { + try (var db = connectToDb(context)) { + return db.getAllPlaylists(); + } + } + + public static Playlist getPlaylistById(Context context, String playlistId) { + try (var db = connectToDb(context)) { + String[] parts = playlistId.split("_"); + int id = Integer.parseInt(parts[1]); + int ownerId = Integer.parseInt(parts[0]); + + return db.getPlaylistById(id, ownerId); + } + } + + public static void addTrackToPlaylist(Context context, String playlistId, String trackId) { + try (var db = connectToDb(context)) { + db.addTrackToPlaylist(playlistId, trackId); + } + } + + public static void removeTrackFromPlaylist(Context context, String playlistId, String trackId) { + try (var db = connectToDb(context)) { + db.removeTrackFromPlaylist(playlistId, trackId); + } + } + + public static List getTracksInPlaylist(Context context, String playlistId) { + try (var db = connectToDb(context)) { + return db.getTracksInPlaylist(playlistId); + } + } + + public static void drop(Context context) { + context.deleteDatabase(PlaylistCacheDb.Constants.DB_NAME); + } + + private static JSONObject getThumb(Playlist playlist) { + try { + return playlist.F.J(); + } catch (Exception e) { + return new JSONObject(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/helpers/PlaylistHelper.java b/app/src/main/java/ru/vtosters/lite/music/cache/helpers/PlaylistHelper.java index 341648c3f..148aa7167 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/helpers/PlaylistHelper.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/helpers/PlaylistHelper.java @@ -1,5 +1,7 @@ package ru.vtosters.lite.music.cache.helpers; +import android.util.Log; +import com.vk.dto.music.MusicTrack; import com.vk.dto.music.Playlist; import com.vtosters.lite.R; import org.json.JSONArray; @@ -26,65 +28,6 @@ public class PlaylistHelper { } } - public static Playlist createCachedPlaylistMetadata(String id) { - var track = TracklistHelper.getTracksOne(id).get(0); - var albumLink = track.I; - var thumb = albumLink.u1(); - return createAlbum( - thumb != null ? thumb.h(600) : "", - albumLink.getTitle(), - M3UDownloader.getArtists(track), - track.y1(), - albumLink.getId() - ); - } - - public static Playlist createAlbum(String photo, String title, String artist, String trackId, int albumId) { - return new Playlist(createAlbumJson(photo, title, artist, trackId, albumId)); - } - - public static JSONObject createAlbumJson(String photo, String title, String artist, String trackId, int albumId) { - try { - var jPhoto = new JSONObject(); - if (!photo.isEmpty()) - jPhoto.put("height", 600) - .put("width", 600) - .putOpt("photo_300", MusicCacheStorageUtils.getTrackThumb(trackId, 300)) - .putOpt("photo_600", MusicCacheStorageUtils.getTrackThumb(trackId, 600)); - return new JSONObject() - .put("id", -2) - .put("owner_id", albumId) - .put("type", 1) - .put("album_type", "main_only") - .put("title", title) - .put("description", albumId + "/ " + AndroidUtils.getString(R.string.cached_album_warning)) - .put("main_artists", new JSONArray() - .put(new JSONObject().put("name", artist) - .put("id", "-1") - .put("domain", "-1"))) - .putOpt("photo", jPhoto) - .put("count", 0); - } catch (JSONException e) { - return null; - } - } - - public static List getAlbumPlaylists() { - List list = new ArrayList<>(); - for (var track : MusicCacheImpl.getPlaylist()) { - var albumLink = track.I; - var thumb = albumLink.u1(); - list.add(createAlbum( - thumb != null ? thumb.h(600) : "", - albumLink.getTitle(), - M3UDownloader.getArtists(track), - track.y1(), - albumLink.getId() - )); - } - return list; - } - public static JSONArray addCachedPlaylists(JSONArray jsonArray, Boolean noPlaylists) { try { if (noPlaylists) { @@ -94,10 +37,16 @@ public class PlaylistHelper { } for (var playlist : MusicCacheImpl.getPlaylists()) { - jsonArray.put(generatePlaylist(playlist.a, playlist.b, playlist.C, playlist.g, playlist.B, playlist.F.J())); + if (noPlaylists) { + jsonArray.put(new JSONArray().put(generatePlaylist(playlist.a, playlist.b, playlist.C, playlist.g, playlist.B, getThumb(playlist)))); + } else { + jsonArray.put(generatePlaylist(playlist.a, playlist.b, playlist.C, playlist.g, playlist.B, getThumb(playlist))); + } + + Log.d("PlaylistHelper", "Playlist cache added: " + playlist.a + " " + playlist.b + " " + playlist.C + " " + playlist.g + " " + playlist.B + " " + playlist.F.J()); } } catch (JSONException e) { - e.printStackTrace(); + e.fillInStackTrace(); } return jsonArray; } @@ -164,7 +113,7 @@ public class PlaylistHelper { } for (var playlist : MusicCacheImpl.getPlaylists()) { - arr.put(playlist.b + "_" + playlist.a); + arr.put(playlist.v1()); } return arr; @@ -197,4 +146,12 @@ public class PlaylistHelper { .put("layout", new JSONObject() .put("name", "separator")); } + + private static JSONObject getThumb(Playlist playlist) { + try { + return playlist.F.J(); + } catch (Exception e) { + return new JSONObject(); + } + } } diff --git a/app/src/main/java/ru/vtosters/lite/music/cache/helpers/TracklistHelper.java b/app/src/main/java/ru/vtosters/lite/music/cache/helpers/TracklistHelper.java index 0eecf6c7c..400970115 100644 --- a/app/src/main/java/ru/vtosters/lite/music/cache/helpers/TracklistHelper.java +++ b/app/src/main/java/ru/vtosters/lite/music/cache/helpers/TracklistHelper.java @@ -8,6 +8,8 @@ import org.json.JSONException; import org.json.JSONObject; import ru.vtosters.hooks.other.Preferences; import ru.vtosters.lite.music.cache.MusicCacheImpl; +import ru.vtosters.lite.music.cache.delegate.MusicCacheDbDelegate; +import ru.vtosters.lite.utils.AndroidUtils; import ru.vtosters.lite.utils.music.MusicCacheStorageUtils; import java.io.File; @@ -22,7 +24,7 @@ public class TracklistHelper { } public static List getTracks() { - List tracks = MusicCacheImpl.getAllTracks(); + List tracks = MusicCacheImpl.getAllOwnTracks(); boolean doNotinvertOrder = Preferences.getBoolValue("invertCachedTracks", false); @@ -33,13 +35,8 @@ public class TracklistHelper { return tracks; } - - public static List getTracks(String id) { - return MusicCacheImpl.getAlbumById(id); - } - - public static List getTracksOne(String id) { - return MusicCacheImpl.getFirstAlbumTrack(id); + public static MusicTrack getTrack(String id) { + return MusicCacheDbDelegate.getTrackById(AndroidUtils.getGlobalContext(), id); } public static JSONArray tracksToIds(List tracks) { diff --git a/app/src/main/java/ru/vtosters/lite/music/downloader/PlaylistDownloader.java b/app/src/main/java/ru/vtosters/lite/music/downloader/PlaylistDownloader.java index dbb1d9a35..234157750 100644 --- a/app/src/main/java/ru/vtosters/lite/music/downloader/PlaylistDownloader.java +++ b/app/src/main/java/ru/vtosters/lite/music/downloader/PlaylistDownloader.java @@ -2,7 +2,9 @@ package ru.vtosters.lite.music.downloader; import android.util.Log; import com.vk.dto.music.MusicTrack; +import ru.vtosters.lite.music.cache.delegate.PlaylistCacheDbDelegate; import ru.vtosters.lite.music.interfaces.Callback; +import ru.vtosters.lite.utils.AndroidUtils; import java.io.File; import java.util.List; @@ -37,7 +39,7 @@ public class PlaylistDownloader { }); } - public static void cachePlaylist(List playlist, Callback callback) { + public static void cachePlaylist(List playlist, Callback callback, String playlistId) { var downloadedTracks = new AtomicInteger(); for (var musicTrack : playlist) TrackDownloader.cacheTrack(musicTrack, new Callback() { @@ -48,6 +50,7 @@ public class PlaylistDownloader { @Override public void onSuccess() { callback.onProgress(downloadedTracks.incrementAndGet()); + PlaylistCacheDbDelegate.addTrackToPlaylist(AndroidUtils.getGlobalContext(), playlistId, musicTrack.y1()); } @Override