Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to mark an item as played #6773

Merged
merged 7 commits into from
Aug 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,11 @@ class FeedFragment : BaseStateFragment<FeedState>() {
)
)
}
if (item.streamType != StreamType.AUDIO_LIVE_STREAM && item.streamType != StreamType.LIVE_STREAM) {
entries.add(
StreamDialogEntry.mark_as_watched
)
}

StreamDialogEntry.setEnabledEntries(entries)
InfoItemDialog(activity, item, StreamDialogEntry.getCommands(context)) { _, which ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.AppDatabase;
import org.schabi.newpipe.database.LocalItem;
import org.schabi.newpipe.database.feed.dao.FeedDAO;
import org.schabi.newpipe.database.history.dao.SearchHistoryDAO;
import org.schabi.newpipe.database.history.dao.StreamHistoryDAO;
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
Expand All @@ -42,7 +43,10 @@
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.local.feed.FeedViewModel;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.util.ExtractorHelper;

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
Expand Down Expand Up @@ -81,6 +85,68 @@ public HistoryRecordManager(final Context context) {
// Watch History
///////////////////////////////////////////////////////

/**
* Marks a stream item as watched such that it is hidden from the feed if watched videos are
* hidden. Adds a history entry and updates the stream progress to 100%.
*
* @see FeedDAO#getLiveOrNotPlayedStreams
* @see FeedViewModel#togglePlayedItems
* @param info the item to mark as watched
* @return a Maybe containing the ID of the item if successful
*/
public Maybe<Long> markAsWatched(final StreamInfoItem info) {
if (!isStreamHistoryEnabled()) {
return Maybe.empty();
}

final OffsetDateTime currentTime = OffsetDateTime.now(ZoneOffset.UTC);
return Maybe.fromCallable(() -> database.runInTransaction(() -> {
final long streamId;
final long duration;
// Duration will not exist if the item was loaded with fast mode, so fetch it if empty
if (info.getDuration() < 0) {
final StreamInfo completeInfo = ExtractorHelper.getStreamInfo(
info.getServiceId(),
info.getUrl(),
false
)
.subscribeOn(Schedulers.io())
.blockingGet();
duration = completeInfo.getDuration();
streamId = streamTable.upsert(new StreamEntity(completeInfo));
} else {
duration = info.getDuration();
streamId = streamTable.upsert(new StreamEntity(info));
}

// Update the stream progress to the full duration of the video
final List<StreamStateEntity> states = streamStateTable.getState(streamId)
.blockingFirst();
if (!states.isEmpty()) {
final StreamStateEntity entity = states.get(0);
entity.setProgressMillis(duration * 1000);
streamStateTable.update(entity);
} else {
final StreamStateEntity entity = new StreamStateEntity(
streamId,
duration * 1000
);
streamStateTable.insert(entity);
}

// Add a history entry
final StreamHistoryEntity latestEntry = streamHistoryTable.getLatestEntry(streamId);
if (latestEntry != null) {
streamHistoryTable.delete(latestEntry);
latestEntry.setAccessDate(currentTime);
latestEntry.setRepeatCount(latestEntry.getRepeatCount() + 1);
return streamHistoryTable.insert(latestEntry);
} else {
return streamHistoryTable.insert(new StreamHistoryEntity(streamId, currentTime));
}
})).subscribeOn(Schedulers.io());
}

public Maybe<Long> onViewed(final StreamInfo info) {
if (!isStreamHistoryEnabled()) {
return Maybe.empty();
Expand Down
13 changes: 12 additions & 1 deletion app/src/main/java/org/schabi/newpipe/util/StreamDialogEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.local.dialog.PlaylistCreationDialog;
import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.player.MainPlayer;
import org.schabi.newpipe.player.helper.PlayerHolder;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
Expand All @@ -18,6 +19,8 @@
import java.util.Collections;
import java.util.List;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;

import static org.schabi.newpipe.player.MainPlayer.PlayerType.AUDIO;
import static org.schabi.newpipe.player.MainPlayer.PlayerType.POPUP;

Expand Down Expand Up @@ -92,8 +95,16 @@ public enum StreamDialogEntry {
item.getThumbnailUrl())),

open_in_browser(R.string.open_in_browser, (fragment, item) ->
ShareUtils.openUrlInBrowser(fragment.getContext(), item.getUrl()));
ShareUtils.openUrlInBrowser(fragment.getContext(), item.getUrl())),


mark_as_watched(R.string.mark_as_watched, (fragment, item) -> {
new HistoryRecordManager(fragment.getContext())
.markAsWatched(item)
.onErrorComplete()
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
});

///////////////
// variables //
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<string name="cancel">Cancel</string>
<string name="fdroid_vlc_url" translatable="false">https://f-droid.org/repository/browse/?fdfilter=vlc&amp;fdid=org.videolan.vlc</string>
<string name="open_in_browser">Open in browser</string>
<string name="mark_as_watched">Mark as watched</string>
<string name="open_in_popup_mode">Open in popup mode</string>
<string name="open_with">Open with</string>
<string name="share">Share</string>
Expand Down Expand Up @@ -709,7 +710,7 @@
<string name="feed_use_dedicated_fetch_method_enable_button">Enable fast mode</string>
<string name="feed_use_dedicated_fetch_method_disable_button">Disable fast mode</string>
<string name="feed_use_dedicated_fetch_method_help_text">Do you think feed loading is too slow? If so, try enabling fast loading (you can change it in settings or by pressing the button below).\n\nNewPipe offers two feed loading strategies:\n• Fetching the whole subscription channel, which is slow but complete.\n• Using a dedicated service endpoint, which is fast but usually not complete.\n\nThe difference between the two is that the fast one usually lacks some information, like the item\'s duration or type (can\'t distinguish between live videos and normal ones) and it may return less items.\n\nYouTube is an example of a service that offers this fast method with its RSS feed.\n\nSo the choice boils down to what you prefer: speed or precise information.</string>
<string name="feed_toggle_show_played_items">Show played items</string>
<string name="feed_toggle_show_played_items">Show watched items</string>
<string name="content_not_supported">This content is not yet supported by NewPipe.\n\nIt will hopefully be supported in a future version.</string>
<string name="detail_sub_channel_thumbnail_view_description">Channel\'s avatar thumbnail</string>
<string name="channel_created_by">Created by %s</string>
Expand Down