diff --git a/app/.gitignore b/app/.gitignore
index 42afabfd2abebf31384ca7797186a27a4b7dbee8..cdb86eeb63e9bc7f6cea978a05bcfc79062f0088 100644
--- a/app/.gitignore
+++ b/app/.gitignore
@@ -1 +1,2 @@
-/build
\ No newline at end of file
+version.properties
+/build
diff --git a/app/build.gradle b/app/build.gradle
index 6592d9072f4c7ff12e8c66c6d5a7b4e0bfa787fb..c2547c6e75bb983e78c0c6bc396ad277f10d6547 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,17 +2,17 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
- id 'kotlin-kapt'
- id 'org.jlleitschuh.gradle.ktlint' version '10.2.0'
+ id 'com.google.devtools.ksp'
+ alias libs.plugins.ktlint
id 'androidx.navigation.safeargs.kotlin'
id 'com.google.dagger.hilt.android'
id 'kotlin-allopen'
id 'kotlin-parcelize'
}
-def versionMajor = 2
-def versionMinor = 12
-def versionPatch = 3
+def appVersionMajor = 2
+def appVersionMinor = 12
+def appVersionPatch = 3
def getGitHash = { ->
def stdOut = new ByteArrayOutputStream()
@@ -43,14 +43,71 @@ def getSentryDsn = { ->
}
android {
- compileSdk 34
+ def versionPropsFile = file('version.properties')
+ Properties versionProps = new Properties()
+
+ if (!versionPropsFile.exists()) {
+ versionProps['VERSION_CHANGE'] = '0'
+ versionProps['VERSION_MAJOR'] = appVersionMajor.toString()
+ versionProps['VERSION_MINOR'] = appVersionMinor.toString()
+ versionProps['VERSION_PATCH'] = appVersionPatch.toString()
+ versionProps['VERSION_CODE'] = (appVersionMajor * 1000000 + appVersionMinor * 1000 + appVersionPatch).toString()
+ versionProps.store(versionPropsFile.newWriter(), null)
+ }
+
+ def getVersionCode = { ->
+ if (versionPropsFile.canRead()) {
+ versionProps.load(new FileInputStream(versionPropsFile))
+ def versionChange = versionProps['VERSION_CHANGE'].toInteger() + 1
+ def versionMinor = versionProps['VERSION_MINOR'].toInteger()
+ def versionMajor = versionProps['VERSION_MAJOR'].toInteger()
+ def versionPatch = versionProps['VERSION_PATCH'].toInteger()
+ // Up version on each 100 cycles of builds
+ if (versionChange >= 100) {
+ versionPatch = versionProps['VERSION_PATCH'].toInteger() + 1
+ versionChange = 0
+ }
+ if (versionPatch == 9) {
+ versionMinor = versionProps['VERSION_MINOR'].toInteger() + 1
+ versionPatch = 0
+ }
+ if (versionMinor == 9) {
+ versionMajor = versionProps['VERSION_MAJOR'].toInteger() + 1
+ versionMinor = 0
+ }
+ def versionCode = versionProps['VERSION_CODE'].toInteger()
+
+ versionProps['VERSION_CHANGE'] = versionChange.toString()
+ versionProps['VERSION_PATCH'] = versionPatch.toString()
+ versionProps['VERSION_MINOR'] = versionMinor.toString()
+ versionProps['VERSION_MAJOR'] = versionMajor.toString()
+ versionProps['VERSION_CODE'] = (versionCode.toInteger() + 1).toString()
+ versionProps.store(versionPropsFile.newWriter(), null)
+ return versionCode
+ }
+ }
+
+ def getVersionName = { ->
+ if (versionPropsFile.canRead()) {
+ versionProps.load(new FileInputStream(versionPropsFile))
+
+ def versionMajor = versionProps['VERSION_MAJOR']
+ def versionMinor = versionProps['VERSION_MINOR']
+ def versionPatch = versionProps['VERSION_PATCH']
+
+ return "${versionMajor}.${versionMinor}.${versionPatch}"
+ }
+ }
+
+ compileSdk = 35
defaultConfig {
- applicationId "foundation.e.apps"
- minSdk 26
- targetSdk 30
- versionCode versionMajor * 1000000 + versionMinor * 1000 + versionPatch
- versionName "${versionMajor}.${versionMinor}.${versionPatch}"
+ applicationId = "foundation.e.apps"
+ minSdk = 30
+ //noinspection OldTargetApi
+ targetSdk = 34
+ versionCode = getVersionCode()
+ versionName = getVersionName()
buildConfigField "String", "BUILD_ID", "\"${getGitHash() + "." + getDate()}\""
buildConfigField("String", "SENTRY_DSN", "\"${getSentryDsn()}\"")
@@ -60,7 +117,7 @@ android {
manifestPlaceholders = [parentalControlPkgName: parentalControlPkgName]
buildConfigField "String", "PACKAGE_NAME_PARENTAL_CONTROL", "\"${parentalControlPkgName}\""
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
@@ -72,22 +129,22 @@ android {
keyPassword "platform"
}
releaseTestConfig {
- storeFile file("../keystore/proprietary.keystore")
- storePassword keystore_password
- keyAlias 'platform.test'
- keyPassword keystore_password
+ storeFile = file("../keystore/proprietary.keystore")
+ storePassword = keystore_password
+ keyAlias = 'platform.test'
+ keyPassword = keystore_password
}
releaseCommunityConfig {
- storeFile file("../keystore/proprietary.keystore")
- storePassword keystore_password
- keyAlias 'platform.dev'
- keyPassword keystore_password
+ storeFile = file("../keystore/proprietary.keystore")
+ storePassword = keystore_password
+ keyAlias = 'platform.dev'
+ keyPassword = keystore_password
}
releaseOfficialConfig {
- storeFile file("../keystore/proprietary.keystore")
- storePassword keystore_password
- keyAlias 'platform.stable'
- keyPassword keystore_password
+ storeFile = file("../keystore/proprietary.keystore")
+ storePassword = keystore_password
+ keyAlias = 'platform.stable'
+ keyPassword = keystore_password
}
}
@@ -111,28 +168,29 @@ android {
buildTypes {
debug {
- signingConfig signingConfigs.debugConfig
+ signingConfig = signingConfigs.debugConfig
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
release {
- minifyEnabled false
+ minifyEnabled = false
+ signingConfig = signingConfigs.debugConfig
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
releaseTest {
- minifyEnabled false
- signingConfig signingConfigs.releaseTestConfig
+ minifyEnabled = false
+ signingConfig = signingConfigs.releaseTestConfig
sourceSets
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
releaseCommunity {
- minifyEnabled false
- signingConfig signingConfigs.releaseCommunityConfig
+ minifyEnabled = false
+ signingConfig = signingConfigs.releaseCommunityConfig
sourceSets
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
releaseOfficial {
- minifyEnabled false
- signingConfig signingConfigs.releaseOfficialConfig
+ minifyEnabled = false
+ signingConfig = signingConfigs.releaseOfficialConfig
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
@@ -143,29 +201,26 @@ android {
}
}
buildFeatures {
- viewBinding true
- aidl true
+ buildConfig = true
+ viewBinding = true
+ aidl = true
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_17
- targetCompatibility JavaVersion.VERSION_17
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
lint {
- lintConfig file('lint.xml')
+ lintConfig = file('lint.xml')
}
- namespace 'foundation.e.apps'
- kotlin.sourceSets.all {
+ namespace = 'foundation.e.apps'
+ kotlin.sourceSets.configureEach {
languageSettings.optIn("kotlin.RequiresOptIn")
}
}
-kapt {
- correctErrorTypes true
-}
-
allOpen {
// allows mocking for classes w/o directly opening them for release builds
annotation 'foundation.e.apps.OpenClass'
@@ -174,116 +229,105 @@ allOpen {
dependencies {
- implementation project(':auth-data-lib')
- implementation project(':parental-control-data')
+ // Project dependencies
+ implementation(project(":auth-data-lib"))
+ implementation(project(":parental-control-data"))
+ // Library dependencies
// TODO: Add splitinstall-lib to a repo https://gitlab.e.foundation/e/os/backlog/-/issues/628
- api files('libs/splitinstall-lib.jar')
-
- implementation 'foundation.e.lib:telemetry:0.0.11-alpha'
- implementation 'foundation.e:gplayapi:3.4.2-0'
- implementation 'androidx.core:core-ktx:1.9.0'
- implementation 'androidx.appcompat:appcompat:1.6.1'
- implementation 'androidx.fragment:fragment-ktx:1.5.6'
- implementation 'com.google.android.material:material:1.5.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
- implementation 'androidx.legacy:legacy-support-v4:1.0.0'
- implementation 'androidx.preference:preference-ktx:1.2.0'
- implementation "androidx.datastore:datastore-preferences:1.0.0"
- implementation 'com.facebook.shimmer:shimmer:0.5.0'
- implementation 'androidx.core:core-google-shortcuts:1.0.0'
- debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
- testImplementation "com.google.truth:truth:1.1.3"
- testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.1.5'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
- // Optional -- Robolectric environment
- testImplementation "androidx.test:core:1.5.0"
- // Optional -- Mockito framework
- testImplementation "org.mockito:mockito-core:5.0.0"
- // Optional -- mockito-kotlin
- testImplementation "org.mockito.kotlin:mockito-kotlin:4.1.0"
- testImplementation 'org.mockito:mockito-inline:5.0.0'
- testImplementation "androidx.arch.core:core-testing:2.2.0"
-
- testImplementation "io.mockk:mockk:1.12.3"
+ api(files("libs/splitinstall-lib.jar"))
+
+ // eFoundation libraries
+ implementation(libs.telemetry)
+ implementation(libs.gplayapi)
+ implementation(libs.elib)
+
+ // AndroidX libraries
+ implementation(libs.core.ktx)
+ implementation(libs.appcompat)
+ implementation(libs.fragment.ktx)
+ implementation(libs.preference.ktx)
+ implementation(libs.constraintlayout)
+ implementation(libs.legacy.support.v4)
+ implementation(libs.datastore.preferences)
+ implementation(libs.viewpager2)
+ implementation(libs.recyclerview)
+ implementation(libs.navigation.fragment.ktx)
+ implementation(libs.navigation.ui.ktx)
+ implementation(libs.activity.ktx)
+
+ // Material Design
+ implementation(libs.material)
- // Coil and PhotoView
- implementation "io.coil-kt:coil:1.4.0"
- implementation 'com.github.Baseflow:PhotoView:2.3.0'
-
- //Protobuf and Gson
- implementation 'com.google.code.gson:gson:2.9.0'
- implementation "com.google.protobuf:protobuf-javalite:3.25.2"
+ // Lifecycle Components
+ implementation(libs.lifecycle.viewmodel.ktx)
+ implementation(libs.lifecycle.livedata.ktx)
+ implementation(libs.lifecycle.runtime.ktx)
+ implementation(libs.lifecycle.extensions)
- // ViewPager2 and RecyclerView
- implementation "androidx.viewpager2:viewpager2:1.0.0"
- implementation "androidx.recyclerview:recyclerview:1.2.1"
+ // WorkManager
+ implementation(libs.work.runtime.ktx)
- //logger
- implementation 'com.jakewharton.timber:timber:5.0.1'
+ // Room
+ ksp(libs.room.compiler)
+ implementation(libs.room.ktx)
+ implementation(libs.room.runtime)
- // Bouncy Castle
- implementation 'org.bouncycastle:bcpg-jdk15on:1.60'
+ // Hilt
+ ksp(libs.hilt.compile)
+ implementation(libs.hilt.android)
+ implementation(libs.hilt.work)
+ ksp(libs.hilt.compiler)
- // Retrofit
- def retrofit_version = "2.9.0"
- implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
- implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
- implementation "com.squareup.retrofit2:converter-jackson:$retrofit_version"
- implementation "com.squareup.moshi:moshi-kotlin:1.13.0"
-// implementation "com.squareup.moshi:moshi-adapters:1.5.0"
- implementation "com.squareup.okhttp3:okhttp:4.9.2"
- implementation "com.squareup.okhttp3:logging-interceptor:4.9.2"
+ // Facebook
+ implementation(libs.shimmer)
- // JSON Converter
- implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
+ // Coroutines
+ implementation(libs.kotlinx.coroutines.core)
+ implementation(libs.kotlinx.coroutines.android)
+ testImplementation(libs.kotlinx.coroutines.test)
+ testImplementation(libs.kotlin.test)
+
+ // Testing dependencies
+ testImplementation(libs.truth)
+ testImplementation(libs.junit)
+ androidTestImplementation(libs.ext.junit)
+ androidTestImplementation(libs.espresso.core)
+ testImplementation(libs.core)
+ testImplementation(libs.mockito.core)
+ testImplementation(libs.mockito.kotlin)
+ testImplementation(libs.mockito.inline)
+ testImplementation(libs.core.testing)
+ testImplementation(libs.mockk)
- // YAML factory
- implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.11.2"
+ // Coil and PhotoView
+ implementation(libs.coil)
+ implementation(libs.photoview)
- // Navigation Components
- def navigation_version = "2.6.0"
- implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
- implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
+ // Protobuf and Gson
+ implementation(libs.gson)
+ implementation(libs.protobuf.javalite)
- // Hilt
- def hilt_version = '2.51.1'
- kapt "com.google.dagger:hilt-compiler:$hilt_version"
- implementation "com.google.dagger:hilt-android:$hilt_version"
- implementation 'androidx.hilt:hilt-work:1.0.0'
- kapt 'androidx.hilt:hilt-compiler:1.0.0'
+ // Logger
+ implementation(libs.timber)
- // Lifecycle Components
- def lifecycle_version = "2.6.1"
- implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
- implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
- implementation "android.arch.lifecycle:extensions:1.1.1"
- implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
+ // Retrofit
+ implementation(libs.retrofit)
+ implementation(libs.converter.moshi)
+ implementation(libs.converter.jackson)
+ implementation(libs.moshi.kotlin)
+ implementation(libs.okhttp)
+ implementation(libs.logging.interceptor)
- // Coroutines
- def coroutines_version = "1.6.0"
- def test_kotlin_version = "1.6.0"
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
- testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
- testImplementation "org.jetbrains.kotlin:kotlin-test:$test_kotlin_version"
+ // JSON Converter
+ implementation(libs.converter.gson)
- // Room
- kapt "androidx.room:room-compiler:2.6.1"
- implementation "androidx.room:room-ktx:2.6.1"
- implementation "androidx.room:room-runtime:2.6.1"
+ // YAML factory
+ implementation(libs.jackson.dataformat.yaml)
- // WorkManager
- implementation 'androidx.work:work-runtime-ktx:2.7.1'
+ // Bouncy Castle
+ implementation(libs.bcpg.jdk15on)
// JSoup
- implementation 'org.jsoup:jsoup:1.13.1'
-
- // elib
- implementation 'foundation.e:elib:0.0.1-alpha11'
-
- // androidx.activity
- def activity_version = "1.6.1"
- implementation("androidx.activity:activity-ktx:$activity_version")
+ implementation(libs.jsoup)
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index fe79aa0933f8fd69ee2db6a916b70b323660e5a6..cce4b11c286be2bcf810c08cc655a72807a746b4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -28,7 +28,8 @@
-
+
+
@@ -61,7 +62,6 @@
-
+
+
+
-
+
+
+ android:exported="true"
+ android:foregroundServiceType="dataSync">
+
+
+
= Build.VERSION_CODES.R) {
- val installerInfo = packageManager.getInstallSourceInfo(packageName)
- installerInfo.originatingPackageName ?: installerInfo.installingPackageName ?: UNKNOWN_VALUE
- } else {
- packageManager.getInstallerPackageName(packageName) ?: UNKNOWN_VALUE
- }
+ val installerInfo = packageManager.getInstallSourceInfo(packageName)
+ installerInfo.originatingPackageName ?: installerInfo.installingPackageName ?: UNKNOWN_VALUE
} catch (e: NameNotFoundException) {
Timber.e("getInstallerName -> $packageName : ${e.localizedMessage}")
UNKNOWN_VALUE
@@ -164,12 +160,7 @@ class AppLoungePackageManager @Inject constructor(
fun getVersionCode(packageName: String): String {
val packageInfo = getPackageInfo(packageName)
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
- packageInfo?.longVersionCode?.toString() ?: UNKNOWN_VALUE
- } else {
- @Suppress("DEPRECATION")
- packageInfo?.versionCode?.toString() ?: UNKNOWN_VALUE
- }
+ return packageInfo?.longVersionCode?.toString() ?: UNKNOWN_VALUE
}
fun getVersionName(packageName: String): String {
diff --git a/app/src/main/java/foundation/e/apps/install/splitinstall/SplitInstallBinder.kt b/app/src/main/java/foundation/e/apps/install/splitinstall/SplitInstallBinder.kt
index 557d5ba3d5fb90d01f1ba9fb84520029f08326dc..69bc609577dabe9292692f97069aa0bfa535fe62 100644
--- a/app/src/main/java/foundation/e/apps/install/splitinstall/SplitInstallBinder.kt
+++ b/app/src/main/java/foundation/e/apps/install/splitinstall/SplitInstallBinder.kt
@@ -113,6 +113,7 @@ class SplitInstallBinder(
if (ignoreList != null && packageName in ignoreList) return
val appInfo = context.packageManager.getPackageInfo(packageName, 0).applicationInfo
+ ?: return
val appLabel = context.packageManager.getApplicationLabel(appInfo)
val callerUid = appInfo.uid
val contentText = context.getString(
diff --git a/app/src/main/java/foundation/e/apps/install/workmanager/InstallAppWorker.kt b/app/src/main/java/foundation/e/apps/install/workmanager/InstallAppWorker.kt
index e2011c231b18ff96b773e2de07fb18cb925dfbff..8fb976c63055a11242eeb073ee10546b5c444dfb 100644
--- a/app/src/main/java/foundation/e/apps/install/workmanager/InstallAppWorker.kt
+++ b/app/src/main/java/foundation/e/apps/install/workmanager/InstallAppWorker.kt
@@ -21,6 +21,7 @@ package foundation.e.apps.install.workmanager
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
+import android.content.pm.ServiceInfo
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.hilt.work.HiltWorker
@@ -100,6 +101,17 @@ class InstallAppWorker @AssistedInject constructor(
.addAction(android.R.drawable.ic_delete, cancel, intent)
.build()
- return ForegroundInfo(atomicInteger.getAndIncrement(), notification)
+ // Set the foreground service type for Android 14+
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ ForegroundInfo(
+ atomicInteger.getAndIncrement(),
+ notification,
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC // Specify a valid service type
+ )
+ } else {
+ ForegroundInfo(
+ atomicInteger.getAndIncrement(),
+ notification)
+ }
}
}
diff --git a/app/src/main/java/foundation/e/apps/ui/MainActivity.kt b/app/src/main/java/foundation/e/apps/ui/MainActivity.kt
index 59d88fcd0cc98d4519cf7f770caf62a627742250..8d914dd59487d691f9da4f4514eed18f4dbe234a 100644
--- a/app/src/main/java/foundation/e/apps/ui/MainActivity.kt
+++ b/app/src/main/java/foundation/e/apps/ui/MainActivity.kt
@@ -25,6 +25,7 @@ import android.os.Bundle
import android.view.View
import android.widget.Toast
import android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT
+import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
@@ -82,6 +83,20 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ // Add an OnBackPressedCallback to handle the back press
+ onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ if (isInitialScreen()) {
+ resetIgnoreStatusForSessionRefresh()
+ finish()
+ } else {
+ // Let the system handle the back press
+ isEnabled = false
+ onBackPressedDispatcher.onBackPressed()
+ }
+ }
+ })
+
binding = ActivityMainBinding.inflate(layoutInflater)
setupBackPressHandlingForTiramisuAndAbove()
@@ -127,7 +142,7 @@ class MainActivity : AppCompatActivity() {
checkGPlayLoginRequest(intent)
}
- override fun onNewIntent(intent: Intent?) {
+ override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
checkGPlayLoginRequest(intent)
findNavController(R.id.fragment).handleDeepLink(intent)
@@ -148,19 +163,7 @@ class MainActivity : AppCompatActivity() {
loginViewModel.startLoginFlow(listOf(PlayStoreAuthenticator::class.java.simpleName))
}
- // In Android 12 (API level 32) and lower, onBackPressed is always called,
- // regardless of any registered instances of OnBackPressedCallback.
- // https://developer.android.com/guide/navigation/navigation-custom-back#onbackpressed
- @Deprecated("Deprecated in Java")
- override fun onBackPressed() {
- if (isInitialScreen()) {
- resetIgnoreStatusForSessionRefresh()
- finish()
- }
- super.onBackPressed()
- }
-
- private fun isInitialScreen(): Boolean {
+ fun isInitialScreen(): Boolean {
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment) as NavHostFragment
@@ -169,7 +172,7 @@ class MainActivity : AppCompatActivity() {
return navController.currentDestination?.id == navController.graph.startDestinationId
}
- private fun resetIgnoreStatusForSessionRefresh() {
+ fun resetIgnoreStatusForSessionRefresh() {
viewModel.shouldIgnoreSessionError = false
}
diff --git a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListFragment.kt b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListFragment.kt
index 3c5fc507d65654fade934894f4cae6a87e219ae5..895c0133422ecc4ed63024d63eecb0e71c488ef3 100644
--- a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListFragment.kt
+++ b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListFragment.kt
@@ -48,6 +48,7 @@ import foundation.e.apps.ui.PrivacyInfoViewModel
import foundation.e.apps.ui.application.subFrags.ApplicationDialogFragment
import foundation.e.apps.ui.parentFragment.TimeoutFragment
import kotlinx.coroutines.launch
+import java.util.Locale
import javax.inject.Inject
@AndroidEntryPoint
@@ -321,7 +322,7 @@ class ApplicationListFragment :
)
viewHolder?.let {
(viewHolder as ApplicationListRVAdapter.ViewHolder).binding.installButton.text =
- String.format("%d%%", progress)
+ String.format(Locale.getDefault(), "%d%%", progress)
}
}
}
diff --git a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt
index 656591845129994cc40c07c33874d2f43842ef99..83ab2b0b612a653971ffd871b74340b85bfd5b39 100644
--- a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt
+++ b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt
@@ -216,7 +216,7 @@ class ApplicationListRVAdapter(
return
}
if (searchApp.ratings.usageQualityScore != -1.0) {
- appRating.text = searchApp.ratings.usageQualityScore.toString()
+ appRating.text = "${searchApp.ratings.usageQualityScore}"
} else {
appRating.text = root.context.getString(R.string.not_available)
}
diff --git a/app/src/main/java/foundation/e/apps/ui/home/HomeFragment.kt b/app/src/main/java/foundation/e/apps/ui/home/HomeFragment.kt
index b349adb42a2038267b47dc9b0a4acab6caa28a80..3992a2b68be98e002b0f007a52e0c14502f3a4ed 100644
--- a/app/src/main/java/foundation/e/apps/ui/home/HomeFragment.kt
+++ b/app/src/main/java/foundation/e/apps/ui/home/HomeFragment.kt
@@ -48,6 +48,7 @@ import foundation.e.apps.ui.home.model.HomeParentRVAdapter
import foundation.e.apps.ui.parentFragment.TimeoutFragment
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
+import java.util.Locale
import javax.inject.Inject
@AndroidEntryPoint
@@ -246,7 +247,7 @@ class HomeFragment : TimeoutFragment(R.layout.fragment_home), ApplicationInstall
)
childViewHolder?.let {
(childViewHolder as HomeChildRVAdapter.ViewHolder).binding.installButton.text =
- String.format("%d%%", progress)
+ String.format(Locale.getDefault(),"%d%%", progress)
}
}
}
diff --git a/app/src/main/java/foundation/e/apps/ui/home/model/FusedHomeDiffUtil.kt b/app/src/main/java/foundation/e/apps/ui/home/model/FusedHomeDiffUtil.kt
index a99a867830921443579be21f61a9f707705b0a6b..c6d4491dc7d7d35c99633a5537ee349f0e74924e 100644
--- a/app/src/main/java/foundation/e/apps/ui/home/model/FusedHomeDiffUtil.kt
+++ b/app/src/main/java/foundation/e/apps/ui/home/model/FusedHomeDiffUtil.kt
@@ -17,6 +17,7 @@
*/
package foundation.e.apps.ui.home.model
+import android.annotation.SuppressLint
import androidx.recyclerview.widget.DiffUtil
import foundation.e.apps.data.application.data.Home
@@ -25,6 +26,7 @@ class FusedHomeDiffUtil : DiffUtil.ItemCallback() {
return oldItem.list == newItem.list
}
+ @SuppressLint("DiffUtilEquals")
override fun areContentsTheSame(oldItem: Home, newItem: Home): Boolean {
return oldItem.title.contentEquals(newItem.title) &&
oldItem.list == newItem.list &&
diff --git a/app/src/main/java/foundation/e/apps/ui/purchase/AppPurchaseFragment.kt b/app/src/main/java/foundation/e/apps/ui/purchase/AppPurchaseFragment.kt
index c49336d72dc0a77a096147b163dfefd4c388c7ab..218da4fcc27cccea61589809a73ae388f98864fe 100644
--- a/app/src/main/java/foundation/e/apps/ui/purchase/AppPurchaseFragment.kt
+++ b/app/src/main/java/foundation/e/apps/ui/purchase/AppPurchaseFragment.kt
@@ -97,8 +97,7 @@ class AppPurchaseFragment : Fragment() {
binding.playStoreWebView.apply {
settings.apply {
allowContentAccess = true
- databaseEnabled = true
- domStorageEnabled = true
+ domStorageEnabled = true // Replaces databaseEnabled for local storage support
javaScriptEnabled = true // Google Play page is tested to not work otherwise
cacheMode = WebSettings.LOAD_DEFAULT
}
diff --git a/app/src/main/java/foundation/e/apps/ui/search/SearchFragment.kt b/app/src/main/java/foundation/e/apps/ui/search/SearchFragment.kt
index c0de635250a46bec2c06f300750b236b4d89f161..17237c92b3cefa304be77af76f494b3e79cc2500 100644
--- a/app/src/main/java/foundation/e/apps/ui/search/SearchFragment.kt
+++ b/app/src/main/java/foundation/e/apps/ui/search/SearchFragment.kt
@@ -65,6 +65,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
+import java.util.Locale
import javax.inject.Inject
@AndroidEntryPoint
@@ -399,7 +400,7 @@ class SearchFragment :
)
viewHolder?.let {
(viewHolder as ApplicationListRVAdapter.ViewHolder).binding.installButton.text =
- String.format("%d%%", progress)
+ String.format(Locale.getDefault(), "%d%%", progress)
}
}
}
@@ -517,7 +518,10 @@ class SearchFragment :
isAccessible = true
get(searchView) as EditText
}?.onSuccess {
- inputMethodManager.showSoftInput(it, InputMethodManager.SHOW_FORCED)
+ // Instead of forcing the keyboard to show, you should use
+ // InputMethodManager.SHOW_IMPLICIT, which is the recommended
+ // way to request the keyboard in modern Android development.
+ inputMethodManager.showSoftInput(it, InputMethodManager.SHOW_IMPLICIT)
}
}
diff --git a/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt b/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt
index 94b5d1fa51b948ca92311d9be137121a7a8320dd..fcd2e3d3a4553bb10e9f9b01ca5edef7971e3419 100644
--- a/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt
+++ b/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt
@@ -91,8 +91,7 @@ class GoogleSignInFragment : Fragment(R.layout.fragment_google_signin) {
binding.webview.apply {
settings.apply {
allowContentAccess = true
- databaseEnabled = true
- domStorageEnabled = true
+ domStorageEnabled = true // Replaces databaseEnabled for local storage support
javaScriptEnabled = true
cacheMode = WebSettings.LOAD_DEFAULT
}
diff --git a/app/src/main/java/foundation/e/apps/ui/updates/UpdatesFragment.kt b/app/src/main/java/foundation/e/apps/ui/updates/UpdatesFragment.kt
index 941ec2f11fc29976b39037ddbb4776ff03225040..9dc547e16e21e52db8abbd670b1e161734aea3f9 100644
--- a/app/src/main/java/foundation/e/apps/ui/updates/UpdatesFragment.kt
+++ b/app/src/main/java/foundation/e/apps/ui/updates/UpdatesFragment.kt
@@ -64,6 +64,7 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import timber.log.Timber
+import java.util.Locale
import javax.inject.Inject
@AndroidEntryPoint
@@ -163,7 +164,7 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), ApplicationI
private fun handleStateNoUpdates(list: List?) {
if (!list.isNullOrEmpty()) {
binding.button.isEnabled = true
- initUpdataAllButton()
+ initUpdateAllButton()
binding.noUpdates.visibility = View.GONE
} else {
binding.noUpdates.visibility = View.VISIBLE
@@ -183,7 +184,7 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), ApplicationI
}
}
- private fun shouldUpdateButtonEnable(workInfoList: MutableList) =
+ private fun shouldUpdateButtonEnable(workInfoList: List) =
!updatesViewModel.updatesList.value?.first.isNullOrEmpty() &&
(
workInfoList.isNullOrEmpty() ||
@@ -283,10 +284,10 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), ApplicationI
clearAndRestartGPlayLogin()
true
}
- initUpdataAllButton()
+ initUpdateAllButton()
}
- private fun initUpdataAllButton() {
+ private fun initUpdateAllButton() {
binding.button.setOnClickListener {
UpdatesWorkManager.startUpdateAllWork(requireContext())
observeUpdateWork()
@@ -303,7 +304,7 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), ApplicationI
}
private fun hasAnyPendingUpdates(
- workInfoList: MutableList
+ workInfoList: List
): Boolean {
val errorStates = listOf(
WorkInfo.State.FAILED,
@@ -370,7 +371,7 @@ class UpdatesFragment : TimeoutFragment(R.layout.fragment_updates), ApplicationI
)
viewHolder?.let {
(viewHolder as ApplicationListRVAdapter.ViewHolder).binding.installButton.text =
- String.format("%d%%", progress)
+ String.format(Locale.getDefault(), "%d%%", progress)
}
}
}
diff --git a/app/src/main/java/foundation/e/apps/ui/updates/UpdatesViewModel.kt b/app/src/main/java/foundation/e/apps/ui/updates/UpdatesViewModel.kt
index 77214dc202ba5ba409265800f313295f2fe0b858..42045a30fd3e760d228f3418d97703c3e25ebce5 100644
--- a/app/src/main/java/foundation/e/apps/ui/updates/UpdatesViewModel.kt
+++ b/app/src/main/java/foundation/e/apps/ui/updates/UpdatesViewModel.kt
@@ -63,7 +63,7 @@ class UpdatesViewModel @Inject constructor(
}, retryBlock)
}
- fun getUpdates(authData: AuthData?) {
+ private fun getUpdates(authData: AuthData?) {
viewModelScope.launch {
val updatesResult = if (authData != null)
updatesManagerRepository.getUpdates(authData)
diff --git a/app/src/main/java/foundation/e/apps/utils/StorageComputer.kt b/app/src/main/java/foundation/e/apps/utils/StorageComputer.kt
index e3ca3c403233413c37b6f1685170859edc30ab98..8d77b40e8e4f3d4594a203f5126ee04c6c426a6d 100644
--- a/app/src/main/java/foundation/e/apps/utils/StorageComputer.kt
+++ b/app/src/main/java/foundation/e/apps/utils/StorageComputer.kt
@@ -22,6 +22,7 @@ import android.os.StatFs
import foundation.e.apps.data.install.models.AppInstall
import java.text.CharacterIterator
import java.text.StringCharacterIterator
+import java.util.Locale
object StorageComputer {
fun spaceMissing(appInstall: AppInstall): Long {
@@ -48,6 +49,6 @@ object StorageComputer {
bytes /= 1000
ci.next()
}
- return String.format("%.1f %cB", bytes / 1000.0, ci.current())
+ return String.format(Locale.getDefault(),"%.1f %cB", bytes / 1000.0, ci.current())
}
}
diff --git a/app/src/main/res/values-night/bools.xml b/app/src/main/res/values-night/bools.xml
deleted file mode 100644
index d1d7a3d17c09015be0d864019e08ddc31a42b01c..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-night/bools.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
- false
-
-
diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml
index f708dbec7838cdeec06010e44a65c49a907c7624..ae1dd975246ef1716442c1265e00d9f6f972c664 100644
--- a/app/src/main/res/values-night/colors.xml
+++ b/app/src/main/res/values-night/colors.xml
@@ -23,7 +23,4 @@
#262626
#353535
-
-
- @color/colorNavBar
\ No newline at end of file
diff --git a/app/src/main/res/values-v27/themes.xml b/app/src/main/res/values-v27/themes.xml
deleted file mode 100644
index 39e4aa9102def865543c1680da213c09b1505245..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-v27/themes.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values/bools.xml b/app/src/main/res/values/bools.xml
deleted file mode 100644
index 9d510f638d559b834dbd851ccda92128c4bb3d4c..0000000000000000000000000000000000000000
--- a/app/src/main/res/values/bools.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
- true
-
-
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index d1fae8b162b244db612890ec48336304d9e55537..765406e983e6f3e67ab380fb55057572ca638491 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -24,7 +24,7 @@
@color/e_background
- @android:color/white
+ @color/colorNavBar
#f2f2f2
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index dc5f734d83f4626f648cfbe42846b27ff48dfd10..8c002522f05ac3678b315f212b362980e1028f05 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -26,7 +26,8 @@
- @style/AppTheme.ActionBarStyle
- @color/colorBackground
- @color/colorBackground
- - @bool/is_day
+ - @bool/isLight
+ - @bool/isLight
- @color/colorNavBar
- @null
- @style/AutoCompleteTextViewStyle
diff --git a/build.gradle b/build.gradle
index f5341756b1d8d174074f2725f454a8261a5c4a61..44178694e038d6dae189aaa6f0f9ad638eab0f9d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,31 +1,30 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
- id 'com.android.application' version '8.1.0' apply false
- id 'com.android.library' version '8.1.0' apply false
- id 'org.jetbrains.kotlin.android' version '2.0.21' apply false
- id "org.jetbrains.kotlin.plugin.allopen" version "2.0.21"
- id 'org.jetbrains.kotlin.jvm' version '2.0.21' apply false
- id 'com.google.dagger.hilt.android' version '2.51.1' apply false
- id 'androidx.navigation.safeargs' version '2.5.3' apply false
- id 'io.gitlab.arturbosch.detekt' version '1.23.1'
+ alias libs.plugins.android.application apply false
+ alias libs.plugins.android.library apply false
+ alias libs.plugins.kotlin.android apply false
+ alias libs.plugins.kotlin.plugin.allopen apply false
+ alias libs.plugins.kotlin.jvm apply false
+ alias libs.plugins.hilt.android apply false
+ alias libs.plugins.ksp apply false
+ alias libs.plugins.navigation.safeargs apply false
+ alias libs.plugins.detekt
+
}
allprojects {
- tasks.withType(JavaCompile) {
- options.deprecation = true
- options.compilerArgs += ['-Werror']
+ tasks.withType(JavaCompile).tap {
+ configureEach {
+ options.deprecation = true
+ options.compilerArgs += ['-Werror']
+ }
}
}
subprojects {
detekt {
- toolVersion = "1.23.1"
-
- source = files(
- "src/main/java"
- )
-
+ source.setFrom("src/main/java", "src/main/kotlin")
config.setFrom("detekt.yml")
baseline = file("detekt-baseline.xml")
parallel = false
@@ -38,7 +37,7 @@ subprojects {
}
}
-task clean(type: Delete) {
+tasks.register('clean', Delete) {
delete rootProject.buildDir
}
diff --git a/gradle.properties b/gradle.properties
index 63b8f402f0608ce71f11e40580cb834403817c06..e080be130ea4b8da1f18675cd61cc2668e20633a 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -19,6 +19,5 @@ android.useAndroidX=true
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
-android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 0000000000000000000000000000000000000000..bd866a780d00c34dd77acde70060cb0b8ed67c94
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,123 @@
+[versions]
+activityKtx = "1.10.0"
+androidGradlePlugin = "8.8.0"
+appcompat = "1.7.0"
+bcpgJdk15on = "1.60"
+coil = "1.4.0"
+constraintlayout = "2.2.0"
+core = "1.6.1"
+coreKtx = "1.15.0"
+coreTesting = "2.2.0"
+datastorePreferences = "1.1.2"
+elib = "0.0.1-alpha11"
+espressoCore = "3.6.1"
+hiltCompiler = "1.2.0"
+hiltWork = "1.2.0"
+lifecycleExtensions = "1.1.1"
+fragmentKtx = "1.8.5"
+gplayapi = "3.4.2-0"
+gson = "2.11.0"
+jacksonDataformatYaml = "2.17.0"
+jsoup = "1.17.2"
+junit = "4.13.2"
+junitVersion = "1.2.1"
+kotlin = "2.1.0"
+hilt = "2.54"
+kotlinxCoroutinesAndroid = "1.10.1"
+ksp = "2.1.0-1.0.29"
+legacySupportV4 = "1.0.0"
+lifecycleViewmodelKtx = "2.8.7"
+loggingInterceptor = "4.11.0"
+material = "1.12.0"
+mockitoCore = "5.14.2"
+mockitoInline = "5.0.0"
+mockitoKotlin = "5.4.0"
+mockk = "1.12.3"
+moshiKotlin = "1.15.1"
+detekt = "1.23.7"
+ktlint = "10.2.0"
+navigation = "2.8.5"
+okhttp = "4.12.0"
+photoview = "2.3.0"
+preferenceKtx = "1.2.1"
+protobufJavalite = "4.28.2"
+room = "2.6.1"
+shimmer = "0.5.0"
+telemetry = "0.0.11-alpha"
+timber = "5.0.1"
+truth = "1.1.4"
+viewpager2 = "1.1.0"
+recyclerview = "1.4.0"
+workRuntimeKtx = "2.10.0"
+
+[libraries]
+activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activityKtx" }
+appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
+bcpg-jdk15on = { module = "org.bouncycastle:bcpg-jdk15on", version.ref = "bcpgJdk15on" }
+coil = { module = "io.coil-kt:coil", version.ref = "coil" }
+constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }
+converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "gson" }
+converter-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "gson" }
+converter-jackson = { module = "com.squareup.retrofit2:converter-jackson", version.ref = "gson" }
+core = { module = "androidx.test:core", version.ref = "core" }
+core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
+core-testing = { module = "androidx.arch.core:core-testing", version.ref = "coreTesting" }
+datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
+elib = { module = "foundation.e:elib", version.ref = "elib" }
+ext-junit = { module = "androidx.test.ext:junit", version.ref = "junitVersion" }
+espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espressoCore" }
+hilt-work = { module = "androidx.hilt:hilt-work", version.ref = "hiltWork" }
+hilt-compiler = { module = "androidx.hilt:hilt-compiler", version.ref = "hiltCompiler" }
+lifecycle-extensions = { module = "android.arch.lifecycle:extensions", version.ref = "lifecycleExtensions" }
+fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragmentKtx" }
+gplayapi = { module = "foundation.e:gplayapi", version.ref = "gplayapi" }
+gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
+hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt"}
+hilt-compile = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt"}
+jackson-dataformat-yaml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", version.ref = "jacksonDataformatYaml" }
+jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
+junit = { module = "junit:junit", version.ref = "junit" }
+kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
+kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinxCoroutinesAndroid" }
+kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinxCoroutinesAndroid" }
+kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutinesAndroid" }
+legacy-support-v4 = { module = "androidx.legacy:legacy-support-v4", version.ref = "legacySupportV4" }
+lifecycle-livedata-ktx = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycleViewmodelKtx" }
+lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
+lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleViewmodelKtx" }
+logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "loggingInterceptor" }
+material = { module = "com.google.android.material:material", version.ref = "material" }
+mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" }
+mockito-inline = { module = "org.mockito:mockito-inline", version.ref = "mockitoInline" }
+mockito-kotlin = { module = "org.mockito.kotlin:mockito-kotlin", version.ref = "mockitoKotlin" }
+mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
+moshi-kotlin = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshiKotlin" }
+navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigation" }
+navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "navigation" }
+okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
+photoview = { module = "com.github.Baseflow:PhotoView", version.ref = "photoview" }
+preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "preferenceKtx" }
+protobuf-javalite = { module = "com.google.protobuf:protobuf-javalite", version.ref = "protobufJavalite" }
+recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" }
+retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "gson" }
+room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
+room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
+room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
+shimmer = { module = "com.facebook.shimmer:shimmer", version.ref = "shimmer" }
+telemetry = { module = "foundation.e.lib:telemetry", version.ref = "telemetry" }
+timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
+truth = { module = "com.google.truth:truth", version.ref = "truth" }
+viewpager2 = { module = "androidx.viewpager2:viewpager2", version.ref = "viewpager2" }
+work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workRuntimeKtx" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" }
+android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" }
+kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+kotlin-plugin-allopen = { id = "org.jetbrains.kotlin.plugin.allopen", version.ref = "kotlin" }
+kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
+hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
+ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
+navigation-safeargs = { id = "androidx.navigation.safeargs", version.ref = "navigation" }
+detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
+ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index fb45f10f541b958ae89af3fbf52208eb5fe31f82..6a66ab375cb89161772cd6cf12962d0e8068a32f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Thu Aug 17 09:40:45 CEST 2023
+#Wed Jan 01 17:01:03 IST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/lint.xml b/lint.xml
index 9debeab74fa18efb7d0a54b4a130841c3c9d72aa..88fe8852e1707a8c87ac2daa66ccb3878315c998 100644
--- a/lint.xml
+++ b/lint.xml
@@ -46,6 +46,8 @@
+
+
diff --git a/settings.gradle b/settings.gradle
index d222ecead54060f5591fbd36ce0d55b64a402b2e..0b35903798457ed980886edba821edacc925afc5 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -10,8 +10,8 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
- maven { url 'https://jitpack.io' }
- maven { url 'https://gitlab.e.foundation/api/v4/groups/9/-/packages/maven'}
+ maven { url = 'https://jitpack.io' }
+ maven { url = 'https://gitlab.e.foundation/api/v4/groups/9/-/packages/maven'}
// Gitlab repository configuration for gplayapi dependency
def ciJobToken = System.getenv("CI_JOB_TOKEN")
@@ -45,8 +45,8 @@ dependencyResolutionManagement {
localProperties.load(new FileInputStream(rootProject.projectDir.path + "/local.properties"))
maven {
- url "https://gitlab.e.foundation/api/v4/projects/1269/packages/maven"
- name "GitLab"
+ url = "https://gitlab.e.foundation/api/v4/projects/1269/packages/maven"
+ name = "GitLab"
credentials(HttpHeaderCredentials) {
name = 'Private-Token'