SetupActivity.kt (6764B) - raw


      1 package me.rhunk.snapenhance.ui.setup
      2 
      3 import android.annotation.SuppressLint
      4 import android.os.Bundle
      5 import androidx.activity.ComponentActivity
      6 import androidx.activity.compose.BackHandler
      7 import androidx.activity.compose.setContent
      8 import androidx.compose.animation.core.animateFloatAsState
      9 import androidx.compose.foundation.background
     10 import androidx.compose.foundation.layout.*
     11 import androidx.compose.material.icons.Icons
     12 import androidx.compose.material.icons.automirrored.filled.ArrowForwardIos
     13 import androidx.compose.material.icons.filled.Check
     14 import androidx.compose.material3.FilledIconButton
     15 import androidx.compose.material3.Icon
     16 import androidx.compose.material3.MaterialTheme
     17 import androidx.compose.material3.Scaffold
     18 import androidx.compose.runtime.getValue
     19 import androidx.compose.runtime.mutableStateOf
     20 import androidx.compose.runtime.remember
     21 import androidx.compose.runtime.setValue
     22 import androidx.compose.ui.Alignment
     23 import androidx.compose.ui.Modifier
     24 import androidx.compose.ui.draw.alpha
     25 import androidx.compose.ui.unit.dp
     26 import androidx.navigation.compose.NavHost
     27 import androidx.navigation.compose.composable
     28 import androidx.navigation.compose.rememberNavController
     29 import me.rhunk.snapenhance.SharedContextHolder
     30 import me.rhunk.snapenhance.common.ui.AppMaterialTheme
     31 import me.rhunk.snapenhance.ui.setup.screens.SetupScreen
     32 import me.rhunk.snapenhance.ui.setup.screens.impl.*
     33 
     34 
     35 class SetupActivity : ComponentActivity() {
     36     @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
     37     override fun onCreate(savedInstanceState: Bundle?) {
     38         super.onCreate(savedInstanceState)
     39 
     40         val setupContext = SharedContextHolder.remote(this).apply {
     41             activity = this@SetupActivity
     42         }
     43 
     44         fun endActivity() {
     45             setupContext.reload()
     46             finish()
     47         }
     48 
     49         val requirements = intent.getIntExtra("requirements", Requirements.FIRST_RUN)
     50 
     51         fun hasRequirement(requirement: Int) = requirements and requirement == requirement
     52 
     53         val requiredScreens = mutableListOf<SetupScreen>()
     54 
     55         with(requiredScreens) {
     56             val isFirstRun = hasRequirement(Requirements.FIRST_RUN)
     57             if (isFirstRun || hasRequirement(Requirements.LANGUAGE)) {
     58                 add(PickLanguageScreen().apply { route = "language" })
     59             }
     60             if (isFirstRun || hasRequirement(Requirements.GRANT_PERMISSIONS)) {
     61                 add(PermissionsScreen().apply { route = "permissions" })
     62             }
     63             if (isFirstRun || hasRequirement(Requirements.SAVE_FOLDER)) {
     64                 add(SaveFolderScreen().apply { route = "saveFolder" })
     65             }
     66             if (isFirstRun || hasRequirement(Requirements.MAPPINGS)) {
     67                 add(MappingsScreen().apply { route = "mappings" })
     68             }
     69             if (isFirstRun || hasRequirement(Requirements.SIF)) {
     70                 add(SecurityScreen().apply { route = "security" })
     71             }
     72         }
     73 
     74         // If there are no required screens, we can just finish the activity
     75         if (requiredScreens.isEmpty()) {
     76             endActivity()
     77             return
     78         }
     79 
     80         requiredScreens.forEach { screen ->
     81             screen.context = setupContext
     82             screen.init()
     83         }
     84 
     85         setContent {
     86             val navController = rememberNavController()
     87             var canGoNext by remember { mutableStateOf(false) }
     88 
     89             fun nextScreen() {
     90                 if (!canGoNext) return
     91                 requiredScreens.firstOrNull()?.onLeave()
     92                 if (requiredScreens.size > 1) {
     93                     canGoNext = false
     94                     requiredScreens.removeFirst()
     95                     navController.navigate(requiredScreens.first().route)
     96                 } else {
     97                     endActivity()
     98                 }
     99             }
    100 
    101             AppMaterialTheme {
    102                 Scaffold(
    103                     containerColor = MaterialTheme.colorScheme.background,
    104                     bottomBar = {
    105                         Column(
    106                             modifier = Modifier
    107                                 .fillMaxWidth(),
    108                             horizontalAlignment = Alignment.CenterHorizontally
    109                         ) {
    110                             val alpha: Float by animateFloatAsState(if (canGoNext) 1f else 0f,
    111                                 label = "NextButton"
    112                             )
    113 
    114                             FilledIconButton(
    115                                 onClick = { nextScreen() },
    116                                 modifier = Modifier.padding(50.dp)
    117                                     .width(60.dp)
    118                                     .height(60.dp)
    119                                     .alpha(alpha)
    120                             ) {
    121                                 Icon(
    122                                     imageVector = if (requiredScreens.size <= 1 && canGoNext) {
    123                                         Icons.Default.Check
    124                                     } else {
    125                                         Icons.AutoMirrored.Default.ArrowForwardIos
    126                                     },
    127                                     contentDescription = null
    128                                 )
    129                             }
    130                         }
    131                     },
    132                 ) {
    133                     Column(
    134                         modifier = Modifier
    135                             .background(MaterialTheme.colorScheme.background)
    136                             .fillMaxSize()
    137                     ) {
    138                         NavHost(
    139                             navController = navController,
    140                             startDestination = requiredScreens.first().route
    141                         ) {
    142                             requiredScreens.forEach { screen ->
    143                                 screen.allowNext = { canGoNext = it }
    144                                 screen.goNext = {
    145                                     canGoNext = true
    146                                     nextScreen()
    147                                 }
    148                                 composable(screen.route) {
    149                                     BackHandler(true) {}
    150                                     Column(
    151                                         modifier = Modifier.fillMaxSize(),
    152                                         verticalArrangement = Arrangement.Center,
    153                                         horizontalAlignment = Alignment.CenterHorizontally
    154                                     ) {
    155                                         screen.Content()
    156                                     }
    157                                 }
    158                             }
    159                         }
    160                     }
    161                 }
    162             }
    163         }
    164     }
    165 }