diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 97587507d..cce84c5d2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -200,6 +200,7 @@ dependencies { implementation(projects.feature.intro) implementation(projects.feature.map) implementation(projects.feature.node) + implementation(projects.feature.settings) // Bundles implementation(libs.bundles.markdown) diff --git a/app/detekt-baseline.xml b/app/detekt-baseline.xml index 8ea03a869..8e02cdb26 100644 --- a/app/detekt-baseline.xml +++ b/app/detekt-baseline.xml @@ -8,10 +8,6 @@ CommentWrapping:SignalMetrics.kt$Metric.SNR$/* Selected 12 as the max to get 4 equal vertical sections. */ ComposableNaming:NodeDetailScreen.kt$notesSection ComposableParamOrder:Channel.kt$ChannelScreen - ComposableParamOrder:ChannelSettingsItemList.kt$ChannelSettingsItemList - ComposableParamOrder:Debug.kt$DecodedPayloadBlock - ComposableParamOrder:DebugSearch.kt$DebugSearchState - ComposableParamOrder:DebugSearch.kt$DebugSearchStateviewModelDefaults ComposableParamOrder:DeviceMetrics.kt$DeviceMetricsChart ComposableParamOrder:EmptyStateContent.kt$EmptyStateContent ComposableParamOrder:EnvironmentCharts.kt$ChartContent @@ -19,7 +15,6 @@ ComposableParamOrder:EnvironmentCharts.kt$MetricPlottingCanvas ComposableParamOrder:HostMetricsLog.kt$HostMetricsItem ComposableParamOrder:HostMetricsLog.kt$LogLine - ComposableParamOrder:MapReportingPreference.kt$MapReportingPreference ComposableParamOrder:Message.kt$MessageScreen ComposableParamOrder:Message.kt$QuickChatRow ComposableParamOrder:MessageActions.kt$MessageActions @@ -29,7 +24,6 @@ ComposableParamOrder:MessageList.kt$MessageList ComposableParamOrder:NodeDetailScreen.kt$DeviceActions ComposableParamOrder:NodeDetailScreen.kt$EnvironmentMetrics - ComposableParamOrder:NodeDetailScreen.kt$NodeActionButton ComposableParamOrder:NodeDetailScreen.kt$NodeDetailList ComposableParamOrder:PaxMetrics.kt$PaxMetricsChart ComposableParamOrder:PowerMetrics.kt$PowerMetricsChart @@ -37,11 +31,7 @@ ComposableParamOrder:Share.kt$ShareScreen ComposableParamOrder:SignalMetrics.kt$SignalMetricsChart ComposableParamOrder:TopLevelNavIcon.kt$ConnectionsNavIcon - ComposableParamOrder:WarningDialog.kt$WarningDialog CyclomaticComplexMethod:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket) - CyclomaticComplexMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - CyclomaticComplexMethod:PositionConfigItemList.kt$@OptIn(ExperimentalPermissionsApi::class) @Composable fun PositionConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - CyclomaticComplexMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket) EmptyClassBlock:DebugLogFile.kt$BinaryLogFile${ } EmptyFunctionBlock:NopInterface.kt$NopInterface${ } EmptyFunctionBlock:NsdManager.kt$<no name provided>${ } @@ -71,44 +61,20 @@ LambdaParameterEventTrailing:Message.kt$onClick LambdaParameterEventTrailing:Message.kt$onSendMessage LambdaParameterEventTrailing:MessageList.kt$onReply - LambdaParameterEventTrailing:NodeDetailScreen.kt$onClick LambdaParameterEventTrailing:NodeDetailScreen.kt$onSaveNotes LambdaParameterEventTrailing:QuickChat.kt$onNavigateUp LambdaParameterEventTrailing:TracerouteLog.kt$onNavigateUp LambdaParameterInRestartableEffect:Channel.kt$onConfirm LambdaParameterInRestartableEffect:MessageList.kt$onUnreadChanged LargeClass:MeshService.kt$MeshService : Service - LongMethod:AmbientLightingConfigItemList.kt$@Composable fun AmbientLightingConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:AudioConfigItemList.kt$@Composable fun AudioConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:CannedMessageConfigItemList.kt$@Composable fun CannedMessageConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:DetectionSensorConfigItemList.kt$@Composable fun DetectionSensorConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:DeviceConfigItemList.kt$@Composable fun DeviceConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:DisplayConfigItemList.kt$@Composable fun DisplayConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) LongMethod:EnvironmentMetrics.kt$@Composable fun EnvironmentMetricsScreen(viewModel: MetricsViewModel = hiltViewModel(), onNavigateUp: () -> Unit) - LongMethod:ExternalNotificationConfigItemList.kt$@Composable fun ExternalNotificationConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:LoRaConfigItemList.kt$@Composable fun LoRaConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) LongMethod:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket) - LongMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:PositionConfigItemList.kt$@OptIn(ExperimentalPermissionsApi::class) @Composable fun PositionConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:PowerConfigItemList.kt$@Composable fun PowerConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket) - LongMethod:SecurityConfigItemList.kt$@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun SecurityConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:SerialConfigItemList.kt$@Composable fun SerialConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:StoreForwardConfigItemList.kt$@Composable fun StoreForwardConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:TelemetryConfigItemList.kt$@Composable fun TelemetryConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) - LongMethod:UserConfigItemList.kt$@Composable fun UserConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) LongParameterList:MessageViewModel.kt$MessageViewModel$( private val nodeRepository: NodeRepository, radioConfigRepository: RadioConfigRepository, quickChatActionRepository: QuickChatActionRepository, private val serviceRepository: ServiceRepository, private val packetRepository: PacketRepository, private val uiPrefs: UiPrefs, private val meshServiceNotifications: MeshServiceNotifications, ) MagicNumber:BluetoothInterface.kt$BluetoothInterface$1000 MagicNumber:BluetoothInterface.kt$BluetoothInterface$500 MagicNumber:BluetoothInterface.kt$BluetoothInterface$512 MagicNumber:Contacts.kt$7 MagicNumber:Contacts.kt$8 - MagicNumber:Debug.kt$3 - MagicNumber:EditChannelDialog.kt$16 - MagicNumber:EditChannelDialog.kt$32 - MagicNumber:LocationRepository.kt$LocationRepository$1000L - MagicNumber:LocationRepository.kt$LocationRepository$30 - MagicNumber:LocationRepository.kt$LocationRepository$31 MagicNumber:MQTTRepository.kt$MQTTRepository$512 MagicNumber:MeshService.kt$MeshService$0xffffffff MagicNumber:MeshService.kt$MeshService$1000 @@ -122,8 +88,6 @@ MagicNumber:MetricsViewModel.kt$MetricsViewModel$1000L MagicNumber:MetricsViewModel.kt$MetricsViewModel$1e-5 MagicNumber:MetricsViewModel.kt$MetricsViewModel$1e-7 - MagicNumber:PacketResponseStateDialog.kt$100 - MagicNumber:PowerConfigItemList.kt$3600 MagicNumber:ProbeTableProvider.kt$ProbeTableProvider$21972 MagicNumber:ProbeTableProvider.kt$ProbeTableProvider$32809 MagicNumber:ProbeTableProvider.kt$ProbeTableProvider$6790 @@ -149,8 +113,6 @@ ModifierClickableOrder:Channel.kt$clickable(onClick = onClick) ModifierMissing:BLEDevices.kt$BLEDevices ModifierMissing:Channel.kt$ChannelScreen - ModifierMissing:ChannelSettingsItemList.kt$ChannelSelection - ModifierMissing:CleanNodeDatabaseScreen.kt$CleanNodeDatabaseScreen ModifierMissing:CommonCharts.kt$ChartHeader ModifierMissing:CommonCharts.kt$Legend ModifierMissing:CommonCharts.kt$TimeLabels @@ -162,26 +124,18 @@ ModifierMissing:EmptyStateContent.kt$EmptyStateContent ModifierMissing:EnvironmentMetrics.kt$EnvironmentMetricsScreen ModifierMissing:HostMetricsLog.kt$HostMetricsLogScreen - ModifierMissing:LoRaConfigItemList.kt$LoRaConfigScreen ModifierMissing:Main.kt$MainScreen - ModifierMissing:MapReportingPreference.kt$MapReportingPreference ModifierMissing:MessageActions.kt$MessageStatusButton ModifierMissing:MessageActions.kt$ReactionButton ModifierMissing:MessageActions.kt$ReplyButton - ModifierMissing:NetworkConfigItemList.kt$NetworkConfigScreen ModifierMissing:NetworkDevices.kt$NetworkDevices ModifierMissing:NodeListScreen.kt$NodeListScreen ModifierMissing:PaxMetrics.kt$PaxMetricsItem ModifierMissing:PaxMetrics.kt$PaxMetricsScreen - ModifierMissing:PositionConfigItemList.kt$PositionConfigScreen ModifierMissing:PositionLog.kt$PositionItem ModifierMissing:PositionLog.kt$PositionLogScreen ModifierMissing:PowerMetrics.kt$PowerMetricsScreen - ModifierMissing:RadioConfig.kt$RadioConfigItemList - ModifierMissing:RadioConfigScreenList.kt$RadioConfigScreenList ModifierMissing:Reaction.kt$ReactionDialog - ModifierMissing:SecurityConfigItemList.kt$SecurityConfigScreen - ModifierMissing:SettingsScreen.kt$SettingsScreen ModifierMissing:Share.kt$ShareScreen ModifierMissing:SharedContactDialog.kt$SharedContactDialog ModifierMissing:SignalMetrics.kt$SignalMetricsScreen @@ -189,8 +143,6 @@ ModifierNotUsedAtRoot:DeviceMetrics.kt$modifier = modifier.weight(weight = Y_AXIS_WEIGHT) ModifierNotUsedAtRoot:DeviceMetrics.kt$modifier = modifier.width(dp) ModifierNotUsedAtRoot:DeviceMetrics.kt$modifier.width(dp) - ModifierNotUsedAtRoot:EditChannelDialog.kt$modifier = modifier.weight(1f) - ModifierNotUsedAtRoot:EditDeviceProfileDialog.kt$modifier = modifier.weight(1f) ModifierNotUsedAtRoot:EnvironmentCharts.kt$modifier = modifier.width(dp) ModifierNotUsedAtRoot:EnvironmentCharts.kt$modifier.width(dp) ModifierNotUsedAtRoot:PaxMetrics.kt$modifier.width(dp) @@ -224,7 +176,6 @@ ModifierReused:SignalMetrics.kt$YAxisLabels( modifier = modifier.weight(weight = Y_AXIS_WEIGHT), Metric.SNR.color, minValue = Metric.SNR.min, maxValue = Metric.SNR.max, ) ModifierWithoutDefault:CommonCharts.kt$modifier ModifierWithoutDefault:EnvironmentCharts.kt$modifier - MultipleEmitters:CleanNodeDatabaseScreen.kt$NodesDeletionPreview MultipleEmitters:CommonCharts.kt$LegendLabel MultipleEmitters:DeviceMetrics.kt$DeviceMetricsChart MultipleEmitters:EnvironmentCharts.kt$EnvironmentMetricsChart @@ -232,13 +183,11 @@ MultipleEmitters:NodeDetailScreen.kt$MetricsSection MultipleEmitters:PaxMetrics.kt$PaxMetricsChart MultipleEmitters:PowerMetrics.kt$PowerMetricsChart - MultipleEmitters:RadioConfig.kt$RadioConfigItemList MultipleEmitters:SignalMetrics.kt$SignalMetricsChart MutableStateAutoboxing:Contacts.kt$mutableStateOf(2) MutableStateParam:MessageList.kt$selectedIds NestedBlockDepth:MeshService.kt$MeshService$private fun handleReceivedAdmin(fromNodeNum: Int, a: AdminProtos.AdminMessage) NestedBlockDepth:MeshService.kt$MeshService$private fun handleReceivedData(packet: MeshPacket) - NestedBlockDepth:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket) NewLineAtEndOfFile:BLEException.kt$com.geeksville.mesh.service.BLEException.kt NewLineAtEndOfFile:BluetoothInterfaceFactory.kt$com.geeksville.mesh.repository.radio.BluetoothInterfaceFactory.kt NewLineAtEndOfFile:BluetoothRepositoryModule.kt$com.geeksville.mesh.repository.bluetooth.BluetoothRepositoryModule.kt @@ -266,27 +215,17 @@ NoEmptyClassBody:DebugLogFile.kt$BinaryLogFile${ } NoSemicolons:DateUtils.kt$DateUtils$; OptionalAbstractKeyword:SyncContinuation.kt$Continuation$abstract - ParameterNaming:ChannelSettingsItemList.kt$onPositiveClicked - ParameterNaming:ChannelSettingsItemList.kt$onSelected - ParameterNaming:CleanNodeDatabaseScreen.kt$onCheckedChanged - ParameterNaming:CleanNodeDatabaseScreen.kt$onDaysChanged ParameterNaming:ContactSharing.kt$onSharedContactRequested ParameterNaming:Contacts.kt$onDeleteSelected ParameterNaming:Contacts.kt$onMuteSelected - ParameterNaming:MapReportingPreference.kt$onMapReportingEnabledChanged - ParameterNaming:MapReportingPreference.kt$onPositionPrecisionChanged - ParameterNaming:MapReportingPreference.kt$onPublishIntervalSecsChanged - ParameterNaming:MapReportingPreference.kt$onShouldReportLocationChanged ParameterNaming:MessageList.kt$onUnreadChanged ParameterNaming:NodeDetailScreen.kt$onFirmwareSelected ParameterNaming:UsbDevices.kt$onDeviceSelected PreviewPublic:Channel.kt$ModemPresetInfoPreview PreviewPublic:EmptyStateContent.kt$EmptyStateContentPreview - PreviewPublic:MapReportingPreference.kt$MapReportingPreview PreviewPublic:Reaction.kt$ReactionItemPreview PreviewPublic:Reaction.kt$ReactionRowPreview RethrowCaughtException:SyncContinuation.kt$Continuation$throw ex - ReturnCount:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket) SwallowedException:BluetoothInterface.kt$BluetoothInterface$ex: CancellationException SwallowedException:Exceptions.kt$ex: Throwable SwallowedException:MeshService.kt$MeshService$ex: BLEException @@ -299,13 +238,10 @@ TooGenericExceptionCaught:BTScanModel.kt$BTScanModel$ex: Throwable TooGenericExceptionCaught:BluetoothInterface.kt$BluetoothInterface$ex: Exception TooGenericExceptionCaught:Exceptions.kt$ex: Throwable - TooGenericExceptionCaught:LanguageUtils.kt$LanguageUtils$e: Exception - TooGenericExceptionCaught:LocationRepository.kt$LocationRepository$e: Exception TooGenericExceptionCaught:MQTTRepository.kt$MQTTRepository$ex: Exception TooGenericExceptionCaught:MeshService.kt$MeshService$ex: Exception TooGenericExceptionCaught:MeshService.kt$MeshService.<no name provided>$ex: Exception TooGenericExceptionCaught:MeshServiceStarter.kt$ServiceStarter$ex: Exception - TooGenericExceptionCaught:RadioConfigViewModel.kt$RadioConfigViewModel$ex: Exception TooGenericExceptionCaught:SafeBluetooth.kt$SafeBluetooth$ex: Exception TooGenericExceptionCaught:SafeBluetooth.kt$SafeBluetooth$ex: NullPointerException TooGenericExceptionCaught:SyncContinuation.kt$Continuation$ex: Throwable @@ -321,16 +257,12 @@ TooManyFunctions:MeshService.kt$MeshService$<no name provided> : Stub TooManyFunctions:MessageViewModel.kt$MessageViewModel : ViewModel TooManyFunctions:NodeDetailScreen.kt$com.geeksville.mesh.ui.node.NodeDetailScreen.kt - TooManyFunctions:RadioConfigViewModel.kt$RadioConfigViewModel : ViewModel TooManyFunctions:RadioInterfaceService.kt$RadioInterfaceService TooManyFunctions:SafeBluetooth.kt$SafeBluetooth : Closeable TooManyFunctions:UIState.kt$UIViewModel : ViewModel TopLevelPropertyNaming:Constants.kt$const val prefix = "com.geeksville.mesh" - UnusedParameter:ChannelSettingsItemList.kt$onBack: () -> Unit - UnusedParameter:ChannelSettingsItemList.kt$title: String UtilityClassWithPublicConstructor:NetworkRepositoryModule.kt$NetworkRepositoryModule ViewModelForwarding:Main.kt$VersionChecks(uIViewModel) - ViewModelInjection:DebugSearch.kt$viewModel Wrapping:Message.kt${ event -> when (event) { is MessageScreenEvent.SendMessage -> { viewModel.sendMessage(event.text, contactKey, event.replyingToPacketId) if (event.replyingToPacketId != null) replyingToPacketId = null messageInputState.clearText() } is MessageScreenEvent.SendReaction -> viewModel.sendReaction(event.emoji, event.messageId, contactKey) is MessageScreenEvent.DeleteMessages -> { viewModel.deleteMessages(event.ids) selectedMessageIds.value = emptySet() showDeleteDialog = false } is MessageScreenEvent.ClearUnreadCount -> viewModel.clearUnreadCount(contactKey, event.lastReadMessageId) is MessageScreenEvent.NodeDetails -> navigateToNodeDetails(event.node.num) is MessageScreenEvent.SetTitle -> viewModel.setTitle(event.title) is MessageScreenEvent.NavigateToMessages -> navigateToMessages(event.contactKey) is MessageScreenEvent.NavigateToNodeDetails -> navigateToNodeDetails(event.nodeNum) MessageScreenEvent.NavigateBack -> onNavigateBack() is MessageScreenEvent.CopyToClipboard -> { clipboardManager.nativeClipboard.setPrimaryClip(ClipData.newPlainText(event.text, event.text)) selectedMessageIds.value = emptySet() } } } diff --git a/app/src/main/java/com/geeksville/mesh/model/UIState.kt b/app/src/main/java/com/geeksville/mesh/model/UIState.kt index 85751f9ff..8acdfd751 100644 --- a/app/src/main/java/com/geeksville/mesh/model/UIState.kt +++ b/app/src/main/java/com/geeksville/mesh/model/UIState.kt @@ -29,15 +29,11 @@ import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope import com.geeksville.mesh.AdminProtos import com.geeksville.mesh.AppOnlyProtos -import com.geeksville.mesh.ChannelProtos -import com.geeksville.mesh.ChannelProtos.ChannelSettings import com.geeksville.mesh.ConfigProtos.Config import com.geeksville.mesh.LocalOnlyProtos.LocalConfig import com.geeksville.mesh.LocalOnlyProtos.LocalModuleConfig import com.geeksville.mesh.MeshProtos -import com.geeksville.mesh.channel import com.geeksville.mesh.channelSet -import com.geeksville.mesh.channelSettings import com.geeksville.mesh.config import com.geeksville.mesh.copy import com.geeksville.mesh.repository.radio.MeshActivity @@ -106,34 +102,6 @@ fun getInitials(fullName: String): String { private fun String.withoutEmojis(): String = filterNot { char -> char.isSurrogate() } -/** - * Builds a [Channel] list from the difference between two [ChannelSettings] lists. Only changes are included in the - * resulting list. - * - * @param new The updated [ChannelSettings] list. - * @param old The current [ChannelSettings] list (required when disabling unused channels). - * @return A [Channel] list containing only the modified channels. - */ -internal fun getChannelList(new: List, old: List): List = - buildList { - for (i in 0..maxOf(old.lastIndex, new.lastIndex)) { - if (old.getOrNull(i) != new.getOrNull(i)) { - add( - channel { - role = - when (i) { - 0 -> ChannelProtos.Channel.Role.PRIMARY - in 1..new.lastIndex -> ChannelProtos.Channel.Role.SECONDARY - else -> ChannelProtos.Channel.Role.DISABLED - } - index = i - settings = new.getOrNull(i) ?: channelSettings {} - }, - ) - } - } - } - data class Contact( val contactKey: String, val shortName: String, diff --git a/app/src/main/java/com/geeksville/mesh/navigation/ChannelsNavigation.kt b/app/src/main/java/com/geeksville/mesh/navigation/ChannelsNavigation.kt index e84cf926b..83974f67a 100644 --- a/app/src/main/java/com/geeksville/mesh/navigation/ChannelsNavigation.kt +++ b/app/src/main/java/com/geeksville/mesh/navigation/ChannelsNavigation.kt @@ -24,11 +24,12 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.composable import androidx.navigation.navDeepLink import androidx.navigation.navigation -import com.geeksville.mesh.ui.settings.radio.components.ChannelConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.LoRaConfigScreen import com.geeksville.mesh.ui.sharing.ChannelScreen import org.meshtastic.core.navigation.ChannelsRoutes import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI +import org.meshtastic.feature.settings.navigation.ConfigRoute +import org.meshtastic.feature.settings.radio.component.ChannelConfigScreen +import org.meshtastic.feature.settings.radio.component.LoRaConfigScreen /** Navigation graph for for the top level ChannelScreen - [ChannelsRoutes.Channels]. */ fun NavGraphBuilder.channelsGraph(navController: NavHostController) { diff --git a/app/src/main/java/com/geeksville/mesh/navigation/ConnectionsNavigation.kt b/app/src/main/java/com/geeksville/mesh/navigation/ConnectionsNavigation.kt index 6663ead2a..976fda5dc 100644 --- a/app/src/main/java/com/geeksville/mesh/navigation/ConnectionsNavigation.kt +++ b/app/src/main/java/com/geeksville/mesh/navigation/ConnectionsNavigation.kt @@ -25,12 +25,12 @@ import androidx.navigation.compose.composable import androidx.navigation.navDeepLink import androidx.navigation.navigation import com.geeksville.mesh.ui.connections.ConnectionsScreen -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel -import com.geeksville.mesh.ui.settings.radio.components.LoRaConfigScreen import org.meshtastic.core.navigation.ConnectionsRoutes import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI import org.meshtastic.core.navigation.NodesRoutes import org.meshtastic.core.navigation.SettingsRoutes +import org.meshtastic.feature.settings.radio.RadioConfigViewModel +import org.meshtastic.feature.settings.radio.component.LoRaConfigScreen /** Navigation graph for for the top level ConnectionsScreen - [ConnectionsRoutes.Connections]. */ fun NavGraphBuilder.connectionsGraph(navController: NavHostController) { diff --git a/app/src/main/java/com/geeksville/mesh/repository/radio/BluetoothInterface.kt b/app/src/main/java/com/geeksville/mesh/repository/radio/BluetoothInterface.kt index feb2e9c1b..1ed6fb51c 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/radio/BluetoothInterface.kt +++ b/app/src/main/java/com/geeksville/mesh/repository/radio/BluetoothInterface.kt @@ -37,6 +37,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import org.meshtastic.core.analytics.platform.PlatformAnalytics import org.meshtastic.core.model.util.anonymize import timber.log.Timber import java.lang.reflect.Method @@ -104,6 +105,7 @@ constructor( context: Application, bluetoothRepository: BluetoothRepository, private val service: RadioInterfaceService, + analytics: PlatformAnalytics, @Assisted val address: String, ) : IRadioInterface { @@ -195,7 +197,7 @@ constructor( Timber.i("Creating radio interface service. device=${address.anonymize}") // Note this constructor also does no comm - val s = SafeBluetooth(context, device) + val s = SafeBluetooth(context, device, analytics) safe = s startConnect() diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt index 17997c93e..4a56d43d5 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -40,8 +40,6 @@ import com.geeksville.mesh.MeshProtos import com.geeksville.mesh.MeshProtos.FromRadio.PayloadVariantCase import com.geeksville.mesh.MeshProtos.MeshPacket import com.geeksville.mesh.MeshProtos.ToRadio -import com.geeksville.mesh.MeshUtilApplication -import com.geeksville.mesh.MeshUtilApplication.Companion.analytics import com.geeksville.mesh.ModuleConfigProtos import com.geeksville.mesh.PaxcountProtos import com.geeksville.mesh.Portnums @@ -54,7 +52,6 @@ import com.geeksville.mesh.copy import com.geeksville.mesh.fromRadio import com.geeksville.mesh.model.NO_DEVICE_SELECTED import com.geeksville.mesh.position -import com.geeksville.mesh.repository.location.LocationRepository import com.geeksville.mesh.repository.network.MQTTRepository import com.geeksville.mesh.repository.radio.RadioInterfaceService import com.geeksville.mesh.telemetry @@ -77,7 +74,9 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.meshtastic.core.analytics.DataPair +import org.meshtastic.core.analytics.platform.PlatformAnalytics import org.meshtastic.core.common.hasLocationPermission +import org.meshtastic.core.data.repository.LocationRepository import org.meshtastic.core.data.repository.MeshLogRepository import org.meshtastic.core.data.repository.NodeRepository import org.meshtastic.core.data.repository.PacketRepository @@ -152,6 +151,8 @@ class MeshService : Service() { @Inject lateinit var serviceBroadcasts: MeshServiceBroadcasts + @Inject lateinit var analytics: PlatformAnalytics + private val tracerouteStartTimes = ConcurrentHashMap() companion object { @@ -869,13 +870,9 @@ class MeshService : Service() { serviceBroadcasts.broadcastReceivedData(dataPacket) } - MeshUtilApplication.analytics.track("num_data_receive", DataPair("num_data_receive", 1)) + analytics.track("num_data_receive", DataPair("num_data_receive", 1)) - MeshUtilApplication.analytics.track( - "data_receive", - DataPair("num_bytes", bytes.size), - DataPair("type", data.portnumValue), - ) + analytics.track("data_receive", DataPair("num_bytes", bytes.size), DataPair("type", data.portnumValue)) } } } @@ -1122,7 +1119,7 @@ class MeshService : Service() { sendNow(p) sentPackets.add(p) } catch (ex: Exception) { - Timber.e("Error sending queued message:", ex) + Timber.e(ex, "Error sending queued message:") } } offlineSentPackets.removeAll(sentPackets) @@ -1239,7 +1236,7 @@ class MeshService : Service() { /** Send in analytics about mesh connection */ private fun reportConnection() { val radioModel = DataPair("radio_model", myNodeInfo?.model ?: "unknown") - MeshUtilApplication.analytics.track( + analytics.track( "mesh_connect", DataPair("num_nodes", numNodes), DataPair("num_online", numOnlineNodes), @@ -1266,10 +1263,7 @@ class MeshService : Service() { val now = System.currentTimeMillis() connectTimeMsec = 0L - MeshUtilApplication.analytics.track( - "connected_seconds", - DataPair("connected_seconds", (now - connectTimeMsec) / 1000.0), - ) + analytics.track("connected_seconds", DataPair("connected_seconds", (now - connectTimeMsec) / 1000.0)) } // Have our timeout fire in the appropriate number of seconds @@ -1298,12 +1292,8 @@ class MeshService : Service() { stopLocationRequests() stopMqttClientProxy() - MeshUtilApplication.analytics.track( - "mesh_disconnect", - DataPair("num_nodes", numNodes), - DataPair("num_online", numOnlineNodes), - ) - MeshUtilApplication.analytics.track("num_nodes", DataPair("num_nodes", numNodes)) + analytics.track("mesh_disconnect", DataPair("num_nodes", numNodes), DataPair("num_online", numOnlineNodes)) + analytics.track("num_nodes", DataPair("num_nodes", numNodes)) // broadcast an intent with our new connection state serviceBroadcasts.broadcastConnection() @@ -1315,7 +1305,7 @@ class MeshService : Service() { connectTimeMsec = System.currentTimeMillis() startConfig() } catch (ex: InvalidProtocolBufferException) { - Timber.e("Invalid protocol buffer sent by device - update device software and try again", ex) + Timber.e(ex, "Invalid protocol buffer sent by device - update device software and try again") } catch (ex: RadioNotConnectedException) { // note: no need to call startDeviceSleep(), because this exception could only have // reached us if it was @@ -2104,7 +2094,7 @@ class MeshService : Service() { try { sendNow(p) } catch (ex: Exception) { - Timber.e("Error sending message, so enqueueing", ex) + Timber.e(ex, "Error sending message, so enqueueing") enqueueForSending(p) } } else { @@ -2115,11 +2105,7 @@ class MeshService : Service() { // Keep a record of DataPackets, so GUIs can show proper chat history rememberDataPacket(p, false) - MeshUtilApplication.analytics.track( - "data_send", - DataPair("num_bytes", bytes.size), - DataPair("type", p.dataType), - ) + analytics.track("data_send", DataPair("num_bytes", bytes.size), DataPair("type", p.dataType)) } } diff --git a/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt index 5bf6cd962..afe855e21 100644 --- a/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt +++ b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt @@ -31,7 +31,6 @@ import android.os.Build import android.os.DeadObjectException import android.os.Handler import android.os.Looper -import com.geeksville.mesh.MeshUtilApplication.Companion.analytics import com.geeksville.mesh.concurrent.CallbackContinuation import com.geeksville.mesh.concurrent.Continuation import com.geeksville.mesh.concurrent.SyncContinuation @@ -43,6 +42,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.Runnable import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import org.meshtastic.core.analytics.platform.PlatformAnalytics import timber.log.Timber import java.io.Closeable import java.util.Random @@ -63,7 +63,11 @@ fun longBLEUUID(hexFour: String): UUID = UUID.fromString("0000$hexFour-0000-1000 * * This class fixes the API by using coroutines to let you safely do a series of BTLE operations. */ -class SafeBluetooth(private val context: Context, private val device: BluetoothDevice) : Closeable { +class SafeBluetooth( + private val context: Context, + private val device: BluetoothDevice, + private val analytics: PlatformAnalytics, +) : Closeable { // / Timeout before we declare a bluetooth operation failed (used for synchronous API operations only) var timeoutMsec = 20 * 1000L @@ -430,7 +434,7 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD try { it.completion.resumeWithException(ex) } catch (ex: Exception) { - Timber.e("Mystery exception, why were we informed about our own exceptions?", ex) + Timber.e(ex, "Mystery exception, why were we informed about our own exceptions?") } } workQueue.clear() diff --git a/app/src/main/java/com/geeksville/mesh/ui/Main.kt b/app/src/main/java/com/geeksville/mesh/ui/Main.kt index 7d66a0ae3..578689587 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Main.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Main.kt @@ -75,7 +75,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.geeksville.mesh.BuildConfig import com.geeksville.mesh.MeshProtos -import com.geeksville.mesh.MeshUtilApplication.Companion.analytics +import com.geeksville.mesh.MeshUtilApplication import com.geeksville.mesh.model.BTScanModel import com.geeksville.mesh.model.UIViewModel import com.geeksville.mesh.navigation.channelsGraph @@ -83,7 +83,6 @@ import com.geeksville.mesh.navigation.connectionsGraph import com.geeksville.mesh.navigation.contactsGraph import com.geeksville.mesh.navigation.mapGraph import com.geeksville.mesh.navigation.nodesGraph -import com.geeksville.mesh.navigation.settingsGraph import com.geeksville.mesh.repository.radio.MeshActivity import com.geeksville.mesh.service.MeshService import com.geeksville.mesh.ui.common.components.ScannedQrCodeDialog @@ -114,6 +113,7 @@ import org.meshtastic.core.ui.icon.Nodes import org.meshtastic.core.ui.icon.Settings import org.meshtastic.core.ui.theme.StatusColors.StatusBlue import org.meshtastic.core.ui.theme.StatusColors.StatusGreen +import org.meshtastic.feature.settings.navigation.settingsGraph import timber.log.Timber enum class TopLevelDestination(@StringRes val label: Int, val icon: ImageVector, val route: Route) { @@ -158,7 +158,7 @@ fun MainScreen(uIViewModel: UIViewModel = hiltViewModel(), scanModel: BTScanMode } } - analytics.addNavigationTrackingEffect(navController = navController) + MeshUtilApplication.analytics.addNavigationTrackingEffect(navController = navController) VersionChecks(uIViewModel) val alertDialogState by uIViewModel.currentAlert.collectAsStateWithLifecycle() diff --git a/app/src/main/java/com/geeksville/mesh/ui/common/components/ScannedQrCodeDialog.kt b/app/src/main/java/com/geeksville/mesh/ui/common/components/ScannedQrCodeDialog.kt index 591d42435..89059ae01 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/common/components/ScannedQrCodeDialog.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/common/components/ScannedQrCodeDialog.kt @@ -55,9 +55,9 @@ import com.geeksville.mesh.AppOnlyProtos.ChannelSet import com.geeksville.mesh.ConfigProtos.Config.LoRaConfig.ModemPreset import com.geeksville.mesh.channelSet import com.geeksville.mesh.copy -import com.geeksville.mesh.ui.settings.radio.components.ChannelSelection import org.meshtastic.core.model.Channel import org.meshtastic.core.strings.R +import org.meshtastic.feature.settings.radio.component.ChannelSelection @Composable fun ScannedQrCodeDialog( diff --git a/app/src/main/java/com/geeksville/mesh/ui/common/components/ScannedQrCodeViewModel.kt b/app/src/main/java/com/geeksville/mesh/ui/common/components/ScannedQrCodeViewModel.kt index 38b54cb8f..34d6f16df 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/common/components/ScannedQrCodeViewModel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/common/components/ScannedQrCodeViewModel.kt @@ -26,12 +26,12 @@ import com.geeksville.mesh.ConfigProtos.Config import com.geeksville.mesh.LocalOnlyProtos.LocalConfig import com.geeksville.mesh.channelSet import com.geeksville.mesh.config -import com.geeksville.mesh.model.getChannelList import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import org.meshtastic.core.data.repository.RadioConfigRepository +import org.meshtastic.core.proto.getChannelList import org.meshtastic.core.service.ServiceRepository import timber.log.Timber import javax.inject.Inject diff --git a/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsScreen.kt index a601a1443..0a6c746e0 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsScreen.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsScreen.kt @@ -55,15 +55,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.ConfigProtos import com.geeksville.mesh.model.BTScanModel import com.geeksville.mesh.model.DeviceListEntry -import com.geeksville.mesh.navigation.ConfigRoute -import com.geeksville.mesh.navigation.getNavRouteFrom import com.geeksville.mesh.ui.connections.components.BLEDevices import com.geeksville.mesh.ui.connections.components.ConnectionsSegmentedBar import com.geeksville.mesh.ui.connections.components.CurrentlyConnectedInfo import com.geeksville.mesh.ui.connections.components.NetworkDevices import com.geeksville.mesh.ui.connections.components.UsbDevices -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel -import com.geeksville.mesh.ui.settings.radio.components.PacketResponseStateDialog import com.google.accompanist.permissions.ExperimentalPermissionsApi import kotlinx.coroutines.delay import org.meshtastic.core.navigation.Route @@ -73,6 +69,10 @@ import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.MainAppBar import org.meshtastic.core.ui.component.SettingsItem import org.meshtastic.core.ui.component.TitledCard +import org.meshtastic.feature.settings.navigation.ConfigRoute +import org.meshtastic.feature.settings.navigation.getNavRouteFrom +import org.meshtastic.feature.settings.radio.RadioConfigViewModel +import org.meshtastic.feature.settings.radio.component.PacketResponseStateDialog fun String?.isIPAddress(): Boolean = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { @Suppress("DEPRECATION") diff --git a/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailScreen.kt index c77152a42..83e0a1f04 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailScreen.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/node/NodeDetailScreen.kt @@ -1121,31 +1121,6 @@ private fun PowerMetrics(node: Node) { } } -@Composable -fun NodeActionButton( - modifier: Modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp).height(48.dp), - title: String, - enabled: Boolean, - icon: ImageVector? = null, - iconTint: Color? = null, - onClick: () -> Unit, -) { - Button(onClick = { onClick() }, enabled = enabled, modifier = modifier) { - Row(verticalAlignment = Alignment.CenterVertically) { - if (icon != null) { - Icon( - imageVector = icon, - contentDescription = title, - modifier = Modifier.size(24.dp), - tint = iconTint ?: LocalContentColor.current, - ) - Spacer(modifier = Modifier.width(8.dp)) - } - Text(text = title, style = MaterialTheme.typography.bodyLarge, modifier = Modifier.weight(1f)) - } - } -} - @Preview(showBackground = true) @Composable private fun NodeDetailsPreview(@PreviewParameter(NodePreviewParameterProvider::class) node: Node) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/sharing/Channel.kt b/app/src/main/java/com/geeksville/mesh/ui/sharing/Channel.kt index cce17689e..97b5d4779 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/sharing/Channel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/sharing/Channel.kt @@ -95,12 +95,7 @@ import com.geeksville.mesh.ConfigProtos import com.geeksville.mesh.MeshUtilApplication.Companion.analytics import com.geeksville.mesh.channelSet import com.geeksville.mesh.copy -import com.geeksville.mesh.navigation.ConfigRoute -import com.geeksville.mesh.navigation.getNavRouteFrom import com.geeksville.mesh.ui.common.components.ScannedQrCodeDialog -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel -import com.geeksville.mesh.ui.settings.radio.components.ChannelSelection -import com.geeksville.mesh.ui.settings.radio.components.PacketResponseStateDialog import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState @@ -118,6 +113,11 @@ import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.AdaptiveTwoPane import org.meshtastic.core.ui.component.MainAppBar import org.meshtastic.core.ui.component.PreferenceFooter +import org.meshtastic.feature.settings.navigation.ConfigRoute +import org.meshtastic.feature.settings.navigation.getNavRouteFrom +import org.meshtastic.feature.settings.radio.RadioConfigViewModel +import org.meshtastic.feature.settings.radio.component.ChannelSelection +import org.meshtastic.feature.settings.radio.component.PacketResponseStateDialog import timber.log.Timber /** diff --git a/app/src/main/java/com/geeksville/mesh/ui/sharing/ChannelViewModel.kt b/app/src/main/java/com/geeksville/mesh/ui/sharing/ChannelViewModel.kt index 4b05764f1..20ec42095 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/sharing/ChannelViewModel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/sharing/ChannelViewModel.kt @@ -28,7 +28,6 @@ import com.geeksville.mesh.LocalOnlyProtos.LocalConfig import com.geeksville.mesh.channelSet import com.geeksville.mesh.config import com.geeksville.mesh.copy -import com.geeksville.mesh.model.getChannelList import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -37,6 +36,7 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import org.meshtastic.core.data.repository.RadioConfigRepository import org.meshtastic.core.model.util.toChannelSet +import org.meshtastic.core.proto.getChannelList import org.meshtastic.core.service.ServiceRepository import timber.log.Timber import javax.inject.Inject diff --git a/build.gradle.kts b/build.gradle.kts index 8a8c59fb4..70b1c5d66 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -78,4 +78,5 @@ dependencies { kover(projects.feature.intro) kover(projects.feature.map) kover(projects.feature.node) + kover(projects.feature.settings) } \ No newline at end of file diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts index 37da5a7ef..0db09ac50 100644 --- a/core/data/build.gradle.kts +++ b/core/data/build.gradle.kts @@ -25,6 +25,7 @@ plugins { android { namespace = "org.meshtastic.core.data" } dependencies { + implementation(projects.core.analytics) implementation(projects.core.database) implementation(projects.core.datastore) implementation(projects.core.di) @@ -33,6 +34,7 @@ dependencies { implementation(projects.core.prefs) implementation(projects.core.proto) + implementation(libs.core.location.altitude) implementation(libs.kotlinx.coroutines.android) implementation(libs.kotlinx.serialization.json) implementation(libs.timber) diff --git a/core/data/detekt-baseline.xml b/core/data/detekt-baseline.xml index 6f500e50a..b15fbf373 100644 --- a/core/data/detekt-baseline.xml +++ b/core/data/detekt-baseline.xml @@ -2,7 +2,11 @@ + MagicNumber:LocationRepository.kt$LocationRepository$1000L + MagicNumber:LocationRepository.kt$LocationRepository$30 + MagicNumber:LocationRepository.kt$LocationRepository$31 MagicNumber:PacketRepository.kt$PacketRepository$500 + TooGenericExceptionCaught:LocationRepository.kt$LocationRepository$e: Exception TooManyFunctions:PacketRepository.kt$PacketRepository diff --git a/app/src/main/java/com/geeksville/mesh/repository/location/LocationRepositoryModule.kt b/core/data/src/main/kotlin/org/meshtastic/core/data/di/DataModule.kt similarity index 93% rename from app/src/main/java/com/geeksville/mesh/repository/location/LocationRepositoryModule.kt rename to core/data/src/main/kotlin/org/meshtastic/core/data/di/DataModule.kt index 3728d58f3..241f70218 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/location/LocationRepositoryModule.kt +++ b/core/data/src/main/kotlin/org/meshtastic/core/data/di/DataModule.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.repository.location +package org.meshtastic.core.data.di import android.content.Context import android.location.LocationManager @@ -28,7 +28,7 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) -object LocationRepositoryModule { +object DataModule { @Provides @Singleton diff --git a/app/src/main/java/com/geeksville/mesh/repository/location/LocationRepository.kt b/core/data/src/main/kotlin/org/meshtastic/core/data/repository/LocationRepository.kt similarity index 93% rename from app/src/main/java/com/geeksville/mesh/repository/location/LocationRepository.kt rename to core/data/src/main/kotlin/org/meshtastic/core/data/repository/LocationRepository.kt index 18359f8e6..7849ea1df 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/location/LocationRepository.kt +++ b/core/data/src/main/kotlin/org/meshtastic/core/data/repository/LocationRepository.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.repository.location +package org.meshtastic.core.data.repository import android.Manifest.permission.ACCESS_COARSE_LOCATION import android.Manifest.permission.ACCESS_FINE_LOCATION @@ -27,13 +27,13 @@ import androidx.core.location.LocationListenerCompat import androidx.core.location.LocationManagerCompat import androidx.core.location.LocationRequestCompat import androidx.core.location.altitude.AltitudeConverterCompat -import com.geeksville.mesh.MeshUtilApplication import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.asExecutor import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.callbackFlow +import org.meshtastic.core.analytics.platform.PlatformAnalytics import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @@ -44,6 +44,7 @@ class LocationRepository constructor( private val context: Application, private val locationManager: dagger.Lazy, + private val analytics: PlatformAnalytics, ) { /** Status of whether the app is actively subscribed to location changes. */ @@ -88,7 +89,7 @@ constructor( "Starting location updates with $providerList intervalMs=${intervalMs}ms and minDistanceM=${minDistanceM}m", ) _receivingLocationUpdates.value = true - MeshUtilApplication.analytics.track("location_start") // Figure out how many users needed to use the phone GPS + analytics.track("location_start") // Figure out how many users needed to use the phone GPS try { providerList.forEach { provider -> @@ -107,7 +108,7 @@ constructor( awaitClose { Timber.i("Stopping location requests") _receivingLocationUpdates.value = false - MeshUtilApplication.analytics.track("location_stop") + analytics.track("location_stop") LocationManagerCompat.removeUpdates(this@requestLocationUpdates, locationListener) } diff --git a/core/proto/src/main/kotlin/org/meshtastic/core/proto/ProtoExtensions.kt b/core/proto/src/main/kotlin/org/meshtastic/core/proto/ProtoExtensions.kt index b62e31f95..037187240 100644 --- a/core/proto/src/main/kotlin/org/meshtastic/core/proto/ProtoExtensions.kt +++ b/core/proto/src/main/kotlin/org/meshtastic/core/proto/ProtoExtensions.kt @@ -19,9 +19,13 @@ package org.meshtastic.core.proto import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource +import com.geeksville.mesh.ChannelProtos +import com.geeksville.mesh.ChannelProtos.ChannelSettings import com.geeksville.mesh.MeshProtos import com.geeksville.mesh.MeshProtos.MeshPacket import com.geeksville.mesh.MeshProtos.Position +import com.geeksville.mesh.channel +import com.geeksville.mesh.channelSettings import java.text.DateFormat import kotlin.time.Duration.Companion.days @@ -46,3 +50,30 @@ fun MeshPacket.toPosition(): Position? = if (!decoded.wantResponse) { } else { null } + +/** + * Builds a [Channel] list from the difference between two [ChannelSettings] lists. Only changes are included in the + * resulting list. + * + * @param new The updated [ChannelSettings] list. + * @param old The current [ChannelSettings] list (required when disabling unused channels). + * @return A [Channel] list containing only the modified channels. + */ +fun getChannelList(new: List, old: List): List = buildList { + for (i in 0..maxOf(old.lastIndex, new.lastIndex)) { + if (old.getOrNull(i) != new.getOrNull(i)) { + add( + channel { + role = + when (i) { + 0 -> ChannelProtos.Channel.Role.PRIMARY + in 1..new.lastIndex -> ChannelProtos.Channel.Role.SECONDARY + else -> ChannelProtos.Channel.Role.DISABLED + } + index = i + settings = new.getOrNull(i) ?: channelSettings {} + }, + ) + } + } +} diff --git a/feature/settings/build.gradle.kts b/feature/settings/build.gradle.kts new file mode 100644 index 000000000..58c9fe287 --- /dev/null +++ b/feature/settings/build.gradle.kts @@ -0,0 +1,44 @@ +/* + * 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 . + */ + +plugins { + alias(libs.plugins.kover) + alias(libs.plugins.meshtastic.android.library) + alias(libs.plugins.meshtastic.android.library.compose) + alias(libs.plugins.meshtastic.hilt) +} + +android { namespace = "org.meshtastic.feature.settings" } + +dependencies { + implementation(projects.core.common) + implementation(projects.core.data) + implementation(projects.core.database) + implementation(projects.core.datastore) + implementation(projects.core.model) + implementation(projects.core.navigation) + implementation(projects.core.prefs) + implementation(projects.core.proto) + implementation(projects.core.service) + implementation(projects.core.strings) + implementation(projects.core.ui) + + implementation(libs.accompanist.permissions) + implementation(libs.kotlinx.collections.immutable) + implementation(libs.timber) + implementation(libs.zxing.android.embedded) +} diff --git a/feature/settings/detekt-baseline.xml b/feature/settings/detekt-baseline.xml new file mode 100644 index 000000000..6b33612e1 --- /dev/null +++ b/feature/settings/detekt-baseline.xml @@ -0,0 +1,70 @@ + + + + + ComposableParamOrder:ChannelSettingsItemList.kt$ChannelSettingsItemList + ComposableParamOrder:Debug.kt$DecodedPayloadBlock + ComposableParamOrder:DebugSearch.kt$DebugSearchState + ComposableParamOrder:DebugSearch.kt$DebugSearchStateviewModelDefaults + ComposableParamOrder:MapReportingPreference.kt$MapReportingPreference + ComposableParamOrder:NodeActionButton.kt$NodeActionButton + ComposableParamOrder:WarningDialog.kt$WarningDialog + CyclomaticComplexMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + CyclomaticComplexMethod:PositionConfigItemList.kt$@OptIn(ExperimentalPermissionsApi::class) @Composable fun PositionConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + CyclomaticComplexMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket) + LambdaParameterEventTrailing:NodeActionButton.kt$onClick + LongMethod:AmbientLightingConfigItemList.kt$@Composable fun AmbientLightingConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:AudioConfigItemList.kt$@Composable fun AudioConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:CannedMessageConfigItemList.kt$@Composable fun CannedMessageConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:DetectionSensorConfigItemList.kt$@Composable fun DetectionSensorConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:DeviceConfigItemList.kt$@Composable fun DeviceConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:DisplayConfigItemList.kt$@Composable fun DisplayConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:ExternalNotificationConfigItemList.kt$@Composable fun ExternalNotificationConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:LoRaConfigItemList.kt$@Composable fun LoRaConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:NetworkConfigItemList.kt$@Composable fun NetworkConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:PositionConfigItemList.kt$@OptIn(ExperimentalPermissionsApi::class) @Composable fun PositionConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:PowerConfigItemList.kt$@Composable fun PowerConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket) + LongMethod:SecurityConfigItemList.kt$@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun SecurityConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:SerialConfigItemList.kt$@Composable fun SerialConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:StoreForwardConfigItemList.kt$@Composable fun StoreForwardConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:TelemetryConfigItemList.kt$@Composable fun TelemetryConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + LongMethod:UserConfigItemList.kt$@Composable fun UserConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) + MagicNumber:Debug.kt$3 + MagicNumber:EditChannelDialog.kt$16 + MagicNumber:EditChannelDialog.kt$32 + MagicNumber:PacketResponseStateDialog.kt$100 + MagicNumber:PowerConfigItemList.kt$3600 + ModifierMissing:ChannelSettingsItemList.kt$ChannelSelection + ModifierMissing:CleanNodeDatabaseScreen.kt$CleanNodeDatabaseScreen + ModifierMissing:LoRaConfigItemList.kt$LoRaConfigScreen + ModifierMissing:MapReportingPreference.kt$MapReportingPreference + ModifierMissing:NetworkConfigItemList.kt$NetworkConfigScreen + ModifierMissing:PositionConfigItemList.kt$PositionConfigScreen + ModifierMissing:RadioConfig.kt$RadioConfigItemList + ModifierMissing:RadioConfigScreenList.kt$RadioConfigScreenList + ModifierMissing:SecurityConfigItemList.kt$SecurityConfigScreen + ModifierMissing:SettingsScreen.kt$SettingsScreen + ModifierNotUsedAtRoot:EditChannelDialog.kt$modifier = modifier.weight(1f) + ModifierNotUsedAtRoot:EditDeviceProfileDialog.kt$modifier = modifier.weight(1f) + MultipleEmitters:CleanNodeDatabaseScreen.kt$NodesDeletionPreview + MultipleEmitters:RadioConfig.kt$RadioConfigItemList + NestedBlockDepth:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket) + ParameterNaming:ChannelSettingsItemList.kt$onPositiveClicked + ParameterNaming:ChannelSettingsItemList.kt$onSelected + ParameterNaming:CleanNodeDatabaseScreen.kt$onCheckedChanged + ParameterNaming:CleanNodeDatabaseScreen.kt$onDaysChanged + ParameterNaming:MapReportingPreference.kt$onMapReportingEnabledChanged + ParameterNaming:MapReportingPreference.kt$onPositionPrecisionChanged + ParameterNaming:MapReportingPreference.kt$onPublishIntervalSecsChanged + ParameterNaming:MapReportingPreference.kt$onShouldReportLocationChanged + PreviewPublic:MapReportingPreference.kt$MapReportingPreview + ReturnCount:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket) + TooGenericExceptionCaught:LanguageUtils.kt$LanguageUtils$e: Exception + TooGenericExceptionCaught:RadioConfigViewModel.kt$RadioConfigViewModel$ex: Exception + TooManyFunctions:RadioConfigViewModel.kt$RadioConfigViewModel : ViewModel + UnusedParameter:ChannelSettingsItemList.kt$onBack: () -> Unit + UnusedParameter:ChannelSettingsItemList.kt$title: String + ViewModelInjection:DebugSearch.kt$viewModel + + diff --git a/app/src/androidTest/java/com/geeksville/mesh/compose/DebugFiltersTest.kt b/feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/debugging/DebugFiltersTest.kt similarity index 82% rename from app/src/androidTest/java/com/geeksville/mesh/compose/DebugFiltersTest.kt rename to feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/debugging/DebugFiltersTest.kt index a894e69e8..82d19e45c 100644 --- a/app/src/androidTest/java/com/geeksville/mesh/compose/DebugFiltersTest.kt +++ b/feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/debugging/DebugFiltersTest.kt @@ -15,11 +15,13 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.compose +package org.meshtastic.feature.settings.debugging import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.test.assertIsDisplayed @@ -31,11 +33,11 @@ import androidx.compose.ui.test.performTextInput import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry -import com.geeksville.mesh.ui.debug.FilterMode import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.meshtastic.core.strings.R +import org.meshtastic.feature.settings.debugging.DebugViewModel.UiMeshLog @RunWith(AndroidJUnit4::class) class DebugFiltersTest { @@ -47,20 +49,19 @@ class DebugFiltersTest { val context = InstrumentationRegistry.getInstrumentation().targetContext val filterLabel = context.getString(R.string.debug_filters) composeTestRule.setContent { - var filterTexts by - androidx.compose.runtime.remember { androidx.compose.runtime.mutableStateOf(listOf()) } - var customFilterText by androidx.compose.runtime.remember { androidx.compose.runtime.mutableStateOf("") } + var filterTexts by remember { mutableStateOf(listOf()) } + var customFilterText by remember { mutableStateOf("") } val presetFilters = listOf("Error", "Warning", "Info") val logs = listOf( - com.geeksville.mesh.model.DebugViewModel.UiMeshLog( + UiMeshLog( uuid = "1", messageType = "Info", formattedReceivedDate = "2024-01-01 12:00:00", logMessage = "Sample log message", ), ) - com.geeksville.mesh.ui.debug.DebugFilterBar( + DebugFilterBar( filterTexts = filterTexts, onFilterTextsChange = { filterTexts = it }, customFilterText = customFilterText, @@ -78,17 +79,16 @@ class DebugFiltersTest { val context = InstrumentationRegistry.getInstrumentation().targetContext val activeFiltersLabel = context.getString(R.string.debug_active_filters) composeTestRule.setContent { - var filterTexts by - androidx.compose.runtime.remember { androidx.compose.runtime.mutableStateOf(listOf()) } - var customFilterText by androidx.compose.runtime.remember { androidx.compose.runtime.mutableStateOf("") } + var filterTexts by remember { mutableStateOf(listOf()) } + var customFilterText by remember { mutableStateOf("") } Column(modifier = Modifier.padding(16.dp)) { - com.geeksville.mesh.ui.debug.DebugActiveFilters( + DebugActiveFilters( filterTexts = filterTexts, onFilterTextsChange = { filterTexts = it }, filterMode = FilterMode.OR, onFilterModeChange = {}, ) - com.geeksville.mesh.ui.debug.DebugCustomFilterInput( + DebugCustomFilterInput( customFilterText = customFilterText, onCustomFilterTextChange = { customFilterText = it }, filterTexts = filterTexts, @@ -111,9 +111,8 @@ class DebugFiltersTest { val context = InstrumentationRegistry.getInstrumentation().targetContext val activeFiltersLabel = context.getString(R.string.debug_active_filters) composeTestRule.setContent { - var filterTexts by - androidx.compose.runtime.remember { androidx.compose.runtime.mutableStateOf(listOf("A", "B")) } - com.geeksville.mesh.ui.debug.DebugActiveFilters( + var filterTexts by remember { mutableStateOf(listOf("A", "B")) } + DebugActiveFilters( filterTexts = filterTexts, onFilterTextsChange = { filterTexts = it }, filterMode = FilterMode.OR, diff --git a/app/src/androidTest/java/com/geeksville/mesh/compose/DebugSearchTest.kt b/feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/debugging/DebugSearchTest.kt similarity index 85% rename from app/src/androidTest/java/com/geeksville/mesh/compose/DebugSearchTest.kt rename to feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/debugging/DebugSearchTest.kt index 3024648cd..0ba49ad64 100644 --- a/app/src/androidTest/java/com/geeksville/mesh/compose/DebugSearchTest.kt +++ b/feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/debugging/DebugSearchTest.kt @@ -15,12 +15,13 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.compose +package org.meshtastic.feature.settings.debugging import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.test.assertIsDisplayed @@ -32,13 +33,13 @@ import androidx.compose.ui.test.performTextInput import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry -import com.geeksville.mesh.model.LogSearchManager.SearchState -import com.geeksville.mesh.ui.debug.DebugSearchBar -import com.geeksville.mesh.ui.debug.FilterMode import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.meshtastic.core.strings.R +import org.meshtastic.feature.settings.debugging.DebugViewModel.UiMeshLog +import org.meshtastic.feature.settings.debugging.LogSearchManager.SearchMatch +import org.meshtastic.feature.settings.debugging.LogSearchManager.SearchState @RunWith(AndroidJUnit4::class) class DebugSearchTest { @@ -66,7 +67,7 @@ class DebugSearchTest { val context = InstrumentationRegistry.getInstrumentation().targetContext val placeholder = context.getString(R.string.debug_default_search) composeTestRule.setContent { - var searchText by androidx.compose.runtime.remember { mutableStateOf("test") } + var searchText by remember { mutableStateOf("test") } DebugSearchBar( searchState = SearchState(searchText = searchText), onSearchTextChange = { searchText = it }, @@ -91,10 +92,7 @@ class DebugSearchTest { SearchState( searchText = searchText, currentMatchIndex = currentMatchIndex, - allMatches = - List(matchCount) { - com.geeksville.mesh.model.LogSearchManager.SearchMatch(it, 0, 6, "Packet") - }, + allMatches = List(matchCount) { SearchMatch(it, 0, 6, "Packet") }, hasMatches = true, ), onSearchTextChange = {}, @@ -117,19 +115,19 @@ class DebugSearchTest { val context = InstrumentationRegistry.getInstrumentation().targetContext val filterLabel = context.getString(R.string.debug_filters) composeTestRule.setContent { - var filterTexts by androidx.compose.runtime.remember { mutableStateOf(listOf()) } - var customFilterText by androidx.compose.runtime.remember { mutableStateOf("") } + var filterTexts by remember { mutableStateOf(listOf()) } + var customFilterText by remember { mutableStateOf("") } val presetFilters = listOf("Error", "Warning", "Info") val logs = listOf( - com.geeksville.mesh.model.DebugViewModel.UiMeshLog( + UiMeshLog( uuid = "1", messageType = "Info", formattedReceivedDate = "2024-01-01 12:00:00", logMessage = "Sample log message", ), ) - com.geeksville.mesh.ui.debug.DebugFilterBar( + DebugFilterBar( filterTexts = filterTexts, onFilterTextsChange = { filterTexts = it }, customFilterText = customFilterText, @@ -147,16 +145,16 @@ class DebugSearchTest { val context = InstrumentationRegistry.getInstrumentation().targetContext val activeFiltersLabel = context.getString(R.string.debug_active_filters) composeTestRule.setContent { - var filterTexts by androidx.compose.runtime.remember { mutableStateOf(listOf()) } - var customFilterText by androidx.compose.runtime.remember { mutableStateOf("") } + var filterTexts by remember { mutableStateOf(listOf()) } + var customFilterText by remember { mutableStateOf("") } Column(modifier = Modifier.padding(16.dp)) { - com.geeksville.mesh.ui.debug.DebugActiveFilters( + DebugActiveFilters( filterTexts = filterTexts, onFilterTextsChange = { filterTexts = it }, filterMode = FilterMode.OR, onFilterModeChange = {}, ) - com.geeksville.mesh.ui.debug.DebugCustomFilterInput( + DebugCustomFilterInput( customFilterText = customFilterText, onCustomFilterTextChange = { customFilterText = it }, filterTexts = filterTexts, @@ -177,8 +175,8 @@ class DebugSearchTest { val context = InstrumentationRegistry.getInstrumentation().targetContext val activeFiltersLabel = context.getString(R.string.debug_active_filters) composeTestRule.setContent { - var filterTexts by androidx.compose.runtime.remember { mutableStateOf(listOf("A", "B")) } - com.geeksville.mesh.ui.debug.DebugActiveFilters( + var filterTexts by remember { mutableStateOf(listOf("A", "B")) } + DebugActiveFilters( filterTexts = filterTexts, onFilterTextsChange = { filterTexts = it }, filterMode = FilterMode.OR, diff --git a/app/src/androidTest/java/com/geeksville/mesh/compose/EditDeviceProfileDialogTest.kt b/feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/radio/component/EditDeviceProfileDialogTest.kt similarity index 97% rename from app/src/androidTest/java/com/geeksville/mesh/compose/EditDeviceProfileDialogTest.kt rename to feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/radio/component/EditDeviceProfileDialogTest.kt index a11fadc51..1f1495083 100644 --- a/app/src/androidTest/java/com/geeksville/mesh/compose/EditDeviceProfileDialogTest.kt +++ b/feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/radio/component/EditDeviceProfileDialogTest.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.compose +package org.meshtastic.feature.settings.radio.component import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.createComposeRule @@ -26,7 +26,6 @@ import androidx.test.platform.app.InstrumentationRegistry import com.geeksville.mesh.ClientOnlyProtos.DeviceProfile import com.geeksville.mesh.deviceProfile import com.geeksville.mesh.position -import com.geeksville.mesh.ui.settings.radio.components.EditDeviceProfileDialog import org.junit.Assert import org.junit.Rule import org.junit.Test diff --git a/app/src/androidTest/java/com/geeksville/mesh/compose/MapReportingPreferenceTest.kt b/feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/radio/component/MapReportingPreferenceTest.kt similarity index 97% rename from app/src/androidTest/java/com/geeksville/mesh/compose/MapReportingPreferenceTest.kt rename to feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/radio/component/MapReportingPreferenceTest.kt index 56ff5c707..e6ce58fae 100644 --- a/app/src/androidTest/java/com/geeksville/mesh/compose/MapReportingPreferenceTest.kt +++ b/feature/settings/src/androidTest/kotlin/org/meshtastic/feature/settings/radio/component/MapReportingPreferenceTest.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.compose +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.layout.Column import androidx.compose.ui.platform.LocalFocusManager @@ -26,7 +26,6 @@ import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry -import com.geeksville.mesh.ui.settings.radio.components.MapReportingPreference import org.junit.Assert import org.junit.Rule import org.junit.Test diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsScreen.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/SettingsScreen.kt similarity index 95% rename from app/src/main/java/com/geeksville/mesh/ui/settings/SettingsScreen.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/SettingsScreen.kt index 3950ecb74..75d30c5a9 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsScreen.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/SettingsScreen.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings +package org.meshtastic.feature.settings import android.Manifest import android.app.Activity @@ -58,15 +58,7 @@ import androidx.compose.ui.unit.dp import androidx.core.net.toUri import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.geeksville.mesh.BuildConfig import com.geeksville.mesh.ClientOnlyProtos.DeviceProfile -import com.geeksville.mesh.navigation.getNavRouteFrom -import com.geeksville.mesh.ui.settings.radio.RadioConfigItemList -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel -import com.geeksville.mesh.ui.settings.radio.components.EditDeviceProfileDialog -import com.geeksville.mesh.ui.settings.radio.components.PacketResponseStateDialog -import com.geeksville.mesh.util.LanguageUtils -import com.geeksville.mesh.util.LanguageUtils.getLanguageMap import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.rememberMultiplePermissionsState import kotlinx.coroutines.delay @@ -80,6 +72,13 @@ import org.meshtastic.core.ui.component.SettingsItemDetail import org.meshtastic.core.ui.component.SettingsItemSwitch import org.meshtastic.core.ui.component.TitledCard import org.meshtastic.core.ui.theme.MODE_DYNAMIC +import org.meshtastic.feature.settings.navigation.getNavRouteFrom +import org.meshtastic.feature.settings.radio.RadioConfigItemList +import org.meshtastic.feature.settings.radio.RadioConfigViewModel +import org.meshtastic.feature.settings.radio.component.EditDeviceProfileDialog +import org.meshtastic.feature.settings.radio.component.PacketResponseStateDialog +import org.meshtastic.feature.settings.util.LanguageUtils +import org.meshtastic.feature.settings.util.LanguageUtils.getLanguageMap import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @@ -371,7 +370,12 @@ fun SettingsScreen( settingsLauncher.launch(intent) } - AppVersionButton(excludedModulesUnlocked) { settingsViewModel.unlockExcludedModules() } + AppVersionButton( + excludedModulesUnlocked = excludedModulesUnlocked, + appVersionName = settingsViewModel.appVersionName, + ) { + settingsViewModel.unlockExcludedModules() + } } } } @@ -383,7 +387,11 @@ private const val UNLOCK_TIMEOUT_SECONDS = 1 // Timeout in seconds to reset the /** A button to display the app version. Clicking it 5 times will unlock the excluded modules. */ @Composable -private fun AppVersionButton(excludedModulesUnlocked: Boolean, onUnlockExcludedModules: () -> Unit) { +private fun AppVersionButton( + excludedModulesUnlocked: Boolean, + appVersionName: String, + onUnlockExcludedModules: () -> Unit, +) { val context = LocalContext.current var clickCount by remember { mutableIntStateOf(0) } @@ -397,7 +405,7 @@ private fun AppVersionButton(excludedModulesUnlocked: Boolean, onUnlockExcludedM SettingsItemDetail( text = stringResource(R.string.app_version), icon = Icons.Rounded.Memory, - trailingText = BuildConfig.VERSION_NAME, + trailingText = appVersionName, ) { clickCount = clickCount.inc().coerceIn(0, UNLOCK_CLICK_COUNT) diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsViewModel.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/SettingsViewModel.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/SettingsViewModel.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/SettingsViewModel.kt index 78f3791d6..e09bb1de8 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/SettingsViewModel.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/SettingsViewModel.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings +package org.meshtastic.feature.settings import android.app.Application import android.net.Uri @@ -38,6 +38,7 @@ import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import org.meshtastic.core.common.BuildConfigProvider import org.meshtastic.core.data.repository.MeshLogRepository import org.meshtastic.core.data.repository.NodeRepository import org.meshtastic.core.data.repository.RadioConfigRepository @@ -70,6 +71,7 @@ constructor( private val meshLogRepository: MeshLogRepository, private val uiPrefs: UiPrefs, private val uiPreferencesDataSource: UiPreferencesDataSource, + private val buildConfigProvider: BuildConfigProvider, ) : ViewModel() { val myNodeInfo: StateFlow = nodeRepository.myNodeInfo @@ -108,6 +110,9 @@ constructor( private val _excludedModulesUnlocked = MutableStateFlow(false) val excludedModulesUnlocked: StateFlow = _excludedModulesUnlocked.asStateFlow() + val appVersionName + get() = buildConfigProvider.versionName + fun setProvideLocation(value: Boolean) { myNodeNum?.let { uiPrefs.setShouldProvideNodeLocation(it, value) } } diff --git a/app/src/main/java/com/geeksville/mesh/ui/debug/Debug.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/Debug.kt similarity index 99% rename from app/src/main/java/com/geeksville/mesh/ui/debug/Debug.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/Debug.kt index aad95916e..f2b7cd9ec 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/debug/Debug.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/Debug.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.debug +package org.meshtastic.feature.settings.debugging import android.content.Context import android.net.Uri @@ -75,11 +75,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.datastore.core.IOException import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.geeksville.mesh.model.DebugViewModel -import com.geeksville.mesh.model.DebugViewModel.UiMeshLog import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -90,7 +87,9 @@ import org.meshtastic.core.ui.component.MainAppBar import org.meshtastic.core.ui.component.SimpleAlertDialog import org.meshtastic.core.ui.theme.AnnotationColor import org.meshtastic.core.ui.theme.AppTheme +import org.meshtastic.feature.settings.debugging.DebugViewModel.UiMeshLog import timber.log.Timber +import java.io.IOException import java.io.OutputStreamWriter import java.nio.charset.StandardCharsets import java.text.SimpleDateFormat diff --git a/app/src/main/java/com/geeksville/mesh/ui/debug/DebugFilters.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/DebugFilters.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/debug/DebugFilters.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/DebugFilters.kt index 5aa6a5e0a..2da02d439 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/debug/DebugFilters.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/DebugFilters.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.debug +package org.meshtastic.feature.settings.debugging import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -56,8 +56,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp -import com.geeksville.mesh.model.DebugViewModel.UiMeshLog import org.meshtastic.core.strings.R +import org.meshtastic.feature.settings.debugging.DebugViewModel.UiMeshLog @Composable fun DebugCustomFilterInput( diff --git a/app/src/main/java/com/geeksville/mesh/ui/debug/DebugSearch.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/DebugSearch.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/debug/DebugSearch.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/DebugSearch.kt index 700f9cf9a..31283ce5e 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/debug/DebugSearch.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/DebugSearch.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.debug +package org.meshtastic.feature.settings.debugging import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -53,12 +53,11 @@ import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel -import com.geeksville.mesh.model.DebugViewModel -import com.geeksville.mesh.model.DebugViewModel.UiMeshLog -import com.geeksville.mesh.model.LogSearchManager.SearchMatch -import com.geeksville.mesh.model.LogSearchManager.SearchState import org.meshtastic.core.strings.R import org.meshtastic.core.ui.theme.AppTheme +import org.meshtastic.feature.settings.debugging.DebugViewModel.UiMeshLog +import org.meshtastic.feature.settings.debugging.LogSearchManager.SearchMatch +import org.meshtastic.feature.settings.debugging.LogSearchManager.SearchState @Composable internal fun DebugSearchNavigation( diff --git a/app/src/main/java/com/geeksville/mesh/model/DebugViewModel.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/DebugViewModel.kt similarity index 99% rename from app/src/main/java/com/geeksville/mesh/model/DebugViewModel.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/DebugViewModel.kt index a26588d90..f3e582348 100644 --- a/app/src/main/java/com/geeksville/mesh/model/DebugViewModel.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/debugging/DebugViewModel.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.model +package org.meshtastic.feature.settings.debugging import androidx.compose.runtime.Immutable import androidx.lifecycle.ViewModel @@ -26,7 +26,6 @@ import com.geeksville.mesh.PaxcountProtos import com.geeksville.mesh.Portnums.PortNum import com.geeksville.mesh.StoreAndForwardProtos import com.geeksville.mesh.TelemetryProtos -import com.geeksville.mesh.ui.debug.FilterMode import com.google.protobuf.InvalidProtocolBufferException import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.ImmutableList diff --git a/app/src/main/java/com/geeksville/mesh/navigation/SettingsNavigation.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavigation.kt similarity index 90% rename from app/src/main/java/com/geeksville/mesh/navigation/SettingsNavigation.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavigation.kt index 26eb67200..a5233615c 100644 --- a/app/src/main/java/com/geeksville/mesh/navigation/SettingsNavigation.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/navigation/SettingsNavigation.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.navigation +package org.meshtastic.feature.settings.navigation import androidx.annotation.StringRes import androidx.compose.material.icons.Icons @@ -57,38 +57,38 @@ import androidx.navigation.navDeepLink import androidx.navigation.navigation import com.geeksville.mesh.AdminProtos import com.geeksville.mesh.MeshProtos.DeviceMetadata -import com.geeksville.mesh.ui.debug.DebugScreen -import com.geeksville.mesh.ui.settings.SettingsScreen -import com.geeksville.mesh.ui.settings.radio.CleanNodeDatabaseScreen -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel -import com.geeksville.mesh.ui.settings.radio.components.AmbientLightingConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.AudioConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.BluetoothConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.CannedMessageConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.ChannelConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.DetectionSensorConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.DeviceConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.DisplayConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.ExternalNotificationConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.LoRaConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.MQTTConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.NeighborInfoConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.NetworkConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.PaxcounterConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.PositionConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.PowerConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.RangeTestConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.RemoteHardwareConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.SecurityConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.SerialConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.StoreForwardConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.TelemetryConfigScreen -import com.geeksville.mesh.ui.settings.radio.components.UserConfigScreen import org.meshtastic.core.navigation.DEEP_LINK_BASE_URI import org.meshtastic.core.navigation.NodesRoutes import org.meshtastic.core.navigation.Route import org.meshtastic.core.navigation.SettingsRoutes import org.meshtastic.core.strings.R +import org.meshtastic.feature.settings.SettingsScreen +import org.meshtastic.feature.settings.debugging.DebugScreen +import org.meshtastic.feature.settings.radio.CleanNodeDatabaseScreen +import org.meshtastic.feature.settings.radio.RadioConfigViewModel +import org.meshtastic.feature.settings.radio.component.AmbientLightingConfigScreen +import org.meshtastic.feature.settings.radio.component.AudioConfigScreen +import org.meshtastic.feature.settings.radio.component.BluetoothConfigScreen +import org.meshtastic.feature.settings.radio.component.CannedMessageConfigScreen +import org.meshtastic.feature.settings.radio.component.ChannelConfigScreen +import org.meshtastic.feature.settings.radio.component.DetectionSensorConfigScreen +import org.meshtastic.feature.settings.radio.component.DeviceConfigScreen +import org.meshtastic.feature.settings.radio.component.DisplayConfigScreen +import org.meshtastic.feature.settings.radio.component.ExternalNotificationConfigScreen +import org.meshtastic.feature.settings.radio.component.LoRaConfigScreen +import org.meshtastic.feature.settings.radio.component.MQTTConfigScreen +import org.meshtastic.feature.settings.radio.component.NeighborInfoConfigScreen +import org.meshtastic.feature.settings.radio.component.NetworkConfigScreen +import org.meshtastic.feature.settings.radio.component.PaxcounterConfigScreen +import org.meshtastic.feature.settings.radio.component.PositionConfigScreen +import org.meshtastic.feature.settings.radio.component.PowerConfigScreen +import org.meshtastic.feature.settings.radio.component.RangeTestConfigScreen +import org.meshtastic.feature.settings.radio.component.RemoteHardwareConfigScreen +import org.meshtastic.feature.settings.radio.component.SecurityConfigScreen +import org.meshtastic.feature.settings.radio.component.SerialConfigScreen +import org.meshtastic.feature.settings.radio.component.StoreForwardConfigScreen +import org.meshtastic.feature.settings.radio.component.TelemetryConfigScreen +import org.meshtastic.feature.settings.radio.component.UserConfigScreen fun getNavRouteFrom(routeName: String): Route? = ConfigRoute.entries.find { it.name == routeName }?.route ?: ModuleRoute.entries.find { it.name == routeName }?.route diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/CleanNodeDatabaseScreen.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/CleanNodeDatabaseScreen.kt similarity index 99% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/CleanNodeDatabaseScreen.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/CleanNodeDatabaseScreen.kt index a6423c681..a7d4f9c38 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/CleanNodeDatabaseScreen.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/CleanNodeDatabaseScreen.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio +package org.meshtastic.feature.settings.radio import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/CleanNodeDatabaseViewModel.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/CleanNodeDatabaseViewModel.kt similarity index 99% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/CleanNodeDatabaseViewModel.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/CleanNodeDatabaseViewModel.kt index 54adbef68..1b616102b 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/CleanNodeDatabaseViewModel.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/CleanNodeDatabaseViewModel.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio +package org.meshtastic.feature.settings.radio import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfig.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/RadioConfig.kt similarity index 96% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfig.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/RadioConfig.kt index 1a63250c2..b5b6361cc 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfig.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/RadioConfig.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio +package org.meshtastic.feature.settings.radio import androidx.annotation.StringRes import androidx.compose.foundation.layout.Column @@ -42,9 +42,6 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.geeksville.mesh.navigation.ConfigRoute -import com.geeksville.mesh.navigation.ModuleRoute -import com.geeksville.mesh.ui.settings.radio.components.WarningDialog import org.meshtastic.core.navigation.Route import org.meshtastic.core.navigation.SettingsRoutes import org.meshtastic.core.strings.R @@ -52,6 +49,9 @@ import org.meshtastic.core.ui.component.SettingsItem import org.meshtastic.core.ui.component.TitledCard import org.meshtastic.core.ui.theme.AppTheme import org.meshtastic.core.ui.theme.StatusColors.StatusRed +import org.meshtastic.feature.settings.navigation.ConfigRoute +import org.meshtastic.feature.settings.navigation.ModuleRoute +import org.meshtastic.feature.settings.radio.component.WarningDialog @Suppress("LongMethod", "CyclomaticComplexMethod") @Composable diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfigViewModel.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/RadioConfigViewModel.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfigViewModel.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/RadioConfigViewModel.kt index f17653293..e2e3cd694 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/RadioConfigViewModel.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/RadioConfigViewModel.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio +package org.meshtastic.feature.settings.radio import android.Manifest import android.app.Application @@ -42,12 +42,7 @@ import com.geeksville.mesh.ModuleConfigProtos import com.geeksville.mesh.Portnums import com.geeksville.mesh.config import com.geeksville.mesh.deviceProfile -import com.geeksville.mesh.model.getChannelList import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.navigation.ConfigRoute -import com.geeksville.mesh.navigation.ModuleRoute -import com.geeksville.mesh.repository.location.LocationRepository -import com.geeksville.mesh.util.UiText import com.google.protobuf.MessageLite import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -63,6 +58,7 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.json.JSONObject +import org.meshtastic.core.data.repository.LocationRepository import org.meshtastic.core.data.repository.NodeRepository import org.meshtastic.core.data.repository.RadioConfigRepository import org.meshtastic.core.database.entity.MyNodeEntity @@ -73,10 +69,14 @@ import org.meshtastic.core.model.util.toChannelSet import org.meshtastic.core.navigation.SettingsRoutes import org.meshtastic.core.prefs.analytics.AnalyticsPrefs import org.meshtastic.core.prefs.map.MapConsentPrefs +import org.meshtastic.core.proto.getChannelList import org.meshtastic.core.service.ConnectionState import org.meshtastic.core.service.IMeshService import org.meshtastic.core.service.ServiceRepository import org.meshtastic.core.strings.R +import org.meshtastic.feature.settings.navigation.ConfigRoute +import org.meshtastic.feature.settings.navigation.ModuleRoute +import org.meshtastic.feature.settings.util.UiText import timber.log.Timber import java.io.FileOutputStream import javax.inject.Inject diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/ResponseState.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/ResponseState.kt similarity index 92% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/ResponseState.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/ResponseState.kt index d9e59dce1..8c6df952a 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/ResponseState.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/ResponseState.kt @@ -15,9 +15,9 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio +package org.meshtastic.feature.settings.radio -import com.geeksville.mesh.util.UiText +import org.meshtastic.feature.settings.util.UiText /** Generic sealed class defines each possible state of a response. */ sealed class ResponseState { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/AmbientLightingConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/AmbientLightingConfigItemList.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/AmbientLightingConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/AmbientLightingConfigItemList.kt index e0f49b71f..34beef468 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/AmbientLightingConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/AmbientLightingConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -28,11 +28,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun AmbientLightingConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/AudioConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/AudioConfigItemList.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/AudioConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/AudioConfigItemList.kt index fed6e3562..8f5c0e4fc 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/AudioConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/AudioConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -29,12 +29,12 @@ import androidx.navigation.NavController import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.AudioConfig import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.DropDownPreference import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun AudioConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/BluetoothConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/BluetoothConfigItemList.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/BluetoothConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/BluetoothConfigItemList.kt index e535bed80..2631b445b 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/BluetoothConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/BluetoothConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -29,12 +29,12 @@ import androidx.navigation.NavController import com.geeksville.mesh.ConfigProtos.Config.BluetoothConfig import com.geeksville.mesh.config import com.geeksville.mesh.copy -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.DropDownPreference import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun BluetoothConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/CannedMessageConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/CannedMessageConfigItemList.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/CannedMessageConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/CannedMessageConfigItemList.kt index 6c4b09e70..bea528626 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/CannedMessageConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/CannedMessageConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions @@ -35,12 +35,12 @@ import androidx.navigation.NavController import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.CannedMessageConfig import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.DropDownPreference import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun CannedMessageConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ChannelLegend.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ChannelLegend.kt similarity index 99% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ChannelLegend.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ChannelLegend.kt index 2e19d3644..8c8751d86 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ChannelLegend.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ChannelLegend.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.annotation.StringRes import androidx.compose.foundation.clickable diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ChannelSettingsItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ChannelSettingsItemList.kt similarity index 99% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ChannelSettingsItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ChannelSettingsItemList.kt index 6520898fe..f028afca2 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ChannelSettingsItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ChannelSettingsItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.FastOutSlowInEasing @@ -73,7 +73,6 @@ import androidx.navigation.NavController import com.geeksville.mesh.ChannelProtos.ChannelSettings import com.geeksville.mesh.ConfigProtos.Config.LoRaConfig import com.geeksville.mesh.channelSettings -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.model.Channel import org.meshtastic.core.model.DeviceVersion import org.meshtastic.core.strings.R @@ -83,6 +82,7 @@ import org.meshtastic.core.ui.component.SecurityIcon import org.meshtastic.core.ui.component.dragContainer import org.meshtastic.core.ui.component.dragDropItemsIndexed import org.meshtastic.core.ui.component.rememberDragDropState +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable private fun ChannelItem( diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ConfigState.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ConfigState.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ConfigState.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ConfigState.kt index 62a0498d5..94da1a977 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ConfigState.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ConfigState.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/DetectionSensorConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DetectionSensorConfigItemList.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/DetectionSensorConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DetectionSensorConfigItemList.kt index 4da4725d5..a7a208d18 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/DetectionSensorConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DetectionSensorConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions @@ -32,12 +32,12 @@ import androidx.navigation.NavController import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.DropDownPreference import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun DetectionSensorConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/DeviceConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DeviceConfigItemList.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/DeviceConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DeviceConfigItemList.kt index 2e7263314..3563fea39 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/DeviceConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DeviceConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column @@ -50,12 +50,12 @@ import androidx.navigation.NavController import com.geeksville.mesh.ConfigProtos.Config.DeviceConfig import com.geeksville.mesh.config import com.geeksville.mesh.copy -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.DropDownPreference import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel private val DeviceConfig.Role.description: Int get() = diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/DisplayConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DisplayConfigItemList.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/DisplayConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DisplayConfigItemList.kt index f567834f9..a6bdddbc6 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/DisplayConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DisplayConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -29,12 +29,12 @@ import androidx.navigation.NavController import com.geeksville.mesh.ConfigProtos.Config.DisplayConfig import com.geeksville.mesh.config import com.geeksville.mesh.copy -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.DropDownPreference import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun DisplayConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/EditChannelDialog.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/EditChannelDialog.kt similarity index 99% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/EditChannelDialog.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/EditChannelDialog.kt index 04257bb9e..abd6f413a 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/EditChannelDialog.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/EditChannelDialog.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/EditDeviceProfileDialog.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/EditDeviceProfileDialog.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/EditDeviceProfileDialog.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/EditDeviceProfileDialog.kt index b9601e168..7278ef9d4 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/EditDeviceProfileDialog.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/EditDeviceProfileDialog.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ExternalNotificationConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ExternalNotificationConfigItemList.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ExternalNotificationConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ExternalNotificationConfigItemList.kt index c35c3a4c7..3f93d259c 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/ExternalNotificationConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/ExternalNotificationConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions @@ -34,12 +34,12 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference import org.meshtastic.core.ui.component.TextDividerPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun ExternalNotificationConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/LoRaConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/LoRaConfigItemList.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/LoRaConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/LoRaConfigItemList.kt index a6deea4a9..c77746549 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/LoRaConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/LoRaConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height @@ -35,7 +35,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.config import com.geeksville.mesh.copy -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.model.Channel import org.meshtastic.core.model.ChannelOption import org.meshtastic.core.model.RegionInfo @@ -47,6 +46,7 @@ import org.meshtastic.core.ui.component.PreferenceDivider import org.meshtastic.core.ui.component.SignedIntegerEditTextPreference import org.meshtastic.core.ui.component.SwitchPreference import org.meshtastic.core.ui.component.TitledCard +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun LoRaConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/MQTTConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/MQTTConfigItemList.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/MQTTConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/MQTTConfigItemList.kt index 01cadf8e8..7539822be 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/MQTTConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/MQTTConfigItemList.kt @@ -17,7 +17,7 @@ @file:Suppress("LongMethod") -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions @@ -33,12 +33,12 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.EditPasswordPreference import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun MQTTConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/MapReportingPreference.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/MapReportingPreference.kt similarity index 99% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/MapReportingPreference.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/MapReportingPreference.kt index 8d5d1b610..2007e848f 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/MapReportingPreference.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/MapReportingPreference.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/NeighborInfoConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/NeighborInfoConfigItemList.kt similarity index 96% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/NeighborInfoConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/NeighborInfoConfigItemList.kt index d09d870a7..fc4da425b 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/NeighborInfoConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/NeighborInfoConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -28,11 +28,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun NeighborInfoConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/NetworkConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/NetworkConfigItemList.kt similarity index 99% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/NetworkConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/NetworkConfigItemList.kt index 3619ae91b..e90b8ed49 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/NetworkConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/NetworkConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.activity.compose.rememberLauncherForActivityResult import androidx.compose.foundation.layout.fillMaxWidth @@ -43,7 +43,6 @@ import androidx.navigation.NavController import com.geeksville.mesh.ConfigProtos.Config.NetworkConfig import com.geeksville.mesh.config import com.geeksville.mesh.copy -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanOptions import org.meshtastic.core.strings.R @@ -54,6 +53,7 @@ import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SimpleAlertDialog import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable private fun ScanErrorDialog(onDismiss: () -> Unit = {}) = diff --git a/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/NodeActionButton.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/NodeActionButton.kt new file mode 100644 index 000000000..804ae8f4a --- /dev/null +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/NodeActionButton.kt @@ -0,0 +1,62 @@ +/* + * 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 . + */ + +package org.meshtastic.feature.settings.radio.component + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Button +import androidx.compose.material3.Icon +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp + +@Composable +fun NodeActionButton( + modifier: Modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp).height(48.dp), + title: String, + enabled: Boolean, + icon: ImageVector? = null, + iconTint: Color? = null, + onClick: () -> Unit, +) { + Button(onClick = { onClick() }, enabled = enabled, modifier = modifier) { + Row(verticalAlignment = Alignment.CenterVertically) { + if (icon != null) { + Icon( + imageVector = icon, + contentDescription = title, + modifier = Modifier.size(24.dp), + tint = iconTint ?: LocalContentColor.current, + ) + Spacer(modifier = Modifier.width(8.dp)) + } + Text(text = title, style = MaterialTheme.typography.bodyLarge, modifier = Modifier.weight(1f)) + } + } +} diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PacketResponseStateDialog.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PacketResponseStateDialog.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PacketResponseStateDialog.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PacketResponseStateDialog.kt index e3ad7e26e..d10287b03 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PacketResponseStateDialog.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PacketResponseStateDialog.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.activity.compose.LocalOnBackPressedDispatcherOwner import androidx.compose.animation.core.animateFloatAsState @@ -36,8 +36,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.geeksville.mesh.ui.settings.radio.ResponseState import org.meshtastic.core.strings.R +import org.meshtastic.feature.settings.radio.ResponseState @Composable fun PacketResponseStateDialog(state: ResponseState, onDismiss: () -> Unit = {}, onComplete: () -> Unit = {}) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PaxcounterConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PaxcounterConfigItemList.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PaxcounterConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PaxcounterConfigItemList.kt index d5d635b2f..dbce6cc57 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PaxcounterConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PaxcounterConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -28,12 +28,12 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SignedIntegerEditTextPreference import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun PaxcounterConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PositionConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PositionConfigItemList.kt similarity index 99% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PositionConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PositionConfigItemList.kt index b53ed04e2..c4d963f2f 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PositionConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PositionConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import android.Manifest import android.annotation.SuppressLint @@ -43,7 +43,6 @@ import com.geeksville.mesh.ConfigProtos import com.geeksville.mesh.ConfigProtos.Config.PositionConfig import com.geeksville.mesh.config import com.geeksville.mesh.copy -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.rememberPermissionState import kotlinx.coroutines.launch @@ -54,6 +53,7 @@ import org.meshtastic.core.ui.component.DropDownPreference import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @OptIn(ExperimentalPermissionsApi::class) @Composable diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PowerConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PowerConfigItemList.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PowerConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PowerConfigItemList.kt index 5e18b4a6d..2d2bb3ec2 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/PowerConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PowerConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -28,11 +28,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.config import com.geeksville.mesh.copy -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun PowerConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/RadioConfigScreenList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/RadioConfigScreenList.kt similarity index 96% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/RadioConfigScreenList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/RadioConfigScreenList.kt index 7398032c5..a037c1462 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/RadioConfigScreenList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/RadioConfigScreenList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues @@ -29,11 +29,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.geeksville.mesh.ui.settings.radio.ResponseState import com.google.protobuf.MessageLite import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.MainAppBar import org.meshtastic.core.ui.component.PreferenceFooter +import org.meshtastic.feature.settings.radio.ResponseState @Composable fun RadioConfigScreenList( diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/RangeTestConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/RangeTestConfigItemList.kt similarity index 96% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/RangeTestConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/RangeTestConfigItemList.kt index 11d54dd81..abda41b83 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/RangeTestConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/RangeTestConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -28,11 +28,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun RangeTestConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/RemoteHardwareConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/RemoteHardwareConfigItemList.kt similarity index 96% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/RemoteHardwareConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/RemoteHardwareConfigItemList.kt index bf0d7ce3d..8d72dc097 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/RemoteHardwareConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/RemoteHardwareConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -28,11 +28,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.EditListPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun RemoteHardwareConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/SecurityConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/SecurityConfigItemList.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/SecurityConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/SecurityConfigItemList.kt index 289c30535..b4757f863 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/SecurityConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/SecurityConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import android.app.Activity import android.content.Intent @@ -46,8 +46,6 @@ import androidx.navigation.NavController import com.geeksville.mesh.ConfigProtos.Config.SecurityConfig import com.geeksville.mesh.config import com.geeksville.mesh.copy -import com.geeksville.mesh.ui.node.NodeActionButton -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import com.google.protobuf.ByteString import org.meshtastic.core.model.util.encodeToString import org.meshtastic.core.model.util.toByteString @@ -57,6 +55,7 @@ import org.meshtastic.core.ui.component.EditBase64Preference import org.meshtastic.core.ui.component.EditListPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel import java.security.SecureRandom @OptIn(ExperimentalMaterial3ExpressiveApi::class) diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/SerialConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/SerialConfigItemList.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/SerialConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/SerialConfigItemList.kt index 370da2c49..b56c7e737 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/SerialConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/SerialConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -29,12 +29,12 @@ import androidx.navigation.NavController import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig.SerialConfig import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.DropDownPreference import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun SerialConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/StoreForwardConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/StoreForwardConfigItemList.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/StoreForwardConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/StoreForwardConfigItemList.kt index ad88360a1..ef1b187d5 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/StoreForwardConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/StoreForwardConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -28,11 +28,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun StoreForwardConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/TelemetryConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/TelemetryConfigItemList.kt similarity index 98% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/TelemetryConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/TelemetryConfigItemList.kt index 777714ece..54a760b26 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/TelemetryConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/TelemetryConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.material3.HorizontalDivider @@ -28,11 +28,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.copy import com.geeksville.mesh.moduleConfig -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.strings.R import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun TelemetryConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/UserConfigItemList.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/UserConfigItemList.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/UserConfigItemList.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/UserConfigItemList.kt index 9be4f52a8..96da4ddb5 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/UserConfigItemList.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/UserConfigItemList.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions @@ -30,7 +30,6 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import com.geeksville.mesh.copy -import com.geeksville.mesh.ui.settings.radio.RadioConfigViewModel import org.meshtastic.core.database.model.isUnmessageableRole import org.meshtastic.core.model.DeviceVersion import org.meshtastic.core.strings.R @@ -38,6 +37,7 @@ import org.meshtastic.core.ui.component.EditTextPreference import org.meshtastic.core.ui.component.PreferenceCategory import org.meshtastic.core.ui.component.RegularPreference import org.meshtastic.core.ui.component.SwitchPreference +import org.meshtastic.feature.settings.radio.RadioConfigViewModel @Composable fun UserConfigScreen(navController: NavController, viewModel: RadioConfigViewModel = hiltViewModel()) { diff --git a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/WarningDialog.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/WarningDialog.kt similarity index 97% rename from app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/WarningDialog.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/WarningDialog.kt index 71cc9e527..d701440dc 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/settings/radio/components/WarningDialog.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/WarningDialog.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.ui.settings.radio.components +package org.meshtastic.feature.settings.radio.component import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Warning diff --git a/app/src/main/java/com/geeksville/mesh/util/LanguageUtils.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/util/LanguageUtils.kt similarity index 95% rename from app/src/main/java/com/geeksville/mesh/util/LanguageUtils.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/util/LanguageUtils.kt index 98919d104..3e310ced5 100644 --- a/app/src/main/java/com/geeksville/mesh/util/LanguageUtils.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/util/LanguageUtils.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.util +package org.meshtastic.feature.settings.util import android.content.Context import androidx.appcompat.app.AppCompatDelegate @@ -46,7 +46,7 @@ object LanguageUtils { add(SYSTEM_DEFAULT) try { - resources.getXml(com.geeksville.mesh.R.xml.locales_config).use { parser -> + resources.getXml(org.meshtastic.feature.settings.R.xml.locales_config).use { parser -> while (parser.eventType != XmlPullParser.END_DOCUMENT) { if (parser.eventType == XmlPullParser.START_TAG && parser.name == "locale") { val languageTag = diff --git a/app/src/main/java/com/geeksville/mesh/util/UiText.kt b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/util/UiText.kt similarity index 73% rename from app/src/main/java/com/geeksville/mesh/util/UiText.kt rename to feature/settings/src/main/kotlin/org/meshtastic/feature/settings/util/UiText.kt index 47912b64f..b92ff1546 100644 --- a/app/src/main/java/com/geeksville/mesh/util/UiText.kt +++ b/feature/settings/src/main/kotlin/org/meshtastic/feature/settings/util/UiText.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package com.geeksville.mesh.util +package org.meshtastic.feature.settings.util import android.content.Context import androidx.annotation.StringRes @@ -25,20 +25,17 @@ import androidx.compose.ui.res.stringResource @Suppress("SpreadOperator") sealed class UiText { data class DynamicString(val value: String) : UiText() + class StringResource(@StringRes val resId: Int, vararg val args: Any) : UiText() @Composable - fun asString(): String { - return when (this) { - is DynamicString -> value - is StringResource -> stringResource(resId, *args) - } + fun asString(): String = when (this) { + is DynamicString -> value + is StringResource -> stringResource(resId, *args) } - fun asString(context: Context): String { - return when (this) { - is DynamicString -> value - is StringResource -> context.getString(resId, *args) - } + fun asString(context: Context): String = when (this) { + is DynamicString -> value + is StringResource -> context.getString(resId, *args) } } diff --git a/app/src/main/res/xml/locales_config.xml b/feature/settings/src/main/res/xml/locales_config.xml similarity index 100% rename from app/src/main/res/xml/locales_config.xml rename to feature/settings/src/main/res/xml/locales_config.xml diff --git a/settings.gradle.kts b/settings.gradle.kts index 7de9fcdea..46ac9f060 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -34,6 +34,7 @@ include( ":feature:intro", ":feature:map", ":feature:node", + ":feature:settings", ":mesh_service_example", ) rootProject.name = "MeshtasticAndroid"