mirror of
https://github.com/wgtunnel/android.git
synced 2026-06-02 00:29:08 +02:00
fix: auto-tunnel screen not loading without wifi
Fixes auto tunnel screen failing to load if you haven't connected to wifi once. Fixes import via url. Closes #1108 Closes #1105
This commit is contained in:
+26
-21
@@ -1,42 +1,47 @@
|
||||
package com.zaneschepke.wireguardautotunnel.ui.screens.tunnels.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.zaneschepke.wireguardautotunnel.R
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.dialog.InfoDialog
|
||||
import com.zaneschepke.wireguardautotunnel.ui.common.textbox.ConfigurationTextBox
|
||||
|
||||
@Composable
|
||||
fun UrlImportDialog(onDismiss: () -> Unit, onConfirm: (String) -> Unit) {
|
||||
var url by remember { mutableStateOf("") }
|
||||
var isError by remember { mutableStateOf(false) }
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = { Text(stringResource(R.string.add_from_url)) },
|
||||
text = {
|
||||
Column(modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp)) {
|
||||
OutlinedTextField(
|
||||
LaunchedEffect(url) { isError = false }
|
||||
|
||||
InfoDialog(
|
||||
onDismiss = onDismiss,
|
||||
title = stringResource(R.string.add_from_url),
|
||||
body = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(24.dp)) {
|
||||
Text(
|
||||
stringResource(R.string.import_url_description),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
ConfigurationTextBox(
|
||||
value = url,
|
||||
label = stringResource(R.string.enter_config_url),
|
||||
hint = stringResource(R.string.example_import_url),
|
||||
onValueChange = { url = it },
|
||||
label = { Text(stringResource(R.string.enter_config_url)) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
isError = isError,
|
||||
)
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = { onConfirm(url) }, enabled = url.isNotBlank()) {
|
||||
Text(stringResource(R.string.okay))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismiss) { Text(stringResource(R.string.cancel)) }
|
||||
confirmText = stringResource(R.string.okay),
|
||||
onAttest = {
|
||||
if (url.isNotBlank() && url.startsWith("https://")) {
|
||||
onConfirm(url)
|
||||
} else isError = true
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
+19
-12
@@ -1,7 +1,6 @@
|
||||
package com.zaneschepke.wireguardautotunnel.viewmodel
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.wireguard.android.backend.WgQuickBackend
|
||||
import com.zaneschepke.wireguardautotunnel.R
|
||||
@@ -24,9 +23,11 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.TunnelName
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.asStringValue
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.saveTunnelsUniquely
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.request.prepareGet
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
import java.time.Instant
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.combine
|
||||
@@ -50,6 +51,7 @@ constructor(
|
||||
private val settingsRepository: GeneralSettingRepository,
|
||||
private val monitoringSettingsRepository: MonitoringSettingsRepository,
|
||||
private val rootShellUtils: RootShellUtils,
|
||||
private val httpClient: HttpClient,
|
||||
private val fileUtils: FileUtils,
|
||||
) : ContainerHost<SharedAppUiState, LocalSideEffect>, ViewModel() {
|
||||
|
||||
@@ -239,18 +241,23 @@ constructor(
|
||||
fun importFromQr(conf: String) = intent { importFromClipboard(conf) }
|
||||
|
||||
fun importFromUrl(url: String) = intent {
|
||||
runCatching {
|
||||
val url = URL(url)
|
||||
val uri = url.toURI().toString().toUri()
|
||||
importFromUri(uri)
|
||||
}
|
||||
.onFailure {
|
||||
postSideEffect(
|
||||
GlobalSideEffect.Toast(
|
||||
StringValue.StringResource(R.string.error_download_failed)
|
||||
try {
|
||||
httpClient.prepareGet(url).execute { response ->
|
||||
if (response.status.value in 200..299) {
|
||||
val body = response.bodyAsText()
|
||||
importFromClipboard(body)
|
||||
} else {
|
||||
throw IOException(
|
||||
"Failed to download file with error status: ${response.status.value}"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
postSideEffect(
|
||||
GlobalSideEffect.Toast(StringValue.StringResource(R.string.error_download_failed))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun importFromUri(uri: Uri) = intent {
|
||||
|
||||
@@ -459,4 +459,6 @@
|
||||
<string name="copy_from">Copy from</string>
|
||||
<string name="mode">Mode</string>
|
||||
<string name="app_selection">App selection</string>
|
||||
<string name="example_import_url" translatable="false">https://123.com/tun.conf</string>
|
||||
<string name="import_url_description">The URL must be secure and serve a .conf file.</string>
|
||||
</resources>
|
||||
|
||||
+4
-2
@@ -15,8 +15,6 @@ import com.wireguard.android.util.RootShell
|
||||
import com.zaneschepke.networkmonitor.AndroidNetworkMonitor.WifiDetectionMethod.*
|
||||
import com.zaneschepke.networkmonitor.shizuku.ShizukuShell
|
||||
import com.zaneschepke.networkmonitor.util.*
|
||||
import kotlin.concurrent.atomics.AtomicReference
|
||||
import kotlin.concurrent.atomics.ExperimentalAtomicApi
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
@@ -24,6 +22,8 @@ import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import timber.log.Timber
|
||||
import kotlin.concurrent.atomics.AtomicReference
|
||||
import kotlin.concurrent.atomics.ExperimentalAtomicApi
|
||||
|
||||
class AndroidNetworkMonitor(
|
||||
private val appContext: Context,
|
||||
@@ -212,6 +212,8 @@ class AndroidNetworkMonitor(
|
||||
|
||||
connectivityManager?.registerNetworkCallback(request, wifiCallback!!)
|
||||
|
||||
trySend(TransportEvent.Unknown)
|
||||
|
||||
awaitClose {
|
||||
runCatching { connectivityManager?.unregisterNetworkCallback(wifiCallback!!) }
|
||||
.onFailure { Timber.e(it, "Error unregistering WiFi network callback") }
|
||||
|
||||
Reference in New Issue
Block a user