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 hide played items in a feed #3371

Merged
merged 9 commits into from
Jun 18, 2021

Conversation

mauriciocolli
Copy link
Contributor

@mauriciocolli mauriciocolli commented Apr 5, 2020

What is it?

  • Bug fix
  • Feature
  • Code base improvement
  • Meta improvement to the project

Description of the changes in your PR

  • Let the user hide played items inside of a feed.
  • Use components from the new Groupie list library for displaying the feed list.
    • This allows for easier development of lists, and will make it easier to seamlessly update the list in the future (e.g. without blocking the view of the user with the loading progress).

Fixes #3611

Testing apk

The APK can be found by going to the "Checks" tab below the title and then on "artifacts" on the right.

@mauriciocolli mauriciocolli added feature request Issue is related to a feature in the app GUI Issue is related to the graphical user interface labels Apr 5, 2020
@TobiGr TobiGr added this to the 0.19.3 milestone Apr 6, 2020
@TobiGr TobiGr added the feed Issue is related to the feed label Apr 11, 2020
Copy link
Member

@Stypox Stypox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! I especially like the new groupie-based StreamItem holder. :-D

@gkeegan
Copy link
Contributor

gkeegan commented Apr 15, 2020

Question: Does this hide videos that have been only barely been started watching? (Like for a few seconds or minutes, or a few percent of total video time)

I know it hides stuff that a significant portion has been watched from the gif, but idk about that.

@Stypox
Copy link
Member

Stypox commented Apr 15, 2020

Does this hide videos that have been only barely been started watching?

I don't think so, this would require to change the way stream states are saved. Currently timestamps are only saved if at least 5s into the video and (I think) 10s before the end, but they should be saved always imo. Then it would be the player's job to start playing a video from the beginning when the saved stream state is <=5s or >=(duration-10s). This would be a rather simple change, but I think will go in another PR, unless @mauriciocolli wants to implement it here.

@Stypox
Copy link
Member

Stypox commented Apr 15, 2020

After testing on my phone I found some things that should be improved:

  • the "eye" button should be shown in the app bar even when the "what's new" fragment is in a main page tab. It is inconvenient to have to click two buttons to access it. There are no space problems, and even if there where, it could just be shown as "ifRoom"
  • When switching fast from the feed tab to another tab, the menu takes a little amout of time to reload, and during that time the three-dot menu can be opened, resulting in a gray square.
  • The feed list updates are blocking the UI, and I only have 34 subscriptions. Have you tested the performance with hundreds of subscriptions? Anyway, can't list item filterings (i.e. dataset update) be done on another thread, while obviously keeping the list re-rendering on the ui one?

@TobiGr TobiGr modified the milestones: 0.19.3, 0.19.4 Apr 23, 2020
@TobiGr TobiGr modified the milestones: 0.19.4, 0.20.0 May 18, 2020
@mauriciocolli
Copy link
Contributor Author

@Stypox

the "eye" button should be shown in the app bar even when the "what's new" fragment is in a main page tab. It is inconvenient to have to click two buttons to access it. There are no space problems, and even if there where, it could just be shown as "ifRoom"

When switching fast from the feed tab to another tab, the menu takes a little amout of time to reload, and during that time the three-dot menu can be opened, resulting in a gray square.

The two are related, it looked very bad so I disabled it from the main page.

Though the second has nothing to do with this changes, the view pager seems to let the animation end to finally setup the menu, you can test it by instead pressing the tab's icon, it should be instantly changed.

I think it's possible to improve how fast it does that, but that's for another pull request.

The feed list updates are blocking the UI, and I only have 34 subscriptions.

I thought that the method that I was using did that, but apparently not. Fixed it.

Have you tested the performance with hundreds of subscriptions?

Should not matter even if it had thousands, there's a limit to how many items are pulled from the database.

@wb9688 wb9688 modified the milestones: 0.20.0, 0.19.6 Jun 27, 2020
Stypox
Stypox previously requested changes Jun 27, 2020
Comment on lines +5 to +6
android:endColor="#B2000000"
android:startColor="#E6000000"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer the shadow to be more transparent, something like this:

Suggested change
android:endColor="#B2000000"
android:startColor="#E6000000"/>
android:endColor="#6C000000"
android:startColor="#A0000000"/>

Also, what about making the color different based on the theme? Imo the black shadow looks a little bit strange in the white theme, but maybe it's just an impression.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer the shadow to be more transparent

IMO, that much more transparency makes it hard to read when the thumbnail doesn't use darker colors.

But I do like to see the thumbnail a little better...

What about making the gradient a little lighter towards the end, what do you say on a 90% → 40% gradient instead of the current 90% → 70%?

Also, what about making the color different based on the theme?

B&W or some other color?

Imo the black shadow looks a little bit strange in the white theme, but maybe it's just an impression.

To me it isn't much different/stranger than any other dark thumbnail.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

B&W or some other color?

I was thinking about B&W, but then you are right, there is actually no need for this.
So, let's use a 90% → 40% black shadow, it seems the best option.

android:layout_alignBottom="@id/itemThumbnailView"
android:layout_gravity="top|left"
android:background="@drawable/item_in_history_indicator_background"
android:ellipsize="end"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a good idea? In theory the ellipsize should never be triggered, but even if it is I'd prefer marquee
(also below)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if it was just one view or even a list that you can select an element it'd be fine with the marquee, but with this much items, I don't think so. What about the users that use the bigger fonts and have a bunch of items that are already played, wouldn't that be too distracting?

I think that's why the marquee effect is designed to only start when the item is actually selected (otherwise you have to call setSelected(true) manually).

Maybe an auto-sizing text view would work better here, even though we won't be able adapt all sizes, most of them will be fine with that. It'd also work better on the mini version of the stream item.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using marquee, but never calling setSelected(true) on it, so that the IN HISTORY text fades at the end instead of showing three points? Anyway, if this would look too strange, I'm ok with not changing anything, since "in theory the ellipsize should never be triggered"

@TobiGr TobiGr modified the milestones: 0.19.6, 0.20.0 Jul 7, 2020
@wb9688 wb9688 modified the milestones: 0.20.0, 0.20.1 Jul 29, 2020
@Stypox Stypox modified the milestones: 0.20.1, 0.20.2 Oct 4, 2020
@Stypox Stypox removed this from the 0.20.2 milestone Oct 4, 2020
@Stypox
Copy link
Member

Stypox commented Jan 16, 2021

@mauriciocolli could you rebase, please? Then I would like to merge this.

@Stypox
Copy link
Member

Stypox commented Jun 7, 2021

  • Rebased again @TobiGr @mauriciocolli
  • Increased the end threshold, used to consider a stream finished, to 60 seconds, since usually the sponsor, the bye-bye by the creator and YouTube's end screens take ~60s (e.g. see videos from "Two Minutes Paper" or by "Linus Tech Tips")
  • Fixed stream state not being saved correctly at the end of a video (see https://stackoverflow.com/a/57848897/9481500)
  • Probably also fixed stream progress not being correctly retained when switching players due to the point above
  • Renamed progressTime to progressMillis for better understandability
  • Save stream state even if progress is less than 5 seconds, if the current time is more than 1/4 of the video length.
  • @opusforlife2 please test again, I can't reproduce your problem above

@Stypox Stypox force-pushed the feed-hide-played-items branch 2 times, most recently from 60b5de3 to faa93ca Compare June 9, 2021 14:21
@Stypox
Copy link
Member

Stypox commented Jun 9, 2021

  • Rebased again @TobiGr
  • Do not hide feed buttons (show/hide & help) behind three-dot menu, instead make them visible ifRoom. This makes the eye button visible when the feed fragment is used in the main page, which is good in my opinion.
  • Fix long-press menu and readd open-in-browser button

Copy link
Member

@TobiGr TobiGr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get this crash when using a tablet emulator for viewing the feed. Are all layouts updated?

Crash log
2021-06-10 22:35:50.738 10153-10153/org.schabi.newpipe.debug.feedhideplayeditems E/AndroidRuntime: FATAL EXCEPTION: main
    Process: org.schabi.newpipe.debug.feedhideplayeditems, PID: 10153
    java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to androidx.constraintlayout.widget.ConstraintLayout
        at org.schabi.newpipe.databinding.ListStreamItemBinding.bind(ListStreamItemBinding.java:104)
        at org.schabi.newpipe.local.feed.item.StreamItem.initializeViewBinding(StreamItem.kt:44)
        at org.schabi.newpipe.local.feed.item.StreamItem.initializeViewBinding(StreamItem.kt:23)
        at com.xwray.groupie.viewbinding.BindableItem.createViewHolder(BindableItem.java:39)
        at com.xwray.groupie.viewbinding.BindableItem.createViewHolder(BindableItem.java:23)
        at com.xwray.groupie.GroupAdapter.onCreateViewHolder(GroupAdapter.java:209)
        at com.xwray.groupie.GroupAdapter.onCreateViewHolder(GroupAdapter.java:20)
        at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7078)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6235)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:561)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at androidx.swiperefreshlayout.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:689)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1103)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at androidx.drawerlayout.widget.DrawerLayout.onLayout(DrawerLayout.java:1231)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
2021-06-10 22:35:50.739 10153-10153/org.schabi.newpipe.debug.feedhideplayeditems E/AndroidRuntime:     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:784)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3470)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2938)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
        at android.view.Choreographer.doCallbacks(Choreographer.java:796)
        at android.view.Choreographer.doFrame(Choreographer.java:731)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2021-06-10 22:35:50.740 10153-10153/org.schabi.newpipe.debug.feedhideplayeditems E/ACRA: ACRA caught a ClassCastException for org.schabi.newpipe.debug.feedhideplayeditems
    java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to androidx.constraintlayout.widget.ConstraintLayout
        at org.schabi.newpipe.databinding.ListStreamItemBinding.bind(ListStreamItemBinding.java:104)
        at org.schabi.newpipe.local.feed.item.StreamItem.initializeViewBinding(StreamItem.kt:44)
        at org.schabi.newpipe.local.feed.item.StreamItem.initializeViewBinding(StreamItem.kt:23)
        at com.xwray.groupie.viewbinding.BindableItem.createViewHolder(BindableItem.java:39)
        at com.xwray.groupie.viewbinding.BindableItem.createViewHolder(BindableItem.java:23)
        at com.xwray.groupie.GroupAdapter.onCreateViewHolder(GroupAdapter.java:209)
        at com.xwray.groupie.GroupAdapter.onCreateViewHolder(GroupAdapter.java:20)
        at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7078)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6235)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.GridLayoutManager.layoutChunk(GridLayoutManager.java:561)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(GridLayoutManager.java:170)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at androidx.swiperefreshlayout.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:689)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1103)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at androidx.drawerlayout.widget.DrawerLayout.onLayout(DrawerLayout.java:1231)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
2021-06-10 22:35:50.740 10153-10153/org.schabi.newpipe.debug.feedhideplayeditems E/ACRA:     at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:784)
        at android.view.View.layout(View.java:22844)
        at android.view.ViewGroup.layout(ViewGroup.java:6389)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3470)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2938)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
        at android.view.Choreographer.doCallbacks(Choreographer.java:796)
        at android.view.Choreographer.doFrame(Choreographer.java:731)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Comment on lines 28 to 37
/**
* Playback state will not be saved, if playback time is less than this threshold.
*/
private static final int PLAYBACK_SAVE_THRESHOLD_START_SECONDS = 5;
private static final long PLAYBACK_SAVE_THRESHOLD_START_MILLISECONDS = 5000; // 5000ms = 5s

/**
* Playback state will not be saved, if time left is less than this threshold.
* @see #isFinished(long)
* @see org.schabi.newpipe.database.feed.dao.FeedDAO#getLiveOrNotPlayedStreams()
*/
private static final int PLAYBACK_SAVE_THRESHOLD_END_SECONDS = 10;
public static final long PLAYBACK_FINISHED_END_MILLISECONDS = 60000; // 60000ms = 60s
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That inline comments can be moved into the JDoc

@opusforlife2
Copy link
Collaborator

please test again, I can't reproduce your problem above

@Stypox Seems to be fixed now. 👍

@Stypox
Copy link
Member

Stypox commented Jun 15, 2021

  • applied the requested changes @TobiGr
  • improved the two grid and list item layouts and fixed the related crash reported by @TobiGr
  • fixed group feeds not being updated correctly (no stream finished checks were present, so all streams that were opened at least once were hidden)
  • reshow feed in onResume() if grid/list view mode changed in the settings

Copy link
Member

@TobiGr TobiGr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks to all involved!

@TobiGr TobiGr merged commit be676ad into TeamNewPipe:dev Jun 18, 2021
This was referenced Jun 26, 2021
TobiGr added a commit that referenced this pull request Aug 6, 2021
The resource was added in #3371, but its usages have been removed in the same PR (e58fead)
@TobiGr TobiGr mentioned this pull request Aug 6, 2021
5 tasks
@mauriciocolli mauriciocolli deleted the feed-hide-played-items branch December 8, 2021 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Issue is related to a feature in the app feed Issue is related to the feed GUI Issue is related to the graphical user interface
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Display which NEW videos have been added.
7 participants