Skip to content

Commit 54c2b49

Browse files
Restore clear menu
1 parent 2bafa2c commit 54c2b49

6 files changed

Lines changed: 122 additions & 108 deletions

File tree

app/src/main/java/org/schabi/newpipe/local/history/HistoryFragment.kt

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,26 @@ package org.schabi.newpipe.local.history
22

33
import android.os.Bundle
44
import android.view.LayoutInflater
5+
import android.view.Menu
6+
import android.view.MenuInflater
7+
import android.view.MenuItem
58
import android.view.View
69
import android.view.ViewGroup
10+
import android.widget.Toast
11+
import androidx.appcompat.app.AlertDialog
712
import androidx.appcompat.app.AppCompatActivity
813
import androidx.compose.material3.Surface
14+
import androidx.core.view.MenuProvider
915
import androidx.fragment.app.Fragment
1016
import androidx.fragment.compose.content
17+
import androidx.lifecycle.lifecycleScope
18+
import kotlinx.coroutines.CoroutineExceptionHandler
19+
import kotlinx.coroutines.launch
20+
import kotlinx.coroutines.rx3.await
1121
import org.schabi.newpipe.R
22+
import org.schabi.newpipe.error.ErrorInfo
23+
import org.schabi.newpipe.error.ErrorUtil.Companion.openActivity
24+
import org.schabi.newpipe.error.UserAction
1225
import org.schabi.newpipe.ui.screens.HistoryScreen
1326
import org.schabi.newpipe.ui.theme.AppTheme
1427

@@ -29,6 +42,53 @@ class HistoryFragment : Fragment() {
2942
view: View,
3043
savedInstanceState: Bundle?,
3144
) {
32-
(activity as AppCompatActivity).supportActionBar?.setTitle(R.string.title_activity_history)
45+
val context = requireActivity()
46+
(context as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.title_activity_history)
47+
48+
val recordManager = HistoryRecordManager(context)
49+
context.addMenuProvider(
50+
object : MenuProvider {
51+
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
52+
menuInflater.inflate(R.menu.menu_history, menu)
53+
}
54+
55+
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
56+
when (menuItem.itemId) {
57+
R.id.action_history_clear -> {
58+
AlertDialog.Builder(context)
59+
.setTitle(R.string.delete_view_history_alert)
60+
.setNegativeButton(R.string.cancel) { dialog, which -> dialog.dismiss() }
61+
.setPositiveButton(R.string.delete) { dialog, which ->
62+
viewLifecycleOwner.lifecycleScope.launch {
63+
launch(getExceptionHandler("Clear orphaned records")) {
64+
recordManager.deleteCompleteStreamStateHistory().await()
65+
Toast
66+
.makeText(context, R.string.watch_history_states_deleted, Toast.LENGTH_SHORT)
67+
.show()
68+
}
69+
70+
launch(getExceptionHandler("Delete search history")) {
71+
recordManager.deleteWholeStreamHistory().await()
72+
Toast.makeText(context, R.string.watch_history_deleted, Toast.LENGTH_SHORT)
73+
.show()
74+
}
75+
76+
launch(getExceptionHandler("Clear orphaned records")) {
77+
recordManager.removeOrphanedRecords().await()
78+
}
79+
}
80+
}
81+
.show()
82+
}
83+
}
84+
return true
85+
}
86+
},
87+
viewLifecycleOwner
88+
)
89+
}
90+
91+
private fun getExceptionHandler(action: String) = CoroutineExceptionHandler { _, throwable ->
92+
openActivity(requireContext(), ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY, action))
3393
}
3494
}

app/src/main/java/org/schabi/newpipe/local/history/HistoryViewModel.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import kotlinx.coroutines.Dispatchers
1212
import kotlinx.coroutines.flow.flatMapLatest
1313
import kotlinx.coroutines.flow.flowOn
1414
import kotlinx.coroutines.flow.map
15-
import kotlinx.coroutines.launch
16-
import kotlinx.coroutines.rx3.await
1715
import org.schabi.newpipe.NewPipeDatabase
1816
import org.schabi.newpipe.ui.components.items.Stream
1917

@@ -41,12 +39,6 @@ class HistoryViewModel(
4139
savedStateHandle[ORDER_KEY] = sortKey
4240
}
4341

44-
fun deleteWatchHistory() {
45-
viewModelScope.launch(Dispatchers.IO) {
46-
historyDao.deleteAll().await()
47-
}
48-
}
49-
5042
companion object {
5143
private const val ORDER_KEY = "order"
5244
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.schabi.newpipe.ui.components.common
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.ExperimentalLayoutApi
5+
import androidx.compose.foundation.layout.FlowRow
6+
import androidx.compose.material.icons.Icons
7+
import androidx.compose.material.icons.automirrored.filled.PlaylistPlay
8+
import androidx.compose.material.icons.filled.Headphones
9+
import androidx.compose.material.icons.filled.PictureInPicture
10+
import androidx.compose.runtime.Composable
11+
import androidx.compose.ui.Alignment
12+
import androidx.compose.ui.platform.LocalContext
13+
import androidx.compose.ui.unit.dp
14+
import org.schabi.newpipe.R
15+
import org.schabi.newpipe.ktx.findFragmentActivity
16+
import org.schabi.newpipe.player.playqueue.PlayQueue
17+
import org.schabi.newpipe.util.NavigationHelper
18+
19+
@OptIn(ExperimentalLayoutApi::class)
20+
@Composable
21+
fun PlaybackControlButtons(queue: PlayQueue) {
22+
val context = LocalContext.current
23+
24+
FlowRow(horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally)) {
25+
IconButtonWithLabel(
26+
icon = Icons.Default.Headphones,
27+
label = R.string.controls_background_title,
28+
onClick = { NavigationHelper.playOnBackgroundPlayer(context, queue, false) },
29+
)
30+
31+
IconButtonWithLabel(
32+
icon = Icons.AutoMirrored.Filled.PlaylistPlay,
33+
label = R.string.play_all,
34+
onClick = { NavigationHelper.playOnMainPlayer(context.findFragmentActivity(), queue) },
35+
)
36+
37+
IconButtonWithLabel(
38+
icon = Icons.Default.PictureInPicture,
39+
label = R.string.controls_popup_title,
40+
onClick = { NavigationHelper.playOnPopupPlayer(context, queue, false) },
41+
)
42+
}
43+
}

app/src/main/java/org/schabi/newpipe/ui/screens/HistoryScreen.kt

Lines changed: 6 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -7,69 +7,42 @@ import androidx.compose.foundation.layout.FlowRow
77
import androidx.compose.foundation.layout.Row
88
import androidx.compose.foundation.layout.fillMaxWidth
99
import androidx.compose.foundation.layout.padding
10-
import androidx.compose.material.icons.Icons
11-
import androidx.compose.material.icons.automirrored.filled.PlaylistPlay
12-
import androidx.compose.material.icons.filled.ClearAll
13-
import androidx.compose.material.icons.filled.Headphones
14-
import androidx.compose.material.icons.filled.PictureInPicture
15-
import androidx.compose.material3.AlertDialog
16-
import androidx.compose.material3.Icon
1710
import androidx.compose.material3.SegmentedButton
1811
import androidx.compose.material3.SegmentedButtonDefaults
1912
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
2013
import androidx.compose.material3.Surface
2114
import androidx.compose.material3.Text
22-
import androidx.compose.material3.TextButton
2315
import androidx.compose.runtime.Composable
2416
import androidx.compose.runtime.getValue
25-
import androidx.compose.runtime.mutableStateOf
26-
import androidx.compose.runtime.remember
27-
import androidx.compose.runtime.setValue
2817
import androidx.compose.ui.Alignment
2918
import androidx.compose.ui.Modifier
30-
import androidx.compose.ui.platform.LocalContext
3119
import androidx.compose.ui.res.stringResource
3220
import androidx.compose.ui.tooling.preview.Preview
3321
import androidx.compose.ui.unit.dp
3422
import androidx.lifecycle.compose.collectAsStateWithLifecycle
3523
import androidx.lifecycle.viewmodel.compose.viewModel
3624
import androidx.paging.compose.collectAsLazyPagingItems
3725
import org.schabi.newpipe.R
38-
import org.schabi.newpipe.ktx.findFragmentActivity
3926
import org.schabi.newpipe.local.history.HistoryViewModel
4027
import org.schabi.newpipe.local.history.SortKey
28+
import org.schabi.newpipe.player.playqueue.PlayQueue
4129
import org.schabi.newpipe.player.playqueue.SinglePlayQueue
42-
import org.schabi.newpipe.ui.components.common.IconButtonWithLabel
30+
import org.schabi.newpipe.ui.components.common.PlaybackControlButtons
4331
import org.schabi.newpipe.ui.components.items.ItemList
4432
import org.schabi.newpipe.ui.theme.AppTheme
45-
import org.schabi.newpipe.util.NavigationHelper
4633

4734
@Composable
4835
fun HistoryScreen(viewModel: HistoryViewModel = viewModel()) {
49-
val context = LocalContext.current
5036
val sortKey by viewModel.sortKey.collectAsStateWithLifecycle()
5137
val historyItems = viewModel.historyItems.collectAsLazyPagingItems()
52-
5338
val streams = historyItems.itemSnapshotList.mapNotNull { it?.toStreamInfoItem() }
5439
val queue = SinglePlayQueue(streams, 0)
55-
val onClickBackground = {
56-
NavigationHelper.playOnBackgroundPlayer(context, queue, false)
57-
}
58-
val onClickPopup = {
59-
NavigationHelper.playOnPopupPlayer(context, queue, false)
60-
}
61-
val onClickPlayAll = {
62-
NavigationHelper.playOnMainPlayer(context.findFragmentActivity(), queue)
63-
}
6440

6541
ItemList(historyItems, header = {
6642
HistoryHeader(
6743
sortKey = sortKey,
6844
onSelectSortKey = viewModel::updateOrder,
69-
onClickClear = viewModel::deleteWatchHistory,
70-
onClickBackground = onClickBackground,
71-
onClickPlayAll = onClickPlayAll,
72-
onClickPopup = onClickPopup,
45+
queue = queue
7346
)
7447
})
7548
}
@@ -78,11 +51,8 @@ fun HistoryScreen(viewModel: HistoryViewModel = viewModel()) {
7851
@Composable
7952
private fun HistoryHeader(
8053
sortKey: SortKey,
54+
queue: PlayQueue,
8155
onSelectSortKey: (SortKey) -> Unit,
82-
onClickClear: () -> Unit,
83-
onClickBackground: () -> Unit,
84-
onClickPlayAll: () -> Unit,
85-
onClickPopup: () -> Unit
8656
) {
8757
FlowRow(
8858
modifier = Modifier
@@ -93,7 +63,7 @@ private fun HistoryHeader(
9363
) {
9464
HistorySortRow(sortKey, onSelectSortKey)
9565

96-
HistoryButtons(onClickClear, onClickBackground, onClickPlayAll, onClickPopup)
66+
PlaybackControlButtons(queue)
9767
}
9868
}
9969

@@ -123,75 +93,13 @@ private fun HistorySortRow(
12393
}
12494
}
12595

126-
@OptIn(ExperimentalLayoutApi::class)
127-
@Composable
128-
private fun HistoryButtons(
129-
onClickClear: () -> Unit,
130-
onClickBackground: () -> Unit,
131-
onClickPlayAll: () -> Unit,
132-
onClickPopup: () -> Unit
133-
) {
134-
FlowRow(horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally)) {
135-
IconButtonWithLabel(
136-
icon = Icons.Default.Headphones,
137-
label = R.string.controls_background_title,
138-
onClick = onClickBackground,
139-
)
140-
141-
IconButtonWithLabel(
142-
icon = Icons.AutoMirrored.Filled.PlaylistPlay,
143-
label = R.string.play_all,
144-
onClick = onClickPlayAll,
145-
)
146-
147-
IconButtonWithLabel(
148-
icon = Icons.Default.PictureInPicture,
149-
label = R.string.controls_popup_title,
150-
onClick = onClickPopup,
151-
)
152-
153-
var openClearDialog by remember { mutableStateOf(false) }
154-
155-
TextButton(onClick = { openClearDialog = true }) {
156-
Row(
157-
horizontalArrangement = Arrangement.spacedBy(4.dp),
158-
verticalAlignment = Alignment.CenterVertically,
159-
) {
160-
Icon(imageVector = Icons.Default.ClearAll, contentDescription = null)
161-
Text(text = stringResource(R.string.clear))
162-
}
163-
}
164-
165-
if (openClearDialog) {
166-
AlertDialog(
167-
onDismissRequest = { openClearDialog = false },
168-
title = { Text(text = stringResource(R.string.delete_view_history_alert)) },
169-
text = { Text(text = stringResource(R.string.delete_view_history_description)) },
170-
confirmButton = {
171-
TextButton(onClick = {
172-
onClickClear()
173-
openClearDialog = false
174-
}) {
175-
Text(stringResource(R.string.delete))
176-
}
177-
},
178-
dismissButton = {
179-
TextButton(onClick = { openClearDialog = false }) {
180-
Text(stringResource(R.string.cancel))
181-
}
182-
},
183-
)
184-
}
185-
}
186-
}
187-
18896
@Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO)
18997
@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
19098
@Composable
19199
private fun HistoryHeaderPreview() {
192100
AppTheme {
193101
Surface {
194-
HistoryHeader(SortKey.MOST_PLAYED, {}, {}, {}, {}, {})
102+
HistoryHeader(SortKey.MOST_PLAYED, SinglePlayQueue(listOf(), 0)) {}
195103
}
196104
}
197105
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<menu xmlns:android="http://schemas.android.com/apk/res/android"
2+
xmlns:app="http://schemas.android.com/apk/res-auto"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
tools:context="org.schabi.newpipe.history.HistoryActivity">
5+
6+
<item
7+
android:id="@+id/action_history_clear"
8+
android:orderInCategory="940"
9+
android:title="@string/clear_views_history_title"
10+
app:showAsAction="never" />
11+
</menu>

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ core-ktx = "1.15.0"
1515
desugar-jdk-libs-nio = "2.0.4"
1616
documentFile = "1.0.1"
1717
exoplayer = "2.18.7"
18-
fragment-compose = "1.8.5"
18+
fragment-compose = "1.8.6"
1919
gradle = "8.7.3"
2020
groupie = "2.10.1"
2121
hilt = "2.51.1"

0 commit comments

Comments
 (0)