refactor: objectbox to room
Migrated app from using ObjectBox library for db to Room as ObjectBox is not FLOSS compliant. Migrated app to using version catalog for managing dependancies. Added floss build flavor for F-Droid and general build flavor for all other builds. Floss build excludes google analytics and crashlytics. Other performance improvements and refactors.
This commit is contained in:
parent
991d1224ab
commit
3c5aff31aa
|
@ -1,14 +1,9 @@
|
||||||
val rExtra = rootProject.extra
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
alias(libs.plugins.android.application)
|
||||||
id("org.jetbrains.kotlin.android")
|
alias(libs.plugins.kotlin.android)
|
||||||
kotlin("kapt")
|
alias(libs.plugins.hilt.android)
|
||||||
id("com.google.dagger.hilt.android")
|
|
||||||
id("com.google.gms.google-services")
|
|
||||||
id("com.google.firebase.crashlytics")
|
|
||||||
id("org.jetbrains.kotlin.plugin.serialization")
|
id("org.jetbrains.kotlin.plugin.serialization")
|
||||||
id("io.objectbox")
|
alias(libs.plugins.ksp)
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
@ -16,8 +11,8 @@ android {
|
||||||
compileSdk = 34
|
compileSdk = 34
|
||||||
|
|
||||||
val versionMajor = 2
|
val versionMajor = 2
|
||||||
val versionMinor = 4
|
val versionMinor = 5
|
||||||
val versionPatch = 5
|
val versionPatch = 0
|
||||||
val versionBuild = 0
|
val versionBuild = 0
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
@ -27,6 +22,10 @@ android {
|
||||||
versionCode = versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
|
versionCode = versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
|
||||||
versionName = "${versionMajor}.${versionMinor}.${versionPatch}"
|
versionName = "${versionMajor}.${versionMinor}.${versionPatch}"
|
||||||
|
|
||||||
|
multiDexEnabled = true
|
||||||
|
|
||||||
|
resourceConfigurations.addAll(listOf("en"))
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
useSupportLibrary = true
|
useSupportLibrary = true
|
||||||
|
@ -36,13 +35,35 @@ android {
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
isDebuggable = false
|
isDebuggable = false
|
||||||
isMinifyEnabled = false
|
isMinifyEnabled = true
|
||||||
|
isShrinkResources = true
|
||||||
proguardFiles(
|
proguardFiles(
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
"proguard-rules.pro"
|
"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 {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
@ -52,9 +73,11 @@ android {
|
||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose = true
|
compose = true
|
||||||
|
buildConfig = true
|
||||||
|
|
||||||
}
|
}
|
||||||
composeOptions {
|
composeOptions {
|
||||||
kotlinCompilerExtensionVersion = "1.4.8"
|
kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get()
|
||||||
}
|
}
|
||||||
packaging {
|
packaging {
|
||||||
resources {
|
resources {
|
||||||
|
@ -63,68 +86,69 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val generalImplementation by configurations
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("androidx.core:core-ktx:1.12.0")
|
implementation(libs.androidx.core.ktx)
|
||||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||||
implementation("androidx.activity:activity-compose:1.7.2")
|
implementation(libs.androidx.activity.compose)
|
||||||
implementation(platform("androidx.compose:compose-bom:2023.03.00"))
|
implementation(platform(libs.androidx.compose.bom))
|
||||||
implementation("androidx.compose.ui:ui")
|
implementation(libs.androidx.compose.ui)
|
||||||
implementation("androidx.compose.ui:ui-graphics")
|
implementation(libs.androidx.compose.ui.graphics)
|
||||||
implementation("androidx.compose.ui:ui-tooling-preview")
|
implementation(libs.androidx.compose.ui.tooling.preview)
|
||||||
implementation("androidx.compose.material3:material3:1.1.1")
|
implementation(libs.androidx.material3)
|
||||||
implementation("androidx.appcompat:appcompat:1.6.1")
|
implementation(libs.androidx.appcompat)
|
||||||
|
|
||||||
testImplementation("junit:junit:4.13.2")
|
//test
|
||||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
androidTestImplementation(libs.androidx.junit)
|
||||||
androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00"))
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
androidTestImplementation(platform(libs.androidx.compose.bom))
|
||||||
debugImplementation("androidx.compose.ui:ui-tooling")
|
androidTestImplementation(libs.androidx.compose.ui.test)
|
||||||
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
debugImplementation(libs.androidx.compose.ui.tooling)
|
||||||
|
debugImplementation(libs.androidx.compose.manifest)
|
||||||
|
|
||||||
//wireguard tunnel
|
//wg
|
||||||
implementation("com.wireguard.android:tunnel:1.0.20230706")
|
implementation(libs.tunnel)
|
||||||
|
|
||||||
//logging
|
//logging
|
||||||
implementation("com.jakewharton.timber:timber:5.0.1")
|
implementation(libs.timber)
|
||||||
|
|
||||||
// compose navigation
|
// compose navigation
|
||||||
implementation("androidx.navigation:navigation-compose:2.7.2")
|
implementation(libs.androidx.navigation.compose)
|
||||||
implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
|
implementation(libs.androidx.hilt.navigation.compose)
|
||||||
|
|
||||||
// hilt
|
// hilt
|
||||||
implementation("com.google.dagger:hilt-android:${rExtra.get("hiltVersion")}")
|
implementation(libs.hilt.android)
|
||||||
kapt("com.google.dagger:hilt-android-compiler:${rExtra.get("hiltVersion")}")
|
ksp(libs.hilt.android.compiler)
|
||||||
|
|
||||||
//accompanist
|
//accompanist
|
||||||
implementation("com.google.accompanist:accompanist-systemuicontroller:${rExtra.get("accompanistVersion")}")
|
implementation(libs.accompanist.systemuicontroller)
|
||||||
implementation("com.google.accompanist:accompanist-permissions:${rExtra.get("accompanistVersion")}")
|
implementation(libs.accompanist.permissions)
|
||||||
implementation("com.google.accompanist:accompanist-flowlayout:${rExtra.get("accompanistVersion")}")
|
implementation(libs.accompanist.flowlayout)
|
||||||
implementation("com.google.accompanist:accompanist-navigation-animation:${rExtra.get("accompanistVersion")}")
|
implementation(libs.accompanist.navigation.animation)
|
||||||
implementation("com.google.accompanist:accompanist-drawablepainter:${rExtra.get("accompanistVersion")}")
|
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
|
//lifecycle
|
||||||
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.6.2")
|
implementation(libs.lifecycle.runtime.compose)
|
||||||
|
|
||||||
//icons
|
//icons
|
||||||
implementation("androidx.compose.material:material-icons-extended:1.5.1")
|
implementation(libs.material.icons.extended)
|
||||||
|
//serialization
|
||||||
|
implementation(libs.kotlinx.serialization.json)
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
|
|
||||||
|
|
||||||
|
|
||||||
//firebase crashlytics
|
//firebase crashlytics
|
||||||
implementation(platform("com.google.firebase:firebase-bom:32.0.0"))
|
generalImplementation(platform(libs.firebase.bom))
|
||||||
implementation("com.google.firebase:firebase-crashlytics-ktx")
|
generalImplementation(libs.google.firebase.crashlytics.ktx)
|
||||||
implementation("com.google.firebase:firebase-analytics-ktx")
|
generalImplementation(libs.google.firebase.analytics.ktx)
|
||||||
|
|
||||||
//barcode scanning
|
//barcode scanning
|
||||||
implementation("com.google.android.gms:play-services-code-scanner:16.1.0")
|
implementation(libs.play.services.code.scanner)
|
||||||
}
|
|
||||||
|
|
||||||
kapt {
|
|
||||||
correctErrorTypes = true
|
|
||||||
}
|
}
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -114,8 +114,5 @@
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.mlkit.vision.DEPENDENCIES"
|
android:name="com.google.mlkit.vision.DEPENDENCIES"
|
||||||
android:value="barcode_ui"/>
|
android:value="barcode_ui"/>
|
||||||
<meta-data
|
|
||||||
android:name="firebase_crashlytics_collection_enabled"
|
|
||||||
android:value="true" />
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
|
@ -1,6 +1,11 @@
|
||||||
package com.zaneschepke.wireguardautotunnel
|
package com.zaneschepke.wireguardautotunnel
|
||||||
|
|
||||||
object Constants {
|
object Constants {
|
||||||
const val VPN_CONNECTIVITY_CHECK_INTERVAL = 3000L;
|
const val VPN_CONNECTIVITY_CHECK_INTERVAL = 3000L
|
||||||
const val VPN_STATISTIC_CHECK_INTERVAL = 10000L;
|
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
|
||||||
}
|
}
|
|
@ -3,32 +3,17 @@ package com.zaneschepke.wireguardautotunnel
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
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 dagger.hilt.android.HiltAndroidApp
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
class WireGuardAutoTunnel : Application() {
|
class WireGuardAutoTunnel : Application() {
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var settingsRepo : Repository<Settings>
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
if(BuildConfig.DEBUG) {
|
if(BuildConfig.DEBUG) {
|
||||||
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(false);
|
|
||||||
Timber.plant(Timber.DebugTree())
|
Timber.plant(Timber.DebugTree())
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
MlKit.initialize(this)
|
|
||||||
} catch (e : Exception) {
|
|
||||||
Timber.e(e.message)
|
|
||||||
}
|
|
||||||
settingsRepo.init()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -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<Settings> {
|
|
||||||
return store.boxFor(Settings::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
fun provideBoxForTunnels(store : BoxStore) : Box<TunnelConfig> {
|
|
||||||
return store.boxFor(TunnelConfig::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +1,27 @@
|
||||||
package com.zaneschepke.wireguardautotunnel.module
|
package com.zaneschepke.wireguardautotunnel.module
|
||||||
|
|
||||||
import com.zaneschepke.wireguardautotunnel.repository.Repository
|
import com.zaneschepke.wireguardautotunnel.repository.AppDatabase
|
||||||
import com.zaneschepke.wireguardautotunnel.repository.SettingsBox
|
import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa
|
||||||
import com.zaneschepke.wireguardautotunnel.repository.TunnelBox
|
import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
|
|
||||||
import dagger.Binds
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@InstallIn(SingletonComponent::class)
|
@InstallIn(SingletonComponent::class)
|
||||||
abstract class RepositoryModule {
|
class RepositoryModule {
|
||||||
|
|
||||||
@Binds
|
|
||||||
@Singleton
|
@Singleton
|
||||||
abstract fun provideSettingsRepository(settingsBox: SettingsBox) : Repository<Settings>
|
@Provides
|
||||||
|
fun provideSettingsRepository(appDatabase: AppDatabase) : SettingsDoa {
|
||||||
|
return appDatabase.settingDao()
|
||||||
|
}
|
||||||
|
|
||||||
@Binds
|
|
||||||
@Singleton
|
@Singleton
|
||||||
abstract fun provideTunnelRepository(tunnelBox: TunnelBox) : Repository<TunnelConfig>
|
@Provides
|
||||||
|
fun provideTunnelConfigRepository(appDatabase: AppDatabase) : TunnelConfigDao {
|
||||||
|
return appDatabase.tunnelConfigDoa()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -3,9 +3,8 @@ package com.zaneschepke.wireguardautotunnel.receiver
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
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.foreground.ServiceManager
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -17,7 +16,7 @@ import javax.inject.Inject
|
||||||
class BootReceiver : BroadcastReceiver() {
|
class BootReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var settingsRepo : Repository<Settings>
|
lateinit var settingsRepo : SettingsDoa
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
|
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
|
||||||
|
|
|
@ -3,9 +3,9 @@ package com.zaneschepke.wireguardautotunnel.receiver
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
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.foreground.ServiceManager
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -18,16 +18,16 @@ import javax.inject.Inject
|
||||||
class NotificationActionReceiver : BroadcastReceiver() {
|
class NotificationActionReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var settingsRepo : Repository<Settings>
|
lateinit var settingsRepo : SettingsDoa
|
||||||
override fun onReceive(context: Context, intent: Intent?) {
|
override fun onReceive(context: Context, intent: Intent?) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
try {
|
try {
|
||||||
val settings = settingsRepo.getAll()
|
val settings = settingsRepo.getAll()
|
||||||
if (!settings.isNullOrEmpty()) {
|
if (settings.isNotEmpty()) {
|
||||||
val setting = settings.first()
|
val setting = settings.first()
|
||||||
if (setting.defaultTunnel != null) {
|
if (setting.defaultTunnel != null) {
|
||||||
ServiceManager.stopVpnService(context)
|
ServiceManager.stopVpnService(context)
|
||||||
delay(1000)
|
delay(Constants.TOGGLE_TUNNEL_DELAY)
|
||||||
ServiceManager.startVpnService(context, setting.defaultTunnel.toString())
|
ServiceManager.startVpnService(context, setting.defaultTunnel.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.zaneschepke.wireguardautotunnel.repository
|
||||||
|
|
||||||
|
import androidx.room.TypeConverter
|
||||||
|
|
||||||
|
class DatabaseListConverters {
|
||||||
|
@TypeConverter
|
||||||
|
fun listToString(value: MutableList<String>): String {
|
||||||
|
return value.joinToString()
|
||||||
|
}
|
||||||
|
@TypeConverter
|
||||||
|
fun <T> stringToList(value: String): MutableList<String> {
|
||||||
|
if(value.isEmpty()) return mutableListOf()
|
||||||
|
return value.split(",").toMutableList()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +0,0 @@
|
||||||
package com.zaneschepke.wireguardautotunnel.repository
|
|
||||||
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
interface Repository<T> {
|
|
||||||
suspend fun save(t : T)
|
|
||||||
suspend fun saveAll(t : List<T>)
|
|
||||||
suspend fun getById(id : Long) : T?
|
|
||||||
suspend fun getAll() : List<T>?
|
|
||||||
suspend fun delete(t : T) : Boolean?
|
|
||||||
suspend fun count() : Long?
|
|
||||||
|
|
||||||
val itemFlow : Flow<MutableList<T>>
|
|
||||||
|
|
||||||
fun init()
|
|
||||||
}
|
|
|
@ -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<Settings>, private val boxStore : BoxStore) : Repository<Settings> {
|
|
||||||
|
|
||||||
@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<Settings>) {
|
|
||||||
boxStore.awaitCallInTx {
|
|
||||||
box.put(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getById(id: Long): Settings? {
|
|
||||||
return boxStore.awaitCallInTx {
|
|
||||||
box[id]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getAll(): List<Settings>? {
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<Settings>)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM settings WHERE id=:id")
|
||||||
|
suspend fun getById(id: Long): Settings?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM settings")
|
||||||
|
suspend fun getAll(): List<Settings>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM settings")
|
||||||
|
fun getAllFlow(): Flow<MutableList<Settings>>
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(t: Settings)
|
||||||
|
|
||||||
|
@Query("SELECT COUNT('id') FROM settings")
|
||||||
|
suspend fun count(): Long
|
||||||
|
}
|
|
@ -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<TunnelConfig>,private val boxStore : BoxStore) : Repository<TunnelConfig> {
|
|
||||||
|
|
||||||
@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<TunnelConfig>) {
|
|
||||||
boxStore.awaitCallInTx {
|
|
||||||
box.put(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getById(id: Long): TunnelConfig? {
|
|
||||||
return boxStore.awaitCallInTx {
|
|
||||||
box[id]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getAll(): List<TunnelConfig>? {
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<TunnelConfig>)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM TunnelConfig WHERE id=:id")
|
||||||
|
suspend fun getById(id: Long): TunnelConfig?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM TunnelConfig")
|
||||||
|
suspend fun getAll(): List<TunnelConfig>
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(t: TunnelConfig)
|
||||||
|
|
||||||
|
@Query("SELECT COUNT('id') FROM TunnelConfig")
|
||||||
|
suspend fun count(): Long
|
||||||
|
|
||||||
|
@Query("SELECT * FROM tunnelconfig")
|
||||||
|
fun getAllFlow(): Flow<MutableList<TunnelConfig>>
|
||||||
|
}
|
|
@ -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<String> = mutableListOf(),
|
||||||
|
@ColumnInfo(name = "default_tunnel") var defaultTunnel : String? = null,
|
||||||
|
@ColumnInfo(name = "is_always_on_vpn_enabled") var isAlwaysOnVpnEnabled : Boolean = false,
|
||||||
|
)
|
|
@ -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 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.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
|
@Entity(indices = [Index(value = ["name"], unique = true)])
|
||||||
@Entity
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class TunnelConfig(
|
data class TunnelConfig(
|
||||||
@Id
|
@PrimaryKey(autoGenerate = true) val id : Int = 0,
|
||||||
var id : Long = 0,
|
@ColumnInfo(name = "name") var name : String,
|
||||||
@Unique(onConflict = ConflictStrategy.REPLACE)
|
@ColumnInfo(name = "wg_quick") var wgQuick : String,
|
||||||
var name : String,
|
){
|
||||||
var wgQuick : String
|
|
||||||
) {
|
|
||||||
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return Json.encodeToString(serializer(), this)
|
return Json.encodeToString(serializer(), this)
|
|
@ -5,9 +5,8 @@ import android.app.Service
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Context.ACTIVITY_SERVICE
|
import android.content.Context.ACTIVITY_SERVICE
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
|
||||||
import com.google.firebase.ktx.Firebase
|
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
import com.zaneschepke.wireguardautotunnel.R
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
object ServiceManager {
|
object ServiceManager {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
|
@ -43,7 +42,7 @@ object ServiceManager {
|
||||||
Action.STOP -> context.startService(intent)
|
Action.STOP -> context.startService(intent)
|
||||||
}
|
}
|
||||||
} catch (e : Exception) {
|
} catch (e : Exception) {
|
||||||
e.message?.let { Firebase.crashlytics.log(it) }
|
Timber.e(e.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,14 @@ import android.os.SystemClock
|
||||||
import com.wireguard.android.backend.Tunnel
|
import com.wireguard.android.backend.Tunnel
|
||||||
import com.zaneschepke.wireguardautotunnel.Constants
|
import com.zaneschepke.wireguardautotunnel.Constants
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
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.MobileDataService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.network.NetworkService
|
import com.zaneschepke.wireguardautotunnel.service.network.NetworkService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.network.NetworkStatus
|
import com.zaneschepke.wireguardautotunnel.service.network.NetworkStatus
|
||||||
import com.zaneschepke.wireguardautotunnel.service.network.WifiService
|
import com.zaneschepke.wireguardautotunnel.service.network.WifiService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
|
import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
|
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -39,7 +39,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
|
||||||
lateinit var mobileDataService : NetworkService<MobileDataService>
|
lateinit var mobileDataService : NetworkService<MobileDataService>
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var settingsRepo: Repository<Settings>
|
lateinit var settingsRepo: SettingsDoa
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var notificationService : NotificationService
|
lateinit var notificationService : NotificationService
|
||||||
|
@ -131,7 +131,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
|
||||||
private fun startWatcherJob() {
|
private fun startWatcherJob() {
|
||||||
watcherJob = CoroutineScope(Dispatchers.IO).launch {
|
watcherJob = CoroutineScope(Dispatchers.IO).launch {
|
||||||
val settings = settingsRepo.getAll();
|
val settings = settingsRepo.getAll();
|
||||||
if(!settings.isNullOrEmpty()) {
|
if(settings.isNotEmpty()) {
|
||||||
setting = settings[0]
|
setting = settings[0]
|
||||||
}
|
}
|
||||||
launch {
|
launch {
|
||||||
|
|
|
@ -5,12 +5,11 @@ import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
import com.zaneschepke.wireguardautotunnel.R
|
||||||
import com.zaneschepke.wireguardautotunnel.receiver.NotificationActionReceiver
|
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.notification.NotificationService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.HandshakeStatus
|
import com.zaneschepke.wireguardautotunnel.service.tunnel.HandshakeStatus
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
|
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -28,7 +27,7 @@ class WireGuardTunnelService : ForegroundService() {
|
||||||
lateinit var vpnService : VpnService
|
lateinit var vpnService : VpnService
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var settingsRepo: Repository<Settings>
|
lateinit var settingsRepo: SettingsDoa
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var notificationService : NotificationService
|
lateinit var notificationService : NotificationService
|
||||||
|
@ -62,7 +61,7 @@ class WireGuardTunnelService : ForegroundService() {
|
||||||
} else {
|
} else {
|
||||||
Timber.d("Tunnel config null, starting default tunnel")
|
Timber.d("Tunnel config null, starting default tunnel")
|
||||||
val settings = settingsRepo.getAll();
|
val settings = settingsRepo.getAll();
|
||||||
if(!settings.isNullOrEmpty()) {
|
if(settings.isNotEmpty()) {
|
||||||
val setting = settings[0]
|
val setting = settings[0]
|
||||||
if(setting.defaultTunnel != null && setting.isAlwaysOnVpnEnabled) {
|
if(setting.defaultTunnel != null && setting.isAlwaysOnVpnEnabled) {
|
||||||
val tunnelConfig = TunnelConfig.from(setting.defaultTunnel!!)
|
val tunnelConfig = TunnelConfig.from(setting.defaultTunnel!!)
|
||||||
|
|
|
@ -3,11 +3,10 @@ package com.zaneschepke.wireguardautotunnel.service.shortcut
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
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.Action
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
|
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardTunnelService
|
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardTunnelService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -18,14 +17,14 @@ import javax.inject.Inject
|
||||||
class ShortcutsActivity : AppCompatActivity() {
|
class ShortcutsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var settingsRepo : Repository<Settings>
|
lateinit var settingsRepo : SettingsDoa
|
||||||
|
|
||||||
private val scope = CoroutineScope(Dispatchers.Main);
|
private val scope = CoroutineScope(Dispatchers.Main);
|
||||||
|
|
||||||
private fun attemptWatcherServiceToggle(tunnelConfig : String) {
|
private fun attemptWatcherServiceToggle(tunnelConfig : String) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val settings = settingsRepo.getAll()
|
val settings = settingsRepo.getAll()
|
||||||
if (!settings.isNullOrEmpty()) {
|
if (settings.isNotEmpty()) {
|
||||||
val setting = settings.first()
|
val setting = settings.first()
|
||||||
if(setting.isAutoTunnelEnabled) {
|
if(setting.isAutoTunnelEnabled) {
|
||||||
ServiceManager.toggleWatcherServiceForeground(this@ShortcutsActivity, tunnelConfig)
|
ServiceManager.toggleWatcherServiceForeground(this@ShortcutsActivity, tunnelConfig)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import androidx.core.graphics.drawable.IconCompat
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
import com.zaneschepke.wireguardautotunnel.R
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.Action
|
import com.zaneschepke.wireguardautotunnel.service.foreground.Action
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardTunnelService
|
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardTunnelService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
|
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
|
||||||
|
|
||||||
object ShortcutsManager {
|
object ShortcutsManager {
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@ import android.service.quicksettings.Tile
|
||||||
import android.service.quicksettings.TileService
|
import android.service.quicksettings.TileService
|
||||||
import com.wireguard.android.backend.Tunnel
|
import com.wireguard.android.backend.Tunnel
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
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.foreground.ServiceManager
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
|
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 dagger.hilt.android.AndroidEntryPoint
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -23,10 +23,10 @@ import javax.inject.Inject
|
||||||
class TunnelControlTile : TileService() {
|
class TunnelControlTile : TileService() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var settingsRepo : Repository<Settings>
|
lateinit var settingsRepo : SettingsDoa
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var configRepo : Repository<TunnelConfig>
|
lateinit var configRepo : TunnelConfigDao
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var vpnService : VpnService
|
lateinit var vpnService : VpnService
|
||||||
|
|
|
@ -3,7 +3,7 @@ package com.zaneschepke.wireguardautotunnel.service.tunnel
|
||||||
import com.wireguard.android.backend.Statistics
|
import com.wireguard.android.backend.Statistics
|
||||||
import com.wireguard.android.backend.Tunnel
|
import com.wireguard.android.backend.Tunnel
|
||||||
import com.wireguard.crypto.Key
|
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
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
|
|
||||||
interface VpnService : Tunnel {
|
interface VpnService : Tunnel {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import com.wireguard.android.backend.Statistics
|
||||||
import com.wireguard.android.backend.Tunnel
|
import com.wireguard.android.backend.Tunnel
|
||||||
import com.wireguard.crypto.Key
|
import com.wireguard.crypto.Key
|
||||||
import com.zaneschepke.wireguardautotunnel.Constants
|
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 com.zaneschepke.wireguardautotunnel.util.NumberUtils
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
|
@ -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<String> = mutableListOf(),
|
|
||||||
var defaultTunnel : String? = null,
|
|
||||||
var isAlwaysOnVpnEnabled : Boolean = false,
|
|
||||||
)
|
|
|
@ -33,6 +33,7 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||||
import com.google.accompanist.permissions.isGranted
|
import com.google.accompanist.permissions.isGranted
|
||||||
import com.google.accompanist.permissions.rememberPermissionState
|
import com.google.accompanist.permissions.rememberPermissionState
|
||||||
import com.wireguard.android.backend.GoBackend
|
import com.wireguard.android.backend.GoBackend
|
||||||
|
import com.zaneschepke.wireguardautotunnel.Constants
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
import com.zaneschepke.wireguardautotunnel.R
|
||||||
import com.zaneschepke.wireguardautotunnel.ui.common.PermissionRequestFailedScreen
|
import com.zaneschepke.wireguardautotunnel.ui.common.PermissionRequestFailedScreen
|
||||||
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.BottomNavBar
|
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.BottomNavBar
|
||||||
|
@ -143,12 +144,12 @@ class MainActivity : AppCompatActivity() {
|
||||||
when (initialState.destination.route) {
|
when (initialState.destination.route) {
|
||||||
Routes.Settings.name, Routes.Support.name ->
|
Routes.Settings.name, Routes.Support.name ->
|
||||||
slideInHorizontally(
|
slideInHorizontally(
|
||||||
initialOffsetX = { -1000 },
|
initialOffsetX = { -Constants.SLIDE_IN_TRANSITION_OFFSET },
|
||||||
animationSpec = tween(500)
|
animationSpec = tween(Constants.SLIDE_IN_ANIMATION_DURATION)
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
fadeIn(animationSpec = tween(1000))
|
fadeIn(animationSpec = tween(Constants.FADE_IN_ANIMATION_DURATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
|
@ -158,19 +159,19 @@ class MainActivity : AppCompatActivity() {
|
||||||
when (initialState.destination.route) {
|
when (initialState.destination.route) {
|
||||||
Routes.Main.name ->
|
Routes.Main.name ->
|
||||||
slideInHorizontally(
|
slideInHorizontally(
|
||||||
initialOffsetX = { 1000 },
|
initialOffsetX = { Constants.SLIDE_IN_TRANSITION_OFFSET },
|
||||||
animationSpec = tween(500)
|
animationSpec = tween(Constants.SLIDE_IN_ANIMATION_DURATION)
|
||||||
)
|
)
|
||||||
|
|
||||||
Routes.Support.name -> {
|
Routes.Support.name -> {
|
||||||
slideInHorizontally(
|
slideInHorizontally(
|
||||||
initialOffsetX = { -1000 },
|
initialOffsetX = { -Constants.SLIDE_IN_TRANSITION_OFFSET },
|
||||||
animationSpec = tween(500)
|
animationSpec = tween(Constants.SLIDE_IN_ANIMATION_DURATION)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
fadeIn(animationSpec = tween(1000))
|
fadeIn(animationSpec = tween(Constants.FADE_IN_ANIMATION_DURATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) { SettingsScreen(padding = padding, snackbarHostState = snackbarHostState, navController = navController, focusRequester = focusRequester) }
|
}) { SettingsScreen(padding = padding, snackbarHostState = snackbarHostState, navController = navController, focusRequester = focusRequester) }
|
||||||
|
@ -178,20 +179,20 @@ class MainActivity : AppCompatActivity() {
|
||||||
when (initialState.destination.route) {
|
when (initialState.destination.route) {
|
||||||
Routes.Settings.name, Routes.Main.name ->
|
Routes.Settings.name, Routes.Main.name ->
|
||||||
slideInHorizontally(
|
slideInHorizontally(
|
||||||
initialOffsetX = { 1000 },
|
initialOffsetX = { Constants.SLIDE_IN_ANIMATION_DURATION },
|
||||||
animationSpec = tween(500)
|
animationSpec = tween(Constants.SLIDE_IN_ANIMATION_DURATION)
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
fadeIn(animationSpec = tween(1000))
|
fadeIn(animationSpec = tween(Constants.FADE_IN_ANIMATION_DURATION))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) { SupportScreen(padding = padding, focusRequester) }
|
}) { SupportScreen(padding = padding, focusRequester) }
|
||||||
composable("${Routes.Config.name}/{id}", enterTransition = {
|
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)}
|
}) { ConfigScreen(padding = padding, navController = navController, id = it.arguments?.getString("id"), focusRequester = focusRequester)}
|
||||||
composable("${Routes.Detail.name}/{id}", enterTransition = {
|
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")) }
|
}) { DetailScreen(padding = padding, id = it.arguments?.getString("id")) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@ import androidx.compose.runtime.mutableStateListOf
|
||||||
import androidx.compose.runtime.toMutableStateList
|
import androidx.compose.runtime.toMutableStateList
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
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.shortcut.ShortcutsManager
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
@ -22,8 +22,8 @@ import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class ConfigViewModel @Inject constructor(private val application : Application,
|
class ConfigViewModel @Inject constructor(private val application : Application,
|
||||||
private val tunnelRepo : Repository<TunnelConfig>,
|
private val tunnelRepo : TunnelConfigDao,
|
||||||
private val settingsRepo : Repository<Settings>) : ViewModel() {
|
private val settingsRepo : SettingsDoa) : ViewModel() {
|
||||||
|
|
||||||
private val _tunnel = MutableStateFlow<TunnelConfig?>(null)
|
private val _tunnel = MutableStateFlow<TunnelConfig?>(null)
|
||||||
private val _tunnelName = MutableStateFlow("")
|
private val _tunnelName = MutableStateFlow("")
|
||||||
|
@ -140,14 +140,15 @@ class ConfigViewModel @Inject constructor(private val application : Application,
|
||||||
tunnelRepo.save(it)
|
tunnelRepo.save(it)
|
||||||
ShortcutsManager.createTunnelShortcuts(application, it)
|
ShortcutsManager.createTunnelShortcuts(application, it)
|
||||||
val settings = settingsRepo.getAll()
|
val settings = settingsRepo.getAll()
|
||||||
if(settings != null) {
|
if(settings.isEmpty()) {
|
||||||
val setting = settings[0]
|
return
|
||||||
if(setting.defaultTunnel != null) {
|
}
|
||||||
if(it.id == TunnelConfig.from(setting.defaultTunnel!!).id) {
|
val setting = settings[0]
|
||||||
settingsRepo.save(setting.copy(
|
if(setting.defaultTunnel != null) {
|
||||||
defaultTunnel = it.toString()
|
if(it.id == TunnelConfig.from(setting.defaultTunnel!!).id) {
|
||||||
))
|
settingsRepo.save(setting.copy(
|
||||||
}
|
defaultTunnel = it.toString()
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ package com.zaneschepke.wireguardautotunnel.ui.screens.detail
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.wireguard.config.Config
|
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.VpnService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
@ -12,7 +12,7 @@ import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class DetailViewModel @Inject constructor(private val tunnelRepo : Repository<TunnelConfig>, private val vpnService : VpnService
|
class DetailViewModel @Inject constructor(private val tunnelRepo : TunnelConfigDao, private val vpnService : VpnService
|
||||||
|
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
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.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.FileOpen
|
import androidx.compose.material.icons.filled.FileOpen
|
||||||
|
@ -73,8 +73,8 @@ import androidx.navigation.NavController
|
||||||
import com.wireguard.android.backend.Tunnel
|
import com.wireguard.android.backend.Tunnel
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
import com.zaneschepke.wireguardautotunnel.R
|
||||||
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
|
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.HandshakeStatus
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
|
|
||||||
import com.zaneschepke.wireguardautotunnel.ui.Routes
|
import com.zaneschepke.wireguardautotunnel.ui.Routes
|
||||||
import com.zaneschepke.wireguardautotunnel.ui.common.RowListItem
|
import com.zaneschepke.wireguardautotunnel.ui.common.RowListItem
|
||||||
import com.zaneschepke.wireguardautotunnel.ui.theme.brickRed
|
import com.zaneschepke.wireguardautotunnel.ui.theme.brickRed
|
||||||
|
@ -249,7 +249,7 @@ fun MainScreen(
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.nestedScroll(nestedScrollConnection),
|
.nestedScroll(nestedScrollConnection),
|
||||||
) {
|
) {
|
||||||
itemsIndexed(tunnels.toList()) { _, tunnel ->
|
items(tunnels, key = { tunnel -> tunnel.id }) {tunnel ->
|
||||||
val focusRequester = FocusRequester();
|
val focusRequester = FocusRequester();
|
||||||
RowListItem(leadingIcon = Icons.Rounded.Circle,
|
RowListItem(leadingIcon = Icons.Rounded.Circle,
|
||||||
leadingIconColor = if (tunnelName == tunnel.name) when (handshakeStatus) {
|
leadingIconColor = if (tunnelName == tunnel.name) when (handshakeStatus) {
|
||||||
|
|
|
@ -9,21 +9,26 @@ import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.wireguard.config.BadConfigException
|
import com.wireguard.config.BadConfigException
|
||||||
import com.wireguard.config.Config
|
import com.wireguard.config.Config
|
||||||
|
import com.zaneschepke.wireguardautotunnel.Constants
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
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.barcode.CodeScanner
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceState
|
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceState
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
|
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
|
||||||
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardConnectivityWatcherService
|
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardConnectivityWatcherService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.shortcut.ShortcutsManager
|
import com.zaneschepke.wireguardautotunnel.service.shortcut.ShortcutsManager
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
|
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
|
import com.zaneschepke.wireguardautotunnel.repository.model.Settings
|
||||||
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
|
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
|
||||||
import com.zaneschepke.wireguardautotunnel.ui.ViewState
|
import com.zaneschepke.wireguardautotunnel.ui.ViewState
|
||||||
|
import com.zaneschepke.wireguardautotunnel.util.NumberUtils
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -31,15 +36,15 @@ import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class MainViewModel @Inject constructor(private val application : Application,
|
class MainViewModel @Inject constructor(private val application : Application,
|
||||||
private val tunnelRepo : Repository<TunnelConfig>,
|
private val tunnelRepo : TunnelConfigDao,
|
||||||
private val settingsRepo : Repository<Settings>,
|
private val settingsRepo : SettingsDoa,
|
||||||
private val vpnService: VpnService,
|
private val vpnService: VpnService,
|
||||||
private val codeScanner: CodeScanner
|
private val codeScanner: CodeScanner
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val _viewState = MutableStateFlow(ViewState())
|
private val _viewState = MutableStateFlow(ViewState())
|
||||||
val viewState get() = _viewState.asStateFlow()
|
val viewState get() = _viewState.asStateFlow()
|
||||||
val tunnels get() = tunnelRepo.itemFlow
|
val tunnels get() = tunnelRepo.getAllFlow()
|
||||||
val state get() = vpnService.state
|
val state get() = vpnService.state
|
||||||
|
|
||||||
val handshakeStatus get() = vpnService.handshakeStatus
|
val handshakeStatus get() = vpnService.handshakeStatus
|
||||||
|
@ -47,14 +52,9 @@ class MainViewModel @Inject constructor(private val application : Application,
|
||||||
private val _settings = MutableStateFlow(Settings())
|
private val _settings = MutableStateFlow(Settings())
|
||||||
val settings get() = _settings.asStateFlow()
|
val settings get() = _settings.asStateFlow()
|
||||||
|
|
||||||
private val defaultConfigName = {
|
|
||||||
"tunnel${(Math.random() * 100000).toInt()}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
settingsRepo.itemFlow.collect {
|
settingsRepo.getAllFlow().filter { it.isNotEmpty() }.collect {
|
||||||
val settings = it.first()
|
val settings = it.first()
|
||||||
validateWatcherServiceState(settings)
|
validateWatcherServiceState(settings)
|
||||||
_settings.emit(settings)
|
_settings.emit(settings)
|
||||||
|
@ -75,7 +75,7 @@ class MainViewModel @Inject constructor(private val application : Application,
|
||||||
if(tunnelRepo.count() == 1L) {
|
if(tunnelRepo.count() == 1L) {
|
||||||
ServiceManager.stopWatcherService(application.applicationContext)
|
ServiceManager.stopWatcherService(application.applicationContext)
|
||||||
val settings = settingsRepo.getAll()
|
val settings = settingsRepo.getAll()
|
||||||
if(!settings.isNullOrEmpty()) {
|
if(settings.isNotEmpty()) {
|
||||||
val setting = settings[0]
|
val setting = settings[0]
|
||||||
setting.defaultTunnel = null
|
setting.defaultTunnel = null
|
||||||
setting.isAutoTunnelEnabled = false
|
setting.isAutoTunnelEnabled = false
|
||||||
|
@ -99,7 +99,7 @@ class MainViewModel @Inject constructor(private val application : Application,
|
||||||
suspend fun onTunnelQRSelected() {
|
suspend fun onTunnelQRSelected() {
|
||||||
codeScanner.scan().collect {
|
codeScanner.scan().collect {
|
||||||
if(!it.isNullOrEmpty() && it.contains(application.resources.getString(R.string.config_validation))) {
|
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)
|
saveTunnel(tunnelConfig)
|
||||||
} else if(!it.isNullOrEmpty() && it.contains(application.resources.getString(R.string.barcode_downloading))) {
|
} else if(!it.isNullOrEmpty() && it.contains(application.resources.getString(R.string.barcode_downloading))) {
|
||||||
showSnackBarMessage(application.resources.getString(R.string.barcode_downloading_message))
|
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) {
|
fun onTunnelFileSelected(uri : Uri) {
|
||||||
try {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val fileName = getFileName(application.applicationContext, uri)
|
try {
|
||||||
val extension = getFileExtensionFromFileName(fileName)
|
val fileName = getFileName(application.applicationContext, uri)
|
||||||
if(extension != ".conf") {
|
val extension = getFileExtensionFromFileName(fileName)
|
||||||
viewModelScope.launch {
|
if (extension != ".conf") {
|
||||||
showSnackBarMessage(application.resources.getString(R.string.file_extension_message))
|
launch {
|
||||||
|
showSnackBarMessage(application.resources.getString(R.string.file_extension_message))
|
||||||
|
}
|
||||||
|
return@launch
|
||||||
}
|
}
|
||||||
return
|
val stream = application.applicationContext.contentResolver.openInputStream(uri)
|
||||||
}
|
stream ?: return@launch
|
||||||
val stream = application.applicationContext.contentResolver.openInputStream(uri)
|
val bufferReader = stream.bufferedReader(charset = Charsets.UTF_8)
|
||||||
stream ?: return
|
|
||||||
val bufferReader = stream.bufferedReader(charset = Charsets.UTF_8)
|
|
||||||
val config = Config.parse(bufferReader)
|
val config = Config.parse(bufferReader)
|
||||||
val tunnelName = getNameFromFileName(fileName)
|
val tunnelName = getNameFromFileName(fileName)
|
||||||
saveTunnel(TunnelConfig(name = tunnelName, wgQuick = config.toWgQuickString()))
|
saveTunnel(TunnelConfig(name = tunnelName, wgQuick = config.toWgQuickString()))
|
||||||
stream.close()
|
stream.close()
|
||||||
} catch(_: BadConfigException) {
|
} catch (_: BadConfigException) {
|
||||||
viewModelScope.launch {
|
launch {
|
||||||
showSnackBarMessage(application.applicationContext.getString(R.string.bad_config))
|
showSnackBarMessage(application.applicationContext.getString(R.string.bad_config))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveTunnel(tunnelConfig : TunnelConfig) {
|
private suspend fun saveTunnel(tunnelConfig : TunnelConfig) {
|
||||||
viewModelScope.launch {
|
tunnelRepo.save(tunnelConfig)
|
||||||
tunnelRepo.save(tunnelConfig)
|
ShortcutsManager.createTunnelShortcuts(application.applicationContext, tunnelConfig)
|
||||||
ShortcutsManager.createTunnelShortcuts(application.applicationContext, tunnelConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("Range")
|
@SuppressLint("Range")
|
||||||
|
@ -149,14 +149,14 @@ class MainViewModel @Inject constructor(private val application : Application,
|
||||||
Timber.d("Exception getting config name")
|
Timber.d("Exception getting config name")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
cursor ?: return defaultConfigName()
|
cursor ?: return NumberUtils.generateRandomTunnelName()
|
||||||
cursor.use {
|
cursor.use {
|
||||||
if(cursor.moveToFirst()) {
|
if(cursor.moveToFirst()) {
|
||||||
return cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
|
return cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return defaultConfigName()
|
return NumberUtils.generateRandomTunnelName()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun showSnackBarMessage(message : String) {
|
suspend fun showSnackBarMessage(message : String) {
|
||||||
|
@ -170,7 +170,7 @@ class MainViewModel @Inject constructor(private val application : Application,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
delay(3000)
|
delay(Constants.SNACKBAR_DELAY)
|
||||||
dismissSnackBar()
|
dismissSnackBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ import com.google.accompanist.permissions.isGranted
|
||||||
import com.google.accompanist.permissions.rememberPermissionState
|
import com.google.accompanist.permissions.rememberPermissionState
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
import com.zaneschepke.wireguardautotunnel.R
|
||||||
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
|
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.Routes
|
||||||
import com.zaneschepke.wireguardautotunnel.ui.common.ClickableIconButton
|
import com.zaneschepke.wireguardautotunnel.ui.common.ClickableIconButton
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
|
@ -6,35 +6,41 @@ import android.location.LocationManager
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.zaneschepke.wireguardautotunnel.R
|
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.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 com.zaneschepke.wireguardautotunnel.ui.ViewState
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class SettingsViewModel @Inject constructor(private val application : Application,
|
class SettingsViewModel @Inject constructor(private val application : Application,
|
||||||
private val tunnelRepo : Repository<TunnelConfig>, private val settingsRepo : Repository<Settings>
|
private val tunnelRepo : TunnelConfigDao, private val settingsRepo : SettingsDoa
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val _trustedSSIDs = MutableStateFlow(emptyList<String>())
|
private val _trustedSSIDs = MutableStateFlow(emptyList<String>())
|
||||||
val trustedSSIDs = _trustedSSIDs.asStateFlow()
|
val trustedSSIDs = _trustedSSIDs.asStateFlow()
|
||||||
private val _settings = MutableStateFlow(Settings())
|
private val _settings = MutableStateFlow(Settings())
|
||||||
val settings get() = _settings.asStateFlow()
|
val settings get() = _settings.asStateFlow()
|
||||||
val tunnels get() = tunnelRepo.itemFlow
|
val tunnels get() = tunnelRepo.getAllFlow()
|
||||||
private val _viewState = MutableStateFlow(ViewState())
|
private val _viewState = MutableStateFlow(ViewState())
|
||||||
val viewState get() = _viewState.asStateFlow()
|
val viewState get() = _viewState.asStateFlow()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
checkLocationServicesEnabled()
|
checkLocationServicesEnabled()
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
settingsRepo.itemFlow.collect {
|
settingsRepo.getAllFlow().filter { it.isNotEmpty() }.collect {
|
||||||
val settings = it.first()
|
val settings = it.first()
|
||||||
_settings.emit(settings)
|
_settings.emit(settings)
|
||||||
_trustedSSIDs.emit(settings.trustedNetworkSSIDs.toList())
|
_trustedSSIDs.emit(settings.trustedNetworkSSIDs.toList())
|
||||||
|
|
|
@ -13,6 +13,10 @@ object NumberUtils {
|
||||||
return bytes.toBigDecimal().divide(BYTES_IN_KB.toBigDecimal())
|
return bytes.toBigDecimal().divide(BYTES_IN_KB.toBigDecimal())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun generateRandomTunnelName() : String {
|
||||||
|
return "tunnel${(Math.random() * 100000).toInt()}"
|
||||||
|
}
|
||||||
|
|
||||||
fun formatDecimalTwoPlaces(bigDecimal: BigDecimal) : String {
|
fun formatDecimalTwoPlaces(bigDecimal: BigDecimal) : String {
|
||||||
val df = DecimalFormat("#.##")
|
val df = DecimalFormat("#.##")
|
||||||
return df.format(bigDecimal)
|
return df.format(bigDecimal)
|
||||||
|
|
|
@ -91,4 +91,5 @@
|
||||||
<string name="search_icon">Search Icon</string>
|
<string name="search_icon">Search Icon</string>
|
||||||
<string name="attempt_connection">Attempting connection..</string>
|
<string name="attempt_connection">Attempting connection..</string>
|
||||||
<string name="vpn_starting">VPN Starting</string>
|
<string name="vpn_starting">VPN Starting</string>
|
||||||
|
<string name="db_name">wg-tunnel-db</string>
|
||||||
</resources>
|
</resources>
|
|
@ -1,20 +1,18 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
val objectBoxVersion by extra("3.7.0")
|
|
||||||
val hiltVersion by extra("2.48")
|
|
||||||
val accompanistVersion by extra("0.31.2-alpha")
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("io.objectbox:objectbox-gradle-plugin:$objectBoxVersion")
|
if (BuildHelper.isReleaseBuild(gradle) && BuildHelper.isGeneralFlavor(gradle)) {
|
||||||
classpath("com.google.gms:google-services:4.3.15")
|
classpath(libs.google.services)
|
||||||
classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.9")
|
classpath(libs.firebase.crashlytics.gradle)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application") version "8.2.0-beta03" apply false
|
alias(libs.plugins.android.application) apply false
|
||||||
id("org.jetbrains.kotlin.android") version "1.8.22" apply false
|
alias(libs.plugins.kotlin.android) apply false
|
||||||
id("com.google.dagger.hilt.android") version "2.48" apply false
|
alias(libs.plugins.hilt.android) apply false
|
||||||
kotlin("plugin.serialization") version "1.8.22" apply false
|
kotlin("plugin.serialization").version(libs.versions.kotlin).apply(false)
|
||||||
|
alias(libs.plugins.ksp) apply false
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
plugins {
|
||||||
|
`kotlin-dsl` // enable the Kotlin-DSL
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
|
@ -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"))
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,5 +21,3 @@ kotlin.code.style=official
|
||||||
# resources declared in the library itself and none from the library's dependencies,
|
# resources declared in the library itself and none from the library's dependencies,
|
||||||
# thereby reducing the size of the R class for that library
|
# thereby reducing the size of the R class for that library
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
#enable buildconfig values
|
|
||||||
android.defaults.buildfeatures.buildconfig=true
|
|
|
@ -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" }
|
Loading…
Reference in New Issue