diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 61cceaa..b816cbc 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -21,7 +21,7 @@ android {
}
// don't forget to add another "s this is counter intuitive I know but not my fault
- buildConfigField("String", "VASTAI_KEY", "null")
+ buildConfigField("String", "VASTAI_KEY", "\"\"")
buildConfigField("String", "VASIAI_API_ENDPOINT", "\"https://cloud.vast.ai/api/v0\"")
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 65075a9..9a7a2e0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
+
Unit) {
+ val available = canAskForPermission(permission, activity)
+
+ if (hasPermission(permission)) {
+ callback(true, false)
+ } else if (available) { // no permission but can request
+ requestPermission(permission, activity) { callback(it, true) }
+ } else { // no permission and can't request
+ callback(false, false)
+ }
+ }
+
+ // TODO should this be private? I mean it doesn't check for other stuff so it's a waste to register an activity if we don't have to
+ private fun requestPermission(permission: String, activity: ComponentActivity, callback: (Boolean) -> Unit) {
+ activity.registerForActivityResult(
+ ActivityResultContracts.RequestPermission(),
+ callback
+ ).launch(permission)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/eu/m724/vastapp/activity/login/LoginActivity.kt b/app/src/main/java/eu/m724/vastapp/activity/login/LoginActivity.kt
index a4a9f6f..b6ad807 100644
--- a/app/src/main/java/eu/m724/vastapp/activity/login/LoginActivity.kt
+++ b/app/src/main/java/eu/m724/vastapp/activity/login/LoginActivity.kt
@@ -9,7 +9,6 @@ import androidx.activity.enableEdgeToEdge
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.AnimatedVisibility
-import androidx.compose.animation.animateColor
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloat
@@ -48,7 +47,6 @@ import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
@@ -65,12 +63,12 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.lifecycleScope
import eu.m724.vastapp.BuildConfig
import eu.m724.vastapp.R
+import eu.m724.vastapp.activity.PermissionChecker
import eu.m724.vastapp.activity.dashboard.DashboardActivity
import eu.m724.vastapp.ui.theme.VastappTheme
import eu.m724.vastapp.vastai.data.User
import kotlinx.coroutines.launch
import org.chromium.net.CronetEngine
-import org.w3c.dom.Text
import java.util.concurrent.Executors
import kotlin.random.Random
@@ -80,9 +78,30 @@ class LoginActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ // TODO move this where and run this when we need it
+ val permissionChecker = PermissionChecker(applicationContext)
+ if (!permissionChecker.permissionExists("com.termux.permission.RUN_COMMAND")) {
+ Toast.makeText(
+ applicationContext,
+ R.string.no_termux,
+ Toast.LENGTH_SHORT
+ ).show()
+ } else {
+ permissionChecker.requestIfNoPermission("com.termux.permission.RUN_COMMAND", this) { granted, asked ->
+ if (granted || !asked) return@requestIfNoPermission
+
+ Toast.makeText(
+ applicationContext,
+ getString(R.string.command_permission_denied),
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+
+ }
+
dashboardLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
- ) { result -> finish() } // TODO re-login here
+ ) { _ -> finish() } // TODO re-login here
val executor = Executors.newSingleThreadExecutor()
val cronetEngine = CronetEngine.Builder(baseContext).build()
@@ -94,7 +113,7 @@ class LoginActivity : ComponentActivity() {
}
}
- lifecycleScope.launch { // TODO I was suggested not to launch an activity from a lifecyclescope
+ lifecycleScope.launch { // TODO I was suggested not to launch an activity from a lifecycle scope
loginViewModel.uiState.collect { state ->
if (state is LoginUiState.Success) {
loadApp(state.user)
@@ -134,12 +153,11 @@ class LoginActivity : ComponentActivity() {
@Composable
fun LoginApp(loginViewModel: LoginViewModel) {
- val coroutineScope = rememberCoroutineScope()
val uiState by loginViewModel.uiState.collectAsState()
- val loginErrorMessage by loginViewModel.error.observeAsState() // TODO put this in uistate
+ val loginErrorMessage by loginViewModel.error.observeAsState() // TODO put this in uiState
val isIdle by remember(uiState) { derivedStateOf { uiState !is LoginUiState.Loading } }
- var apiKey by rememberSaveable { mutableStateOf(BuildConfig.VASTAI_KEY ?: "") }
+ var apiKey by rememberSaveable { mutableStateOf(BuildConfig.VASTAI_KEY) }
var advancedOpen by rememberSaveable { mutableStateOf(false) }
val transition = updateTransition(targetState = advancedOpen, label = "Advanced Menu Transition")
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 335a976..87bb00f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -20,4 +20,6 @@
having fun?
checkbox is angry
none yet sorry
+ If you change your mind, do so from settings
+ Termuxn\'t
\ No newline at end of file