diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9f3b9c6..773d63f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,14 +1,9 @@ -val rExtra = rootProject.extra - plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") - kotlin("kapt") - id("com.google.dagger.hilt.android") - id("com.google.gms.google-services") - id("com.google.firebase.crashlytics") + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.hilt.android) id("org.jetbrains.kotlin.plugin.serialization") - id("io.objectbox") + alias(libs.plugins.ksp) } android { @@ -16,8 +11,8 @@ android { compileSdk = 34 val versionMajor = 2 - val versionMinor = 4 - val versionPatch = 5 + val versionMinor = 5 + val versionPatch = 0 val versionBuild = 0 defaultConfig { @@ -27,6 +22,10 @@ android { versionCode = versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild versionName = "${versionMajor}.${versionMinor}.${versionPatch}" + multiDexEnabled = true + + resourceConfigurations.addAll(listOf("en")) + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true @@ -36,13 +35,35 @@ android { buildTypes { release { isDebuggable = false - isMinifyEnabled = false + isMinifyEnabled = true + isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) + //for release testing + signingConfig = signingConfigs.getByName("debug") + } + debug { + isDebuggable = true } } + flavorDimensions.add("type") + productFlavors { + create("floss") { + dimension = "type" + applicationIdSuffix = ".floss" + } + create("general") { + dimension = "type" + if (BuildHelper.isReleaseBuild(gradle) && BuildHelper.isGeneralFlavor(gradle)) + { + apply(plugin = "com.google.gms.google-services") + apply(plugin = "com.google.firebase.crashlytics") + } + } + } + compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 @@ -52,9 +73,11 @@ android { } buildFeatures { compose = true + buildConfig = true + } composeOptions { - kotlinCompilerExtensionVersion = "1.4.8" + kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get() } packaging { resources { @@ -63,68 +86,69 @@ android { } } +val generalImplementation by configurations dependencies { - implementation("androidx.core:core-ktx:1.12.0") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") - implementation("androidx.activity:activity-compose:1.7.2") - implementation(platform("androidx.compose:compose-bom:2023.03.00")) - implementation("androidx.compose.ui:ui") - implementation("androidx.compose.ui:ui-graphics") - implementation("androidx.compose.ui:ui-tooling-preview") - implementation("androidx.compose.material3:material3:1.1.1") - implementation("androidx.appcompat:appcompat:1.6.1") + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.ui.graphics) + implementation(libs.androidx.compose.ui.tooling.preview) + implementation(libs.androidx.material3) + implementation(libs.androidx.appcompat) - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") - androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00")) - androidTestImplementation("androidx.compose.ui:ui-test-junit4") - debugImplementation("androidx.compose.ui:ui-tooling") - debugImplementation("androidx.compose.ui:ui-test-manifest") + //test + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.compose.ui.test) + debugImplementation(libs.androidx.compose.ui.tooling) + debugImplementation(libs.androidx.compose.manifest) - //wireguard tunnel - implementation("com.wireguard.android:tunnel:1.0.20230706") + //wg + implementation(libs.tunnel) //logging - implementation("com.jakewharton.timber:timber:5.0.1") + implementation(libs.timber) // compose navigation - implementation("androidx.navigation:navigation-compose:2.7.2") - implementation("androidx.hilt:hilt-navigation-compose:1.0.0") + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.hilt.navigation.compose) // hilt - implementation("com.google.dagger:hilt-android:${rExtra.get("hiltVersion")}") - kapt("com.google.dagger:hilt-android-compiler:${rExtra.get("hiltVersion")}") + implementation(libs.hilt.android) + ksp(libs.hilt.android.compiler) //accompanist - implementation("com.google.accompanist:accompanist-systemuicontroller:${rExtra.get("accompanistVersion")}") - implementation("com.google.accompanist:accompanist-permissions:${rExtra.get("accompanistVersion")}") - implementation("com.google.accompanist:accompanist-flowlayout:${rExtra.get("accompanistVersion")}") - implementation("com.google.accompanist:accompanist-navigation-animation:${rExtra.get("accompanistVersion")}") - implementation("com.google.accompanist:accompanist-drawablepainter:${rExtra.get("accompanistVersion")}") + implementation(libs.accompanist.systemuicontroller) + implementation(libs.accompanist.permissions) + implementation(libs.accompanist.flowlayout) + implementation(libs.accompanist.navigation.animation) + implementation(libs.accompanist.drawablepainter) + + //room + implementation(libs.androidx.room.runtime) + annotationProcessor(libs.androidx.room.compiler) + ksp(libs.androidx.room.compiler) + implementation(libs.androidx.room.ktx) + - //db - implementation("io.objectbox:objectbox-kotlin:${rExtra.get("objectBoxVersion")}") //lifecycle - implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.2") + implementation(libs.lifecycle.runtime.compose) //icons - implementation("androidx.compose.material:material-icons-extended:1.5.1") - - - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") - + implementation(libs.material.icons.extended) + //serialization + implementation(libs.kotlinx.serialization.json) //firebase crashlytics - implementation(platform("com.google.firebase:firebase-bom:32.0.0")) - implementation("com.google.firebase:firebase-crashlytics-ktx") - implementation("com.google.firebase:firebase-analytics-ktx") + generalImplementation(platform(libs.firebase.bom)) + generalImplementation(libs.google.firebase.crashlytics.ktx) + generalImplementation(libs.google.firebase.analytics.ktx) //barcode scanning - implementation("com.google.android.gms:play-services-code-scanner:16.1.0") -} - -kapt { - correctErrorTypes = true + implementation(libs.play.services.code.scanner) } \ No newline at end of file diff --git a/app/objectbox-models/default.json b/app/objectbox-models/default.json deleted file mode 100644 index dd7a8ab..0000000 --- a/app/objectbox-models/default.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", - "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", - "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", - "entities": [ - { - "id": "1:2692736974585027589", - "lastPropertyId": "15:5057486545428188436", - "name": "TunnelConfig", - "properties": [ - { - "id": "1:1985347930017457084", - "name": "id", - "type": 6, - "flags": 1 - }, - { - "id": "12:2409068226744965585", - "name": "name", - "indexId": "1:4811206443952699137", - "type": 9, - "flags": 34848 - }, - { - "id": "13:8987443291286312275", - "name": "wgQuick", - "type": 9 - } - ], - "relations": [] - }, - { - "id": "2:8887605597748372702", - "lastPropertyId": "9:4468844863383145378", - "name": "Settings", - "properties": [ - { - "id": "1:7485739868216068651", - "name": "id", - "type": 6, - "flags": 1 - }, - { - "id": "2:5814013113141456749", - "name": "isAutoTunnelEnabled", - "type": 1 - }, - { - "id": "4:5645665441196906014", - "name": "trustedNetworkSSIDs", - "type": 30 - }, - { - "id": "5:4989886999117763881", - "name": "isTunnelOnMobileDataEnabled", - "type": 1 - }, - { - "id": "6:3370284381040192129", - "name": "defaultTunnel", - "type": 9 - }, - { - "id": "9:4468844863383145378", - "name": "isAlwaysOnVpnEnabled", - "type": 1 - } - ], - "relations": [] - } - ], - "lastEntityId": "2:8887605597748372702", - "lastIndexId": "1:4811206443952699137", - "lastRelationId": "0:0", - "lastSequenceId": "0:0", - "modelVersion": 5, - "modelVersionParserMinimum": 5, - "retiredEntityUids": [], - "retiredIndexUids": [], - "retiredPropertyUids": [ - 1763475292291320186, - 6483820955437198310, - 8323071516033820771, - 5904440563612311217, - 1408037976996390989, - 7737847485212546994, - 8215616901775229364, - 8021610768066328637, - 6174306582797008721, - 2175939938544485767, - 7555225587864607050, - 969146862000617878, - 5057486545428188436, - 2814640993034665120, - 4981008812459251156 - ], - "retiredRelationUids": [], - "version": 1 -} \ No newline at end of file diff --git a/app/objectbox-models/default.json.bak b/app/objectbox-models/default.json.bak deleted file mode 100644 index d408486..0000000 --- a/app/objectbox-models/default.json.bak +++ /dev/null @@ -1,94 +0,0 @@ -{ - "_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.", - "_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.", - "_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.", - "entities": [ - { - "id": "1:2692736974585027589", - "lastPropertyId": "15:5057486545428188436", - "name": "TunnelConfig", - "properties": [ - { - "id": "1:1985347930017457084", - "name": "id", - "type": 6, - "flags": 1 - }, - { - "id": "12:2409068226744965585", - "name": "name", - "indexId": "1:4811206443952699137", - "type": 9, - "flags": 34848 - }, - { - "id": "13:8987443291286312275", - "name": "wgQuick", - "type": 9 - } - ], - "relations": [] - }, - { - "id": "2:8887605597748372702", - "lastPropertyId": "8:4981008812459251156", - "name": "Settings", - "properties": [ - { - "id": "1:7485739868216068651", - "name": "id", - "type": 6, - "flags": 1 - }, - { - "id": "2:5814013113141456749", - "name": "isAutoTunnelEnabled", - "type": 1 - }, - { - "id": "4:5645665441196906014", - "name": "trustedNetworkSSIDs", - "type": 30 - }, - { - "id": "5:4989886999117763881", - "name": "isTunnelOnMobileDataEnabled", - "type": 1 - }, - { - "id": "6:3370284381040192129", - "name": "defaultTunnel", - "type": 9 - } - ], - "relations": [] - } - ], - "lastEntityId": "2:8887605597748372702", - "lastIndexId": "1:4811206443952699137", - "lastRelationId": "0:0", - "lastSequenceId": "0:0", - "modelVersion": 5, - "modelVersionParserMinimum": 5, - "retiredEntityUids": [], - "retiredIndexUids": [], - "retiredPropertyUids": [ - 1763475292291320186, - 6483820955437198310, - 8323071516033820771, - 5904440563612311217, - 1408037976996390989, - 7737847485212546994, - 8215616901775229364, - 8021610768066328637, - 6174306582797008721, - 2175939938544485767, - 7555225587864607050, - 969146862000617878, - 5057486545428188436, - 2814640993034665120, - 4981008812459251156 - ], - "retiredRelationUids": [], - "version": 1 -} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f674159..d762f13 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -114,8 +114,5 @@ - \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/Constants.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/Constants.kt index 7bffe0b..2cf4afe 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/Constants.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/Constants.kt @@ -1,6 +1,11 @@ package com.zaneschepke.wireguardautotunnel object Constants { - const val VPN_CONNECTIVITY_CHECK_INTERVAL = 3000L; - const val VPN_STATISTIC_CHECK_INTERVAL = 10000L; + const val VPN_CONNECTIVITY_CHECK_INTERVAL = 3000L + const val VPN_STATISTIC_CHECK_INTERVAL = 10000L + const val SNACKBAR_DELAY = 3000L + const val TOGGLE_TUNNEL_DELAY = 1000L + const val FADE_IN_ANIMATION_DURATION = 1000 + const val SLIDE_IN_ANIMATION_DURATION = 500 + const val SLIDE_IN_TRANSITION_OFFSET = 1000 } \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt index 39204da..2a0368e 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/WireGuardAutoTunnel.kt @@ -3,32 +3,17 @@ package com.zaneschepke.wireguardautotunnel import android.app.Application import android.content.Context import android.content.pm.PackageManager -import com.google.firebase.crashlytics.FirebaseCrashlytics -import com.google.mlkit.common.MlKit -import com.zaneschepke.wireguardautotunnel.repository.Repository -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings import dagger.hilt.android.HiltAndroidApp import timber.log.Timber -import javax.inject.Inject @HiltAndroidApp class WireGuardAutoTunnel : Application() { - @Inject - lateinit var settingsRepo : Repository - override fun onCreate() { super.onCreate() if(BuildConfig.DEBUG) { - FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(false); Timber.plant(Timber.DebugTree()) } - try { - MlKit.initialize(this) - } catch (e : Exception) { - Timber.e(e.message) - } - settingsRepo.init() } companion object { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/BoxModule.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/BoxModule.kt deleted file mode 100644 index 45a74f0..0000000 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/BoxModule.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.zaneschepke.wireguardautotunnel.module - -import android.content.Context -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.MyObjectBox -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import io.objectbox.Box -import io.objectbox.BoxStore -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -class BoxModule { - - @Provides - @Singleton - fun provideBoxStore(@ApplicationContext context : Context) : BoxStore { - return MyObjectBox.builder() - .androidContext(context.applicationContext) - .build() - } - - @Provides - @Singleton - fun provideBoxForSettings(store : BoxStore) : Box { - return store.boxFor(Settings::class.java) - } - - @Provides - @Singleton - fun provideBoxForTunnels(store : BoxStore) : Box { - return store.boxFor(TunnelConfig::class.java) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/DatabaseModule.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/DatabaseModule.kt new file mode 100644 index 0000000..32aa46c --- /dev/null +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/DatabaseModule.kt @@ -0,0 +1,25 @@ +package com.zaneschepke.wireguardautotunnel.module + +import android.content.Context +import androidx.room.Room +import com.zaneschepke.wireguardautotunnel.R +import com.zaneschepke.wireguardautotunnel.repository.AppDatabase +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +class DatabaseModule { + @Provides + @Singleton + fun provideDatabase(@ApplicationContext context : Context) : AppDatabase { + return Room.databaseBuilder( + context, + AppDatabase::class.java, context.getString(R.string.db_name) + ).build() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/RepositoryModule.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/RepositoryModule.kt index 4626425..ca056b8 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/RepositoryModule.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/module/RepositoryModule.kt @@ -1,25 +1,27 @@ package com.zaneschepke.wireguardautotunnel.module -import com.zaneschepke.wireguardautotunnel.repository.Repository -import com.zaneschepke.wireguardautotunnel.repository.SettingsBox -import com.zaneschepke.wireguardautotunnel.repository.TunnelBox -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig -import dagger.Binds +import com.zaneschepke.wireguardautotunnel.repository.AppDatabase +import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa +import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao import dagger.Module +import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) -abstract class RepositoryModule { +class RepositoryModule { - @Binds @Singleton - abstract fun provideSettingsRepository(settingsBox: SettingsBox) : Repository + @Provides + fun provideSettingsRepository(appDatabase: AppDatabase) : SettingsDoa { + return appDatabase.settingDao() + } - @Binds @Singleton - abstract fun provideTunnelRepository(tunnelBox: TunnelBox) : Repository + @Provides + fun provideTunnelConfigRepository(appDatabase: AppDatabase) : TunnelConfigDao { + return appDatabase.tunnelConfigDoa() + } } \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/BootReceiver.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/BootReceiver.kt index 03b8e9f..ae743f0 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/BootReceiver.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/BootReceiver.kt @@ -3,9 +3,8 @@ package com.zaneschepke.wireguardautotunnel.receiver import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import com.zaneschepke.wireguardautotunnel.repository.Repository +import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -17,7 +16,7 @@ import javax.inject.Inject class BootReceiver : BroadcastReceiver() { @Inject - lateinit var settingsRepo : Repository + lateinit var settingsRepo : SettingsDoa override fun onReceive(context: Context, intent: Intent) { if (intent.action == Intent.ACTION_BOOT_COMPLETED) { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt index 93a10ae..ebe4120 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt @@ -3,9 +3,9 @@ package com.zaneschepke.wireguardautotunnel.receiver import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import com.zaneschepke.wireguardautotunnel.repository.Repository +import com.zaneschepke.wireguardautotunnel.Constants +import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -18,16 +18,16 @@ import javax.inject.Inject class NotificationActionReceiver : BroadcastReceiver() { @Inject - lateinit var settingsRepo : Repository + lateinit var settingsRepo : SettingsDoa override fun onReceive(context: Context, intent: Intent?) { CoroutineScope(Dispatchers.IO).launch { try { val settings = settingsRepo.getAll() - if (!settings.isNullOrEmpty()) { + if (settings.isNotEmpty()) { val setting = settings.first() if (setting.defaultTunnel != null) { ServiceManager.stopVpnService(context) - delay(1000) + delay(Constants.TOGGLE_TUNNEL_DELAY) ServiceManager.startVpnService(context, setting.defaultTunnel.toString()) } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/AppDatabase.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/AppDatabase.kt new file mode 100644 index 0000000..9e3d162 --- /dev/null +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/AppDatabase.kt @@ -0,0 +1,14 @@ +package com.zaneschepke.wireguardautotunnel.repository + +import androidx.room.Database +import androidx.room.RoomDatabase +import androidx.room.TypeConverters +import com.zaneschepke.wireguardautotunnel.repository.model.Settings +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig + +@Database(entities = [Settings::class, TunnelConfig::class], version = 1) +@TypeConverters(DatabaseListConverters::class) +abstract class AppDatabase : RoomDatabase() { + abstract fun settingDao(): SettingsDoa + abstract fun tunnelConfigDoa() : TunnelConfigDao +} \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/DatabaseListConverters.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/DatabaseListConverters.kt new file mode 100644 index 0000000..e4e94c8 --- /dev/null +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/DatabaseListConverters.kt @@ -0,0 +1,15 @@ +package com.zaneschepke.wireguardautotunnel.repository + +import androidx.room.TypeConverter + +class DatabaseListConverters { + @TypeConverter + fun listToString(value: MutableList): String { + return value.joinToString() + } + @TypeConverter + fun stringToList(value: String): MutableList { + if(value.isEmpty()) return mutableListOf() + return value.split(",").toMutableList() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/Repository.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/Repository.kt deleted file mode 100644 index 4f1b59f..0000000 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/Repository.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.zaneschepke.wireguardautotunnel.repository - -import kotlinx.coroutines.flow.Flow - -interface Repository { - suspend fun save(t : T) - suspend fun saveAll(t : List) - suspend fun getById(id : Long) : T? - suspend fun getAll() : List? - suspend fun delete(t : T) : Boolean? - suspend fun count() : Long? - - val itemFlow : Flow> - - fun init() -} \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/SettingsBox.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/SettingsBox.kt deleted file mode 100644 index 0ba02d3..0000000 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/SettingsBox.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.zaneschepke.wireguardautotunnel.repository - -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings -import io.objectbox.Box -import io.objectbox.BoxStore -import io.objectbox.kotlin.awaitCallInTx -import io.objectbox.kotlin.toFlow -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.launch -import javax.inject.Inject - - -class SettingsBox @Inject constructor(private val box : Box, private val boxStore : BoxStore) : Repository { - - @OptIn(ExperimentalCoroutinesApi::class) - override val itemFlow = box.query().build().subscribe().toFlow() - - override fun init() { - CoroutineScope(Dispatchers.IO).launch { - if(getAll().isNullOrEmpty()) { - save(Settings()) - } - } - } - - override suspend fun save(t : Settings) { - boxStore.awaitCallInTx { - box.put(t) - } - } - - override suspend fun saveAll(t : List) { - boxStore.awaitCallInTx { - box.put(t) - } - } - - override suspend fun getById(id: Long): Settings? { - return boxStore.awaitCallInTx { - box[id] - } - } - - override suspend fun getAll(): List? { - return boxStore.awaitCallInTx { - box.all - } - } - - override suspend fun delete(t : Settings): Boolean? { - return boxStore.awaitCallInTx { - box.remove(t) - } - } - - override suspend fun count() : Long? { - return boxStore.awaitCallInTx { - box.count() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/SettingsDoa.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/SettingsDoa.kt new file mode 100644 index 0000000..49120a3 --- /dev/null +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/SettingsDoa.kt @@ -0,0 +1,34 @@ +package com.zaneschepke.wireguardautotunnel.repository + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.zaneschepke.wireguardautotunnel.repository.model.Settings +import kotlinx.coroutines.flow.Flow + +@Dao +interface SettingsDoa { + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun save(t: Settings) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun saveAll(t: List) + + @Query("SELECT * FROM settings WHERE id=:id") + suspend fun getById(id: Long): Settings? + + @Query("SELECT * FROM settings") + suspend fun getAll(): List + + @Query("SELECT * FROM settings") + fun getAllFlow(): Flow> + + @Delete + suspend fun delete(t: Settings) + + @Query("SELECT COUNT('id') FROM settings") + suspend fun count(): Long +} \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/TunnelBox.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/TunnelBox.kt deleted file mode 100644 index ea845da..0000000 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/TunnelBox.kt +++ /dev/null @@ -1,57 +0,0 @@ -package com.zaneschepke.wireguardautotunnel.repository - -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig -import io.objectbox.Box -import io.objectbox.BoxStore -import io.objectbox.kotlin.awaitCallInTx -import io.objectbox.kotlin.toFlow -import kotlinx.coroutines.ExperimentalCoroutinesApi -import timber.log.Timber -import javax.inject.Inject - -class TunnelBox @Inject constructor(private val box : Box,private val boxStore : BoxStore) : Repository { - - @OptIn(ExperimentalCoroutinesApi::class) - override val itemFlow = box.query().build().subscribe().toFlow() - override fun init() { - - } - - override suspend fun save(t : TunnelConfig) { - Timber.d("Saving tunnel config") - boxStore.awaitCallInTx { - box.put(t) - } - - } - - override suspend fun saveAll(t : List) { - boxStore.awaitCallInTx { - box.put(t) - } - } - - override suspend fun getById(id: Long): TunnelConfig? { - return boxStore.awaitCallInTx { - box[id] - } - } - - override suspend fun getAll(): List? { - return boxStore.awaitCallInTx { - box.all - } - } - - override suspend fun delete(t : TunnelConfig): Boolean? { - return boxStore.awaitCallInTx { - box.remove(t) - } - } - - override suspend fun count() : Long? { - return boxStore.awaitCallInTx { - box.count() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/TunnelConfigDao.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/TunnelConfigDao.kt new file mode 100644 index 0000000..2533c7a --- /dev/null +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/TunnelConfigDao.kt @@ -0,0 +1,34 @@ +package com.zaneschepke.wireguardautotunnel.repository + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig +import kotlinx.coroutines.flow.Flow + +@Dao +interface TunnelConfigDao{ + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun save(t: TunnelConfig) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun saveAll(t: List) + + @Query("SELECT * FROM TunnelConfig WHERE id=:id") + suspend fun getById(id: Long): TunnelConfig? + + @Query("SELECT * FROM TunnelConfig") + suspend fun getAll(): List + + @Delete + suspend fun delete(t: TunnelConfig) + + @Query("SELECT COUNT('id') FROM TunnelConfig") + suspend fun count(): Long + + @Query("SELECT * FROM tunnelconfig") + fun getAllFlow(): Flow> +} \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/model/Settings.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/model/Settings.kt new file mode 100644 index 0000000..dd67942 --- /dev/null +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/model/Settings.kt @@ -0,0 +1,15 @@ +package com.zaneschepke.wireguardautotunnel.repository.model + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity +data class Settings( + @PrimaryKey(autoGenerate = true) val id : Int = 0, + @ColumnInfo(name = "is_tunnel_enabled") var isAutoTunnelEnabled : Boolean = false, + @ColumnInfo(name = "is_tunnel_on_mobile_data_enabled") var isTunnelOnMobileDataEnabled : Boolean = false, + @ColumnInfo(name = "trusted_network_ssids") var trustedNetworkSSIDs : MutableList = mutableListOf(), + @ColumnInfo(name = "default_tunnel") var defaultTunnel : String? = null, + @ColumnInfo(name = "is_always_on_vpn_enabled") var isAlwaysOnVpnEnabled : Boolean = false, +) \ No newline at end of file diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/TunnelConfig.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/model/TunnelConfig.kt similarity index 88% rename from app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/TunnelConfig.kt rename to app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/model/TunnelConfig.kt index 2d22faa..bd80f66 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/TunnelConfig.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/repository/model/TunnelConfig.kt @@ -1,25 +1,21 @@ -package com.zaneschepke.wireguardautotunnel.service.tunnel.model +package com.zaneschepke.wireguardautotunnel.repository.model +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.Index +import androidx.room.PrimaryKey import com.wireguard.config.Config -import io.objectbox.annotation.ConflictStrategy -import io.objectbox.annotation.Entity -import io.objectbox.annotation.Id -import io.objectbox.annotation.Unique import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import java.io.InputStream - -@Entity +@Entity(indices = [Index(value = ["name"], unique = true)]) @Serializable data class TunnelConfig( - @Id - var id : Long = 0, - @Unique(onConflict = ConflictStrategy.REPLACE) - var name : String, - var wgQuick : String -) { - + @PrimaryKey(autoGenerate = true) val id : Int = 0, + @ColumnInfo(name = "name") var name : String, + @ColumnInfo(name = "wg_quick") var wgQuick : String, +){ override fun toString(): String { return Json.encodeToString(serializer(), this) diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt index 816eea5..35b00a8 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt @@ -5,9 +5,8 @@ import android.app.Service import android.content.Context import android.content.Context.ACTIVITY_SERVICE import android.content.Intent -import com.google.firebase.crashlytics.ktx.crashlytics -import com.google.firebase.ktx.Firebase import com.zaneschepke.wireguardautotunnel.R +import timber.log.Timber object ServiceManager { @Suppress("DEPRECATION") @@ -43,7 +42,7 @@ object ServiceManager { Action.STOP -> context.startService(intent) } } catch (e : Exception) { - e.message?.let { Firebase.crashlytics.log(it) } + Timber.e(e.message) } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt index e24faec..37e24d4 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt @@ -10,14 +10,14 @@ import android.os.SystemClock import com.wireguard.android.backend.Tunnel import com.zaneschepke.wireguardautotunnel.Constants import com.zaneschepke.wireguardautotunnel.R -import com.zaneschepke.wireguardautotunnel.repository.Repository +import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa +import com.zaneschepke.wireguardautotunnel.repository.model.Settings import com.zaneschepke.wireguardautotunnel.service.network.MobileDataService import com.zaneschepke.wireguardautotunnel.service.network.NetworkService import com.zaneschepke.wireguardautotunnel.service.network.NetworkStatus import com.zaneschepke.wireguardautotunnel.service.network.WifiService import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -39,7 +39,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() { lateinit var mobileDataService : NetworkService @Inject - lateinit var settingsRepo: Repository + lateinit var settingsRepo: SettingsDoa @Inject lateinit var notificationService : NotificationService @@ -131,7 +131,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() { private fun startWatcherJob() { watcherJob = CoroutineScope(Dispatchers.IO).launch { val settings = settingsRepo.getAll(); - if(!settings.isNullOrEmpty()) { + if(settings.isNotEmpty()) { setting = settings[0] } launch { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt index b875591..62d9c9e 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt @@ -5,12 +5,11 @@ import android.content.Intent import android.os.Bundle import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.receiver.NotificationActionReceiver -import com.zaneschepke.wireguardautotunnel.repository.Repository +import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService import com.zaneschepke.wireguardautotunnel.service.tunnel.HandshakeStatus import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -28,7 +27,7 @@ class WireGuardTunnelService : ForegroundService() { lateinit var vpnService : VpnService @Inject - lateinit var settingsRepo: Repository + lateinit var settingsRepo: SettingsDoa @Inject lateinit var notificationService : NotificationService @@ -62,7 +61,7 @@ class WireGuardTunnelService : ForegroundService() { } else { Timber.d("Tunnel config null, starting default tunnel") val settings = settingsRepo.getAll(); - if(!settings.isNullOrEmpty()) { + if(settings.isNotEmpty()) { val setting = settings[0] if(setting.defaultTunnel != null && setting.isAlwaysOnVpnEnabled) { val tunnelConfig = TunnelConfig.from(setting.defaultTunnel!!) diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt index 2ebb866..bb5cc30 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt @@ -3,11 +3,10 @@ package com.zaneschepke.wireguardautotunnel.service.shortcut import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.zaneschepke.wireguardautotunnel.R -import com.zaneschepke.wireguardautotunnel.repository.Repository +import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa import com.zaneschepke.wireguardautotunnel.service.foreground.Action import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardTunnelService -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -18,14 +17,14 @@ import javax.inject.Inject class ShortcutsActivity : AppCompatActivity() { @Inject - lateinit var settingsRepo : Repository + lateinit var settingsRepo : SettingsDoa private val scope = CoroutineScope(Dispatchers.Main); private fun attemptWatcherServiceToggle(tunnelConfig : String) { scope.launch { val settings = settingsRepo.getAll() - if (!settings.isNullOrEmpty()) { + if (settings.isNotEmpty()) { val setting = settings.first() if(setting.isAutoTunnelEnabled) { ServiceManager.toggleWatcherServiceForeground(this@ShortcutsActivity, tunnelConfig) diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsManager.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsManager.kt index 04c0e9d..8798319 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsManager.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsManager.kt @@ -8,7 +8,7 @@ import androidx.core.graphics.drawable.IconCompat import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.service.foreground.Action import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardTunnelService -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig object ShortcutsManager { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt index 65e8469..0dc9479 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt @@ -5,11 +5,11 @@ import android.service.quicksettings.Tile import android.service.quicksettings.TileService import com.wireguard.android.backend.Tunnel import com.zaneschepke.wireguardautotunnel.R -import com.zaneschepke.wireguardautotunnel.repository.Repository +import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa +import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -23,10 +23,10 @@ import javax.inject.Inject class TunnelControlTile : TileService() { @Inject - lateinit var settingsRepo : Repository + lateinit var settingsRepo : SettingsDoa @Inject - lateinit var configRepo : Repository + lateinit var configRepo : TunnelConfigDao @Inject lateinit var vpnService : VpnService diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/VpnService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/VpnService.kt index 346a49a..1557c20 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/VpnService.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/VpnService.kt @@ -3,7 +3,7 @@ package com.zaneschepke.wireguardautotunnel.service.tunnel import com.wireguard.android.backend.Statistics import com.wireguard.android.backend.Tunnel import com.wireguard.crypto.Key -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig import kotlinx.coroutines.flow.SharedFlow interface VpnService : Tunnel { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt index 2f40c71..87116c7 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt @@ -6,7 +6,7 @@ import com.wireguard.android.backend.Statistics import com.wireguard.android.backend.Tunnel import com.wireguard.crypto.Key import com.zaneschepke.wireguardautotunnel.Constants -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.util.NumberUtils import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/Settings.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/Settings.kt deleted file mode 100644 index a868467..0000000 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/model/Settings.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.zaneschepke.wireguardautotunnel.service.tunnel.model - -import io.objectbox.annotation.Entity -import io.objectbox.annotation.Id - -@Entity -data class Settings( - @Id - var id : Long = 0, - var isAutoTunnelEnabled : Boolean = false, - var isTunnelOnMobileDataEnabled : Boolean = false, - var trustedNetworkSSIDs : MutableList = mutableListOf(), - var defaultTunnel : String? = null, - var isAlwaysOnVpnEnabled : Boolean = false, -) diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt index 4e5758a..b72f801 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/MainActivity.kt @@ -33,6 +33,7 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState import com.wireguard.android.backend.GoBackend +import com.zaneschepke.wireguardautotunnel.Constants import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.ui.common.PermissionRequestFailedScreen import com.zaneschepke.wireguardautotunnel.ui.common.navigation.BottomNavBar @@ -143,12 +144,12 @@ class MainActivity : AppCompatActivity() { when (initialState.destination.route) { Routes.Settings.name, Routes.Support.name -> slideInHorizontally( - initialOffsetX = { -1000 }, - animationSpec = tween(500) + initialOffsetX = { -Constants.SLIDE_IN_TRANSITION_OFFSET }, + animationSpec = tween(Constants.SLIDE_IN_ANIMATION_DURATION) ) else -> { - fadeIn(animationSpec = tween(1000)) + fadeIn(animationSpec = tween(Constants.FADE_IN_ANIMATION_DURATION)) } } }) { @@ -158,19 +159,19 @@ class MainActivity : AppCompatActivity() { when (initialState.destination.route) { Routes.Main.name -> slideInHorizontally( - initialOffsetX = { 1000 }, - animationSpec = tween(500) + initialOffsetX = { Constants.SLIDE_IN_TRANSITION_OFFSET }, + animationSpec = tween(Constants.SLIDE_IN_ANIMATION_DURATION) ) Routes.Support.name -> { slideInHorizontally( - initialOffsetX = { -1000 }, - animationSpec = tween(500) + initialOffsetX = { -Constants.SLIDE_IN_TRANSITION_OFFSET }, + animationSpec = tween(Constants.SLIDE_IN_ANIMATION_DURATION) ) } else -> { - fadeIn(animationSpec = tween(1000)) + fadeIn(animationSpec = tween(Constants.FADE_IN_ANIMATION_DURATION)) } } }) { SettingsScreen(padding = padding, snackbarHostState = snackbarHostState, navController = navController, focusRequester = focusRequester) } @@ -178,20 +179,20 @@ class MainActivity : AppCompatActivity() { when (initialState.destination.route) { Routes.Settings.name, Routes.Main.name -> slideInHorizontally( - initialOffsetX = { 1000 }, - animationSpec = tween(500) + initialOffsetX = { Constants.SLIDE_IN_ANIMATION_DURATION }, + animationSpec = tween(Constants.SLIDE_IN_ANIMATION_DURATION) ) else -> { - fadeIn(animationSpec = tween(1000)) + fadeIn(animationSpec = tween(Constants.FADE_IN_ANIMATION_DURATION)) } } }) { SupportScreen(padding = padding, focusRequester) } composable("${Routes.Config.name}/{id}", enterTransition = { - fadeIn(animationSpec = tween(1000)) + fadeIn(animationSpec = tween(Constants.FADE_IN_ANIMATION_DURATION)) }) { ConfigScreen(padding = padding, navController = navController, id = it.arguments?.getString("id"), focusRequester = focusRequester)} composable("${Routes.Detail.name}/{id}", enterTransition = { - fadeIn(animationSpec = tween(1000)) + fadeIn(animationSpec = tween(Constants.FADE_IN_ANIMATION_DURATION)) }) { DetailScreen(padding = padding, id = it.arguments?.getString("id")) } } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigViewModel.kt index 25a0c07..6afe299 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigViewModel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/config/ConfigViewModel.kt @@ -9,10 +9,10 @@ import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.toMutableStateList import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.zaneschepke.wireguardautotunnel.repository.Repository +import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa +import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao import com.zaneschepke.wireguardautotunnel.service.shortcut.ShortcutsManager -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -22,8 +22,8 @@ import javax.inject.Inject @HiltViewModel class ConfigViewModel @Inject constructor(private val application : Application, - private val tunnelRepo : Repository, - private val settingsRepo : Repository) : ViewModel() { + private val tunnelRepo : TunnelConfigDao, + private val settingsRepo : SettingsDoa) : ViewModel() { private val _tunnel = MutableStateFlow(null) private val _tunnelName = MutableStateFlow("") @@ -140,14 +140,15 @@ class ConfigViewModel @Inject constructor(private val application : Application, tunnelRepo.save(it) ShortcutsManager.createTunnelShortcuts(application, it) val settings = settingsRepo.getAll() - if(settings != null) { - val setting = settings[0] - if(setting.defaultTunnel != null) { - if(it.id == TunnelConfig.from(setting.defaultTunnel!!).id) { - settingsRepo.save(setting.copy( - defaultTunnel = it.toString() - )) - } + if(settings.isEmpty()) { + return + } + val setting = settings[0] + if(setting.defaultTunnel != null) { + if(it.id == TunnelConfig.from(setting.defaultTunnel!!).id) { + settingsRepo.save(setting.copy( + defaultTunnel = it.toString() + )) } } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/detail/DetailViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/detail/DetailViewModel.kt index 59c5698..c6f39ac 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/detail/DetailViewModel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/detail/DetailViewModel.kt @@ -2,9 +2,9 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.detail import androidx.lifecycle.ViewModel import com.wireguard.config.Config -import com.zaneschepke.wireguardautotunnel.repository.Repository +import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow @@ -12,7 +12,7 @@ import timber.log.Timber import javax.inject.Inject @HiltViewModel -class DetailViewModel @Inject constructor(private val tunnelRepo : Repository, private val vpnService : VpnService +class DetailViewModel @Inject constructor(private val tunnelRepo : TunnelConfigDao, private val vpnService : VpnService ) : ViewModel() { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt index 42f085b..cbca1db 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt @@ -18,7 +18,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.FileOpen @@ -73,8 +73,8 @@ import androidx.navigation.NavController import com.wireguard.android.backend.Tunnel import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.service.tunnel.HandshakeStatus -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.ui.Routes import com.zaneschepke.wireguardautotunnel.ui.common.RowListItem import com.zaneschepke.wireguardautotunnel.ui.theme.brickRed @@ -249,7 +249,7 @@ fun MainScreen( .fillMaxSize() .nestedScroll(nestedScrollConnection), ) { - itemsIndexed(tunnels.toList()) { _, tunnel -> + items(tunnels, key = { tunnel -> tunnel.id }) {tunnel -> val focusRequester = FocusRequester(); RowListItem(leadingIcon = Icons.Rounded.Circle, leadingIconColor = if (tunnelName == tunnel.name) when (handshakeStatus) { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt index 8caed38..e82eba2 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt @@ -9,21 +9,26 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.wireguard.config.BadConfigException import com.wireguard.config.Config +import com.zaneschepke.wireguardautotunnel.Constants import com.zaneschepke.wireguardautotunnel.R -import com.zaneschepke.wireguardautotunnel.repository.Repository +import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa +import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao import com.zaneschepke.wireguardautotunnel.service.barcode.CodeScanner import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceState import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardConnectivityWatcherService import com.zaneschepke.wireguardautotunnel.service.shortcut.ShortcutsManager import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig +import com.zaneschepke.wireguardautotunnel.repository.model.Settings +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.ui.ViewState +import com.zaneschepke.wireguardautotunnel.util.NumberUtils import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -31,15 +36,15 @@ import javax.inject.Inject @HiltViewModel class MainViewModel @Inject constructor(private val application : Application, - private val tunnelRepo : Repository, - private val settingsRepo : Repository, + private val tunnelRepo : TunnelConfigDao, + private val settingsRepo : SettingsDoa, private val vpnService: VpnService, private val codeScanner: CodeScanner ) : ViewModel() { private val _viewState = MutableStateFlow(ViewState()) val viewState get() = _viewState.asStateFlow() - val tunnels get() = tunnelRepo.itemFlow + val tunnels get() = tunnelRepo.getAllFlow() val state get() = vpnService.state val handshakeStatus get() = vpnService.handshakeStatus @@ -47,14 +52,9 @@ class MainViewModel @Inject constructor(private val application : Application, private val _settings = MutableStateFlow(Settings()) val settings get() = _settings.asStateFlow() - private val defaultConfigName = { - "tunnel${(Math.random() * 100000).toInt()}" - } - - init { - viewModelScope.launch { - settingsRepo.itemFlow.collect { + viewModelScope.launch(Dispatchers.IO) { + settingsRepo.getAllFlow().filter { it.isNotEmpty() }.collect { val settings = it.first() validateWatcherServiceState(settings) _settings.emit(settings) @@ -75,7 +75,7 @@ class MainViewModel @Inject constructor(private val application : Application, if(tunnelRepo.count() == 1L) { ServiceManager.stopWatcherService(application.applicationContext) val settings = settingsRepo.getAll() - if(!settings.isNullOrEmpty()) { + if(settings.isNotEmpty()) { val setting = settings[0] setting.defaultTunnel = null setting.isAutoTunnelEnabled = false @@ -99,7 +99,7 @@ class MainViewModel @Inject constructor(private val application : Application, suspend fun onTunnelQRSelected() { codeScanner.scan().collect { if(!it.isNullOrEmpty() && it.contains(application.resources.getString(R.string.config_validation))) { - val tunnelConfig = TunnelConfig(name = defaultConfigName(), wgQuick = it) + val tunnelConfig = TunnelConfig(name = NumberUtils.generateRandomTunnelName(), wgQuick = it) saveTunnel(tunnelConfig) } else if(!it.isNullOrEmpty() && it.contains(application.resources.getString(R.string.barcode_downloading))) { showSnackBarMessage(application.resources.getString(R.string.barcode_downloading_message)) @@ -110,34 +110,34 @@ class MainViewModel @Inject constructor(private val application : Application, } fun onTunnelFileSelected(uri : Uri) { - try { - val fileName = getFileName(application.applicationContext, uri) - val extension = getFileExtensionFromFileName(fileName) - if(extension != ".conf") { - viewModelScope.launch { - showSnackBarMessage(application.resources.getString(R.string.file_extension_message)) + viewModelScope.launch(Dispatchers.IO) { + try { + val fileName = getFileName(application.applicationContext, uri) + val extension = getFileExtensionFromFileName(fileName) + if (extension != ".conf") { + launch { + showSnackBarMessage(application.resources.getString(R.string.file_extension_message)) + } + return@launch } - return - } - val stream = application.applicationContext.contentResolver.openInputStream(uri) - stream ?: return - val bufferReader = stream.bufferedReader(charset = Charsets.UTF_8) + val stream = application.applicationContext.contentResolver.openInputStream(uri) + stream ?: return@launch + val bufferReader = stream.bufferedReader(charset = Charsets.UTF_8) val config = Config.parse(bufferReader) val tunnelName = getNameFromFileName(fileName) saveTunnel(TunnelConfig(name = tunnelName, wgQuick = config.toWgQuickString())) - stream.close() - } catch(_: BadConfigException) { - viewModelScope.launch { - showSnackBarMessage(application.applicationContext.getString(R.string.bad_config)) + stream.close() + } catch (_: BadConfigException) { + launch { + showSnackBarMessage(application.applicationContext.getString(R.string.bad_config)) + } } } } - private fun saveTunnel(tunnelConfig : TunnelConfig) { - viewModelScope.launch { - tunnelRepo.save(tunnelConfig) - ShortcutsManager.createTunnelShortcuts(application.applicationContext, tunnelConfig) - } + private suspend fun saveTunnel(tunnelConfig : TunnelConfig) { + tunnelRepo.save(tunnelConfig) + ShortcutsManager.createTunnelShortcuts(application.applicationContext, tunnelConfig) } @SuppressLint("Range") @@ -149,14 +149,14 @@ class MainViewModel @Inject constructor(private val application : Application, Timber.d("Exception getting config name") null } - cursor ?: return defaultConfigName() + cursor ?: return NumberUtils.generateRandomTunnelName() cursor.use { if(cursor.moveToFirst()) { return cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)) } } } - return defaultConfigName() + return NumberUtils.generateRandomTunnelName() } suspend fun showSnackBarMessage(message : String) { @@ -170,7 +170,7 @@ class MainViewModel @Inject constructor(private val application : Application, } } )) - delay(3000) + delay(Constants.SNACKBAR_DELAY) dismissSnackBar() } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt index 753244e..3275815 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsScreen.kt @@ -69,7 +69,7 @@ import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState import com.zaneschepke.wireguardautotunnel.R import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.ui.Routes import com.zaneschepke.wireguardautotunnel.ui.common.ClickableIconButton import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsViewModel.kt index 256fb7d..0a4ecde 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/settings/SettingsViewModel.kt @@ -6,35 +6,41 @@ import android.location.LocationManager import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.zaneschepke.wireguardautotunnel.R -import com.zaneschepke.wireguardautotunnel.repository.Repository +import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa +import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao +import com.zaneschepke.wireguardautotunnel.repository.model.Settings +import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings -import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.ui.ViewState import dagger.hilt.android.lifecycle.HiltViewModel +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.collectLatest +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class SettingsViewModel @Inject constructor(private val application : Application, - private val tunnelRepo : Repository, private val settingsRepo : Repository + private val tunnelRepo : TunnelConfigDao, private val settingsRepo : SettingsDoa ) : ViewModel() { private val _trustedSSIDs = MutableStateFlow(emptyList()) val trustedSSIDs = _trustedSSIDs.asStateFlow() private val _settings = MutableStateFlow(Settings()) val settings get() = _settings.asStateFlow() - val tunnels get() = tunnelRepo.itemFlow + val tunnels get() = tunnelRepo.getAllFlow() private val _viewState = MutableStateFlow(ViewState()) val viewState get() = _viewState.asStateFlow() init { checkLocationServicesEnabled() - viewModelScope.launch { - settingsRepo.itemFlow.collect { + viewModelScope.launch(Dispatchers.IO) { + settingsRepo.getAllFlow().filter { it.isNotEmpty() }.collect { val settings = it.first() _settings.emit(settings) _trustedSSIDs.emit(settings.trustedNetworkSSIDs.toList()) diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/NumberUtils.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/NumberUtils.kt index 7cdeddc..dd2a5b8 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/NumberUtils.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/NumberUtils.kt @@ -13,6 +13,10 @@ object NumberUtils { return bytes.toBigDecimal().divide(BYTES_IN_KB.toBigDecimal()) } + fun generateRandomTunnelName() : String { + return "tunnel${(Math.random() * 100000).toInt()}" + } + fun formatDecimalTwoPlaces(bigDecimal: BigDecimal) : String { val df = DecimalFormat("#.##") return df.format(bigDecimal) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7a2536e..8297e67 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -91,4 +91,5 @@ Search Icon Attempting connection.. VPN Starting + wg-tunnel-db \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 95714b7..3ecbf9b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,20 +1,18 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - buildscript { - val objectBoxVersion by extra("3.7.0") - val hiltVersion by extra("2.48") - val accompanistVersion by extra("0.31.2-alpha") - dependencies { - classpath("io.objectbox:objectbox-gradle-plugin:$objectBoxVersion") - classpath("com.google.gms:google-services:4.3.15") - classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.9") + if (BuildHelper.isReleaseBuild(gradle) && BuildHelper.isGeneralFlavor(gradle)) { + classpath(libs.google.services) + classpath(libs.firebase.crashlytics.gradle) + } } } + + plugins { - id("com.android.application") version "8.2.0-beta03" apply false - id("org.jetbrains.kotlin.android") version "1.8.22" apply false - id("com.google.dagger.hilt.android") version "2.48" apply false - kotlin("plugin.serialization") version "1.8.22" apply false + alias(libs.plugins.android.application) apply false + alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.hilt.android) apply false + kotlin("plugin.serialization").version(libs.versions.kotlin).apply(false) + alias(libs.plugins.ksp) apply false } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..37871be --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + `kotlin-dsl` // enable the Kotlin-DSL +} + +repositories { + google() + mavenCentral() +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/BuildHelper.kt b/buildSrc/src/main/kotlin/BuildHelper.kt new file mode 100644 index 0000000..13b6bd4 --- /dev/null +++ b/buildSrc/src/main/kotlin/BuildHelper.kt @@ -0,0 +1,29 @@ +import org.gradle.api.invocation.Gradle + +object BuildHelper { + private fun getCurrentFlavor(gradle : Gradle): String { + val taskRequestsStr = gradle.startParameter.taskRequests.toString() + val pattern: java.util.regex.Pattern = if (taskRequestsStr.contains("assemble")) { + java.util.regex.Pattern.compile("assemble(\\w+)(Release|Debug)") + } else { + java.util.regex.Pattern.compile("bundle(\\w+)(Release|Debug)") + } + + val matcher = pattern.matcher(taskRequestsStr) + val flavor = if (matcher.find()) { + matcher.group(1).lowercase() + } else { + print("NO FLAVOR FOUND") + "" + } + return flavor + } + + fun isGeneralFlavor(gradle : Gradle) : Boolean { + return getCurrentFlavor(gradle) == "general" + } + fun isReleaseBuild(gradle: Gradle) : Boolean { + return (gradle.startParameter.taskNames.size > 0 && gradle.startParameter.taskNames[0].contains( + "Release")) + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 1023be8..2cbd6d1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,5 +21,3 @@ kotlin.code.style=official # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true -#enable buildconfig values -android.defaults.buildfeatures.buildconfig=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..487e750 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,89 @@ +[versions] +accompanist = "0.31.2-alpha" +activityCompose = "1.7.2" +androidx-junit = "1.1.5" +appcompat = "1.6.1" +coreKtx = "1.12.0" +espressoCore = "3.5.1" +firebase-crashlytics-gradle = "2.9.9" +google-services = "4.3.15" +hiltAndroid = "2.48" +hiltNavigationCompose = "1.0.0" +junit = "4.13.2" +kotlinx-serialization-json = "1.5.1" +lifecycle-runtime-compose = "2.6.2" +material-icons-extended = "1.5.1" +material3 = "1.1.1" +navigationCompose = "2.7.2" +playServicesCodeScanner = "16.1.0" +roomVersion = "2.6.0-beta01" +timber = "5.0.1" +tunnel = "1.0.20230706" +androidGradlePlugin = "8.2.0-beta03" +kotlin="1.9.10" +ksp="1.9.10-1.0.13" +composeBom="2023.09.00" +firebaseBom="32.2.3" +compose="1.5.1" +crashlytics="18.4.1" +analytics="21.3.0" +composeCompiler="1.5.3" + + +[libraries] +# accompanist +accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanist" } +accompanist-flowlayout = { module = "com.google.accompanist:accompanist-flowlayout", version.ref = "accompanist" } +accompanist-navigation-animation = { module = "com.google.accompanist:accompanist-navigation-animation", version.ref = "accompanist" } +accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" } +accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" } +#room +androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomVersion" } +androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "roomVersion" } +androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomVersion" } + +#compose +androidx-compose-bom = { module = "androidx.compose:compose-bom", version.ref="composeBom" } +androidx-compose-ui-test = { module="androidx.compose.ui:ui-test-junit4", version.ref="compose" } +androidx-compose-ui-tooling = { module="androidx.compose.ui:ui-tooling", version.ref="compose" } +androidx-compose-manifest = { module="androidx.compose.ui:ui-test-manifest", version.ref="compose" } +androidx-compose-ui-graphics = { module="androidx.compose.ui:ui-graphics", version.ref="compose" } +androidx-compose-ui-tooling-preview = { module="androidx.compose.ui:ui-tooling-preview", version.ref="compose" } +androidx-compose-ui = { module="androidx.compose.ui:ui", version.ref="compose" } + +#hilt +hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" } +hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" } + +androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" } +androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" } +androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" } +androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espressoCore" } +androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" } +androidx-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-junit" } +androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-compose" } +androidx-material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" } +androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } + +junit = { module = "junit:junit", version.ref = "junit" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" } +lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle-runtime-compose" } +material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "material-icons-extended" } +play-services-code-scanner = { module = "com.google.android.gms:play-services-code-scanner", version.ref = "playServicesCodeScanner" } + +timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } + +tunnel = { module = "com.wireguard.android:tunnel", version.ref = "tunnel" } + +#firebase +google-firebase-crashlytics-ktx = { module = "com.google.firebase:firebase-crashlytics-ktx", version.ref = "crashlytics" } +google-firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics-ktx", version.ref = "analytics" } +firebase-crashlytics-gradle = { module = "com.google.firebase:firebase-crashlytics-gradle", version.ref = "firebase-crashlytics-gradle" } +firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom"} +google-services = { module = "com.google.gms:google-services", version.ref = "google-services" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hiltAndroid" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }