2026-06-20 13:28:08 +08:00

200 lines
5.9 KiB
Kotlin

package com.jihe.punchnet
import android.app.Application
import android.content.Context
import android.content.Intent
import android.net.VpnService
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.compose.rememberNavController
import com.jihe.punchnet.data.ButtonState
import com.jihe.punchnet.data.ButtonViewModel
import com.jihe.punchnet.data.RouteViewModel
import com.jihe.punchnet.data.ServiceViewModel
import com.jihe.punchnet.screen.MainApp
import com.jihe.punchnet.ui.theme.PunchnetTheme
import kotlinx.coroutines.flow.onEach
class PunchnetApp: Application() {
val buttonModel: ButtonViewModel by lazy {
ViewModelProvider.AndroidViewModelFactory.getInstance(this)
.create(ButtonViewModel::class.java)
}
}
class MainActivity : ComponentActivity() {
private val TAG = "MainActivity"
private val viewModel: RouteViewModel by viewModels {
object: ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun<T: ViewModel> create(modelClass: Class<T>): T {
return RouteViewModel(application) as T
}
}
}
private val serviceModel: ServiceViewModel by viewModels {
object: ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun<T: ViewModel> create(modelClass: Class<T>): T {
return ServiceViewModel(application) as T
}
}
}
/*
val buttonModel: ButtonViewModel by viewModels {
object: ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun<T: ViewModel> create(modelClass: Class<T>): T {
return ButtonViewModel(application) as T
}
}
}
*/
/*
fun prepareAndStartVPN() {
val intent = VpnService.prepare(this)
if (intent != null) {
vpnPermissionLauncher.launch(intent)
} else {
startVpnService(this)
}
}
*/
/*
private fun startVpnService(context: Context) {
val intent = Intent(context, PunchnetService::class.java)
intent.putExtra("argument", PunchnetServiceArgument(
"",
arrayOf(
RouteInfo(
"192.168.80.0/24", "10.211.188.2"
)
)
))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
Toast.makeText(this, "VPN service started", Toast.LENGTH_SHORT).show()
}
*/
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Initialize AppAuthRepository for Split Tunneling
com.jihe.punchnet.data.AppAuthRepository.init(this)
enableEdgeToEdge()
Log.d("DIR", "filesdir = ${this.filesDir}")
val buttonModel = ButtonViewModel()
buttonModel.updateState(ButtonState.ButtonStopped)
setContent {
PunchnetTheme {
MainApp(buttonModel, serviceModel, viewModel, rememberNavController())
/*
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
StartStop(
R.string.start_vpn,
R.string.stop_vpn,
onStart = {
prepareAndStartVPN()
},
onStop = {
// stopVpnService()
},
modifier = Modifier.padding(innerPadding)
)
}
*/
}
}
}
}
@Composable
fun StartStop(
@StringRes start_name_id: Int,
@StringRes stop_name_id: Int,
onStart: ()->Unit,
onStop: ()->Unit,
modifier: Modifier = Modifier,
) {
val start_text = stringResource(start_name_id)
val stop_text = stringResource(stop_name_id)
var button_state by rememberSaveable { mutableStateOf(false) }
var button_text by rememberSaveable() { mutableStateOf(start_text) }
Button(
modifier = modifier,
onClick = {
button_state = !button_state
if (button_state) {
onStart()
button_text = stop_text
} else {
Log.d("STOP", "call on stop")
onStop()
button_text = start_text
}
}
) {
Text (
text = button_text
)
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
PunchnetTheme {
Greeting("Android")
}
}