feat: migrate to forked lib
Migrated app to a forked version of wireguard-android to enable development work on features that require changes to the core lib, like #107 #104 #87 #52 #6 Improved first launch flow by change vpn permission to only launch on first tunnel start Changed to proper database seeding strategy Updated README to account for GitHub packages auth requirement Migrated from deprecated UI components and libs Bump versions
This commit is contained in:
parent
500b85f687
commit
2690ce29e1
|
@ -19,6 +19,8 @@ jobs:
|
|||
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }}
|
||||
KEY_STORE_FILE: 'android_keystore.jks'
|
||||
KEY_STORE_LOCATION: ${{ github.workspace }}/app/keystore/
|
||||
GH_USER: ${{ secrets.GH_USER }}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
|
@ -20,6 +20,8 @@ jobs:
|
|||
SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }}
|
||||
KEY_STORE_FILE: 'android_keystore.jks'
|
||||
KEY_STORE_LOCATION: ${{ github.workspace }}/app/keystore/
|
||||
GH_USER: ${{ secrets.GH_USER }}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
25
README.md
25
README.md
|
@ -71,6 +71,31 @@ The repository for these docs can be found [here](https://github.com/zaneschepke
|
|||
```
|
||||
$ git clone https://github.com/zaneschepke/wgtunnel
|
||||
$ cd wgtunnel
|
||||
```
|
||||
|
||||
Create a personal access token (classic) in GitHuv to be able to pull the wireguard-android github dependencies from GitHub packages
|
||||
as documented [here](https://docs.github.com/en/packages/learn-github-packages/introduction-to-github-packages#authenticating-to-github-packages).
|
||||
|
||||
Alternatively, you can clone [wireguard-android](https://github.com/zaneschepke/wireguard-android) and run the following command to publish the dependency to your local maven repository (requires you have maven installed). This is the ideal approach
|
||||
if you intent to make changes to this lib.
|
||||
|
||||
```
|
||||
$ git clone https://github.com/zaneschepke/wireguard-android
|
||||
$ cd wireguard-android
|
||||
$ brew install maven
|
||||
$ ./gradlew publishToMavenLocal
|
||||
```
|
||||
|
||||
The [wireguard-android](https://github.com/zaneschepke/wireguard-android) dependency is a fork of the official [wireguard-android](https://github.com/WireGuard/wireguard-android) library.
|
||||
|
||||
Add the following lines to local.properties file:
|
||||
```
|
||||
GH_USER=<your github username>
|
||||
GH_TOKEN=<the personal access token with read package permission you just created>
|
||||
```
|
||||
|
||||
And then build the app:
|
||||
```
|
||||
$ ./gradlew assembleDebug
|
||||
```
|
||||
|
||||
|
|
|
@ -156,13 +156,14 @@ dependencies {
|
|||
debugImplementation(libs.androidx.compose.ui.tooling)
|
||||
debugImplementation(libs.androidx.compose.manifest)
|
||||
|
||||
// wg
|
||||
// get tunnel lib from github packages or mavenLocal
|
||||
implementation(libs.tunnel)
|
||||
coreLibraryDesugaring(libs.desugar.jdk.libs)
|
||||
|
||||
// logging
|
||||
implementation(libs.timber)
|
||||
|
||||
|
||||
// compose navigation
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
implementation(libs.androidx.hilt.navigation.compose)
|
||||
|
@ -172,7 +173,6 @@ dependencies {
|
|||
ksp(libs.hilt.android.compiler)
|
||||
|
||||
// accompanist
|
||||
implementation(libs.accompanist.systemuicontroller)
|
||||
implementation(libs.accompanist.permissions)
|
||||
implementation(libs.accompanist.flowlayout)
|
||||
implementation(libs.accompanist.drawablepainter)
|
||||
|
|
|
@ -4,6 +4,7 @@ import androidx.room.testing.MigrationTestHelper
|
|||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.zaneschepke.wireguardautotunnel.data.AppDatabase
|
||||
import com.zaneschepke.wireguardautotunnel.data.Queries
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
@ -26,33 +27,7 @@ class MigrationTest {
|
|||
helper.createDatabase(dbName, 4).apply {
|
||||
// Database has schema version 1. Insert some data using SQL queries.
|
||||
// You can't use DAO classes because they expect the latest schema.
|
||||
execSQL(
|
||||
"INSERT INTO Settings (is_tunnel_enabled," +
|
||||
"is_tunnel_on_mobile_data_enabled," +
|
||||
"trusted_network_ssids," +
|
||||
"default_tunnel," +
|
||||
"is_always_on_vpn_enabled," +
|
||||
"is_tunnel_on_ethernet_enabled," +
|
||||
"is_shortcuts_enabled," +
|
||||
"is_battery_saver_enabled," +
|
||||
"is_tunnel_on_wifi_enabled," +
|
||||
"is_kernel_enabled," +
|
||||
"is_restore_on_boot_enabled," +
|
||||
"is_multi_tunnel_enabled)" +
|
||||
" VALUES " +
|
||||
"('false'," +
|
||||
"'false'," +
|
||||
"'[trustedSSID1,trustedSSID2]'," +
|
||||
"'defaultTunnel'," +
|
||||
"'false'," +
|
||||
"'false'," +
|
||||
"'false'," +
|
||||
"'false'," +
|
||||
"'false'," +
|
||||
"'false'," +
|
||||
"'false'," +
|
||||
"'false')",
|
||||
)
|
||||
execSQL(Queries.createDefaultSettings())
|
||||
execSQL(
|
||||
"INSERT INTO TunnelConfig (name, wg_quick)" + " VALUES ('hello', 'hello')",
|
||||
)
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.zaneschepke.wireguardautotunnel.data
|
||||
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import timber.log.Timber
|
||||
|
||||
class DatabaseCallback : RoomDatabase.Callback() {
|
||||
override fun onCreate(db: SupportSQLiteDatabase) = db.run {
|
||||
// Notice non-ui thread is here
|
||||
beginTransaction()
|
||||
try {
|
||||
execSQL(Queries.createDefaultSettings())
|
||||
Timber.i("Bootstrapping settings data")
|
||||
setTransactionSuccessful()
|
||||
} catch (e : Exception) {
|
||||
Timber.e(e)
|
||||
} finally {
|
||||
endTransaction()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.zaneschepke.wireguardautotunnel.data
|
||||
|
||||
object Queries {
|
||||
fun createDefaultSettings() : String {
|
||||
return """
|
||||
INSERT INTO Settings (is_tunnel_enabled,
|
||||
is_tunnel_on_mobile_data_enabled,
|
||||
trusted_network_ssids,
|
||||
default_tunnel,
|
||||
is_always_on_vpn_enabled,
|
||||
is_tunnel_on_ethernet_enabled,
|
||||
is_shortcuts_enabled,
|
||||
is_battery_saver_enabled,
|
||||
is_tunnel_on_wifi_enabled,
|
||||
is_kernel_enabled,
|
||||
is_restore_on_boot_enabled,
|
||||
is_multi_tunnel_enabled)
|
||||
VALUES
|
||||
('false',
|
||||
'false',
|
||||
'[trustedSSID1,trustedSSID2]',
|
||||
NULL,
|
||||
'false',
|
||||
'false',
|
||||
'false',
|
||||
'false',
|
||||
'false',
|
||||
'false',
|
||||
'false',
|
||||
'false')
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
|||
import androidx.room.Room
|
||||
import com.zaneschepke.wireguardautotunnel.R
|
||||
import com.zaneschepke.wireguardautotunnel.data.AppDatabase
|
||||
import com.zaneschepke.wireguardautotunnel.data.DatabaseCallback
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
@ -23,6 +24,7 @@ class DatabaseModule {
|
|||
context.getString(R.string.db_name),
|
||||
)
|
||||
.fallbackToDestructiveMigration()
|
||||
.addCallback(DatabaseCallback())
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.zaneschepke.wireguardautotunnel.data.repository.TunnelConfigRepositor
|
|||
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
|
||||
import com.zaneschepke.wireguardautotunnel.util.goAsync
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
|
@ -21,8 +22,10 @@ class BootReceiver : BroadcastReceiver() {
|
|||
if (Intent.ACTION_BOOT_COMPLETED != intent?.action) return@goAsync
|
||||
val settings = settingsRepository.getSettings()
|
||||
if (settings.isAutoTunnelEnabled) {
|
||||
Timber.i("Starting watcher service from boot")
|
||||
ServiceManager.startWatcherServiceForeground(context!!)
|
||||
} else if(settings.isAlwaysOnVpnEnabled) {
|
||||
Timber.i("Starting tunnel from boot")
|
||||
ServiceManager.startVpnServicePrimaryTunnel(context!!, settings, tunnelConfigRepository.getAll().firstOrNull())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,12 +152,16 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
|
|||
wakeLock =
|
||||
(getSystemService(Context.POWER_SERVICE) as PowerManager).run {
|
||||
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "$tag::lock").apply {
|
||||
if (isBatterySaverOn) {
|
||||
Timber.d("Initiating wakelock with timeout")
|
||||
acquire(Constants.BATTERY_SAVER_WATCHER_WAKE_LOCK_TIMEOUT)
|
||||
} else {
|
||||
Timber.d("Initiating wakelock with zero timeout")
|
||||
acquire(Constants.DEFAULT_WATCHER_WAKE_LOCK_TIMEOUT)
|
||||
try {
|
||||
if (isBatterySaverOn) {
|
||||
Timber.d("Initiating wakelock with timeout")
|
||||
acquire(Constants.BATTERY_SAVER_WATCHER_WAKE_LOCK_TIMEOUT)
|
||||
} else {
|
||||
Timber.d("Initiating wakelock with zero timeout")
|
||||
acquire(Constants.DEFAULT_WATCHER_WAKE_LOCK_TIMEOUT)
|
||||
}
|
||||
} finally {
|
||||
release()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import javax.inject.Inject
|
|||
class WireGuardTunnel
|
||||
@Inject
|
||||
constructor(
|
||||
@Userspace private val userspaceBackend: Backend,
|
||||
@Userspace private val userspaceBackend : Backend,
|
||||
@Kernel private val kernelBackend: Backend,
|
||||
private val settingsRepository: SettingsRepository
|
||||
) : VpnService {
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package com.zaneschepke.wireguardautotunnel.ui
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.zaneschepke.wireguardautotunnel.data.SettingsDao
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class ActivityViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
private val settingsRepo: SettingsDao,
|
||||
) : ViewModel() {}
|
||||
constructor() : ViewModel() {
|
||||
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@ import android.net.Uri
|
|||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.SystemBarStyle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SnackbarData
|
||||
|
@ -20,13 +22,12 @@ import androidx.compose.material3.SnackbarHostState
|
|||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.material3.surfaceColorAtElevation
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusProperties
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.compose.NavHost
|
||||
|
@ -35,7 +36,6 @@ import androidx.navigation.compose.rememberNavController
|
|||
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.R
|
||||
import com.zaneschepke.wireguardautotunnel.WireGuardAutoTunnel
|
||||
import com.zaneschepke.wireguardautotunnel.data.datastore.DataStoreManager
|
||||
|
@ -47,7 +47,6 @@ import com.zaneschepke.wireguardautotunnel.ui.screens.config.ConfigScreen
|
|||
import com.zaneschepke.wireguardautotunnel.ui.screens.main.MainScreen
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.settings.SettingsScreen
|
||||
import com.zaneschepke.wireguardautotunnel.ui.screens.support.SupportScreen
|
||||
import com.zaneschepke.wireguardautotunnel.ui.theme.TransparentSystemBars
|
||||
import com.zaneschepke.wireguardautotunnel.ui.theme.WireguardAutoTunnelTheme
|
||||
import com.zaneschepke.wireguardautotunnel.util.Constants
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
@ -70,6 +69,8 @@ class MainActivity : AppCompatActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
enableEdgeToEdge(navigationBarStyle = SystemBarStyle.dark(Color.Transparent.toArgb()))
|
||||
|
||||
// load preferences into memory and init data
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
|
@ -80,13 +81,12 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
setContent {
|
||||
// val activityViewModel = hiltViewModel<ActivityViewModel>()
|
||||
//val activityViewModel = hiltViewModel<ActivityViewModel>()
|
||||
|
||||
val navController = rememberNavController()
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
|
||||
WireguardAutoTunnelTheme {
|
||||
TransparentSystemBars()
|
||||
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
|
||||
|
@ -134,9 +134,11 @@ class MainActivity : AppCompatActivity() {
|
|||
)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.focusable().focusProperties { up = focusRequester },
|
||||
modifier = Modifier
|
||||
.focusable()
|
||||
.focusProperties { up = focusRequester },
|
||||
bottomBar =
|
||||
if (notificationPermissionState != null && notificationPermissionState.status.isGranted) {
|
||||
if (notificationPermissionState == null || notificationPermissionState.status.isGranted) {
|
||||
{
|
||||
BottomNavBar(
|
||||
navController,
|
||||
|
@ -151,66 +153,64 @@ class MainActivity : AppCompatActivity() {
|
|||
{}
|
||||
},
|
||||
) { padding ->
|
||||
if (notificationPermissionState != null && !notificationPermissionState.status.isGranted) {
|
||||
PermissionRequestFailedScreen(
|
||||
padding = padding,
|
||||
onRequestAgain = {
|
||||
val intentSettings =
|
||||
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intentSettings.data =
|
||||
Uri.fromParts(
|
||||
Constants.URI_PACKAGE_SCHEME,
|
||||
this.packageName,
|
||||
null,
|
||||
)
|
||||
startActivity(intentSettings)
|
||||
},
|
||||
message = getString(R.string.notification_permission_required),
|
||||
getString(R.string.open_settings),
|
||||
)
|
||||
return@Scaffold
|
||||
}
|
||||
NavHost(navController, startDestination = Screen.Main.route) {
|
||||
composable(
|
||||
Screen.Main.route,
|
||||
) {
|
||||
MainScreen(
|
||||
padding = padding,
|
||||
focusRequester = focusRequester,
|
||||
showSnackbarMessage = { message -> showSnackBarMessage(message) },
|
||||
navController = navController,
|
||||
Column(modifier = Modifier.padding(padding)) {
|
||||
if (notificationPermissionState != null && !notificationPermissionState.status.isGranted) {
|
||||
PermissionRequestFailedScreen(
|
||||
onRequestAgain = {
|
||||
val intentSettings =
|
||||
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intentSettings.data =
|
||||
Uri.fromParts(
|
||||
Constants.URI_PACKAGE_SCHEME,
|
||||
this@MainActivity.packageName,
|
||||
null,
|
||||
)
|
||||
startActivity(intentSettings)
|
||||
},
|
||||
message = getString(R.string.notification_permission_required),
|
||||
getString(R.string.open_settings),
|
||||
)
|
||||
return@Scaffold
|
||||
}
|
||||
composable(
|
||||
Screen.Settings.route,
|
||||
) {
|
||||
SettingsScreen(
|
||||
padding = padding,
|
||||
showSnackbarMessage = { message -> showSnackBarMessage(message) },
|
||||
focusRequester = focusRequester,
|
||||
)
|
||||
}
|
||||
composable(
|
||||
Screen.Support.route,
|
||||
) {
|
||||
SupportScreen(
|
||||
padding = padding,
|
||||
focusRequester = focusRequester,
|
||||
showSnackbarMessage = { message -> showSnackBarMessage(message) },
|
||||
)
|
||||
}
|
||||
composable("${Screen.Config.route}/{id}") {
|
||||
val id = it.arguments?.getString("id")
|
||||
if (!id.isNullOrBlank()) {
|
||||
ConfigScreen(
|
||||
NavHost(navController, startDestination = Screen.Main.route) {
|
||||
composable(
|
||||
Screen.Main.route,
|
||||
) {
|
||||
MainScreen(
|
||||
focusRequester = focusRequester,
|
||||
showSnackbarMessage = { message -> showSnackBarMessage(message) },
|
||||
navController = navController,
|
||||
id = id,
|
||||
showSnackbarMessage = { message ->
|
||||
showSnackBarMessage(message)
|
||||
},
|
||||
)
|
||||
}
|
||||
composable(
|
||||
Screen.Settings.route,
|
||||
) {
|
||||
SettingsScreen(
|
||||
showSnackbarMessage = { message -> showSnackBarMessage(message) },
|
||||
focusRequester = focusRequester,
|
||||
)
|
||||
}
|
||||
composable(
|
||||
Screen.Support.route,
|
||||
) {
|
||||
SupportScreen(
|
||||
focusRequester = focusRequester,
|
||||
showSnackbarMessage = { message -> showSnackBarMessage(message) },
|
||||
)
|
||||
}
|
||||
composable("${Screen.Config.route}/{id}") {
|
||||
val id = it.arguments?.getString("id")
|
||||
if (!id.isNullOrBlank()) {
|
||||
ConfigScreen(
|
||||
navController = navController,
|
||||
id = id,
|
||||
showSnackbarMessage = { message ->
|
||||
showSnackBarMessage(message)
|
||||
},
|
||||
focusRequester = focusRequester,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.zaneschepke.wireguardautotunnel.ui.common
|
|||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
|
@ -17,7 +16,6 @@ import kotlinx.coroutines.launch
|
|||
|
||||
@Composable
|
||||
fun PermissionRequestFailedScreen(
|
||||
padding: PaddingValues,
|
||||
onRequestAgain: () -> Unit,
|
||||
message: String,
|
||||
buttonText: String
|
||||
|
@ -26,7 +24,7 @@ fun PermissionRequestFailedScreen(
|
|||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = Modifier.fillMaxSize().padding(padding),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
Text(message, textAlign = TextAlign.Center, modifier = Modifier.padding(15.dp))
|
||||
Button(
|
||||
|
|
|
@ -19,7 +19,6 @@ import androidx.compose.runtime.CompositionLocalProvider
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
|
@ -33,7 +32,6 @@ fun CustomSnackBar(
|
|||
isRtl: Boolean = true,
|
||||
containerColor: Color = MaterialTheme.colorScheme.surface
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
Snackbar(
|
||||
containerColor = containerColor,
|
||||
modifier =
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.zaneschepke.wireguardautotunnel.ui.screens.config
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.focusGroup
|
||||
|
@ -29,7 +28,7 @@ import androidx.compose.material.icons.rounded.ContentCopy
|
|||
import androidx.compose.material.icons.rounded.Delete
|
||||
import androidx.compose.material.icons.rounded.Refresh
|
||||
import androidx.compose.material.icons.rounded.Save
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.BasicAlertDialog
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FabPosition
|
||||
|
@ -51,7 +50,6 @@ import androidx.compose.runtime.mutableStateOf
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
|
@ -86,9 +84,7 @@ import kotlinx.coroutines.delay
|
|||
|
||||
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
||||
@OptIn(
|
||||
ExperimentalComposeUiApi::class,
|
||||
ExperimentalMaterial3Api::class,
|
||||
ExperimentalFoundationApi::class,
|
||||
)
|
||||
@Composable
|
||||
fun ConfigScreen(
|
||||
|
@ -145,7 +141,7 @@ fun ConfigScreen(
|
|||
showAuthPrompt = false
|
||||
isAuthenticated = true
|
||||
},
|
||||
onError = { error ->
|
||||
onError = {
|
||||
showAuthPrompt = false
|
||||
showSnackbarMessage(Event.Error.AuthenticationFailed.message)
|
||||
},
|
||||
|
@ -161,20 +157,20 @@ fun ConfigScreen(
|
|||
remember(uiState.packages) {
|
||||
uiState.packages.sortedBy { viewModel.getPackageLabel(it) }
|
||||
}
|
||||
AlertDialog(onDismissRequest = { showApplicationsDialog = false }) {
|
||||
BasicAlertDialog(onDismissRequest = { showApplicationsDialog = false }) {
|
||||
Surface(
|
||||
tonalElevation = 2.dp,
|
||||
shadowElevation = 2.dp,
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
color = MaterialTheme.colorScheme.surface,
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
.fillMaxHeight(if (uiState.isAllApplicationsEnabled) 1 / 5f else 4 / 5f),
|
||||
Modifier.fillMaxWidth()
|
||||
.fillMaxHeight(if (uiState.isAllApplicationsEnabled) 1 / 5f else 4 / 5f),
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
Row(
|
||||
modifier =
|
||||
Modifier.fillMaxWidth().padding(horizontal = 20.dp, vertical = 7.dp),
|
||||
Modifier.fillMaxWidth().padding(horizontal = 20.dp, vertical = 7.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
|
@ -187,8 +183,8 @@ fun ConfigScreen(
|
|||
if (!uiState.isAllApplicationsEnabled) {
|
||||
Row(
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp, vertical = 7.dp),
|
||||
Modifier.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp, vertical = 7.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
|
@ -219,8 +215,8 @@ fun ConfigScreen(
|
|||
}
|
||||
Row(
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp, vertical = 7.dp),
|
||||
Modifier.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp, vertical = 7.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
|
@ -262,9 +258,9 @@ fun ConfigScreen(
|
|||
Checkbox(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
checked =
|
||||
(uiState.checkedPackageNames.contains(
|
||||
pack.packageName
|
||||
)),
|
||||
(uiState.checkedPackageNames.contains(
|
||||
pack.packageName
|
||||
)),
|
||||
onCheckedChange = {
|
||||
if (it) {
|
||||
viewModel.onAddCheckedPackage(pack.packageName)
|
||||
|
@ -299,7 +295,7 @@ fun ConfigScreen(
|
|||
var fobColor by remember { mutableStateOf(secondaryColor) }
|
||||
FloatingActionButton(
|
||||
modifier =
|
||||
Modifier.padding(bottom = 90.dp).onFocusChanged {
|
||||
Modifier.onFocusChanged {
|
||||
if (WireGuardAutoTunnel.isRunningOnAndroidTv()) {
|
||||
fobColor = if (it.isFocused) hoverColor else secondaryColor
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.zaneschepke.wireguardautotunnel.ui.screens.main
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
|
@ -20,7 +19,6 @@ import androidx.compose.foundation.gestures.ScrollableDefaults
|
|||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
|
@ -45,10 +43,10 @@ import androidx.compose.material.icons.rounded.Edit
|
|||
import androidx.compose.material.icons.rounded.Info
|
||||
import androidx.compose.material.icons.rounded.Star
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FabPosition
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
|
@ -110,12 +108,10 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun MainScreen(
|
||||
viewModel: MainViewModel = hiltViewModel(),
|
||||
padding: PaddingValues,
|
||||
focusRequester: FocusRequester,
|
||||
showSnackbarMessage: (String) -> Unit,
|
||||
navController: NavController
|
||||
|
@ -344,7 +340,6 @@ fun MainScreen(
|
|||
)
|
||||
Modifier.focusRequester(focusRequester)
|
||||
else Modifier)
|
||||
.padding(bottom = 90.dp)
|
||||
.onFocusChanged {
|
||||
if (WireGuardAutoTunnel.isRunningOnAndroidTv()) {
|
||||
fobColor = if (it.isFocused) hoverColor else secondaryColor
|
||||
|
@ -367,7 +362,7 @@ fun MainScreen(
|
|||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = Modifier.fillMaxSize().padding(padding),
|
||||
modifier = Modifier.fillMaxSize().padding(innerPadding),
|
||||
) {
|
||||
Text(text = stringResource(R.string.no_tunnels), fontStyle = FontStyle.Italic)
|
||||
}
|
||||
|
@ -398,7 +393,7 @@ fun MainScreen(
|
|||
)
|
||||
}
|
||||
if (!WireGuardAutoTunnel.isRunningOnAndroidTv()) {
|
||||
Divider()
|
||||
HorizontalDivider()
|
||||
Row(
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
|
@ -430,7 +425,7 @@ fun MainScreen(
|
|||
)
|
||||
}
|
||||
}
|
||||
Divider()
|
||||
HorizontalDivider()
|
||||
Row(
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
|
@ -461,8 +456,7 @@ fun MainScreen(
|
|||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
.fillMaxHeight(.90f)
|
||||
.overscroll(ScrollableDefaults.overscrollEffect())
|
||||
.padding(innerPadding),
|
||||
.overscroll(ScrollableDefaults.overscrollEffect()),
|
||||
state = rememberLazyListState(0, uiState.tunnels.count()),
|
||||
userScrollEnabled = true,
|
||||
reverseLayout = true,
|
||||
|
|
|
@ -20,7 +20,6 @@ import androidx.compose.foundation.layout.Column
|
|||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
|
@ -95,7 +94,6 @@ import java.io.File
|
|||
@Composable
|
||||
fun SettingsScreen(
|
||||
viewModel: SettingsViewModel = hiltViewModel(),
|
||||
padding: PaddingValues,
|
||||
showSnackbarMessage: (String) -> Unit,
|
||||
focusRequester: FocusRequester
|
||||
) {
|
||||
|
@ -127,7 +125,7 @@ fun SettingsScreen(
|
|||
rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
result: ActivityResult ->
|
||||
if (result.resultCode == Activity.RESULT_OK) {
|
||||
val intent = result.data
|
||||
result.data
|
||||
// Handle the Intent
|
||||
}
|
||||
viewModel.setBatteryOptimizeDisableShown()
|
||||
|
@ -248,7 +246,7 @@ fun SettingsScreen(
|
|||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Top,
|
||||
modifier = Modifier.fillMaxSize().verticalScroll(scrollState).padding(padding),
|
||||
modifier = Modifier.fillMaxSize().verticalScroll(scrollState),
|
||||
) {
|
||||
Icon(
|
||||
Icons.Rounded.LocationOff,
|
||||
|
@ -314,7 +312,7 @@ fun SettingsScreen(
|
|||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
modifier = Modifier.fillMaxSize().padding(padding),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
Text(
|
||||
stringResource(R.string.one_tunnel_required),
|
||||
|
@ -347,7 +345,7 @@ fun SettingsScreen(
|
|||
.fillMaxWidth(fillMaxWidth)
|
||||
.padding(top = 10.dp)
|
||||
} else {
|
||||
Modifier.fillMaxWidth(fillMaxWidth).padding(top = 60.dp)
|
||||
Modifier.fillMaxWidth(fillMaxWidth).padding(top = 20.dp)
|
||||
})
|
||||
.padding(bottom = 10.dp),
|
||||
) {
|
||||
|
|
|
@ -8,7 +8,6 @@ import androidx.compose.foundation.focusable
|
|||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
|
@ -20,10 +19,10 @@ import androidx.compose.foundation.rememberScrollState
|
|||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.ArrowForward
|
||||
import androidx.compose.material.icons.automirrored.rounded.ArrowForward
|
||||
import androidx.compose.material.icons.rounded.Book
|
||||
import androidx.compose.material.icons.rounded.Mail
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
|
@ -58,7 +57,6 @@ import com.zaneschepke.wireguardautotunnel.util.Event
|
|||
@Composable
|
||||
fun SupportScreen(
|
||||
viewModel: SupportViewModel = hiltViewModel(),
|
||||
padding: PaddingValues,
|
||||
showSnackbarMessage: (String) -> Unit,
|
||||
focusRequester: FocusRequester
|
||||
) {
|
||||
|
@ -107,7 +105,6 @@ fun SupportScreen(
|
|||
Modifier.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.focusable()
|
||||
.padding(padding),
|
||||
) {
|
||||
Surface(
|
||||
tonalElevation = 2.dp,
|
||||
|
@ -155,10 +152,16 @@ fun SupportScreen(
|
|||
modifier = Modifier.padding(start = 10.dp),
|
||||
)
|
||||
}
|
||||
Icon(Icons.Rounded.ArrowForward, stringResource(id = R.string.go))
|
||||
Icon(
|
||||
Icons.AutoMirrored.Rounded.ArrowForward,
|
||||
stringResource(id = R.string.go)
|
||||
)
|
||||
}
|
||||
}
|
||||
Divider(color = MaterialTheme.colorScheme.onBackground, thickness = 0.5.dp)
|
||||
HorizontalDivider(
|
||||
thickness = 0.5.dp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
TextButton(
|
||||
onClick = { openWebPage(context.resources.getString(R.string.discord_url)) },
|
||||
modifier = Modifier.padding(vertical = 5.dp),
|
||||
|
@ -180,10 +183,16 @@ fun SupportScreen(
|
|||
modifier = Modifier.padding(start = 10.dp),
|
||||
)
|
||||
}
|
||||
Icon(Icons.Rounded.ArrowForward, stringResource(id = R.string.go))
|
||||
Icon(
|
||||
Icons.AutoMirrored.Rounded.ArrowForward,
|
||||
stringResource(id = R.string.go)
|
||||
)
|
||||
}
|
||||
}
|
||||
Divider(color = MaterialTheme.colorScheme.onBackground, thickness = 0.5.dp)
|
||||
HorizontalDivider(
|
||||
thickness = 0.5.dp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
TextButton(
|
||||
onClick = { openWebPage(context.resources.getString(R.string.github_url)) },
|
||||
modifier = Modifier.padding(vertical = 5.dp),
|
||||
|
@ -205,10 +214,16 @@ fun SupportScreen(
|
|||
modifier = Modifier.padding(start = 10.dp),
|
||||
)
|
||||
}
|
||||
Icon(Icons.Rounded.ArrowForward, stringResource(id = R.string.go))
|
||||
Icon(
|
||||
Icons.AutoMirrored.Rounded.ArrowForward,
|
||||
stringResource(id = R.string.go)
|
||||
)
|
||||
}
|
||||
}
|
||||
Divider(color = MaterialTheme.colorScheme.onBackground, thickness = 0.5.dp)
|
||||
HorizontalDivider(
|
||||
thickness = 0.5.dp,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
)
|
||||
TextButton(
|
||||
onClick = { launchEmail() },
|
||||
modifier = Modifier.padding(vertical = 5.dp),
|
||||
|
@ -226,7 +241,10 @@ fun SupportScreen(
|
|||
modifier = Modifier.padding(start = 10.dp),
|
||||
)
|
||||
}
|
||||
Icon(Icons.Rounded.ArrowForward, stringResource(id = R.string.go))
|
||||
Icon(
|
||||
Icons.AutoMirrored.Rounded.ArrowForward,
|
||||
stringResource(id = R.string.go)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
package com.zaneschepke.wireguardautotunnel.ui.theme
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
|
||||
@Composable
|
||||
fun TransparentSystemBars() {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val useDarkIcons = !isSystemInDarkTheme()
|
||||
|
||||
DisposableEffect(systemUiController, useDarkIcons) {
|
||||
systemUiController.setSystemBarsColor(
|
||||
color = Color.Transparent,
|
||||
darkIcons = useDarkIcons,
|
||||
)
|
||||
|
||||
onDispose {}
|
||||
}
|
||||
}
|
|
@ -140,7 +140,7 @@
|
|||
<string name="exported_configs_message">Exported configs to downloads</string>
|
||||
<string name="status">status</string>
|
||||
<string name="tunnel_on_wifi">Tunnel on untrusted wifi</string>
|
||||
<string name="my_email" translatable="false">zanecschepke@gmail.com</string>
|
||||
<string name="my_email" translatable="false">support@zaneschepke.com</string>
|
||||
<string name="email_subject">WG Tunnel Support</string>
|
||||
<string name="email_chooser">Send an email…</string>
|
||||
<string name="go">go</string>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import org.gradle.api.invocation.Gradle
|
||||
import java.io.File
|
||||
|
||||
object BuildHelper {
|
||||
private fun getCurrentFlavor(gradle: Gradle): String {
|
||||
|
@ -21,6 +22,17 @@ object BuildHelper {
|
|||
return flavor
|
||||
}
|
||||
|
||||
fun getLocalProperty(key: String, file: String = "local.properties"): String? {
|
||||
val properties = java.util.Properties()
|
||||
val localProperties = File(file)
|
||||
if (localProperties.isFile) {
|
||||
java.io.InputStreamReader(java.io.FileInputStream(localProperties), Charsets.UTF_8).use { reader ->
|
||||
properties.load(reader)
|
||||
}
|
||||
} else return null
|
||||
return properties.getProperty(key)
|
||||
}
|
||||
|
||||
fun isGeneralFlavor(gradle: Gradle): Boolean {
|
||||
return getCurrentFlavor(gradle) == "general"
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
object Constants {
|
||||
const val VERSION_NAME = "3.3.5"
|
||||
const val VERSION_NAME = "3.3.6"
|
||||
const val JVM_TARGET = "17"
|
||||
const val VERSION_CODE = 33500
|
||||
const val VERSION_CODE = 33600
|
||||
const val TARGET_SDK = 34
|
||||
const val MIN_SDK = 26
|
||||
const val APP_ID = "com.zaneschepke.wireguardautotunnel"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
What's new:
|
||||
- Improve first launch flow
|
||||
- Switch to wireguard lib fork
|
||||
- Request VPN permission on first VPN start
|
||||
- Bump versions
|
|
@ -10,35 +10,35 @@ datastorePreferences = "1.0.0"
|
|||
desugar_jdk_libs = "2.0.4"
|
||||
espressoCore = "3.5.1"
|
||||
firebase-crashlytics-gradle = "2.9.9"
|
||||
google-services = "4.4.0"
|
||||
google-services = "4.4.1"
|
||||
hiltAndroid = "2.50"
|
||||
hiltNavigationCompose = "1.1.0"
|
||||
junit = "4.13.2"
|
||||
kotlinx-serialization-json = "1.6.2"
|
||||
lifecycle-runtime-compose = "2.7.0"
|
||||
material3 = "1.2.0-rc01"
|
||||
navigationCompose = "2.7.6"
|
||||
material3 = "1.2.0"
|
||||
navigationCompose = "2.7.7"
|
||||
roomVersion = "2.6.1"
|
||||
timber = "5.0.1"
|
||||
tunnel = "1.0.20230706"
|
||||
androidGradlePlugin = "8.3.0-rc01"
|
||||
tunnel = "1.1.0"
|
||||
androidGradlePlugin = "8.3.0-rc02"
|
||||
kotlin = "1.9.22"
|
||||
ksp = "1.9.22-1.0.16"
|
||||
composeBom = "2024.01.00"
|
||||
firebaseBom = "32.7.1"
|
||||
compose = "1.6.0"
|
||||
crashlytics = "18.6.1"
|
||||
analytics = "21.5.0"
|
||||
composeBom = "2024.02.00"
|
||||
firebaseBom = "32.7.2"
|
||||
compose = "1.6.1"
|
||||
crashlytics = "18.6.2"
|
||||
analytics = "21.5.1"
|
||||
zxingAndroidEmbedded = "4.3.0"
|
||||
zxingCore = "3.5.2"
|
||||
zxingCore = "3.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-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" }
|
||||
accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" }
|
||||
|
||||
#room
|
||||
androidx-biometric-ktx = { module = "androidx.biometric:biometric-ktx", version.ref = "biometricKtx" }
|
||||
|
@ -82,7 +82,7 @@ lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-com
|
|||
material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "compose" }
|
||||
|
||||
timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
|
||||
tunnel = { module = "com.wireguard.android:tunnel", version.ref = "tunnel" }
|
||||
tunnel = { module = "com.zaneschepke:wireguard-android", version.ref = "tunnel" }
|
||||
|
||||
#firebase
|
||||
google-firebase-crashlytics-ktx = { module = "com.google.firebase:firebase-crashlytics-ktx", version.ref = "crashlytics" }
|
||||
|
@ -93,9 +93,9 @@ google-services = { module = "com.google.gms:google-services", version.ref = "go
|
|||
|
||||
zxing-core = { module = "com.google.zxing:core", version.ref = "zxingCore" }
|
||||
zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", version.ref = "zxingAndroidEmbedded" }
|
||||
|
||||
[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" }
|
||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||
androidLibrary = { id = "com.android.library", version.ref = "androidGradlePlugin" }
|
|
@ -2,5 +2,7 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -2,18 +2,42 @@ pluginManagement {
|
|||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
val GITHUB_USER_VAR = "GH_USER"
|
||||
val GITHUB_TOKEN_VAR = "GH_TOKEN"
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
maven {
|
||||
name = "GitHubPackages"
|
||||
url = uri("https://maven.pkg.github.com/zaneschepke/wireguard-android")
|
||||
credentials {
|
||||
username = getLocalProperty(GITHUB_USER_VAR) ?: System.getenv(GITHUB_USER_VAR)
|
||||
password = getLocalProperty(GITHUB_TOKEN_VAR) ?: System.getenv(GITHUB_TOKEN_VAR)
|
||||
}
|
||||
}
|
||||
google()
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
}
|
||||
}
|
||||
|
||||
fun getLocalProperty(key: String, file: String = "local.properties"): String? {
|
||||
val properties = java.util.Properties()
|
||||
val localProperties = File(file)
|
||||
if (localProperties.isFile) {
|
||||
java.io.InputStreamReader(java.io.FileInputStream(localProperties), Charsets.UTF_8).use { reader ->
|
||||
properties.load(reader)
|
||||
}
|
||||
} else return null
|
||||
return properties.getProperty(key)
|
||||
}
|
||||
|
||||
rootProject.name = "WG Tunnel"
|
||||
|
||||
include(":app")
|
||||
|
|
Loading…
Reference in New Issue