diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3ca3a2edd..727a8c7a4 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -73,6 +73,13 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/MainActivity.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/MainActivity.kt
index 3165f059d..e76b33aee 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/MainActivity.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/MainActivity.kt
@@ -3,6 +3,7 @@ package com.zaneschepke.wireguardautotunnel
import ProxySettingsScreen
import android.content.Intent
import android.graphics.Color
+import android.net.Uri
import android.net.VpnService
import android.os.Build
import android.os.Bundle
@@ -29,6 +30,7 @@ import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
@@ -69,6 +71,7 @@ import com.zaneschepke.wireguardautotunnel.domain.sideeffect.GlobalSideEffect
import com.zaneschepke.wireguardautotunnel.ui.LocalIsAndroidTV
import com.zaneschepke.wireguardautotunnel.ui.LocalNavController
import com.zaneschepke.wireguardautotunnel.ui.common.banner.AppAlertBanner
+import com.zaneschepke.wireguardautotunnel.ui.common.dialog.InfoDialog
import com.zaneschepke.wireguardautotunnel.ui.common.dialog.VpnDeniedDialog
import com.zaneschepke.wireguardautotunnel.ui.common.snackbar.CustomSnackBar
import com.zaneschepke.wireguardautotunnel.ui.common.snackbar.SnackbarInfo
@@ -151,6 +154,8 @@ class MainActivity : AppCompatActivity() {
roomBackup = RoomBackup(this)
+ handleWgIntent(intent)
+
installSplashScreen().apply {
setKeepOnScreenCondition { !viewModel.container.stateFlow.value.isAppLoaded }
}
@@ -266,6 +271,19 @@ class MainActivity : AppCompatActivity() {
},
)
+ uiState.pendingWgImportUrl?.let { url ->
+ val host = Uri.parse(url).host ?: url
+ InfoDialog(
+ onDismiss = { viewModel.dismissWgImport() },
+ onAttest = { viewModel.importFromUrl(url) },
+ title = stringResource(R.string.add_from_url),
+ body = {
+ Text(stringResource(R.string.wg_url_confirm_message, host))
+ },
+ confirmText = stringResource(R.string.okay),
+ )
+ }
+
val annotatedMessage = buildAnnotatedString {
append(context.getString(R.string.donation_prompt_prefix))
append(" ")
@@ -514,6 +532,21 @@ class MainActivity : AppCompatActivity() {
}
}
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ handleWgIntent(intent)
+ }
+
+ private fun handleWgIntent(intent: Intent) {
+ if (intent.action == Intent.ACTION_VIEW) {
+ val uri = intent.data ?: return
+ if (uri.scheme == "wg") {
+ val httpsUrl = uri.toString().replaceFirst("wg://", "https://")
+ viewModel.promptWgImport(httpsUrl)
+ }
+ }
+ }
+
override fun onResume() {
super.onResume()
networkMonitor.checkPermissionsAndUpdateState()
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/state/GlobalAppUiState.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/state/GlobalAppUiState.kt
index 42f708258..3d963e742 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/state/GlobalAppUiState.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/state/GlobalAppUiState.kt
@@ -18,4 +18,5 @@ data class GlobalAppUiState(
val selectedTunnelCount: Int = 0,
val alreadyDonated: Boolean = false,
val isPinVerified: Boolean = false,
+ val pendingWgImportUrl: String? = null,
)
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/SharedAppViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/SharedAppViewModel.kt
index ce326db19..4cb9515a2 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/SharedAppViewModel.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/SharedAppViewModel.kt
@@ -300,7 +300,16 @@ class SharedAppViewModel(
fun importFromQr(conf: String) = intent { importFromClipboard(conf) }
+ fun promptWgImport(url: String) = intent {
+ reduce { state.copy(pendingWgImportUrl = url) }
+ }
+
+ fun dismissWgImport() = intent {
+ reduce { state.copy(pendingWgImportUrl = null) }
+ }
+
fun importFromUrl(url: String) = intent {
+ reduce { state.copy(pendingWgImportUrl = null) }
try {
httpClient.prepareGet(url).execute { response ->
if (response.status.value in 200..299) {
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index 7f48eb0d4..760b208d5 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -156,6 +156,7 @@
Ungültige Konfiguration
Matrix-Community beitreten
Download der Konfiguration fehlgeschlagen
+ Möchtest du wirklich Tunnel von %1$s hinzufügen? Verbinde dich niemals mit einem nicht vertrauenswürdigen VPN!
Von URL hinzufügen
Gespeicherte Logs exportieren
Steuere Tunnel und Auto-Tunnel Funktionen.
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 0d75ff504..1b3b51d21 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -182,6 +182,7 @@
Экспорт туннелей как WireGuard
Удалённое управление приложением
Невозможно скачать конфигурацию
+ Добавить туннели от %1$s? Никогда не подключайтесь к неизвестному VPN!
Здесь пока ничего нет!
Выбрать все
Экспорт успешно выполнен
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f2797ec25..0474cc71b 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -170,6 +170,7 @@
Add from URL
Enter config URL
Failed to download config
+ Are you sure you want to add tunnels from %1$s? Never connect to an untrusted VPN!
Save
Search
Select