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