diff options
64 files changed, 3674 insertions, 67 deletions
@@ -15,6 +15,7 @@ local.properties .idea/compiler.xml /.idea/assetWizardSettings.xml /.idea/jarRepositories.xml +/.idea/google-java-format.xml gradle.xml markdown-*.xml *.iml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index b66e2e7..c274a62 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -158,6 +158,7 @@ </codeStyleSettings> <codeStyleSettings language="kotlin"> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> + <option name="RIGHT_MARGIN" value="100" /> <option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" /> <option name="LINE_COMMENT_ADD_SPACE" value="true" /> <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" /> diff --git a/.idea/misc.xml b/.idea/misc.xml index af6eff4..2f6c31d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -5,7 +5,7 @@ <option name="myDefaultNotNull" value="android.support.annotation.NonNull" /> <option name="myNullables"> <value> - <list size="12"> + <list size="15"> <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" /> <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" /> <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" /> @@ -18,12 +18,15 @@ <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" /> <item index="10" class="java.lang.String" itemvalue="android.annotation.Nullable" /> <item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" /> + <item index="12" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.Nullable" /> + <item index="13" class="java.lang.String" itemvalue="io.reactivex.annotations.Nullable" /> + <item index="14" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.Nullable" /> </list> </value> </option> <option name="myNotNulls"> <value> - <list size="11"> + <list size="14"> <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" /> <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" /> <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" /> @@ -35,6 +38,9 @@ <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" /> <item index="9" class="java.lang.String" itemvalue="android.annotation.NonNull" /> <item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" /> + <item index="11" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.NonNull" /> + <item index="12" class="java.lang.String" itemvalue="io.reactivex.annotations.NonNull" /> + <item index="13" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.NonNull" /> </list> </value> </option> diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..797acea --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="RunConfigurationProducerService"> + <option name="ignoredProducers"> + <set> + <option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" /> + </set> + </option> + </component> +</project>
\ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 35e1c73..15fa88c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,14 +4,14 @@ plugins { } android { - compileSdkVersion 29 + compileSdkVersion buildConfig.compileSdk defaultConfig { applicationId "foundation.e.privacycentralapp" - minSdkVersion 24 - targetSdkVersion 29 - versionCode 1 - versionName "1.0" + minSdkVersion buildConfig.minSdk + targetSdkVersion buildConfig.targetSdk + versionCode buildConfig.version.code + versionName buildConfig.version.fullName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -26,17 +26,19 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - kotlinOptions { - jvmTarget = '1.8' - } } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.32" - implementation 'androidx.core:core-ktx:1.3.2' + implementation project(":flow-mvi") + implementation Libs.Kotlin.stdlib + implementation Libs.AndroidX.coreKtx + implementation Libs.AndroidX.Fragment.fragmentKtx implementation 'androidx.appcompat:appcompat:1.2.0' + implementation Libs.AndroidX.Lifecycle.runtime + implementation Libs.AndroidX.Lifecycle.viewmodel + implementation 'com.google.android.material:material:1.3.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a28e77e..2c3b055 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,13 +3,14 @@ package="foundation.e.privacycentralapp"> <application + android:name=".PrivacyCentralApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.PrivacyCentralApp"> - <activity android:name=".MainActivity"> + <activity android:name=".main.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> diff --git a/app/src/main/java/foundation/e/privacycentralapp/MainActivity.kt b/app/src/main/java/foundation/e/privacycentralapp/PrivacyCentralApplication.kt index 3dd2145..87be346 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/MainActivity.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/PrivacyCentralApplication.kt @@ -17,12 +17,6 @@ package foundation.e.privacycentralapp -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity +import android.app.Application -class MainActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - } -} +class PrivacyCentralApplication : Application() diff --git a/app/src/main/java/foundation/e/privacycentralapp/common/RightRadioButton.kt b/app/src/main/java/foundation/e/privacycentralapp/common/RightRadioButton.kt new file mode 100644 index 0000000..bbc108b --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/common/RightRadioButton.kt @@ -0,0 +1,43 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package foundation.e.privacycentralapp.common + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.widget.RadioButton + +/** + * A custom [RadioButton] which displays the radio drawable on the right side. + */ +@SuppressLint("AppCompatCustomView") +class RightRadioButton : RadioButton { + + constructor(context: Context) : super(context) + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) + + // Returns layout direction as right-to-left to draw the compound button on right side. + override fun getLayoutDirection(): Int { + return LAYOUT_DIRECTION_RTL + } +} diff --git a/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt b/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt new file mode 100644 index 0000000..aef994b --- /dev/null +++ b/app/src/main/java/foundation/e/privacycentralapp/dummy/DummyDataSource.kt @@ -0,0 +1,227 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package foundation.e.privacycentralapp.dummy + +import foundation.e.privacycentralapp.R +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlin.random.Random + +// ======================================================// +// +// ================ ==== ==== =============== +// ================ ====== ====== ================ +// ==== ======== ======== ==== ==== +// ==== ========= ========= ==== ==== +// ==== ==================== ================ +// ==== ==== ======== ==== =============== +// ==== ==== ==== ==== ==== +// ================ ==== == ==== ==== +// ================ ==== ==== ==== +// +// ======================================================// + +/** + * This whole file acts as a dummy source. All data classes and method implementations + * are not proper ones and are subject to change anytime. + */ + +/** + * Dummmy permission data class. + */ +data class Permission( + val id: Int, + val name: String, + val iconId: Int, + val packagesRequested: Set<String> = emptySet(), + val packagesAllowed: Set<String> = emptySet() +) + +enum class LocationMode { + REAL_LOCATION, RANDOM_LOCATION, CUSTOM_LOCATION +} + +enum class InternetPrivacyMode { + REAL_IP, HIDE_IP +} + +data class Location(val mode: LocationMode, val latitude: Double, val longitude: Double) + +object DummyDataSource { + + const val trackersCount = 77 + private val _activeTrackersCount = MutableStateFlow(10) + val activeTrackersCount = _activeTrackersCount.asStateFlow() + + private val _location = MutableStateFlow(Location(LocationMode.REAL_LOCATION, 0.0, 0.0)) + val location = _location.asStateFlow() + + private val _internetActivityMode = MutableStateFlow(InternetPrivacyMode.REAL_IP) + val internetActivityMode = _internetActivityMode.asStateFlow() + + /** + * Declare dummy permissions with following ids + * + * [0] -> Body sensor + * [1] -> Calendar + * [2] -> Call Logs + * [3] -> Location + */ + val permissions = arrayOf("Body Sensor", "Calendar", "Call Logs", "Location") + + private val permissionIcons = arrayOf( + R.drawable.ic_body_monitor, + R.drawable.ic_calendar, + R.drawable.ic_call, + R.drawable.ic_location + ) + + val packages = arrayOf( + "facebook", + "uber", + "instagram", + "openstreetmap", + "truecaller", + "netflix", + "firefox", + "pubg", + "amazon", + "calendar", + "zohomail", + "privacycentral" + ) + + val _populatedPermissions = MutableStateFlow(fetchPermissions()) + val populatedPermission = _populatedPermissions.asStateFlow() + + private val _appsUsingLocationPerm = + MutableStateFlow(_populatedPermissions.value[3].packagesAllowed) + val appsUsingLocationPerm = _appsUsingLocationPerm.asStateFlow() + + private fun fetchPermissions(): List<Permission> { + val result = mutableListOf<Permission>() + permissions.forEachIndexed { index, permission -> + when (index) { + 0 -> result.add(Permission(index, permission, permissionIcons[index])) + 1 -> { + val randomPackages = getRandomItems(packages, 8) + val grantedPackages = getRandomItems(randomPackages, 3) + result.add( + Permission( + index, + permission, + permissionIcons[index], + randomPackages, + grantedPackages + ) + ) + } + 2 -> { + val randomPackages = getRandomItems(packages, 10) + val grantedPackages = getRandomItems(randomPackages, 9) + result.add( + Permission( + index, + permission, + permissionIcons[index], + randomPackages, + grantedPackages + ) + ) + } + 3 -> { + val randomPackages = getRandomItems(packages, 5) + val grantedPackages = getRandomItems(randomPackages, 3) + result.add( + Permission( + index, + permission, + permissionIcons[index], + randomPackages, + grantedPackages + ) + ) + } + } + } + return result + } + + private fun <T> getRandomItems(data: Array<T>, limit: Int): Set<T> = + getRandomItems(data.toSet(), limit) + + private fun <T> getRandomItems(data: Set<T>, limit: Int): Set<T> { + val randomItems = mutableSetOf<T>() + val localData = data.toMutableList() + repeat(limit) { + val generated = localData.random() + randomItems.add(generated) + localData.remove(generated) + } + return randomItems + } + + fun getPermission(permissionId: Int): Permission = populatedPermission.value[permissionId] |