kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
Flatten `BluetoothViewModel` (#3138)
rodzic
eedc3ef963
commit
f2d29d4582
|
@ -42,7 +42,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import com.geeksville.mesh.android.GeeksvilleApplication
|
||||
import com.geeksville.mesh.android.Logging
|
||||
import com.geeksville.mesh.android.prefs.UiPrefs
|
||||
import com.geeksville.mesh.model.BluetoothViewModel
|
||||
import com.geeksville.mesh.model.UIViewModel
|
||||
import com.geeksville.mesh.navigation.DEEP_LINK_BASE_URI
|
||||
import com.geeksville.mesh.ui.MainScreen
|
||||
|
@ -58,7 +57,6 @@ import javax.inject.Inject
|
|||
class MainActivity :
|
||||
AppCompatActivity(),
|
||||
Logging {
|
||||
private val bluetoothViewModel: BluetoothViewModel by viewModels()
|
||||
private val model: UIViewModel by viewModels()
|
||||
|
||||
// This is aware of the Activity lifecycle and handles binding to the mesh service.
|
||||
|
@ -108,7 +106,7 @@ class MainActivity :
|
|||
|
||||
val appIntroCompleted by model.appIntroCompleted.collectAsStateWithLifecycle()
|
||||
if (appIntroCompleted) {
|
||||
MainScreen(uIViewModel = model, bluetoothViewModel = bluetoothViewModel)
|
||||
MainScreen(uIViewModel = model)
|
||||
} else {
|
||||
AppIntroductionScreen(
|
||||
onDone = {
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.model
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.geeksville.mesh.repository.bluetooth.BluetoothRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
|
||||
/** Thin view model which adapts the view layer to the `BluetoothRepository`. */
|
||||
@HiltViewModel
|
||||
class BluetoothViewModel @Inject constructor(private val bluetoothRepository: BluetoothRepository) : ViewModel() {
|
||||
/** Called when permissions have been updated. This causes an explicit refresh of the bluetooth state. */
|
||||
fun permissionsUpdated() = bluetoothRepository.refreshState()
|
||||
|
||||
val enabled = bluetoothRepository.state.map { it.enabled }
|
||||
}
|
|
@ -24,12 +24,11 @@ import androidx.navigation.NavHostController
|
|||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.navDeepLink
|
||||
import androidx.navigation.navigation
|
||||
import com.geeksville.mesh.model.BluetoothViewModel
|
||||
import com.geeksville.mesh.ui.connections.ConnectionsScreen
|
||||
import com.geeksville.mesh.ui.settings.radio.components.LoRaConfigScreen
|
||||
|
||||
/** Navigation graph for for the top level ConnectionsScreen - [ConnectionsRoutes.Connections]. */
|
||||
fun NavGraphBuilder.connectionsGraph(navController: NavHostController, bluetoothViewModel: BluetoothViewModel) {
|
||||
fun NavGraphBuilder.connectionsGraph(navController: NavHostController) {
|
||||
@Suppress("ktlint:standard:max-line-length")
|
||||
navigation<ConnectionsRoutes.ConnectionsGraph>(startDestination = ConnectionsRoutes.Connections) {
|
||||
composable<ConnectionsRoutes.Connections>(
|
||||
|
@ -40,7 +39,6 @@ fun NavGraphBuilder.connectionsGraph(navController: NavHostController, bluetooth
|
|||
val parentEntry =
|
||||
remember(backStackEntry) { navController.getBackStackEntry(ConnectionsRoutes.ConnectionsGraph) }
|
||||
ConnectionsScreen(
|
||||
bluetoothViewModel = bluetoothViewModel,
|
||||
radioConfigViewModel = hiltViewModel(parentEntry),
|
||||
onClickNodeChip = {
|
||||
navController.navigate(NodesRoutes.NodeDetailGraph(it)) {
|
||||
|
|
|
@ -81,7 +81,6 @@ import com.geeksville.mesh.android.AddNavigationTracking
|
|||
import com.geeksville.mesh.android.BuildUtils.debug
|
||||
import com.geeksville.mesh.android.setAttributes
|
||||
import com.geeksville.mesh.model.BTScanModel
|
||||
import com.geeksville.mesh.model.BluetoothViewModel
|
||||
import com.geeksville.mesh.model.DeviceVersion
|
||||
import com.geeksville.mesh.model.Node
|
||||
import com.geeksville.mesh.model.UIViewModel
|
||||
|
@ -148,11 +147,7 @@ enum class TopLevelDestination(@StringRes val label: Int, val icon: ImageVector,
|
|||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPermissionsApi::class)
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
@Composable
|
||||
fun MainScreen(
|
||||
uIViewModel: UIViewModel = hiltViewModel(),
|
||||
bluetoothViewModel: BluetoothViewModel = hiltViewModel(),
|
||||
scanModel: BTScanModel = hiltViewModel(),
|
||||
) {
|
||||
fun MainScreen(uIViewModel: UIViewModel = hiltViewModel(), scanModel: BTScanModel = hiltViewModel()) {
|
||||
val navController = rememberNavController()
|
||||
val connectionState by uIViewModel.connectionState.collectAsStateWithLifecycle()
|
||||
val requestChannelSet by uIViewModel.requestChannelSet.collectAsStateWithLifecycle()
|
||||
|
@ -396,7 +391,7 @@ fun MainScreen(
|
|||
nodesGraph(navController, uiViewModel = uIViewModel)
|
||||
mapGraph(navController, uiViewModel = uIViewModel)
|
||||
channelsGraph(navController, uiViewModel = uIViewModel)
|
||||
connectionsGraph(navController, bluetoothViewModel)
|
||||
connectionsGraph(navController)
|
||||
settingsGraph(navController)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import com.geeksville.mesh.ConfigProtos
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.model.BTScanModel
|
||||
import com.geeksville.mesh.model.BluetoothViewModel
|
||||
import com.geeksville.mesh.model.DeviceListEntry
|
||||
import com.geeksville.mesh.model.Node
|
||||
import com.geeksville.mesh.navigation.ConfigRoute
|
||||
|
@ -102,7 +101,6 @@ fun String?.isIPAddress(): Boolean = if (Build.VERSION.SDK_INT < Build.VERSION_C
|
|||
fun ConnectionsScreen(
|
||||
connectionsViewModel: ConnectionsViewModel = hiltViewModel(),
|
||||
scanModel: BTScanModel = hiltViewModel(),
|
||||
bluetoothViewModel: BluetoothViewModel = hiltViewModel(),
|
||||
radioConfigViewModel: RadioConfigViewModel = hiltViewModel(),
|
||||
onClickNodeChip: (Int) -> Unit,
|
||||
onNavigateToSettings: () -> Unit,
|
||||
|
@ -120,7 +118,7 @@ fun ConnectionsScreen(
|
|||
val info by connectionsViewModel.myNodeInfo.collectAsStateWithLifecycle()
|
||||
val ourNode by connectionsViewModel.ourNodeInfo.collectAsStateWithLifecycle()
|
||||
val selectedDevice by scanModel.selectedNotNullFlow.collectAsStateWithLifecycle()
|
||||
val bluetoothEnabled by bluetoothViewModel.enabled.collectAsStateWithLifecycle(false)
|
||||
val bluetoothState by connectionsViewModel.bluetoothState.collectAsStateWithLifecycle()
|
||||
val regionUnset = config.lora.region == ConfigProtos.Config.LoRaConfig.RegionCode.UNSET
|
||||
|
||||
val bleDevices by scanModel.bleDevicesForUi.collectAsStateWithLifecycle()
|
||||
|
@ -264,7 +262,7 @@ fun ConnectionsScreen(
|
|||
btDevices = bleDevices,
|
||||
selectedDevice = selectedDevice,
|
||||
scanModel = scanModel,
|
||||
bluetoothEnabled = bluetoothEnabled,
|
||||
bluetoothEnabled = bluetoothState.enabled,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import com.geeksville.mesh.android.prefs.UiPrefs
|
|||
import com.geeksville.mesh.database.NodeRepository
|
||||
import com.geeksville.mesh.database.entity.MyNodeEntity
|
||||
import com.geeksville.mesh.model.Node
|
||||
import com.geeksville.mesh.repository.bluetooth.BluetoothRepository
|
||||
import com.geeksville.mesh.repository.datastore.RadioConfigRepository
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
@ -37,8 +38,9 @@ import javax.inject.Inject
|
|||
class ConnectionsViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
private val radioConfigRepository: RadioConfigRepository,
|
||||
private val nodeRepository: NodeRepository,
|
||||
radioConfigRepository: RadioConfigRepository,
|
||||
nodeRepository: NodeRepository,
|
||||
bluetoothRepository: BluetoothRepository,
|
||||
private val uiPrefs: UiPrefs,
|
||||
) : ViewModel() {
|
||||
val localConfig: StateFlow<LocalConfig> =
|
||||
|
@ -48,14 +50,13 @@ constructor(
|
|||
LocalConfig.getDefaultInstance(),
|
||||
)
|
||||
|
||||
val connectionState
|
||||
get() = radioConfigRepository.connectionState
|
||||
val connectionState = radioConfigRepository.connectionState
|
||||
|
||||
val myNodeInfo: StateFlow<MyNodeEntity?>
|
||||
get() = nodeRepository.myNodeInfo
|
||||
val myNodeInfo: StateFlow<MyNodeEntity?> = nodeRepository.myNodeInfo
|
||||
|
||||
val ourNodeInfo: StateFlow<Node?>
|
||||
get() = nodeRepository.ourNodeInfo
|
||||
val ourNodeInfo: StateFlow<Node?> = nodeRepository.ourNodeInfo
|
||||
|
||||
val bluetoothState = bluetoothRepository.state
|
||||
|
||||
private val _hasShownNotPairedWarning = MutableStateFlow(uiPrefs.hasShownNotPairedWarning)
|
||||
val hasShownNotPairedWarning: StateFlow<Boolean> = _hasShownNotPairedWarning.asStateFlow()
|
||||
|
|
Ładowanie…
Reference in New Issue