Merge pull request #6919 from ktprograms/channel-details-all-places
Add Show Channel Details where it's missing
This commit is contained in:
commit
2027b743b4
16 changed files with 814 additions and 163 deletions
|
|
@ -11,6 +11,7 @@ import org.schabi.newpipe.database.AppDatabase;
|
|||
import static org.schabi.newpipe.database.AppDatabase.DATABASE_NAME;
|
||||
import static org.schabi.newpipe.database.Migrations.MIGRATION_1_2;
|
||||
import static org.schabi.newpipe.database.Migrations.MIGRATION_2_3;
|
||||
import static org.schabi.newpipe.database.Migrations.MIGRATION_3_4;
|
||||
|
||||
public final class NewPipeDatabase {
|
||||
private static volatile AppDatabase databaseInstance;
|
||||
|
|
@ -22,7 +23,7 @@ public final class NewPipeDatabase {
|
|||
private static AppDatabase getDatabase(final Context context) {
|
||||
return Room
|
||||
.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME)
|
||||
.addMigrations(MIGRATION_1_2, MIGRATION_2_3)
|
||||
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
|||
import org.schabi.newpipe.database.subscription.SubscriptionDAO;
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
||||
|
||||
import static org.schabi.newpipe.database.Migrations.DB_VER_3;
|
||||
import static org.schabi.newpipe.database.Migrations.DB_VER_4;
|
||||
|
||||
@TypeConverters({Converters.class})
|
||||
@Database(
|
||||
|
|
@ -38,7 +38,7 @@ import static org.schabi.newpipe.database.Migrations.DB_VER_3;
|
|||
FeedEntity.class, FeedGroupEntity.class, FeedGroupSubscriptionEntity.class,
|
||||
FeedLastUpdatedEntity.class
|
||||
},
|
||||
version = DB_VER_3
|
||||
version = DB_VER_4
|
||||
)
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
public static final String DATABASE_NAME = "newpipe.db";
|
||||
|
|
|
|||
|
|
@ -9,9 +9,19 @@ import androidx.sqlite.db.SupportSQLiteDatabase;
|
|||
import org.schabi.newpipe.MainActivity;
|
||||
|
||||
public final class Migrations {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Test new migrations manually by importing a database from daily usage //
|
||||
// and checking if the migration works (Use the Database Inspector //
|
||||
// https://developer.android.com/studio/inspect/database). //
|
||||
// If you add a migration point it out in the pull request, so that //
|
||||
// others remember to test it themselves. //
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static final int DB_VER_1 = 1;
|
||||
public static final int DB_VER_2 = 2;
|
||||
public static final int DB_VER_3 = 3;
|
||||
public static final int DB_VER_4 = 4;
|
||||
|
||||
private static final String TAG = Migrations.class.getName();
|
||||
public static final boolean DEBUG = MainActivity.DEBUG;
|
||||
|
|
@ -160,5 +170,14 @@ public final class Migrations {
|
|||
}
|
||||
};
|
||||
|
||||
public static final Migration MIGRATION_3_4 = new Migration(DB_VER_3, DB_VER_4) {
|
||||
@Override
|
||||
public void migrate(@NonNull final SupportSQLiteDatabase database) {
|
||||
database.execSQL(
|
||||
"ALTER TABLE streams ADD COLUMN uploader_url TEXT"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
private Migrations() { }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ data class PlaylistStreamEntry(
|
|||
val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType)
|
||||
item.duration = streamEntity.duration
|
||||
item.uploaderName = streamEntity.uploader
|
||||
item.uploaderUrl = streamEntity.uploaderUrl
|
||||
item.thumbnailUrl = streamEntity.thumbnailUrl
|
||||
|
||||
return item
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class StreamStatisticsEntry(
|
|||
val item = StreamInfoItem(streamEntity.serviceId, streamEntity.url, streamEntity.title, streamEntity.streamType)
|
||||
item.duration = streamEntity.duration
|
||||
item.uploaderName = streamEntity.uploader
|
||||
item.uploaderUrl = streamEntity.uploaderUrl
|
||||
item.thumbnailUrl = streamEntity.thumbnailUrl
|
||||
|
||||
return item
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import androidx.room.Insert
|
|||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import io.reactivex.rxjava3.core.Completable
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import org.schabi.newpipe.database.BasicDAO
|
||||
import org.schabi.newpipe.database.stream.model.StreamEntity
|
||||
|
|
@ -29,6 +30,9 @@ abstract class StreamDAO : BasicDAO<StreamEntity> {
|
|||
@Query("SELECT * FROM streams WHERE url = :url AND service_id = :serviceId")
|
||||
abstract fun getStream(serviceId: Long, url: String): Flowable<List<StreamEntity>>
|
||||
|
||||
@Query("UPDATE streams SET uploader_url = :uploaderUrl WHERE url = :url AND service_id = :serviceId")
|
||||
abstract fun setUploaderUrl(serviceId: Long, url: String, uploaderUrl: String): Completable
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
internal abstract fun silentInsertInternal(stream: StreamEntity): Long
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ data class StreamEntity(
|
|||
@ColumnInfo(name = STREAM_UPLOADER)
|
||||
var uploader: String,
|
||||
|
||||
@ColumnInfo(name = STREAM_UPLOADER_URL)
|
||||
var uploaderUrl: String? = null,
|
||||
|
||||
@ColumnInfo(name = STREAM_THUMBNAIL_URL)
|
||||
var thumbnailUrl: String? = null,
|
||||
|
||||
|
|
@ -64,7 +67,7 @@ data class StreamEntity(
|
|||
constructor(item: StreamInfoItem) : this(
|
||||
serviceId = item.serviceId, url = item.url, title = item.name,
|
||||
streamType = item.streamType, duration = item.duration, uploader = item.uploaderName,
|
||||
thumbnailUrl = item.thumbnailUrl, viewCount = item.viewCount,
|
||||
uploaderUrl = item.uploaderUrl, thumbnailUrl = item.thumbnailUrl, viewCount = item.viewCount,
|
||||
textualUploadDate = item.textualUploadDate, uploadDate = item.uploadDate?.offsetDateTime(),
|
||||
isUploadDateApproximation = item.uploadDate?.isApproximation
|
||||
)
|
||||
|
|
@ -73,7 +76,7 @@ data class StreamEntity(
|
|||
constructor(info: StreamInfo) : this(
|
||||
serviceId = info.serviceId, url = info.url, title = info.name,
|
||||
streamType = info.streamType, duration = info.duration, uploader = info.uploaderName,
|
||||
thumbnailUrl = info.thumbnailUrl, viewCount = info.viewCount,
|
||||
uploaderUrl = info.uploaderUrl, thumbnailUrl = info.thumbnailUrl, viewCount = info.viewCount,
|
||||
textualUploadDate = info.textualUploadDate, uploadDate = info.uploadDate?.offsetDateTime(),
|
||||
isUploadDateApproximation = info.uploadDate?.isApproximation
|
||||
)
|
||||
|
|
@ -82,13 +85,14 @@ data class StreamEntity(
|
|||
constructor(item: PlayQueueItem) : this(
|
||||
serviceId = item.serviceId, url = item.url, title = item.title,
|
||||
streamType = item.streamType, duration = item.duration, uploader = item.uploader,
|
||||
thumbnailUrl = item.thumbnailUrl
|
||||
uploaderUrl = item.uploaderUrl, thumbnailUrl = item.thumbnailUrl
|
||||
)
|
||||
|
||||
fun toStreamInfoItem(): StreamInfoItem {
|
||||
val item = StreamInfoItem(serviceId, url, title, streamType)
|
||||
item.duration = duration
|
||||
item.uploaderName = uploader
|
||||
item.uploaderUrl = uploaderUrl
|
||||
item.thumbnailUrl = thumbnailUrl
|
||||
|
||||
if (viewCount != null) item.viewCount = viewCount as Long
|
||||
|
|
@ -109,6 +113,7 @@ data class StreamEntity(
|
|||
const val STREAM_TYPE = "stream_type"
|
||||
const val STREAM_DURATION = "duration"
|
||||
const val STREAM_UPLOADER = "uploader"
|
||||
const val STREAM_UPLOADER_URL = "uploader_url"
|
||||
const val STREAM_THUMBNAIL_URL = "thumbnail_url"
|
||||
|
||||
const val STREAM_VIEWS = "view_count"
|
||||
|
|
|
|||
|
|
@ -362,6 +362,7 @@ class FeedFragment : BaseStateFragment<FeedState>() {
|
|||
StreamDialogEntry.mark_as_watched
|
||||
)
|
||||
}
|
||||
entries.add(StreamDialogEntry.show_channel_details)
|
||||
|
||||
StreamDialogEntry.setEnabledEntries(entries)
|
||||
InfoItemDialog(activity, item, StreamDialogEntry.getCommands(context)) { _, which ->
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
|||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
|
||||
public class StatisticsPlaylistFragment
|
||||
extends BaseLocalListFragment<List<StreamStatisticsEntry>, Void> {
|
||||
private final CompositeDisposable disposables = new CompositeDisposable();
|
||||
|
|
@ -363,10 +361,7 @@ public class StatisticsPlaylistFragment
|
|||
if (KoreUtils.shouldShowPlayWithKodi(context, infoItem.getServiceId())) {
|
||||
entries.add(StreamDialogEntry.play_with_kodi);
|
||||
}
|
||||
|
||||
if (!isNullOrEmpty(infoItem.getUploaderUrl())) {
|
||||
entries.add(StreamDialogEntry.show_channel_details);
|
||||
}
|
||||
entries.add(StreamDialogEntry.show_channel_details);
|
||||
|
||||
StreamDialogEntry.setEnabledEntries(entries);
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ import io.reactivex.rxjava3.disposables.Disposable;
|
|||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject;
|
||||
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
import static org.schabi.newpipe.ktx.ViewUtils.animate;
|
||||
import static org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout;
|
||||
|
||||
|
|
@ -778,10 +777,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
if (KoreUtils.shouldShowPlayWithKodi(context, infoItem.getServiceId())) {
|
||||
entries.add(StreamDialogEntry.play_with_kodi);
|
||||
}
|
||||
|
||||
if (!isNullOrEmpty(infoItem.getUploaderUrl())) {
|
||||
entries.add(StreamDialogEntry.show_channel_details);
|
||||
}
|
||||
entries.add(StreamDialogEntry.show_channel_details);
|
||||
|
||||
StreamDialogEntry.setEnabledEntries(entries);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ public class PlayQueueItem implements Serializable {
|
|||
private final String thumbnailUrl;
|
||||
@NonNull
|
||||
private final String uploader;
|
||||
private final String uploaderUrl;
|
||||
@NonNull
|
||||
private final StreamType streamType;
|
||||
|
||||
|
|
@ -37,7 +38,8 @@ public class PlayQueueItem implements Serializable {
|
|||
|
||||
PlayQueueItem(@NonNull final StreamInfo info) {
|
||||
this(info.getName(), info.getUrl(), info.getServiceId(), info.getDuration(),
|
||||
info.getThumbnailUrl(), info.getUploaderName(), info.getStreamType());
|
||||
info.getThumbnailUrl(), info.getUploaderName(),
|
||||
info.getUploaderUrl(), info.getStreamType());
|
||||
|
||||
if (info.getStartPosition() > 0) {
|
||||
setRecoveryPosition(info.getStartPosition() * 1000);
|
||||
|
|
@ -46,19 +48,21 @@ public class PlayQueueItem implements Serializable {
|
|||
|
||||
PlayQueueItem(@NonNull final StreamInfoItem item) {
|
||||
this(item.getName(), item.getUrl(), item.getServiceId(), item.getDuration(),
|
||||
item.getThumbnailUrl(), item.getUploaderName(), item.getStreamType());
|
||||
item.getThumbnailUrl(), item.getUploaderName(),
|
||||
item.getUploaderUrl(), item.getStreamType());
|
||||
}
|
||||
|
||||
private PlayQueueItem(@Nullable final String name, @Nullable final String url,
|
||||
final int serviceId, final long duration,
|
||||
@Nullable final String thumbnailUrl, @Nullable final String uploader,
|
||||
@NonNull final StreamType streamType) {
|
||||
final String uploaderUrl, @NonNull final StreamType streamType) {
|
||||
this.title = name != null ? name : EMPTY_STRING;
|
||||
this.url = url != null ? url : EMPTY_STRING;
|
||||
this.serviceId = serviceId;
|
||||
this.duration = duration;
|
||||
this.thumbnailUrl = thumbnailUrl != null ? thumbnailUrl : EMPTY_STRING;
|
||||
this.uploader = uploader != null ? uploader : EMPTY_STRING;
|
||||
this.uploaderUrl = uploaderUrl;
|
||||
this.streamType = streamType;
|
||||
|
||||
this.recoveryPosition = RECOVERY_UNSET;
|
||||
|
|
@ -92,6 +96,10 @@ public class PlayQueueItem implements Serializable {
|
|||
return uploader;
|
||||
}
|
||||
|
||||
public String getUploaderUrl() {
|
||||
return uploaderUrl;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public StreamType getStreamType() {
|
||||
return streamType;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@ package org.schabi.newpipe.util;
|
|||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import org.schabi.newpipe.NewPipeDatabase;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
|
||||
|
|
@ -20,7 +22,9 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
import static org.schabi.newpipe.player.MainPlayer.PlayerType.AUDIO;
|
||||
import static org.schabi.newpipe.player.MainPlayer.PlayerType.POPUP;
|
||||
|
||||
|
|
@ -29,12 +33,30 @@ public enum StreamDialogEntry {
|
|||
// enum values with DEFAULT actions //
|
||||
//////////////////////////////////////
|
||||
|
||||
show_channel_details(R.string.show_channel_details, (fragment, item) ->
|
||||
// For some reason `getParentFragmentManager()` doesn't work, but this does.
|
||||
NavigationHelper.openChannelFragment(
|
||||
fragment.requireActivity().getSupportFragmentManager(),
|
||||
item.getServiceId(), item.getUploaderUrl(), item.getUploaderName())
|
||||
),
|
||||
show_channel_details(R.string.show_channel_details, (fragment, item) -> {
|
||||
if (isNullOrEmpty(item.getUploaderUrl())) {
|
||||
final int serviceId = item.getServiceId();
|
||||
final String url = item.getUrl();
|
||||
Toast.makeText(fragment.getContext(), R.string.loading_channel_details,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
ExtractorHelper.getStreamInfo(serviceId, url, false)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
NewPipeDatabase.getInstance(fragment.getContext()).streamDAO()
|
||||
.setUploaderUrl(serviceId, url, result.getUploaderUrl())
|
||||
.subscribeOn(Schedulers.io()).subscribe();
|
||||
openChannelFragment(fragment, item, result.getUploaderUrl());
|
||||
}, throwable -> Toast.makeText(
|
||||
// TODO: Open the Error Activity
|
||||
fragment.getContext(),
|
||||
R.string.error_show_channel_details,
|
||||
Toast.LENGTH_SHORT
|
||||
).show());
|
||||
} else {
|
||||
openChannelFragment(fragment, item, item.getUploaderUrl());
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Enqueues the stream automatically to the current PlayerType.<br>
|
||||
|
|
@ -179,4 +201,17 @@ public enum StreamDialogEntry {
|
|||
public interface StreamDialogEntryAction {
|
||||
void onClick(Fragment fragment, StreamInfoItem infoItem);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// private method to open channel fragment //
|
||||
/////////////////////////////////////////////
|
||||
|
||||
private static void openChannelFragment(final Fragment fragment,
|
||||
final StreamInfoItem item,
|
||||
final String uploaderUrl) {
|
||||
// For some reason `getParentFragmentManager()` doesn't work, but this does.
|
||||
NavigationHelper.openChannelFragment(
|
||||
fragment.requireActivity().getSupportFragmentManager(),
|
||||
item.getServiceId(), uploaderUrl, item.getUploaderName());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue