2 Commits

Author SHA1 Message Date
white
2954cef0a6 small fixes, added vpn permission request before selection 2025-10-14 20:31:05 +03:00
CherretGit
c49cce1de4 fix JNI 2025-10-14 23:05:49 +07:00
6 changed files with 46 additions and 7 deletions

View File

@@ -240,7 +240,7 @@ class MainActivity : ComponentActivity() {
}
}
composable("debugScreen") { DebugScreen(navController) }
composable("selectionScreen") { StrategySelectionScreen(navController) }
composable("selectionScreen") { StrategySelectionScreen(navController, vpnPermissionLauncher) }
}
}
}

View File

@@ -205,7 +205,7 @@ fun StrategySelectionItem(strategy : StrategyCheckResult, prefs : SharedPreferen
)
FilledTonalIconButton(
onClick = {
disableStrategy(getActiveStrategy(prefs)[0], prefs)
if (getActiveStrategy(prefs).isNotEmpty()) disableStrategy(getActiveStrategy(prefs)[0], prefs)
enableStrategy(strategy.path, prefs)
scope.launch {
snackbarHostState.showSnackbar(

View File

@@ -1,6 +1,9 @@
package com.cherret.zaprett.ui.screen
import android.content.Context.MODE_PRIVATE
import android.content.Intent
import android.net.VpnService
import androidx.activity.result.ActivityResultLauncher
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
@@ -33,29 +36,46 @@ import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.TextButton
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.cherret.zaprett.R
import com.cherret.zaprett.byedpi.ByeDpiVpnService
import com.cherret.zaprett.ui.component.StrategySelectionItem
import com.cherret.zaprett.ui.viewmodel.StrategySelectionViewModel
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun StrategySelectionScreen(navController: NavController, viewModel : StrategySelectionViewModel = viewModel()){
fun StrategySelectionScreen(navController: NavController, vpnLauncher: ActivityResultLauncher<Intent>, viewModel : StrategySelectionViewModel = viewModel()){
val snackbarHostState = remember { SnackbarHostState() }
val strategyStates = viewModel.strategyStates
val context = LocalContext.current
val prefs = context.getSharedPreferences("settings", MODE_PRIVATE)
var showDialog = remember { mutableStateOf(false) }
val requestVpnPermission by viewModel.requestVpnPermission.collectAsState()
if (showDialog.value) {
InfoAlert { showDialog.value = false }
}
LaunchedEffect(requestVpnPermission) {
if (requestVpnPermission) {
val intent = VpnService.prepare(context)
if (intent != null) {
vpnLauncher.launch(intent)
} else {
viewModel.startVpn()
viewModel.clearVpnPermissionRequest()
}
}
}
Scaffold(
topBar = {
TopAppBar(

View File

@@ -28,7 +28,7 @@ class IpsetViewModel(application: Application): BaseListsViewModel(application)
override fun deleteItem(item: String, snackbarHostState: SnackbarHostState, scope: CoroutineScope) {
val wasChecked = checked[item] == true
disableList(item, sharedPreferences)
disableIpset(item, sharedPreferences)
val success = File(item).delete()
if (success) refresh()
if (sharedPreferences.getBoolean("use_module", false)) {

View File

@@ -5,6 +5,7 @@ import android.content.Context.MODE_PRIVATE
import android.content.Intent
import android.util.Log
import androidx.compose.runtime.mutableStateListOf
import androidx.core.content.ContextCompat
import androidx.lifecycle.AndroidViewModel
import com.cherret.zaprett.R
import com.cherret.zaprett.byedpi.ByeDpiVpnService
@@ -22,6 +23,8 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull
import okhttp3.OkHttpClient
@@ -36,6 +39,9 @@ class StrategySelectionViewModel(application: Application) : AndroidViewModel(ap
.build()
val context = application
private val _requestVpnPermission = MutableStateFlow(false)
val requestVpnPermission = _requestVpnPermission.asStateFlow()
val strategyStates = mutableStateListOf<StrategyCheckResult>()
init {
@@ -124,9 +130,10 @@ class StrategySelectionViewModel(application: Application) : AndroidViewModel(ap
})
delay(300L)
}
context.startService(Intent(context, ByeDpiVpnService::class.java).apply {
_requestVpnPermission.value = true
/*context.startService(Intent(context, ByeDpiVpnService::class.java).apply {
action = "START_VPN"
})
})*/
val connected = withTimeoutOrNull(10_000L) {
while (ByeDpiVpnService.status != ServiceStatus.Connected) {
@@ -158,4 +165,10 @@ class StrategySelectionViewModel(application: Application) : AndroidViewModel(ap
strategyStates.clear()
strategyStates.addAll(sorted)
}
fun startVpn() {
ContextCompat.startForegroundService(context, Intent(context, ByeDpiVpnService::class.java).apply { action = "START_VPN" })
}
fun clearVpnPermissionRequest() {
_requestVpnPermission.value = false
}
}

View File

@@ -13,6 +13,8 @@ static PROXY_RUNNING: AtomicBool = AtomicBool::new(false);
#[link(name = "byedpi", kind = "static")]
unsafe extern "C" {
static mut server_fd: i32;
static mut optind: i32;
static mut optreset: i32;
fn main(argc: libc::c_int, argv: *const *const c_char) -> libc::c_int;
fn clear_params();
}
@@ -62,7 +64,11 @@ pub unsafe extern "system" fn Java_com_cherret_zaprett_byedpi_NativeBridge_jniSt
return -1;
}
info!("stopping proxy");
unsafe { clear_params() };
let ret = unsafe { shutdown(server_fd, SHUT_RDWR) };
unsafe {
optreset = 1;
optind = 1;
}
unsafe { clear_params() };
ret as jint
}