diff options
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.kt | 128 |
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() + } +} |