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 }