summaryrefslogtreecommitdiff
path: root/app/src/main/java/foundation/e/advancedprivacy/features/trackers/trackerdetails/TrackerDetailsViewModel.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/foundation/e/advancedprivacy/features/trackers/trackerdetails/TrackerDetailsViewModel.kt')
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/features/trackers/trackerdetails/TrackerDetailsViewModel.kt128
1 files changed, 128 insertions, 0 deletions
diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/trackerdetails/TrackerDetailsViewModel.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/trackerdetails/TrackerDetailsViewModel.kt
new file mode 100644
index 0000000..91a1f2a
--- /dev/null
+++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/trackerdetails/TrackerDetailsViewModel.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2023 MURENA SAS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package foundation.e.advancedprivacy.features.trackers.trackerdetails
+
+import android.net.Uri
+import androidx.annotation.StringRes
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import foundation.e.advancedprivacy.domain.entities.ApplicationDescription
+import foundation.e.advancedprivacy.domain.entities.TrackerMode
+import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase
+import foundation.e.advancedprivacy.domain.usecases.TrackerDetailsUseCase
+import foundation.e.advancedprivacy.domain.usecases.TrackersStateUseCase
+import foundation.e.advancedprivacy.domain.usecases.TrackersStatisticsUseCase
+import foundation.e.advancedprivacy.features.trackers.URL_LEARN_MORE_ABOUT_TRACKERS
+import foundation.e.advancedprivacy.trackers.domain.entities.Tracker
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asSharedFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+class TrackerDetailsViewModel(
+ private val tracker: Tracker,
+ private val trackersStateUseCase: TrackersStateUseCase,
+ private val trackersStatisticsUseCase: TrackersStatisticsUseCase,
+ private val trackerDetailsUseCase: TrackerDetailsUseCase,
+ private val getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase
+) : ViewModel() {
+ private val _state = MutableStateFlow(TrackerDetailsState(tracker = tracker))
+ val state = _state.asStateFlow()
+
+ private val _singleEvents = MutableSharedFlow<SingleEvent>()
+ val singleEvents = _singleEvents.asSharedFlow()
+
+ suspend fun doOnStartedState() = withContext(Dispatchers.IO) {
+ merge(
+ getQuickPrivacyStateUseCase.trackerMode.map {
+ _state.update { s -> s.copy(isTrackersBlockingEnabled = it != TrackerMode.VULNERABLE) }
+ },
+ trackersStatisticsUseCase.listenUpdates().map { fetchStatistics() }
+ ).collect { }
+ }
+
+ fun onToggleUnblockApp(app: ApplicationDescription, isBlocked: Boolean) {
+ viewModelScope.launch(Dispatchers.IO) {
+ if (!state.value.isTrackersBlockingEnabled) {
+ _singleEvents.emit(SingleEvent.ToastTrackersControlDisabled)
+ }
+
+ trackersStateUseCase.blockTracker(app, tracker, isBlocked)
+ updateWhitelist()
+ }
+ }
+
+ fun onToggleBlockAll(isBlocked: Boolean) {
+ viewModelScope.launch(Dispatchers.IO) {
+ if (!state.value.isTrackersBlockingEnabled) {
+ _singleEvents.emit(SingleEvent.ToastTrackersControlDisabled)
+ }
+ trackerDetailsUseCase.toggleTrackerWhitelist(tracker, isBlocked)
+ _state.update {
+ it.copy(
+ isBlockAllActivated = !trackersStateUseCase.isWhitelisted(tracker)
+ )
+ }
+ updateWhitelist()
+ }
+ }
+
+ fun onClickLearnMore() {
+ viewModelScope.launch {
+ _singleEvents.emit(SingleEvent.OpenUrl(Uri.parse(URL_LEARN_MORE_ABOUT_TRACKERS)))
+ }
+ }
+
+ private suspend fun fetchStatistics() = withContext(Dispatchers.IO) {
+ val (blocked, leaked) = trackerDetailsUseCase.getCalls(tracker)
+ val appsWhitWhiteListState = trackerDetailsUseCase.getAppsWithBlockedState(tracker)
+
+ _state.update { s ->
+ s.copy(
+ isBlockAllActivated = !trackersStateUseCase.isWhitelisted(tracker),
+ detectedCount = appsWhitWhiteListState.size,
+ blockedCount = blocked,
+ leakedCount = leaked,
+ appList = appsWhitWhiteListState,
+ )
+ }
+ }
+
+ private suspend fun updateWhitelist() {
+ _state.update { s ->
+ s.copy(
+ isBlockAllActivated = !trackersStateUseCase.isWhitelisted(tracker),
+ appList = trackerDetailsUseCase.enrichWithBlockedState(
+ s.appList.map { it.first }, tracker
+ )
+ )
+ }
+ }
+
+ sealed class SingleEvent {
+ data class ErrorEvent(@StringRes val errorResId: Int) : SingleEvent()
+ object ToastTrackersControlDisabled : SingleEvent()
+ data class OpenUrl(val url: Uri) : SingleEvent()
+ }
+}