Skip to content

Commit

Permalink
Merge pull request #9523 from Jared234/9468_permanently_set_thumbnail
Browse files Browse the repository at this point in the history
Allow the user to permanently set a thumbnail
  • Loading branch information
Stypox committed Jan 12, 2023
2 parents 062570c + 2679a4b commit fd8e92c
Show file tree
Hide file tree
Showing 12 changed files with 879 additions and 33 deletions.
737 changes: 737 additions & 0 deletions app/schemas/org.schabi.newpipe.database.AppDatabase/6.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class DatabaseMigrationTest {
@get:Rule
val testHelper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
AppDatabase::class.java.canonicalName, FrameworkSQLiteOpenHelperFactory()
AppDatabase::class.java.canonicalName,
FrameworkSQLiteOpenHelperFactory()
)

@Test
Expand All @@ -42,7 +43,8 @@ class DatabaseMigrationTest {

databaseInV2.run {
insert(
"streams", SQLiteDatabase.CONFLICT_FAIL,
"streams",
SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", DEFAULT_SERVICE_ID)
put("url", DEFAULT_URL)
Expand All @@ -54,14 +56,16 @@ class DatabaseMigrationTest {
}
)
insert(
"streams", SQLiteDatabase.CONFLICT_FAIL,
"streams",
SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", DEFAULT_SECOND_SERVICE_ID)
put("url", DEFAULT_SECOND_URL)
}
)
insert(
"streams", SQLiteDatabase.CONFLICT_FAIL,
"streams",
SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", DEFAULT_SERVICE_ID)
}
Expand All @@ -70,18 +74,31 @@ class DatabaseMigrationTest {
}

testHelper.runMigrationsAndValidate(
AppDatabase.DATABASE_NAME, Migrations.DB_VER_3,
true, Migrations.MIGRATION_2_3
AppDatabase.DATABASE_NAME,
Migrations.DB_VER_3,
true,
Migrations.MIGRATION_2_3
)

testHelper.runMigrationsAndValidate(
AppDatabase.DATABASE_NAME, Migrations.DB_VER_4,
true, Migrations.MIGRATION_3_4
AppDatabase.DATABASE_NAME,
Migrations.DB_VER_4,
true,
Migrations.MIGRATION_3_4
)

testHelper.runMigrationsAndValidate(
AppDatabase.DATABASE_NAME, Migrations.DB_VER_5,
true, Migrations.MIGRATION_4_5
AppDatabase.DATABASE_NAME,
Migrations.DB_VER_5,
true,
Migrations.MIGRATION_4_5
)

testHelper.runMigrationsAndValidate(
AppDatabase.DATABASE_NAME,
Migrations.DB_VER_6,
true,
Migrations.MIGRATION_5_6
)

val migratedDatabaseV3 = getMigratedDatabase()
Expand Down Expand Up @@ -121,7 +138,8 @@ class DatabaseMigrationTest {
private fun getMigratedDatabase(): AppDatabase {
val database: AppDatabase = Room.databaseBuilder(
ApplicationProvider.getApplicationContext(),
AppDatabase::class.java, AppDatabase.DATABASE_NAME
AppDatabase::class.java,
AppDatabase.DATABASE_NAME
)
.build()
testHelper.closeWhenFinished(database)
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.schabi.newpipe.database.Migrations.MIGRATION_2_3;
import static org.schabi.newpipe.database.Migrations.MIGRATION_3_4;
import static org.schabi.newpipe.database.Migrations.MIGRATION_4_5;
import static org.schabi.newpipe.database.Migrations.MIGRATION_5_6;

import android.content.Context;
import android.database.Cursor;
Expand All @@ -24,7 +25,8 @@ private NewPipeDatabase() {
private static AppDatabase getDatabase(final Context context) {
return Room
.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME)
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5)
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5,
MIGRATION_5_6)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.schabi.newpipe.database;

import static org.schabi.newpipe.database.Migrations.DB_VER_5;
import static org.schabi.newpipe.database.Migrations.DB_VER_6;

import androidx.room.Database;
import androidx.room.RoomDatabase;
Expand Down Expand Up @@ -38,7 +38,7 @@
FeedEntity.class, FeedGroupEntity.class, FeedGroupSubscriptionEntity.class,
FeedLastUpdatedEntity.class
},
version = DB_VER_5
version = DB_VER_6
)
public abstract class AppDatabase extends RoomDatabase {
public static final String DATABASE_NAME = "newpipe.db";
Expand Down
9 changes: 9 additions & 0 deletions app/src/main/java/org/schabi/newpipe/database/Migrations.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public final class Migrations {
public static final int DB_VER_3 = 3;
public static final int DB_VER_4 = 4;
public static final int DB_VER_5 = 5;
public static final int DB_VER_6 = 6;

private static final String TAG = Migrations.class.getName();
public static final boolean DEBUG = MainActivity.DEBUG;
Expand Down Expand Up @@ -188,6 +189,14 @@ public void migrate(@NonNull final SupportSQLiteDatabase database) {
}
};

public static final Migration MIGRATION_5_6 = new Migration(DB_VER_5, DB_VER_6) {
@Override
public void migrate(@NonNull final SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE `playlists` ADD COLUMN `is_thumbnail_permanent` "
+ "INTEGER NOT NULL DEFAULT 0");
}
};

private Migrations() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.PLAYLIST_STREAM_JOIN_TABLE;
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_ID;
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_TABLE;
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_THUMBNAIL_URL;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID_ALIAS;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_PROGRESS_MILLIS;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
Expand Down Expand Up @@ -53,6 +54,15 @@ default Flowable<List<PlaylistStreamEntity>> listByService(final int serviceId)
+ " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId")
Flowable<Integer> getMaximumIndexOf(long playlistId);

@Query("SELECT CASE WHEN COUNT(*) != 0 then " + STREAM_THUMBNAIL_URL + " ELSE :defaultUrl END"
+ " FROM " + STREAM_TABLE
+ " LEFT JOIN " + PLAYLIST_STREAM_JOIN_TABLE
+ " ON " + STREAM_ID + " = " + JOIN_STREAM_ID
+ " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId "
+ " LIMIT 1"
)
Flowable<String> getAutomaticThumbnailUrl(long playlistId, String defaultUrl);

@RewriteQueriesToDropUnusedColumns
@Transaction
@Query("SELECT * FROM " + STREAM_TABLE + " INNER JOIN "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class PlaylistEntity {
public static final String PLAYLIST_ID = "uid";
public static final String PLAYLIST_NAME = "name";
public static final String PLAYLIST_THUMBNAIL_URL = "thumbnail_url";
public static final String PLAYLIST_THUMBNAIL_PERMANENT = "is_thumbnail_permanent";

@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = PLAYLIST_ID)
Expand All @@ -26,9 +27,14 @@ public class PlaylistEntity {
@ColumnInfo(name = PLAYLIST_THUMBNAIL_URL)
private String thumbnailUrl;

public PlaylistEntity(final String name, final String thumbnailUrl) {
@ColumnInfo(name = PLAYLIST_THUMBNAIL_PERMANENT)
private boolean isThumbnailPermanent;

public PlaylistEntity(final String name, final String thumbnailUrl,
final boolean isThumbnailPermanent) {
this.name = name;
this.thumbnailUrl = thumbnailUrl;
this.isThumbnailPermanent = isThumbnailPermanent;
}

public long getUid() {
Expand All @@ -54,4 +60,13 @@ public String getThumbnailUrl() {
public void setThumbnailUrl(final String thumbnailUrl) {
this.thumbnailUrl = thumbnailUrl;
}

public boolean getIsThumbnailPermanent() {
return isThumbnailPermanent;
}

public void setIsThumbnailPermanent(final boolean isThumbnailSet) {
this.isThumbnailPermanent = isThumbnailSet;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.schabi.newpipe.local.bookmark;

import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Parcelable;
import android.text.InputType;
Expand Down Expand Up @@ -31,6 +32,7 @@
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;

import java.util.ArrayList;
import java.util.List;

import icepick.State;
Expand Down Expand Up @@ -256,6 +258,41 @@ private void showRemoteDeleteDialog(final PlaylistRemoteEntity item) {
}

private void showLocalDialog(final PlaylistMetadataEntry selectedItem) {
final String rename = getString(R.string.rename);
final String delete = getString(R.string.delete);
final String unsetThumbnail = getString(R.string.unset_playlist_thumbnail);
final boolean isThumbnailPermanent = localPlaylistManager
.getIsPlaylistThumbnailPermanent(selectedItem.uid);

final AlertDialog.Builder builder = new AlertDialog.Builder(activity);

final ArrayList<String> items = new ArrayList<>();
items.add(rename);
items.add(delete);
if (isThumbnailPermanent) {
items.add(unsetThumbnail);
}

final DialogInterface.OnClickListener action = (d, index) -> {
if (items.get(index).equals(rename)) {
showRenameDialog(selectedItem);
} else if (items.get(index).equals(delete)) {
showDeleteDialog(selectedItem.name,
localPlaylistManager.deletePlaylist(selectedItem.uid));
} else if (isThumbnailPermanent && items.get(index).equals(unsetThumbnail)) {
final String thumbnailUrl = localPlaylistManager
.getAutomaticPlaylistThumbnail(selectedItem.uid);
localPlaylistManager
.changePlaylistThumbnail(selectedItem.uid, thumbnailUrl, false)
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
}
};

builder.setItems(items.toArray(new String[0]), action).create().show();
}

private void showRenameDialog(final PlaylistMetadataEntry selectedItem) {
final DialogEditTextBinding dialogBinding =
DialogEditTextBinding.inflate(getLayoutInflater());
dialogBinding.dialogEditText.setHint(R.string.name);
Expand All @@ -269,11 +306,6 @@ private void showLocalDialog(final PlaylistMetadataEntry selectedItem) {
selectedItem.uid,
dialogBinding.dialogEditText.getText().toString()))
.setNegativeButton(R.string.cancel, null)
.setNeutralButton(R.string.delete, (dialog, which) -> {
showDeleteDialog(selectedItem.name,
localPlaylistManager.deletePlaylist(selectedItem.uid));
dialog.dismiss();
})
.create()
.show();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ private void onPlaylistSelected(@NonNull final LocalPlaylistManager manager,
if (playlist.thumbnailUrl
.equals("drawable://" + R.drawable.placeholder_thumbnail_playlist)) {
playlistDisposables.add(manager
.changePlaylistThumbnail(playlist.uid, streams.get(0).getThumbnailUrl())
.changePlaylistThumbnail(playlist.uid, streams.get(0).getThumbnailUrl(), false)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(ignored -> successToast.show()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ public void removeWatchedStreams(final boolean removePartiallyWatched) {
.zipWith(historyIdsMaybe, (playlist, historyStreamIds) -> {
// Remove Watched, Functionality data
final List<PlaylistStreamEntry> notWatchedItems = new ArrayList<>();
final boolean isThumbnailPermanent = playlistManager
.getIsPlaylistThumbnailPermanent(playlistId);
boolean thumbnailVideoRemoved = false;

if (removePartiallyWatched) {
Expand All @@ -414,7 +416,7 @@ public void removeWatchedStreams(final boolean removePartiallyWatched) {

if (indexInHistory < 0) {
notWatchedItems.add(playlistItem);
} else if (!thumbnailVideoRemoved
} else if (!isThumbnailPermanent && !thumbnailVideoRemoved
&& playlistManager.getPlaylistThumbnail(playlistId)
.equals(playlistItem.getStreamEntity().getThumbnailUrl())) {
thumbnailVideoRemoved = true;
Expand All @@ -435,7 +437,7 @@ public void removeWatchedStreams(final boolean removePartiallyWatched) {
if (indexInHistory < 0 || (streamStateEntity != null
&& !streamStateEntity.isFinished(duration))) {
notWatchedItems.add(playlistItem);
} else if (!thumbnailVideoRemoved
} else if (!isThumbnailPermanent && !thumbnailVideoRemoved
&& playlistManager.getPlaylistThumbnail(playlistId)
.equals(playlistItem.getStreamEntity().getThumbnailUrl())) {
thumbnailVideoRemoved = true;
Expand Down Expand Up @@ -585,8 +587,9 @@ private void changePlaylistName(final String title) {
disposables.add(disposable);
}

private void changeThumbnailUrl(final String thumbnailUrl) {
if (playlistManager == null) {
private void changeThumbnailUrl(final String thumbnailUrl, final boolean isPermanent) {
if (playlistManager == null || (!isPermanent && playlistManager
.getIsPlaylistThumbnailPermanent(playlistId))) {
return;
}

Expand All @@ -600,7 +603,7 @@ private void changeThumbnailUrl(final String thumbnailUrl) {
}

final Disposable disposable = playlistManager
.changePlaylistThumbnail(playlistId, thumbnailUrl)
.changePlaylistThumbnail(playlistId, thumbnailUrl, isPermanent)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(ignore -> successToast.show(), throwable ->
showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK,
Expand All @@ -609,6 +612,10 @@ private void changeThumbnailUrl(final String thumbnailUrl) {
}

private void updateThumbnailUrl() {
if (playlistManager.getIsPlaylistThumbnailPermanent(playlistId)) {
return;
}

final String newThumbnailUrl;

if (!itemListAdapter.getItemsList().isEmpty()) {
Expand All @@ -618,7 +625,7 @@ private void updateThumbnailUrl() {
newThumbnailUrl = "drawable://" + R.drawable.placeholder_thumbnail_playlist;
}

changeThumbnailUrl(newThumbnailUrl);
changeThumbnailUrl(newThumbnailUrl, false);
}

private void deleteItem(final PlaylistStreamEntry item) {
Expand Down Expand Up @@ -786,7 +793,8 @@ context, getPlayQueueStartingAt(item), true))
.setAction(
StreamDialogDefaultEntry.SET_AS_PLAYLIST_THUMBNAIL,
(f, i) ->
changeThumbnailUrl(item.getStreamEntity().getThumbnailUrl()))
changeThumbnailUrl(item.getStreamEntity().getThumbnailUrl(),
true))
.setAction(
StreamDialogDefaultEntry.DELETE,
(f, i) -> deleteItem(item))
Expand Down
Loading

0 comments on commit fd8e92c

Please sign in to comment.