refactor(config): extract screen logic from `NavHost`

pull/1330/head
andrekir 2024-10-16 18:18:12 -03:00 zatwierdzone przez Andre K
rodzic 42f9ef24fd
commit d10b58073c
1 zmienionych plików z 109 dodań i 84 usunięć

Wyświetl plik

@ -65,6 +65,7 @@ import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.config
import com.geeksville.mesh.database.entity.NodeEntity
import com.geeksville.mesh.model.Channel
import com.geeksville.mesh.model.RadioConfigState
import com.geeksville.mesh.model.RadioConfigViewModel
import com.geeksville.mesh.moduleConfig
import com.geeksville.mesh.service.MeshService.ConnectionState
@ -239,107 +240,31 @@ private fun MeshAppBar(
)
}
@Suppress("LongMethod", "CyclomaticComplexMethod")
@Suppress("LongMethod")
@Composable
fun RadioConfigNavHost(
node: NodeEntity?,
viewModel: RadioConfigViewModel = hiltViewModel(),
navController: NavHostController = rememberNavController(),
modifier: Modifier,
modifier: Modifier = Modifier,
) {
val connectionState by viewModel.connectionState.collectAsStateWithLifecycle()
val connected = connectionState == ConnectionState.CONNECTED && node != null
val isLocal = node?.num == viewModel.myNodeNum
val radioConfigState by viewModel.radioConfigState.collectAsStateWithLifecycle()
val deviceProfile by viewModel.deviceProfile.collectAsStateWithLifecycle()
val isWaiting = radioConfigState.responseState.isWaiting()
var showEditDeviceProfileDialog by remember { mutableStateOf(false) }
val importConfigLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) {
showEditDeviceProfileDialog = true
it.data?.data?.let { uri -> viewModel.importProfile(uri) }
}
}
val exportConfigLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) {
it.data?.data?.let { uri -> viewModel.exportProfile(uri) }
}
}
if (showEditDeviceProfileDialog) EditDeviceProfileDialog(
title = if (deviceProfile != null) "Import configuration" else "Export configuration",
deviceProfile = deviceProfile ?: viewModel.currentDeviceProfile,
onConfirm = {
showEditDeviceProfileDialog = false
if (deviceProfile != null) {
viewModel.installProfile(it)
} else {
viewModel.setDeviceProfile(it)
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/*"
putExtra(Intent.EXTRA_TITLE, "${node!!.num.toUInt()}.cfg")
}
exportConfigLauncher.launch(intent)
}
},
onDismiss = {
showEditDeviceProfileDialog = false
viewModel.setDeviceProfile(null)
}
)
if (isWaiting) PacketResponseStateDialog(
radioConfigState.responseState,
onDismiss = {
showEditDeviceProfileDialog = false
viewModel.clearPacketResponse()
},
onComplete = {
val route = radioConfigState.route
if (ConfigRoute.entries.any { it.name == route } ||
ModuleRoute.entries.any { it.name == route }) {
navController.navigate(route)
viewModel.clearPacketResponse()
}
}
)
NavHost(
navController = navController,
startDestination = "home",
modifier = modifier,
) {
composable("home") {
RadioConfigItemList(
enabled = connected && !isWaiting,
isLocal = isLocal,
onRouteClick = { route ->
viewModel.setResponseStateLoading(route)
},
onImport = {
viewModel.clearPacketResponse()
viewModel.setDeviceProfile(null)
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/*"
}
importConfigLauncher.launch(intent)
},
onExport = {
viewModel.clearPacketResponse()
viewModel.setDeviceProfile(null)
showEditDeviceProfileDialog = true
},
RadioConfigScreen(
node = node,
connected = connected,
radioConfigState = radioConfigState,
viewModel = viewModel,
onNavigate = { navController.navigate(route = it) },
)
}
composable(ConfigRoute.USER.name) {
@ -606,6 +531,106 @@ fun RadioConfigNavHost(
}
}
@Suppress("LongMethod", "CyclomaticComplexMethod")
@Composable
fun RadioConfigScreen(
node: NodeEntity?,
connected: Boolean,
radioConfigState: RadioConfigState,
viewModel: RadioConfigViewModel,
modifier: Modifier = Modifier,
onNavigate: (String) -> Unit = {},
) {
val isLocal = node?.num == viewModel.myNodeNum
val isWaiting = radioConfigState.responseState.isWaiting()
val deviceProfile by viewModel.deviceProfile.collectAsStateWithLifecycle()
var showEditDeviceProfileDialog by remember { mutableStateOf(false) }
val importConfigLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) {
showEditDeviceProfileDialog = true
it.data?.data?.let { uri -> viewModel.importProfile(uri) }
}
}
val exportConfigLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) {
it.data?.data?.let { uri -> viewModel.exportProfile(uri) }
}
}
if (showEditDeviceProfileDialog) {
EditDeviceProfileDialog(
title = if (deviceProfile != null) "Import configuration" else "Export configuration",
deviceProfile = deviceProfile ?: viewModel.currentDeviceProfile,
onConfirm = {
showEditDeviceProfileDialog = false
if (deviceProfile != null) {
viewModel.installProfile(it)
} else {
viewModel.setDeviceProfile(it)
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/*"
putExtra(Intent.EXTRA_TITLE, "${node!!.num.toUInt()}.cfg")
}
exportConfigLauncher.launch(intent)
}
},
onDismiss = {
showEditDeviceProfileDialog = false
viewModel.setDeviceProfile(null)
}
)
}
if (isWaiting) {
PacketResponseStateDialog(
state = radioConfigState.responseState,
onDismiss = {
showEditDeviceProfileDialog = false
viewModel.clearPacketResponse()
},
onComplete = {
val route = radioConfigState.route
if (ConfigRoute.entries.any { it.name == route } ||
ModuleRoute.entries.any { it.name == route }) {
onNavigate(route)
viewModel.clearPacketResponse()
}
},
)
}
RadioConfigItemList(
enabled = connected && !isWaiting,
isLocal = isLocal,
modifier = modifier,
onRouteClick = { route ->
viewModel.setResponseStateLoading(route)
},
onImport = {
viewModel.clearPacketResponse()
viewModel.setDeviceProfile(null)
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/*"
}
importConfigLauncher.launch(intent)
},
onExport = {
viewModel.clearPacketResponse()
viewModel.setDeviceProfile(null)
showEditDeviceProfileDialog = true
},
)
}
@Composable
private fun NavCard(
title: String,