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