/*
* Copyright (C) 2024 Leonard Kugis
* Copyright (C) 2023 MURENA SAS
* Copyright (C) 2021 E FOUNDATION
*
* 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 .
*/
package foundation.e.advancedprivacy.data.repositories
import android.content.Context
import foundation.e.advancedprivacy.domain.entities.ApplicationDescription
import foundation.e.advancedprivacy.domain.entities.FeatureState
import foundation.e.advancedprivacy.domain.entities.LocationMode
import foundation.e.advancedprivacy.domain.entities.MainFeatures
import foundation.e.advancedprivacy.domain.repositories.LocalStateRepository
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import foundation.e.advancedprivacy.domain.entities.FakeLocationCoordinate
class LocalStateRepositoryImpl(context: Context) : LocalStateRepository {
companion object {
private const val SHARED_PREFS_FILE = "localState"
private const val KEY_BLOCK_TRACKERS = "blockTrackers"
private const val KEY_IP_SCRAMBLING = "ipScrambling"
private const val KEY_FAKE_ALTITUDE = "fakeAltitude"
private const val KEY_FAKE_SPEED = "fakeSpeed"
private const val KEY_FAKE_BEARING = "fakeBearing"
private const val KEY_FAKE_JITTER = "fakeJitter"
private const val KEY_FAKE_JITTER_ALTITUDE = "fakeJitterAltitude"
private const val KEY_FAKE_JITTER_SPEED = "fakeJitterSpeed"
private const val KEY_FAKE_JITTER_BEARING = "fakeJitterBearing"
private const val KEY_LOCATION_MODE = "locationMode"
private const val KEY_LOCATION_ROUTE = "locationRoute"
private const val KEY_LOCATION_ROUTE_LOOP = "locationRouteLoop"
private const val KEY_FAKE_LATITUDE = "fakeLatitude"
private const val KEY_FAKE_LONGITUDE = "fakeLongitude"
private const val KEY_FIRST_BOOT = "firstBoot"
private const val KEY_HIDE_WARNING_TRACKERS = "hide_warning_trackers"
private const val KEY_HIDE_WARNING_LOCATION = "hide_warning_location"
private const val KEY_HIDE_WARNING_IPSCRAMBLING = "hide_warning_ipscrambling"
}
private val sharedPref = context.getSharedPreferences(SHARED_PREFS_FILE, Context.MODE_PRIVATE)
private val _blockTrackers = MutableStateFlow(sharedPref.getBoolean(KEY_BLOCK_TRACKERS, true))
override val blockTrackers = _blockTrackers.asStateFlow()
override fun setBlockTrackers(enabled: Boolean) {
set(KEY_BLOCK_TRACKERS, enabled)
_blockTrackers.update { enabled }
}
override val areAllTrackersBlocked: MutableStateFlow = MutableStateFlow(false)
override var fakeAltitude: Float
get() = sharedPref.getFloat(KEY_FAKE_ALTITUDE, 3.0f)
set(value) {
sharedPref.edit()
.putFloat(KEY_FAKE_ALTITUDE, value)
.apply()
}
override var fakeSpeed: Float
get() = sharedPref.getFloat(KEY_FAKE_SPEED, 1.0f)
set(value) {
sharedPref.edit()
.putFloat(KEY_FAKE_SPEED, value)
.apply()
}
override var fakeBearing: Float
get() = sharedPref.getFloat(KEY_FAKE_BEARING, 0.0f)
set(value) {
sharedPref.edit()
.putFloat(KEY_FAKE_BEARING, value)
.apply()
}
override var fakeJitter: Float
get() = sharedPref.getFloat(KEY_FAKE_JITTER, 3.0f)
set(value) {
sharedPref.edit()
.putFloat(KEY_FAKE_JITTER, value)
.apply()
}
override var fakeJitterAltitude: Float
get() = sharedPref.getFloat(KEY_FAKE_JITTER_ALTITUDE, 3.0f)
set(value) {
sharedPref.edit()
.putFloat(KEY_FAKE_JITTER_ALTITUDE, value)
.apply()
}
override var fakeJitterSpeed: Float
get() = sharedPref.getFloat(KEY_FAKE_JITTER_SPEED, 0.1f)
set(value) {
sharedPref.edit()
.putFloat(KEY_FAKE_JITTER_SPEED, value)
.apply()
}
override var fakeJitterBearing: Float
get() = sharedPref.getFloat(KEY_FAKE_JITTER_BEARING, 10.0f)
set(value) {
sharedPref.edit()
.putFloat(KEY_FAKE_JITTER_BEARING, value)
.apply()
}
override var fakeLocation: Pair
get() = Pair(
// Initial default value is Quezon City
sharedPref.getFloat(KEY_FAKE_LATITUDE, 14.6760f),
sharedPref.getFloat(KEY_FAKE_LONGITUDE, 121.0437f)
)
set(value) {
sharedPref.edit()
.putFloat(KEY_FAKE_LATITUDE, value.first)
.putFloat(KEY_FAKE_LONGITUDE, value.second)
.apply()
}
override var route: List
get() {
return Gson().fromJson>(sharedPref.getString(KEY_LOCATION_ROUTE, "[]"), object : TypeToken>() {}.type)
}
set(value) {
sharedPref.edit()
.putString(KEY_LOCATION_ROUTE, Gson().toJson(value))
.apply()
}
override var routeLoopEnabled: Boolean
get() = sharedPref.getBoolean(KEY_LOCATION_ROUTE_LOOP, false)
set(value) {
sharedPref.edit()
.putBoolean(KEY_LOCATION_ROUTE_LOOP, value)
.apply()
}
private val _locationMode = MutableStateFlow(LocationMode.valueOf(sharedPref.getString(KEY_LOCATION_MODE, LocationMode.REAL_LOCATION.toString()) ?: "REAL_LOCATION"))
override val locationMode = _locationMode.asStateFlow()
override fun setLocationMode(mode: LocationMode) {
sharedPref.edit()
.putString(KEY_LOCATION_MODE, mode.toString())
.apply()
//set(KEY_LOCATION_MODE, mode.toString())
_locationMode.update { mode }
}
private val _ipScramblingSetting = MutableStateFlow(sharedPref.getBoolean(KEY_IP_SCRAMBLING, false))
override val ipScramblingSetting = _ipScramblingSetting.asStateFlow()
override fun setIpScramblingSetting(enabled: Boolean) {
set(KEY_IP_SCRAMBLING, enabled)
_ipScramblingSetting.update { enabled }
}
override val internetPrivacyMode: MutableStateFlow = MutableStateFlow(FeatureState.OFF)
private val _startVpnDisclaimer = MutableSharedFlow()
override suspend fun emitStartVpnDisclaimer(feature: MainFeatures) {
_startVpnDisclaimer.emit(feature)
}
override val startVpnDisclaimer: SharedFlow = _startVpnDisclaimer
private val _otherVpnRunning = MutableSharedFlow()
override suspend fun emitOtherVpnRunning(appDesc: ApplicationDescription) {
_otherVpnRunning.emit(appDesc)
}
override val otherVpnRunning: SharedFlow = _otherVpnRunning
override var firstBoot: Boolean
get() = sharedPref.getBoolean(KEY_FIRST_BOOT, true)
set(value) = set(KEY_FIRST_BOOT, value)
override var hideWarningTrackers: Boolean
get() = sharedPref.getBoolean(KEY_HIDE_WARNING_TRACKERS, false)
set(value) = set(KEY_HIDE_WARNING_TRACKERS, value)
override var hideWarningLocation: Boolean
get() = sharedPref.getBoolean(KEY_HIDE_WARNING_LOCATION, false)
set(value) = set(KEY_HIDE_WARNING_LOCATION, value)
override var hideWarningIpScrambling: Boolean
get() = sharedPref.getBoolean(KEY_HIDE_WARNING_IPSCRAMBLING, false)
set(value) = set(KEY_HIDE_WARNING_IPSCRAMBLING, value)
private fun set(key: String, value: Boolean) {
sharedPref.edit().putBoolean(key, value).apply()
}
}