Skip to content

Commit ff42678

Browse files
committed
Updated view and viewmodel and remapped the fragments/activities
1 parent 0057192 commit ff42678

10 files changed

Lines changed: 161 additions & 33 deletions

File tree

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

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import androidx.annotation.NonNull;
1515
import androidx.annotation.Nullable;
16+
import androidx.appcompat.app.AlertDialog;
1617
import androidx.viewbinding.ViewBinding;
1718

1819
import com.google.android.material.snackbar.Snackbar;
@@ -26,6 +27,7 @@
2627
import org.schabi.newpipe.databinding.PlaylistControlBinding;
2728
import org.schabi.newpipe.databinding.StatisticPlaylistControlBinding;
2829
import org.schabi.newpipe.error.ErrorInfo;
30+
import org.schabi.newpipe.error.ErrorUtil;
2931
import org.schabi.newpipe.error.UserAction;
3032
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
3133
import org.schabi.newpipe.fragments.list.playlist.PlaylistControlViewHolder;
@@ -34,7 +36,6 @@
3436
import org.schabi.newpipe.local.BaseLocalListFragment;
3537
import org.schabi.newpipe.player.playqueue.PlayQueue;
3638
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
37-
import org.schabi.newpipe.settings.HistorySettingsFragment;
3839
import org.schabi.newpipe.util.NavigationHelper;
3940
import org.schabi.newpipe.util.OnClickGesture;
4041
import org.schabi.newpipe.util.PlayButtonHelper;
@@ -161,14 +162,72 @@ public void held(final LocalItem selectedItem) {
161162
@Override
162163
public boolean onOptionsItemSelected(final MenuItem item) {
163164
if (item.getItemId() == R.id.action_history_clear) {
164-
HistorySettingsFragment
165-
.openDeleteWatchHistoryDialog(requireContext(), recordManager, disposables);
165+
openDeleteWatchHistoryDialog(requireContext(), recordManager, disposables);
166166
} else {
167167
return super.onOptionsItemSelected(item);
168168
}
169169
return true;
170170
}
171171

172+
private static void openDeleteWatchHistoryDialog(
173+
@NonNull final Context context,
174+
final HistoryRecordManager recordManager,
175+
final CompositeDisposable disposables
176+
) {
177+
new AlertDialog.Builder(context)
178+
.setTitle(R.string.delete_view_history_alert)
179+
.setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
180+
.setPositiveButton(R.string.delete, ((dialog, which) -> {
181+
disposables.add(getDeletePlaybackStatesDisposable(context, recordManager));
182+
disposables.add(getWholeStreamHistoryDisposable(context, recordManager));
183+
disposables.add(getRemoveOrphanedRecordsDisposable(context, recordManager));
184+
}))
185+
.show();
186+
}
187+
188+
private static Disposable getDeletePlaybackStatesDisposable(
189+
@NonNull final Context context,
190+
final HistoryRecordManager recordManager
191+
) {
192+
return recordManager.deleteCompleteStreamStateHistory()
193+
.observeOn(AndroidSchedulers.mainThread())
194+
.subscribe(
195+
howManyDeleted -> Toast.makeText(context,
196+
R.string.watch_history_states_deleted, Toast.LENGTH_SHORT).show(),
197+
throwable -> ErrorUtil.openActivity(context,
198+
new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY,
199+
"Delete playback states"))
200+
);
201+
}
202+
203+
private static Disposable getWholeStreamHistoryDisposable(
204+
@NonNull final Context context,
205+
final HistoryRecordManager recordManager
206+
) {
207+
return recordManager.deleteWholeStreamHistory()
208+
.observeOn(AndroidSchedulers.mainThread())
209+
.subscribe(
210+
howManyDeleted -> Toast.makeText(context,
211+
R.string.watch_history_deleted, Toast.LENGTH_SHORT).show(),
212+
throwable -> ErrorUtil.openActivity(context,
213+
new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY,
214+
"Delete from history"))
215+
);
216+
}
217+
218+
private static Disposable getRemoveOrphanedRecordsDisposable(
219+
@NonNull final Context context, final HistoryRecordManager recordManager) {
220+
return recordManager.removeOrphanedRecords()
221+
.observeOn(AndroidSchedulers.mainThread())
222+
.subscribe(
223+
howManyDeleted -> {
224+
},
225+
throwable -> ErrorUtil.openActivity(context,
226+
new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY,
227+
"Clear orphaned records"))
228+
);
229+
}
230+
172231
///////////////////////////////////////////////////////////////////////////
173232
// Fragment LifeCycle - Loading
174233
///////////////////////////////////////////////////////////////////////////
@@ -307,7 +366,7 @@ private void toggleSortMode() {
307366
sortMode = StatisticSortMode.LAST_PLAYED;
308367
setTitle(getString(R.string.title_last_played));
309368
headerBinding.sortButtonIcon.setImageResource(
310-
R.drawable.ic_filter_list);
369+
R.drawable.ic_filter_list);
311370
headerBinding.sortButtonText.setText(R.string.title_most_played);
312371
}
313372
startLoading(true);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
import java.util.concurrent.TimeUnit;
4343

44+
import dagger.hilt.android.AndroidEntryPoint;
4445
import icepick.Icepick;
4546
import icepick.State;
4647

@@ -64,6 +65,7 @@
6465
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
6566
*/
6667

68+
@AndroidEntryPoint
6769
public class SettingsActivity extends AppCompatActivity implements
6870
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback,
6971
PreferenceSearchResultListener {

app/src/main/java/org/schabi/newpipe/settings/components/irreversible_preference/IrreversiblePreference.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,13 @@ fun IrreversiblePreferenceComponent(
2828
modifier: Modifier = Modifier,
2929
enabled: Boolean = true,
3030
) {
31+
val clickModifier = if (enabled) {
32+
Modifier.clickable { onClick() }
33+
} else {
34+
Modifier
35+
}
3136
Row(
32-
modifier = Modifier
33-
.clickable {
34-
if (enabled) {
35-
onClick()
36-
}
37-
}
38-
.then(modifier),
37+
modifier = clickModifier.then(modifier),
3938
verticalAlignment = Alignment.CenterVertically,
4039
) {
4140
val alpha by remember {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.schabi.newpipe.settings.presentation.history_cache
2+
3+
import android.os.Bundle
4+
import android.view.LayoutInflater
5+
import android.view.ViewGroup
6+
import androidx.compose.foundation.layout.fillMaxSize
7+
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.platform.ComposeView
9+
import androidx.compose.ui.platform.ViewCompositionStrategy
10+
import androidx.core.os.bundleOf
11+
import androidx.fragment.app.Fragment
12+
import org.schabi.newpipe.fragments.list.comments.CommentsFragment
13+
import org.schabi.newpipe.ui.theme.AppTheme
14+
import org.schabi.newpipe.util.KEY_SERVICE_ID
15+
import org.schabi.newpipe.util.KEY_URL
16+
17+
class HistoryCacheFragment : Fragment() {
18+
override fun onCreateView(
19+
inflater: LayoutInflater,
20+
container: ViewGroup?,
21+
savedInstanceState: Bundle?,
22+
) = ComposeView(requireContext()).apply {
23+
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
24+
setContent {
25+
AppTheme {
26+
HistoryCacheSettingsScreen(
27+
modifier = Modifier.fillMaxSize()
28+
)
29+
}
30+
}
31+
}
32+
33+
companion object {
34+
@JvmStatic
35+
fun getInstance(serviceId: Int, url: String?) = CommentsFragment().apply {
36+
arguments = bundleOf(KEY_SERVICE_ID to serviceId, KEY_URL to url)
37+
}
38+
}
39+
}

app/src/main/java/org/schabi/newpipe/settings/presentation/history_cache/HistoryCacheSettingsScreen.kt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCach
3232
import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCacheUiEvent.ShowDeleteSearchHistorySnackbar
3333
import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCacheUiEvent.ShowReCaptchaCookiesSnackbar
3434
import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCacheUiEvent.ShowWipeCachedMetadataSnackbar
35+
import org.schabi.newpipe.settings.presentation.history_cache.state.SwitchPreferencesUiState
3536
import org.schabi.newpipe.ui.theme.AppTheme
3637

3738
@Composable
@@ -47,6 +48,7 @@ fun HistoryCacheSettingsScreen(
4748
val clearReCaptchaCookiesSnackbar = stringResource(R.string.recaptcha_cookies_cleared)
4849

4950
LaunchedEffect(key1 = true) {
51+
viewModel.onInit()
5052
viewModel.eventFlow.collect { event ->
5153
val message = when (event) {
5254
is ShowDeletePlaybackSnackbar -> playBackPositionsDeleted
@@ -60,18 +62,21 @@ fun HistoryCacheSettingsScreen(
6062
}
6163
}
6264

63-
val state by viewModel.state.collectAsState()
65+
val switchPreferencesUiState by viewModel.switchState.collectAsState()
66+
val recaptchaCookiesEnabled by viewModel.captchaCookies.collectAsState()
6467
HistoryCacheComponent(
65-
state = state,
66-
onEvent = viewModel::onEvent,
68+
switchPreferences = switchPreferencesUiState,
69+
recaptchaCookiesEnabled = recaptchaCookiesEnabled,
70+
onEvent = { viewModel.onEvent(it) },
6771
snackBarHostState = snackBarHostState,
6872
modifier = modifier
6973
)
7074
}
7175

7276
@Composable
7377
fun HistoryCacheComponent(
74-
state: SwitchPreferencesUiState,
78+
switchPreferences: SwitchPreferencesUiState,
79+
recaptchaCookiesEnabled: Boolean,
7580
onEvent: (HistoryCacheEvent) -> Unit,
7681
snackBarHostState: SnackbarHostState,
7782
modifier: Modifier = Modifier,
@@ -91,14 +96,15 @@ fun HistoryCacheComponent(
9196
verticalArrangement = Arrangement.Center,
9297
) {
9398
HistoryPreferencesComponent(
94-
state = state,
99+
state = switchPreferences,
95100
onEvent = { key, value ->
96101
onEvent(HistoryCacheEvent.OnUpdateBooleanPreference(key, value))
97102
},
98103
modifier = Modifier.fillMaxWidth(),
99104
)
100105
HorizontalDivider(Modifier.fillMaxWidth())
101106
CachePreferencesComponent(
107+
recaptchaCookiesEnabled = recaptchaCookiesEnabled,
102108
onEvent = { onEvent(it) },
103109
modifier = Modifier.fillMaxWidth()
104110
)
@@ -119,7 +125,8 @@ private fun HistoryCacheComponentPreview() {
119125
) {
120126
Surface {
121127
HistoryCacheComponent(
122-
state = state,
128+
switchPreferences = state,
129+
recaptchaCookiesEnabled = false,
123130
onEvent = {
124131
},
125132
snackBarHostState = SnackbarHostState(),

app/src/main/java/org/schabi/newpipe/settings/presentation/history_cache/HistoryCacheSettingsViewModel.kt

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import org.schabi.newpipe.settings.domain.usecases.DeleteCompleteSearchHistory
2121
import org.schabi.newpipe.settings.domain.usecases.DeleteCompleteStreamStateHistory
2222
import org.schabi.newpipe.settings.domain.usecases.DeleteWatchHistory
2323
import org.schabi.newpipe.settings.domain.usecases.get_preference.GetPreference
24-
import org.schabi.newpipe.settings.domain.usecases.update_boolean_preference.UpdatePreference
24+
import org.schabi.newpipe.settings.domain.usecases.update_preference.UpdatePreference
2525
import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCacheEvent
2626
import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCacheEvent.OnClickClearSearchHistory
2727
import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCacheEvent.OnClickClearWatchHistory
@@ -34,29 +34,44 @@ import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCach
3434
import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCacheUiEvent.ShowDeletePlaybackSnackbar
3535
import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCacheUiEvent.ShowDeleteSearchHistorySnackbar
3636
import org.schabi.newpipe.settings.presentation.history_cache.events.HistoryCacheUiEvent.ShowWipeCachedMetadataSnackbar
37+
import org.schabi.newpipe.settings.presentation.history_cache.state.SwitchPreferencesUiState
3738
import org.schabi.newpipe.util.InfoCache
3839
import javax.inject.Inject
3940

4041
@HiltViewModel
4142
class HistoryCacheSettingsViewModel @Inject constructor(
42-
private val updateBooleanPreference: UpdatePreference<Boolean>,
4343
private val updateStringPreference: UpdatePreference<String>,
44+
private val updateBooleanPreference: UpdatePreference<Boolean>,
45+
private val getStringPreference: GetPreference<String>,
4446
private val getBooleanPreference: GetPreference<Boolean>,
4547
private val deleteWatchHistory: DeleteWatchHistory,
4648
private val deleteCompleteStreamStateHistory: DeleteCompleteStreamStateHistory,
4749
private val deleteCompleteSearchHistory: DeleteCompleteSearchHistory,
4850
private val openErrorActivity: OpenErrorActivity,
4951
) : ViewModel() {
50-
private val _state = MutableStateFlow(SwitchPreferencesUiState())
51-
val state: StateFlow<SwitchPreferencesUiState> = _state.asStateFlow()
52+
private val _switchState = MutableStateFlow(SwitchPreferencesUiState())
53+
val switchState: StateFlow<SwitchPreferencesUiState> = _switchState.asStateFlow()
54+
55+
private val _captchaCookies = MutableStateFlow(false)
56+
val captchaCookies: StateFlow<Boolean> = _captchaCookies.asStateFlow()
5257

5358
private val _eventFlow = MutableSharedFlow<HistoryCacheUiEvent>()
5459
val eventFlow = _eventFlow.asSharedFlow()
5560

56-
init {
61+
fun onInit() {
62+
63+
viewModelScope.launch {
64+
val flow = getStringPreference(R.string.recaptcha_cookies_key, "")
65+
flow.collect { preference ->
66+
_captchaCookies.update {
67+
preference.isNotEmpty()
68+
}
69+
}
70+
}
71+
5772
viewModelScope.launch {
5873
getBooleanPreference(R.string.enable_watch_history_key, true).collect { preference ->
59-
_state.update { oldState ->
74+
_switchState.update { oldState ->
6075
oldState.copy(
6176
watchHistoryEnabled = preference
6277
)
@@ -66,7 +81,7 @@ class HistoryCacheSettingsViewModel @Inject constructor(
6681

6782
viewModelScope.launch {
6883
getBooleanPreference(R.string.enable_playback_resume_key, true).collect { preference ->
69-
_state.update { oldState ->
84+
_switchState.update { oldState ->
7085
oldState.copy(
7186
resumePlaybackEnabled = preference
7287
)
@@ -79,7 +94,7 @@ class HistoryCacheSettingsViewModel @Inject constructor(
7994
R.string.enable_playback_state_lists_key,
8095
true
8196
).collect { preference ->
82-
_state.update { oldState ->
97+
_switchState.update { oldState ->
8398
oldState.copy(
8499
positionsInListsEnabled = preference
85100
)
@@ -88,7 +103,7 @@ class HistoryCacheSettingsViewModel @Inject constructor(
88103
}
89104
viewModelScope.launch {
90105
getBooleanPreference(R.string.enable_search_history_key, true).collect { preference ->
91-
_state.update { oldState ->
106+
_switchState.update { oldState ->
92107
oldState.copy(
93108
searchHistoryEnabled = preference
94109
)
@@ -126,7 +141,7 @@ class HistoryCacheSettingsViewModel @Inject constructor(
126141
}
127142
},
128143
onRemoveOrphanedRecords = {
129-
// TODO: ask why original did nothing
144+
// TODO: ask why original in android fragments did nothing
130145
}
131146
)
132147
}
@@ -181,7 +196,7 @@ class HistoryCacheSettingsViewModel @Inject constructor(
181196
updateStringPreference(event.key, "")
182197
DownloaderImpl.getInstance()
183198
.setCookie(ReCaptchaActivity.RECAPTCHA_COOKIES_KEY, "")
184-
_eventFlow.emit(HistoryCacheUiEvent.ShowWipeCachedMetadataSnackbar)
199+
_eventFlow.emit(ShowWipeCachedMetadataSnackbar)
185200
}
186201
}
187202
}

app/src/main/java/org/schabi/newpipe/settings/presentation/history_cache/components/CachePreferences.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import org.schabi.newpipe.ui.theme.SizeTokens.SpacingMedium
2424

2525
@Composable
2626
fun CachePreferencesComponent(
27+
recaptchaCookiesEnabled: Boolean,
2728
onEvent: (HistoryCacheEvent) -> Unit,
2829
modifier: Modifier = Modifier,
2930
) {
@@ -55,7 +56,9 @@ fun CachePreferencesComponent(
5556
IrreversiblePreferenceComponent(
5657
title = stringResource(id = R.string.metadata_cache_wipe_title),
5758
summary = stringResource(id = R.string.metadata_cache_wipe_summary),
58-
onClick = { onEvent(HistoryCacheEvent.OnClickWipeCachedMetadata(R.string.metadata_cache_wipe_key)) },
59+
onClick = {
60+
onEvent(HistoryCacheEvent.OnClickWipeCachedMetadata(R.string.metadata_cache_wipe_key))
61+
},
5962
modifier = Modifier.fillMaxWidth()
6063
)
6164
IrreversiblePreferenceComponent(
@@ -94,7 +97,10 @@ fun CachePreferencesComponent(
9497
IrreversiblePreferenceComponent(
9598
title = stringResource(id = R.string.clear_cookie_title),
9699
summary = stringResource(id = R.string.clear_cookie_summary),
97-
onClick = { onEvent(HistoryCacheEvent.OnClickReCaptchaCookies(R.string.recaptcha_cookies_key)) },
100+
onClick = {
101+
onEvent(HistoryCacheEvent.OnClickReCaptchaCookies(R.string.recaptcha_cookies_key))
102+
},
103+
enabled = recaptchaCookiesEnabled,
98104
modifier = Modifier.fillMaxWidth()
99105
)
100106
if (isDialogVisible) {
@@ -113,6 +119,7 @@ private fun CachePreferencesComponentPreview() {
113119
AppTheme {
114120
Scaffold { padding ->
115121
CachePreferencesComponent(
122+
recaptchaCookiesEnabled = false,
116123
onEvent = {},
117124
modifier = Modifier
118125
.fillMaxWidth()

0 commit comments

Comments
 (0)