WIP

1. Make migration from old base to new
2. Remove track with playlist (not only db deletion)
3. Make download one track add to db
This commit is contained in:
gdlbo
2024-03-17 19:22:57 +03:00
parent ba3f9b9afe
commit c79b419f5e
13 changed files with 414 additions and 152 deletions
@@ -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<MusicAction> hook(final ArrayList<MusicAction> actions, final MusicTrack musicTrack) {
public static ArrayList<MusicAction> hook(ArrayList<MusicAction> 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
);
}
}
}
@@ -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");
@@ -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<MusicTrack>) TracklistHelper.getMyCachedMusicTracks();
response.c = (ArrayList<MusicTrack>) MusicCacheImpl.getPlaylistSongs(ownerId, id);
Log.d("Playlist", "Open playlist " + ownerId + "_" + id);
if (Objects.equals(id, "-1")) {
response.b = PlaylistHelper.createCachedPlaylistMetadata();
} else {
response.c = (ArrayList<MusicTrack>) 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;
}
@@ -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"))));
}
}
});
@@ -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));
}
@@ -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<MusicTrack> getAllTracks() {
return MusicCacheDbDelegate.getAllTracks(AndroidUtils.getGlobalContext());
public static List<MusicTrack> getAllOwnTracks() {
return PlaylistCacheDbDelegate.getTracksInPlaylist(AndroidUtils.getGlobalContext(), AccountManagerUtils.getUserId() + "_-1");
}
public static List<MusicTrack> getAlbumById(String albumId) {
return MusicCacheDbDelegate.getAlbumById(AndroidUtils.getGlobalContext(), albumId);
}
public static List<MusicTrack> getFirstAlbumTrack(String albumId) {
return MusicCacheDbDelegate.getFirstAlbumTrack(AndroidUtils.getGlobalContext(), albumId);
}
public static List<MusicTrack> getPlaylist() {
return MusicCacheDbDelegate.getPlaylist(AndroidUtils.getGlobalContext());
}
public static List<MusicTrack> getPlaylistSongs(String playlist_id, String owner_id) {
return null; // get songs from playlist
public static List<MusicTrack> 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<Playlist> 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();
}
}
@@ -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<MusicTrack> getAllTracks() {
return getTracksWithCursor(getReadableDatabase().query(Constants.TABLE_NAME, null, null, null, null, null, null));
}
public List<MusicTrack> getAlbum(String albumId) {
return getAlbumTracks(albumId, null);
}
public List<MusicTrack> getFirstAlbumTrack(String albumId) {
return getAlbumTracks(albumId, "0,1");
}
private List<MusicTrack> getAlbumTracks(String albumId, @Nullable String limit) {
return getTracksWithCursor(getReadableDatabase().query(
Constants.TABLE_NAME,
@@ -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<Playlist> getAllPlaylists() {
Cursor cursor = getReadableDatabase().query(Constants.TABLE_NAME, null, null, null, null, null, null);
List<Playlist> 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<Playlist> getPlaylistsWithCursor(Cursor cur) {
List<Playlist> 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<MusicTrack> 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<MusicTrack> 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;
}
}
@@ -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<MusicTrack> getAllTracks(Context context) {
public static MusicTrack getTrackById(Context context, String trackId) {
try (var db = connectToDb(context)) {
return db.getAllTracks();
}
}
public static List<MusicTrack> getAlbumById(Context context, String albumId) {
try (var db = connectToDb(context)) {
return db.getAlbum(albumId);
}
}
public static List<MusicTrack> getFirstAlbumTrack(Context context, String albumId) {
try (var db = connectToDb(context)) {
return db.getFirstAlbumTrack(albumId);
}
}
public static List<MusicTrack> getPlaylist(Context context) {
try (var db = connectToDb(context)) {
return db.getPlaylist();
return db.getTrackById(trackId);
}
}
@@ -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<Playlist> 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<MusicTrack> 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();
}
}
}
@@ -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<Playlist> getAlbumPlaylists() {
List<Playlist> 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();
}
}
}
@@ -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<MusicTrack> getTracks() {
List<MusicTrack> tracks = MusicCacheImpl.getAllTracks();
List<MusicTrack> tracks = MusicCacheImpl.getAllOwnTracks();
boolean doNotinvertOrder = Preferences.getBoolValue("invertCachedTracks", false);
@@ -33,13 +35,8 @@ public class TracklistHelper {
return tracks;
}
public static List<MusicTrack> getTracks(String id) {
return MusicCacheImpl.getAlbumById(id);
}
public static List<MusicTrack> getTracksOne(String id) {
return MusicCacheImpl.getFirstAlbumTrack(id);
public static MusicTrack getTrack(String id) {
return MusicCacheDbDelegate.getTrackById(AndroidUtils.getGlobalContext(), id);
}
public static JSONArray tracksToIds(List<MusicTrack> tracks) {
@@ -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<MusicTrack> playlist, Callback callback) {
public static void cachePlaylist(List<MusicTrack> 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