fix: email launch and tunnel import mobile
This commit is contained in:
parent
e11f0f794a
commit
7fdd95ea51
|
@ -133,8 +133,6 @@ android {
|
|||
packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } }
|
||||
}
|
||||
|
||||
val generalImplementation by configurations
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(project(":logcatter"))
|
||||
|
|
|
@ -60,6 +60,7 @@ import com.zaneschepke.wireguardautotunnel.ui.screens.support.SupportScreen
|
|||
import com.zaneschepke.wireguardautotunnel.ui.screens.support.logs.LogsScreen
|
||||
import com.zaneschepke.wireguardautotunnel.ui.theme.WireguardAutoTunnelTheme
|
||||
import com.zaneschepke.wireguardautotunnel.util.Constants
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.requestAutoTunnelTileServiceUpdate
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.requestTunnelTileServiceStateUpdate
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
@ -103,6 +104,12 @@ class MainActivity : AppCompatActivity() {
|
|||
context.requestTunnelTileServiceStateUpdate()
|
||||
}
|
||||
|
||||
with(appUiState.settings) {
|
||||
LaunchedEffect(isAutoTunnelPaused, isAutoTunnelEnabled) {
|
||||
this@MainActivity.requestAutoTunnelTileServiceUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalNavController provides navController) {
|
||||
SnackbarControllerProvider { host ->
|
||||
WireguardAutoTunnelTheme {
|
||||
|
|
|
@ -10,6 +10,7 @@ import androidx.activity.compose.rememberLauncherForActivityResult
|
|||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.zaneschepke.wireguardautotunnel.util.Constants
|
||||
import com.zaneschepke.wireguardautotunnel.util.extensions.isRunningOnTv
|
||||
|
||||
@Composable
|
||||
fun rememberFileImportLauncherForResult(onNoFileExplorer: () -> Unit, onData: (data: Uri) -> Unit): ManagedActivityResultLauncher<String, Uri?> {
|
||||
|
@ -17,7 +18,11 @@ fun rememberFileImportLauncherForResult(onNoFileExplorer: () -> Unit, onData: (d
|
|||
object : ActivityResultContracts.GetContent() {
|
||||
override fun createIntent(context: Context, input: String): Intent {
|
||||
val intent = super.createIntent(context, input).apply {
|
||||
type = Constants.ALLOWED_FILE_TYPES
|
||||
type = if (context.isRunningOnTv()) {
|
||||
Constants.ALLOWED_TV_FILE_TYPES
|
||||
} else {
|
||||
Constants.ALL_FILE_TYPES
|
||||
}
|
||||
}
|
||||
|
||||
/* AndroidTV now comes with stubs that do nothing but display a Toast less helpful than
|
||||
|
|
|
@ -31,7 +31,6 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
|
@ -181,7 +180,7 @@ fun MainScreen(viewModel: MainViewModel = hiltViewModel(), uiState: AppUiState,
|
|||
TunnelImportSheet(
|
||||
showBottomSheet,
|
||||
onDismiss = { showBottomSheet = false },
|
||||
onFileClick = { tunnelFileImportResultLauncher.launch(Constants.ALLOWED_FILE_TYPES) },
|
||||
onFileClick = { tunnelFileImportResultLauncher.launch(Constants.ALLOWED_TV_FILE_TYPES) },
|
||||
onQrClick = { launchQrScanner() },
|
||||
onManualImportClick = {
|
||||
navController.navigate(
|
||||
|
|
|
@ -37,8 +37,11 @@ fun TunnelStatisticsRow(statistics: TunnelStatistics?, tunnelConfig: TunnelConfi
|
|||
val peerTxMB = NumberUtils.bytesToMB(peerTx).toThreeDecimalPlaceString()
|
||||
val peerRxMB = NumberUtils.bytesToMB(peerRx).toThreeDecimalPlaceString()
|
||||
val handshake = statistics?.peerStats(it.publicKey)?.latestHandshakeEpochMillis?.let {
|
||||
if(it == 0L) stringResource(R.string.never) else
|
||||
"${NumberUtils.getSecondsBetweenTimestampAndNow(it)} ${stringResource(R.string.sec)}"
|
||||
if (it == 0L) {
|
||||
stringResource(R.string.never)
|
||||
} else {
|
||||
"${NumberUtils.getSecondsBetweenTimestampAndNow(it)} ${stringResource(R.string.sec)}"
|
||||
}
|
||||
} ?: stringResource(R.string.never)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp),
|
||||
|
|
|
@ -22,7 +22,7 @@ fun PinLockScreen(appViewModel: AppViewModel) {
|
|||
PinLock(
|
||||
title = { pinExists ->
|
||||
Text(
|
||||
color = MaterialTheme.colorScheme.onSecondary,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
text =
|
||||
if (pinExists) {
|
||||
stringResource(id = R.string.enter_pin)
|
||||
|
@ -33,7 +33,8 @@ fun PinLockScreen(appViewModel: AppViewModel) {
|
|||
},
|
||||
)
|
||||
},
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
backgroundColor = MaterialTheme.colorScheme.surface,
|
||||
textColor = MaterialTheme.colorScheme.onSurface,
|
||||
onPinCorrect = {
|
||||
// pin is correct, navigate or hide pin lock
|
||||
if (context.isRunningOnTv()) {
|
||||
|
|
|
@ -13,11 +13,11 @@ object Constants {
|
|||
const val URI_CONTENT_SCHEME = "content"
|
||||
const val TEXT_MIME_TYPE = "text/plain"
|
||||
const val ZIP_FILE_MIME_TYPE = "application/zip"
|
||||
const val ALLOWED_FILE_TYPES = "${TEXT_MIME_TYPE}|${ZIP_FILE_MIME_TYPE}"
|
||||
const val ALLOWED_TV_FILE_TYPES = "${TEXT_MIME_TYPE}|${ZIP_FILE_MIME_TYPE}"
|
||||
const val ALL_FILE_TYPES = "*/*"
|
||||
const val GOOGLE_TV_EXPLORER_STUB = "com.google.android.tv.frameworkpackagestubs"
|
||||
const val ANDROID_TV_EXPLORER_STUB = "com.android.tv.frameworkpackagestubs"
|
||||
const val VPN_SETTINGS_PACKAGE = "android.net.vpn.SETTINGS"
|
||||
const val EMAIL_MIME_TYPE = "plain/text"
|
||||
const val SYSTEM_EXEMPT_SERVICE_TYPE_ID = 1024
|
||||
|
||||
const val SUBSCRIPTION_TIMEOUT = 5_000L
|
||||
|
|
|
@ -12,8 +12,6 @@ import kotlinx.coroutines.CoroutineDispatcher
|
|||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.OutputStream
|
||||
import java.time.Instant
|
||||
import java.util.zip.ZipEntry
|
||||
|
@ -23,23 +21,6 @@ class FileUtils(
|
|||
private val context: Context,
|
||||
private val ioDispatcher: CoroutineDispatcher,
|
||||
) {
|
||||
suspend fun readBytesFromFile(file: File): ByteArray {
|
||||
return withContext(ioDispatcher) {
|
||||
FileInputStream(file).use {
|
||||
it.readBytes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun readTextFromFileName(fileName: String): String {
|
||||
return withContext(ioDispatcher) {
|
||||
context.assets.open(fileName).use { stream ->
|
||||
stream.bufferedReader(Charsets.UTF_8).use {
|
||||
it.readText()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createWgFiles(tunnels: TunnelConfigs): List<File> {
|
||||
return tunnels.map { config ->
|
||||
|
@ -61,43 +42,6 @@ class FileUtils(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun saveByteArrayToDownloads(content: ByteArray, fileName: String): Result<Unit> {
|
||||
return withContext(ioDispatcher) {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
val contentValues =
|
||||
ContentValues().apply {
|
||||
put(MediaColumns.DISPLAY_NAME, fileName)
|
||||
put(MediaColumns.MIME_TYPE, Constants.TEXT_MIME_TYPE)
|
||||
put(MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
|
||||
}
|
||||
val resolver = context.contentResolver
|
||||
val uri =
|
||||
resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
|
||||
if (uri != null) {
|
||||
resolver.openOutputStream(uri).use { output ->
|
||||
output?.write(content)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val target =
|
||||
File(
|
||||
Environment.getExternalStoragePublicDirectory(
|
||||
Environment.DIRECTORY_DOWNLOADS,
|
||||
),
|
||||
fileName,
|
||||
)
|
||||
FileOutputStream(target).use { output ->
|
||||
output.write(content)
|
||||
}
|
||||
}
|
||||
Result.success(Unit)
|
||||
} catch (e: Exception) {
|
||||
Result.failure(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun saveFilesToZip(files: List<File>): Result<Unit> {
|
||||
return withContext(ioDispatcher) {
|
||||
try {
|
||||
|
@ -124,7 +68,7 @@ class FileUtils(
|
|||
}
|
||||
|
||||
// TODO issue with android 9
|
||||
private fun createDownloadsFileOutputStream(fileName: String, mimeType: String = Constants.ALLOWED_FILE_TYPES): OutputStream? {
|
||||
private fun createDownloadsFileOutputStream(fileName: String, mimeType: String = Constants.ALL_FILE_TYPES): OutputStream? {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
val resolver = context.contentResolver
|
||||
val contentValues =
|
||||
|
|
|
@ -44,21 +44,21 @@ fun Context.showToast(resId: Int) {
|
|||
).show()
|
||||
}
|
||||
|
||||
fun Context.launchSupportEmail(): Result<Unit> {
|
||||
return runCatching {
|
||||
val intent =
|
||||
Intent(Intent.ACTION_SENDTO).apply {
|
||||
type = Constants.EMAIL_MIME_TYPE
|
||||
putExtra(Intent.EXTRA_EMAIL, arrayOf(getString(R.string.my_email)))
|
||||
putExtra(Intent.EXTRA_SUBJECT, getString(R.string.email_subject))
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
fun Context.launchSupportEmail() {
|
||||
val intent =
|
||||
Intent(Intent.ACTION_SENDTO).apply {
|
||||
data = Uri.parse("mailto:")
|
||||
putExtra(Intent.EXTRA_EMAIL, arrayOf(getString(R.string.my_email)))
|
||||
putExtra(Intent.EXTRA_SUBJECT, getString(R.string.email_subject))
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
if (intent.resolveActivity(packageManager) != null) {
|
||||
startActivity(
|
||||
Intent.createChooser(intent, getString(R.string.email_chooser)).apply {
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
},
|
||||
)
|
||||
}.onFailure {
|
||||
} else {
|
||||
showToast(R.string.no_email_detected)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ kotlinx-serialization-json = "1.7.3"
|
|||
lifecycle-runtime-compose = "2.8.6"
|
||||
material3 = "1.3.0"
|
||||
navigationCompose = "2.8.2"
|
||||
pinLockCompose = "1.0.3"
|
||||
pinLockCompose = "1.0.4"
|
||||
roomVersion = "2.6.1"
|
||||
timber = "5.0.1"
|
||||
tunnel = "1.2.1"
|
||||
|
|
Loading…
Reference in New Issue