diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/data/domain/TunnelConfig.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/data/domain/TunnelConfig.kt
index 245a940d..028ebc7f 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/data/domain/TunnelConfig.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/data/domain/TunnelConfig.kt
@@ -5,6 +5,7 @@ import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import com.wireguard.config.Config
+import com.zaneschepke.wireguardautotunnel.util.extensions.toWgQuickString
import java.io.InputStream
@Entity(indices = [Index(value = ["name"], unique = true)])
@@ -79,6 +80,12 @@ data class TunnelConfig(
}
}
+ fun tunnelConfigFromAmConfig(config: org.amnezia.awg.config.Config, name: String): TunnelConfig {
+ val amQuick = config.toAwgQuickString(true)
+ val wgQuick = config.toWgQuickString()
+ return TunnelConfig(name = name, wgQuick = wgQuick, amQuick = amQuick)
+ }
+
const val AM_QUICK_DEFAULT = ""
}
}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt
index 3c2628cc..a9728cee 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt
@@ -37,6 +37,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@@ -68,6 +69,7 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.scaledHeight
fun MainScreen(viewModel: MainViewModel = hiltViewModel(), uiState: AppUiState) {
val context = LocalContext.current
val navController = LocalNavController.current
+ val clipboard = LocalClipboardManager.current
val snackbar = SnackbarController.current
var showBottomSheet by remember { mutableStateOf(false) }
@@ -201,12 +203,17 @@ fun MainScreen(viewModel: MainViewModel = hiltViewModel(), uiState: AppUiState)
)
}
},
- ) {
+ ) { padding ->
TunnelImportSheet(
showBottomSheet,
onDismiss = { showBottomSheet = false },
onFileClick = { tunnelFileImportResultLauncher.launch(Constants.ALLOWED_TV_FILE_TYPES) },
onQrClick = { requestPermissionLauncher.launch(android.Manifest.permission.CAMERA) },
+ onClipboardClick = {
+ clipboard.getText()?.text?.let {
+ viewModel.onClipboardImport(it)
+ }
+ },
onManualImportClick = {
navController.navigate(
Route.Config(Constants.MANUAL_TUNNEL_CONFIG_ID),
@@ -218,7 +225,7 @@ fun MainScreen(viewModel: MainViewModel = hiltViewModel(), uiState: AppUiState)
verticalArrangement = Arrangement.spacedBy(5.dp.scaledHeight(), Alignment.Top),
modifier =
Modifier
- .fillMaxSize().padding(it)
+ .fillMaxSize().padding(padding)
.overscroll(ScrollableDefaults.overscrollEffect())
.nestedScroll(nestedScrollConnection),
state = rememberLazyListState(0, uiState.tunnels.count()),
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt
index bd3d24be..c6394fe8 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainViewModel.kt
@@ -261,4 +261,14 @@ constructor(
),
)
}
+
+ fun onClipboardImport(config: String) = viewModelScope.launch(ioDispatcher) {
+ runCatching {
+ val amConfig = TunnelConfig.configFromAmQuick(config)
+ val tunnelConfig = TunnelConfig.tunnelConfigFromAmConfig(amConfig, makeTunnelNameUnique(generateQrCodeDefaultName(config)))
+ saveTunnel(tunnelConfig)
+ }.onFailure {
+ SnackbarController.showMessage(StringValue.StringResource(R.string.error_file_format))
+ }
+ }
}
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/components/TunnelImportSheet.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/components/TunnelImportSheet.kt
index c0cf4586..4007f4a7 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/components/TunnelImportSheet.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/components/TunnelImportSheet.kt
@@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ContentPasteGo
import androidx.compose.material.icons.filled.Create
import androidx.compose.material.icons.filled.FileOpen
import androidx.compose.material.icons.filled.QrCode
@@ -22,9 +23,17 @@ import androidx.compose.ui.unit.dp
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.util.extensions.isRunningOnTv
+// TODO refactor this component
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-fun TunnelImportSheet(show: Boolean, onDismiss: () -> Unit, onFileClick: () -> Unit, onQrClick: () -> Unit, onManualImportClick: () -> Unit) {
+fun TunnelImportSheet(
+ show: Boolean,
+ onDismiss: () -> Unit,
+ onFileClick: () -> Unit,
+ onQrClick: () -> Unit,
+ onManualImportClick: () -> Unit,
+ onClipboardClick: () -> Unit,
+) {
val sheetState = rememberModalBottomSheetState()
val context = LocalContext.current
@@ -77,6 +86,28 @@ fun TunnelImportSheet(show: Boolean, onDismiss: () -> Unit, onFileClick: () -> U
modifier = Modifier.padding(10.dp),
)
}
+ HorizontalDivider()
+ Row(
+ modifier =
+ Modifier
+ .fillMaxWidth()
+ .clickable {
+ onDismiss()
+ onClipboardClick()
+ }
+ .padding(10.dp),
+ ) {
+ val icon = Icons.Filled.ContentPasteGo
+ Icon(
+ icon,
+ contentDescription = icon.name,
+ modifier = Modifier.padding(10.dp),
+ )
+ Text(
+ stringResource(id = R.string.add_from_clipboard),
+ modifier = Modifier.padding(10.dp),
+ )
+ }
}
HorizontalDivider()
Row(
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/scanner/ScannerScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/scanner/ScannerScreen.kt
index c6a9dfdc..ab6da8eb 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/scanner/ScannerScreen.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/scanner/ScannerScreen.kt
@@ -9,11 +9,9 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.journeyapps.barcodescanner.CompoundBarcodeView
import com.zaneschepke.wireguardautotunnel.ui.common.navigation.LocalNavController
-@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun ScannerScreen(viewModel: ScannerViewModel = hiltViewModel()) {
val context = LocalContext.current
diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/scanner/ScannerViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/scanner/ScannerViewModel.kt
index 21b08d00..c39b15fd 100644
--- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/scanner/ScannerViewModel.kt
+++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/scanner/ScannerViewModel.kt
@@ -9,7 +9,6 @@ import com.zaneschepke.wireguardautotunnel.module.IoDispatcher
import com.zaneschepke.wireguardautotunnel.ui.common.snackbar.SnackbarController
import com.zaneschepke.wireguardautotunnel.util.NumberUtils
import com.zaneschepke.wireguardautotunnel.util.StringValue
-import com.zaneschepke.wireguardautotunnel.util.extensions.toWgQuickString
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -45,10 +44,7 @@ constructor(
fun onTunnelQrResult(result: String) = viewModelScope.launch(ioDispatcher) {
kotlin.runCatching {
val amConfig = TunnelConfig.configFromAmQuick(result)
- val amQuick = amConfig.toAwgQuickString(true)
- val wgQuick = amConfig.toWgQuickString()
- val tunnelName = makeTunnelNameUnique(generateQrCodeDefaultName(result))
- val tunnelConfig = TunnelConfig(name = tunnelName, wgQuick = wgQuick, amQuick = amQuick)
+ val tunnelConfig = TunnelConfig.tunnelConfigFromAmConfig(amConfig, makeTunnelNameUnique(generateQrCodeDefaultName(result)))
appDataRepository.tunnels.save(tunnelConfig)
_success.emit(true)
}.onFailure {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 25e4c071..904803b4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -177,4 +177,5 @@
Enable local logging
Configuration change
This change requires an app relaunch. Would you like to proceed?
+ Add from clipboard