NewPipe icon indicating copy to clipboard operation
NewPipe copied to clipboard

Migrate watch history to Jetpack Compose

Open Isira-Seneviratne opened this issue 11 months ago • 14 comments

What is it?

  • [ ] Bugfix (user facing)
  • [x] Feature (user facing)
  • [x] Codebase improvement (dev facing)
  • [ ] Meta improvement to the project (dev facing)

Description of the changes in your PR

  • Rewrite the watch history UI using Jetpack Compose. As part of this change, the ItemList composable was refactored to use separate data classes, in order to further decouple it from the information provided by the extractor and make it more easily reusable.
  • Clean up unused methods in StreamHistoryDAO.
  • Reimplement the watch history retrieval from the Room database using AndroidX Paging for improved efficiency, as it supports pagination.
  • Add stream card and grid composables.
  • Update several relevant dependencies, including the Compose BOM version.
  • Use loading indicator for placeholder items in ItemList.

Before/After Screenshots/Screen Record

Before After
Before After

https://github.com/user-attachments/assets/278e4fa0-a89b-459a-a3bb-2931c4f36dfb

Fixes the following issue(s)

  • Fixes #

APK testing

The APK can be found by going to the "Checks" tab below the title. On the left pane, click on "CI", scroll down to "artifacts" and click "app" to download the zip file which contains the debug APK of this PR. You can find more info and a video demonstration on this wiki page.

Due diligence

Isira-Seneviratne avatar Jan 21 '25 01:01 Isira-Seneviratne

There should be a confirmation screen after "clear history" button clicked I guess

asandikci avatar Feb 02 '25 10:02 asandikci

Is it possible to put get the background, pop up, and play all actions in a single row? The buttons and sort by drop down use a lot of vertical space. What is the reasoning to make the sort by box not to grow to the full width of its parent container in portrait mode?

TobiGr avatar Mar 07 '25 12:03 TobiGr

Is it possible to put get the background, pop up, and play all actions in a single row? The buttons and sort by drop down use a lot of vertical space. What is the reasoning to make the sort by box not to grow to the full width of its parent container in portrait mode?

A scrollable row could be used to keep the buttons in the same row (at the moment, a FlowRow is used to adjust the buttons if the screen width is too narrow). The sort box could also be included in the same row if needed.

Isira-Seneviratne avatar Mar 08 '25 03:03 Isira-Seneviratne

@TobiGr I revised the UI again to use a segmented button instead of a dropdown.

Isira-Seneviratne avatar Mar 11 '25 05:03 Isira-Seneviratne

thanks. I am wondering whether the checkmark is the right icon to use here. Did you try to use the sort icon?

TobiGr avatar Mar 15 '25 11:03 TobiGr

No, but I added the Sort By label for clarity.

image

Isira-Seneviratne avatar Mar 16 '25 07:03 Isira-Seneviratne

I would put the Clear button in the three-dot menu, it's rarely used and especially should not be pressed on by accident.

Stypox avatar Mar 24 '25 16:03 Stypox

I would put the Clear button in the three-dot menu, it's rarely used and especially should not be pressed on by accident.

It opens a confirmation dialog first.

Isira-Seneviratne avatar Mar 24 '25 16:03 Isira-Seneviratne

I know, but I still think it would be better in the 3-dot menu (also because it would use up less space). Consider that if somebody doesn't want history they would just disable it, they wouldn't keep using the clear button.

Stypox avatar Mar 24 '25 16:03 Stypox

Good point. I made the change.

Isira-Seneviratne avatar Mar 24 '25 16:03 Isira-Seneviratne

No, but I added the Sort By label for clarity.

image

Would you please restore earlier default behavior of "sort by" to "date", it defaults to "views" in this PR.

Also noticed a minor bug: last selected option isn't saved, it switches to sort by "views" even after manually changing it to sort by "date" after reopening the app.

ShareASmile avatar Mar 27 '25 02:03 ShareASmile

No, but I added the Sort By label for clarity. image

Would you please restore earlier default behavior of "sort by" to "date", it defaults to "views" in this PR.

Okay.

Also noticed a minor bug: last selected option isn't saved, it switches to sort by "views" even after manually changing it to sort by "date" after reopening the app.

That's because the selected option is not being persisted (the existing app doesn't do it, either).

Isira-Seneviratne avatar Mar 31 '25 01:03 Isira-Seneviratne

Produces Error on data export, I can export with playlist fragment to Jetpack compose PR fine (as I am currently testing the two) It looks specific to this PR or Is it related to what is for #12415 in the first place?

Exception

  • User Action: database import or export
  • Request: Exporting database and settings
  • Content Country: GB
  • Content Language: en-GB
  • App Language: en_GB
  • Service: none
  • Timestamp: 2025-07-11T22:40:21.929+05:30
  • Package: org.schabi.newpipe.debug.HistoryCompose
  • Service: none
  • Version: 0.27.7
  • OS: Linux samsung/a22xnnxx/a22x:13/TP1A.220624.014/A226BXXU7DWH4:user/release-keys 13 - 33
Crash log

[java.lang.IllegalStateException](https://github.com/TeamNewPipe/NewPipe/pull/java.lang.IllegalStateException): Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
	at [androidx.room.RoomDatabase.assertNotMainThread](https://github.com/TeamNewPipe/NewPipe/pull/androidx.room.RoomDatabase.assertNotMainThread)(roomdatabase.android.kt:562)
	at [androidx.room.RoomDatabase.query](https://github.com/TeamNewPipe/NewPipe/pull/androidx.room.RoomDatabase.query)(roomdatabase.android.kt:612)
	at [org.schabi.newpipe.NewPipeDatabase.checkpoint](https://github.com/TeamNewPipe/NewPipe/pull/org.schabi.newpipe.NewPipeDatabase.checkpoint)(newpipedatabase.java:56)
	at [org.schabi.newpipe.settings.BackupRestoreSettingsFragment.exportDatabase](https://github.com/TeamNewPipe/NewPipe/pull/org.schabi.newpipe.settings.BackupRestoreSettingsFragment.exportDatabase)(backuprestoresettingsfragment.java:163)
	at [org.schabi.newpipe.settings.BackupRestoreSettingsFragment.requestExportPathResult](https://github.com/TeamNewPipe/NewPipe/pull/org.schabi.newpipe.settings.BackupRestoreSettingsFragment.requestExportPathResult)(backuprestoresettingsfragment.java:137)
	at [org.schabi.newpipe.settings.BackupRestoreSettingsFragment](https://github.com/TeamNewPipe/NewPipe/pull/org.schabi.newpipe.settings.BackupRestoreSettingsFragment).$r8$lambda$fGteoRaC9h1Pn2xEuX2RRkPtyno(Unknown Source:0)
	at [org.schabi.newpipe.settings.BackupRestoreSettingsFragment](https://github.com/TeamNewPipe/NewPipe/pull/org.schabi.newpipe.settings.BackupRestoreSettingsFragment)$$[ExternalSyntheticLambda8.onActivityResult](https://github.com/TeamNewPipe/NewPipe/pull/ExternalSyntheticLambda8.onActivityResult)(D8$$SyntheticClass:0)
	at [androidx.activity.result.ActivityResultRegistry.doDispatch](https://github.com/TeamNewPipe/NewPipe/pull/androidx.activity.result.ActivityResultRegistry.doDispatch)(activityresultregistry.java:414)
	at [androidx.activity.result.ActivityResultRegistry.dispatchResult](https://github.com/TeamNewPipe/NewPipe/pull/androidx.activity.result.ActivityResultRegistry.dispatchResult)(activityresultregistry.java:371)
	at [androidx.activity.ComponentActivity.onActivityResult](https://github.com/TeamNewPipe/NewPipe/pull/androidx.activity.ComponentActivity.onActivityResult)(componentactivity.java:845)
	at [androidx.fragment.app.FragmentActivity.onActivityResult](https://github.com/TeamNewPipe/NewPipe/pull/androidx.fragment.app.FragmentActivity.onActivityResult)(fragmentactivity.java:151)
	at [android.app.Activity.dispatchActivityResult](https://github.com/TeamNewPipe/NewPipe/pull/android.app.Activity.dispatchActivityResult)(activity.java:8951)
	at [android.app.ActivityThread.deliverResults](https://github.com/TeamNewPipe/NewPipe/pull/android.app.ActivityThread.deliverResults)(activitythread.java:5987)
	at [android.app.ActivityThread.handleSendResult](https://github.com/TeamNewPipe/NewPipe/pull/android.app.ActivityThread.handleSendResult)(activitythread.java:6033)
	at [android.app.servertransaction.ActivityResultItem.execute](https://github.com/TeamNewPipe/NewPipe/pull/android.app.servertransaction.ActivityResultItem.execute)(activityresultitem.java:67)
	at [android.app.servertransaction.ActivityTransactionItem.execute](https://github.com/TeamNewPipe/NewPipe/pull/android.app.servertransaction.ActivityTransactionItem.execute)(activitytransactionitem.java:45)
	at [android.app.servertransaction.TransactionExecutor.executeCallbacks](https://github.com/TeamNewPipe/NewPipe/pull/android.app.servertransaction.TransactionExecutor.executeCallbacks)(transactionexecutor.java:135)
	at [android.app.servertransaction.TransactionExecutor.execute](https://github.com/TeamNewPipe/NewPipe/pull/android.app.servertransaction.TransactionExecutor.execute)(transactionexecutor.java:95)
	at [android.app.ActivityThread](https://github.com/TeamNewPipe/NewPipe/pull/android.app.ActivityThread)$[H.handleMessage](https://github.com/TeamNewPipe/NewPipe/pull/H.handleMessage)(activitythread.java:2574)
	at [android.os.Handler.dispatchMessage](https://github.com/TeamNewPipe/NewPipe/pull/android.os.Handler.dispatchMessage)(handler.java:106)
	at [android.os.Looper.loopOnce](https://github.com/TeamNewPipe/NewPipe/pull/android.os.Looper.loopOnce)(looper.java:226)
	at [android.os.Looper.loop](https://github.com/TeamNewPipe/NewPipe/pull/android.os.Looper.loop)(looper.java:313)
	at [android.app.ActivityThread.main](https://github.com/TeamNewPipe/NewPipe/pull/android.app.ActivityThread.main)(activitythread.java:8762)
	at [java.lang.reflect.Method.invoke](https://github.com/TeamNewPipe/NewPipe/pull/java.lang.reflect.Method.invoke)(Native Method)
	at [com.android.internal.os.RuntimeInit](https://github.com/TeamNewPipe/NewPipe/pull/com.android.internal.os.RuntimeInit)$[MethodAndArgsCaller.run](https://github.com/TeamNewPipe/NewPipe/pull/MethodAndArgsCaller.run)(runtimeinit.java:604)
	at [com.android.internal.os.ZygoteInit.main](https://github.com/TeamNewPipe/NewPipe/pull/com.android.internal.os.ZygoteInit.main)(zygoteinit.java:1067)


ShareASmile avatar Jul 11 '25 17:07 ShareASmile

Produces Error on data export, I can export with playlist fragment to Jetpack compose PR fine (as I am currently testing the two) It looks specific to this PR or Is it related to what is for #12415 in the first place?

Yes, I had to update the Room version in this PR in order to use PagingSource.

Isira-Seneviratne avatar Jul 11 '25 23:07 Isira-Seneviratne

@ShareASmile It should be working now.

Isira-Seneviratne avatar Jul 12 '25 01:07 Isira-Seneviratne

Just did a quick test and now it works flawlessly. Thank you for all your efforts :).

ShareASmile avatar Jul 12 '25 14:07 ShareASmile