Skip to content

Commit 48ad123

Browse files
Implement clear history functionality
1 parent 3f1bd58 commit 48ad123

6 files changed

Lines changed: 111 additions & 89 deletions

File tree

app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.java

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import androidx.annotation.Nullable;
1616
import androidx.paging.PagingSource;
1717
import androidx.room.Dao;
18+
import androidx.room.Delete;
19+
import androidx.room.Insert;
1820
import androidx.room.Query;
1921
import androidx.room.RewriteQueriesToDropUnusedColumns;
2022

@@ -24,36 +26,19 @@
2426

2527
import java.util.List;
2628

29+
import io.reactivex.rxjava3.core.Completable;
2730
import io.reactivex.rxjava3.core.Flowable;
2831

2932
@Dao
30-
public abstract class StreamHistoryDAO implements HistoryDAO<StreamHistoryEntity> {
31-
@Query("SELECT * FROM " + STREAM_HISTORY_TABLE
32-
+ " WHERE " + STREAM_ACCESS_DATE + " = "
33-
+ "(SELECT MAX(" + STREAM_ACCESS_DATE + ") FROM " + STREAM_HISTORY_TABLE + ")")
34-
@Override
35-
@Nullable
36-
public abstract StreamHistoryEntity getLatestEntry();
33+
public abstract class StreamHistoryDAO {
34+
@Insert
35+
public abstract long insert(StreamHistoryEntity entity);
3736

38-
@Override
39-
@Query("SELECT * FROM " + STREAM_HISTORY_TABLE)
40-
public abstract Flowable<List<StreamHistoryEntity>> getAll();
37+
@Delete
38+
public abstract void delete(StreamHistoryEntity entity);
4139

42-
@Override
4340
@Query("DELETE FROM " + STREAM_HISTORY_TABLE)
44-
public abstract int deleteAll();
45-
46-
@Override
47-
public Flowable<List<StreamHistoryEntity>> listByService(final int serviceId) {
48-
throw new UnsupportedOperationException();
49-
}
50-
51-
@Query("SELECT * FROM " + STREAM_TABLE
52-
+ " INNER JOIN " + STREAM_HISTORY_TABLE
53-
+ " ON " + STREAM_ID + " = " + JOIN_STREAM_ID
54-
+ " ORDER BY " + STREAM_ACCESS_DATE + " DESC")
55-
public abstract Flowable<List<StreamHistoryEntry>> getHistory();
56-
41+
public abstract Completable deleteAll();
5742

5843
@Query("SELECT * FROM " + STREAM_TABLE
5944
+ " INNER JOIN " + STREAM_HISTORY_TABLE

app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,8 @@ public Completable deleteStreamHistoryAndState(final long streamId) {
157157
}).subscribeOn(Schedulers.io());
158158
}
159159

160-
public Single<Integer> deleteWholeStreamHistory() {
161-
return Single.fromCallable(streamHistoryTable::deleteAll)
162-
.subscribeOn(Schedulers.io());
160+
public Completable deleteWholeStreamHistory() {
161+
return streamHistoryTable.deleteAll().subscribeOn(Schedulers.io());
163162
}
164163

165164
public Single<Integer> deleteCompleteStreamStateHistory() {

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

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@ package org.schabi.newpipe.local.history
33
import android.app.Application
44
import androidx.lifecycle.AndroidViewModel
55
import androidx.lifecycle.SavedStateHandle
6+
import androidx.lifecycle.viewModelScope
67
import androidx.paging.Pager
78
import androidx.paging.PagingConfig
89
import androidx.paging.map
910
import kotlinx.coroutines.Dispatchers
1011
import kotlinx.coroutines.flow.flatMapLatest
1112
import kotlinx.coroutines.flow.flowOn
1213
import kotlinx.coroutines.flow.map
14+
import kotlinx.coroutines.launch
15+
import kotlinx.coroutines.rx3.await
1316
import org.schabi.newpipe.NewPipeDatabase
14-
import org.schabi.newpipe.database.stream.StreamStatisticsEntry
1517
import org.schabi.newpipe.ui.components.items.Stream
1618
import org.schabi.newpipe.util.Localization
1719
import org.schabi.newpipe.util.ServiceHelper
18-
import org.schabi.newpipe.util.image.ImageStrategy
1920
import java.time.format.DateTimeFormatter
2021
import java.time.format.FormatStyle
2122

@@ -38,14 +39,12 @@ class HistoryViewModel(
3839
}
3940
.map { pagingData ->
4041
pagingData.map {
41-
val thumbnails = ImageStrategy.dbUrlToImageList(it.streamEntity.thumbnailUrl)
42-
val detail = getHistoryDetailText(it, dateTimeFormatter)
43-
44-
Stream(
45-
it.streamEntity.serviceId, it.streamEntity.url, it.streamEntity.title,
46-
thumbnails, it.streamEntity.uploader, it.streamEntity.streamType,
47-
it.streamEntity.uploaderUrl, it.streamEntity.duration, detail
42+
val detail = Localization.concatenateStrings(
43+
Localization.shortViewCount(getApplication(), it.watchCount),
44+
dateTimeFormatter.format(it.latestAccessDate),
45+
ServiceHelper.getNameOfServiceById(it.streamEntity.serviceId),
4846
)
47+
Stream(it.streamEntity, detail)
4948
}
5049
}
5150
.flowOn(Dispatchers.IO)
@@ -54,15 +53,10 @@ class HistoryViewModel(
5453
savedStateHandle[ORDER_KEY] = sortKey
5554
}
5655

57-
fun getHistoryDetailText(
58-
entry: StreamStatisticsEntry,
59-
dateTimeFormatter: DateTimeFormatter,
60-
): String {
61-
return Localization.concatenateStrings(
62-
Localization.shortViewCount(getApplication(), entry.watchCount),
63-
dateTimeFormatter.format(entry.latestAccessDate),
64-
ServiceHelper.getNameOfServiceById(entry.streamEntity.serviceId),
65-
)
56+
fun deleteWatchHistory() {
57+
viewModelScope.launch(Dispatchers.IO) {
58+
historyDao.deleteAll().await()
59+
}
6660
}
6761

6862
companion object {

app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ private static Disposable getWholeStreamHistoryDisposable(
9191
return recordManager.deleteWholeStreamHistory()
9292
.observeOn(AndroidSchedulers.mainThread())
9393
.subscribe(
94-
howManyDeleted -> Toast.makeText(context,
94+
() -> Toast.makeText(context,
9595
R.string.watch_history_deleted, Toast.LENGTH_SHORT).show(),
9696
throwable -> ErrorUtil.openActivity(context,
9797
new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY,
Lines changed: 86 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
11
package org.schabi.newpipe.ui.screens
22

3+
import android.content.res.Configuration
4+
import androidx.compose.foundation.layout.Row
35
import androidx.compose.foundation.layout.padding
6+
import androidx.compose.material.icons.Icons
7+
import androidx.compose.material.icons.filled.ClearAll
48
import androidx.compose.material3.DropdownMenuItem
59
import androidx.compose.material3.ExperimentalMaterial3Api
610
import androidx.compose.material3.ExposedDropdownMenuBox
711
import androidx.compose.material3.ExposedDropdownMenuDefaults
12+
import androidx.compose.material3.Icon
13+
import androidx.compose.material3.IconButton
814
import androidx.compose.material3.MaterialTheme
915
import androidx.compose.material3.MenuAnchorType
16+
import androidx.compose.material3.PlainTooltip
17+
import androidx.compose.material3.Surface
1018
import androidx.compose.material3.Text
1119
import androidx.compose.material3.TextField
20+
import androidx.compose.material3.TooltipBox
21+
import androidx.compose.material3.TooltipDefaults
22+
import androidx.compose.material3.rememberTooltipState
1223
import androidx.compose.runtime.Composable
1324
import androidx.compose.runtime.getValue
1425
import androidx.compose.runtime.mutableStateOf
1526
import androidx.compose.runtime.remember
1627
import androidx.compose.runtime.setValue
28+
import androidx.compose.ui.Alignment
1729
import androidx.compose.ui.Modifier
1830
import androidx.compose.ui.res.stringResource
31+
import androidx.compose.ui.tooling.preview.Preview
1932
import androidx.compose.ui.unit.dp
2033
import androidx.lifecycle.compose.collectAsStateWithLifecycle
2134
import androidx.lifecycle.viewmodel.compose.viewModel
@@ -24,73 +37,103 @@ import org.schabi.newpipe.R
2437
import org.schabi.newpipe.local.history.HistoryViewModel
2538
import org.schabi.newpipe.local.history.SortKey
2639
import org.schabi.newpipe.ui.components.items.ItemList
40+
import org.schabi.newpipe.ui.theme.AppTheme
2741

2842
@Composable
2943
fun HistoryScreen(viewModel: HistoryViewModel = viewModel()) {
3044
val sortKey by viewModel.sortKey.collectAsStateWithLifecycle()
3145
val historyItems = viewModel.historyItems.collectAsLazyPagingItems()
3246

3347
ItemList(historyItems, header = {
34-
HistoryHeader(sortKey, viewModel::updateOrder)
48+
HistoryHeader(sortKey, viewModel::updateOrder, viewModel::deleteWatchHistory)
3549
})
3650
}
3751

3852
@OptIn(ExperimentalMaterial3Api::class)
3953
@Composable
4054
private fun HistoryHeader(
4155
sortKey: SortKey,
42-
onSelectItem: (SortKey) -> Unit,
56+
onSelectSortKey: (SortKey) -> Unit,
57+
onClickClear: () -> Unit,
4358
) {
4459
var expanded by remember { mutableStateOf(false) }
4560
val selected = when (sortKey) {
4661
SortKey.MOST_PLAYED -> R.string.title_most_played
4762
SortKey.LAST_PLAYED -> R.string.title_last_played
4863
}
4964

50-
ExposedDropdownMenuBox(
51-
modifier = Modifier.padding(top = 12.dp, start = 12.dp),
52-
expanded = expanded,
53-
onExpandedChange = { expanded = it },
54-
) {
55-
TextField(
56-
enabled = true,
57-
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable),
58-
value = stringResource(selected),
59-
readOnly = true,
60-
onValueChange = {},
61-
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
62-
colors = ExposedDropdownMenuDefaults.textFieldColors(),
63-
label = { Text(text = stringResource(R.string.history_sort_label)) }
64-
)
65-
66-
ExposedDropdownMenu(
65+
Row(verticalAlignment = Alignment.CenterVertically) {
66+
ExposedDropdownMenuBox(
67+
modifier = Modifier.padding(top = 12.dp, start = 12.dp),
6768
expanded = expanded,
68-
onDismissRequest = { expanded = false },
69+
onExpandedChange = { expanded = it },
6970
) {
70-
DropdownMenuItem(
71-
text = {
72-
Text(
73-
text = stringResource(R.string.title_most_played),
74-
color = MaterialTheme.colorScheme.onBackground,
75-
)
76-
},
77-
onClick = {
78-
expanded = false
79-
onSelectItem(SortKey.MOST_PLAYED)
80-
}
81-
)
82-
DropdownMenuItem(
83-
text = {
84-
Text(
85-
text = stringResource(R.string.title_last_played),
86-
color = MaterialTheme.colorScheme.onBackground,
87-
)
88-
},
89-
onClick = {
90-
expanded = false
91-
onSelectItem(SortKey.LAST_PLAYED)
92-
}
71+
TextField(
72+
enabled = true,
73+
modifier = Modifier.menuAnchor(MenuAnchorType.PrimaryNotEditable),
74+
value = stringResource(selected),
75+
readOnly = true,
76+
onValueChange = {},
77+
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
78+
colors = ExposedDropdownMenuDefaults.textFieldColors(),
79+
label = { Text(text = stringResource(R.string.history_sort_label)) }
9380
)
81+
82+
ExposedDropdownMenu(
83+
expanded = expanded,
84+
onDismissRequest = { expanded = false },
85+
) {
86+
DropdownMenuItem(
87+
text = {
88+
Text(
89+
text = stringResource(R.string.title_most_played),
90+
color = MaterialTheme.colorScheme.onBackground,
91+
)
92+
},
93+
onClick = {
94+
expanded = false
95+
onSelectSortKey(SortKey.MOST_PLAYED)
96+
}
97+
)
98+
DropdownMenuItem(
99+
text = {
100+
Text(
101+
text = stringResource(R.string.title_last_played),
102+
color = MaterialTheme.colorScheme.onBackground,
103+
)
104+
},
105+
onClick = {
106+
expanded = false
107+
onSelectSortKey(SortKey.LAST_PLAYED)
108+
}
109+
)
110+
}
111+
}
112+
113+
TooltipBox(
114+
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
115+
tooltip = {
116+
PlainTooltip { Text(text = stringResource(R.string.clear_views_history_title)) }
117+
},
118+
state = rememberTooltipState(),
119+
) {
120+
IconButton(onClick = onClickClear) {
121+
Icon(
122+
imageVector = Icons.Default.ClearAll,
123+
contentDescription = stringResource(R.string.clear_history_description),
124+
)
125+
}
126+
}
127+
}
128+
}
129+
130+
@Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO)
131+
@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
132+
@Composable
133+
private fun HistoryHeaderPreview() {
134+
AppTheme {
135+
Surface(color = MaterialTheme.colorScheme.background) {
136+
HistoryHeader(SortKey.MOST_PLAYED, {}, {})
94137
}
95138
}
96139
}

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,7 @@
859859
<string name="auto_queue_description">Next</string>
860860
<string name="newpipe_extractor_description">NewPipeExtractor is a library for extracting things from streaming sites. It is a core component of NewPipe, but could be used independently.</string>
861861
<string name="history_sort_label">Sort by</string>
862+
<string name="clear_history_description">Button to clear watch history</string>
862863
<plurals name="comments">
863864
<item quantity="one">%d comment</item>
864865
<item quantity="other">%d comments</item>

0 commit comments

Comments
 (0)