mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Modularize ScannedQrCodeDialog (#3446)
This commit is contained in:
parent
b4c8873484
commit
e691981207
13 changed files with 118 additions and 65 deletions
|
|
@ -226,7 +226,6 @@ dependencies {
|
|||
implementation(libs.coil.svg)
|
||||
implementation(libs.androidx.hilt.lifecycle.viewmodel.compose)
|
||||
implementation(libs.zxing.android.embedded) { isTransitive = false }
|
||||
implementation(libs.zxing.core)
|
||||
implementation(libs.androidx.core.splashscreen)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
implementation(libs.org.eclipse.paho.client.mqttv3)
|
||||
|
|
@ -243,11 +242,9 @@ dependencies {
|
|||
fdroidImplementation(libs.osmdroid.android)
|
||||
fdroidImplementation(libs.osmdroid.geopackage) { exclude(group = "com.j256.ormlite") }
|
||||
|
||||
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
|
||||
androidTestImplementation(libs.androidx.test.runner)
|
||||
androidTestImplementation(libs.hilt.android.testing)
|
||||
|
||||
testImplementation(libs.androidx.test.ext.junit)
|
||||
testImplementation(libs.junit)
|
||||
|
||||
dokkaPlugin(libs.dokka.android.documentation.plugin)
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ import com.geeksville.mesh.navigation.mapGraph
|
|||
import com.geeksville.mesh.navigation.nodesGraph
|
||||
import com.geeksville.mesh.repository.radio.MeshActivity
|
||||
import com.geeksville.mesh.service.MeshService
|
||||
import com.geeksville.mesh.ui.common.components.ScannedQrCodeDialog
|
||||
import com.geeksville.mesh.ui.connections.DeviceType
|
||||
import com.geeksville.mesh.ui.connections.components.ConnectionsNavIcon
|
||||
import com.geeksville.mesh.ui.metrics.annotateTraceroute
|
||||
|
|
@ -118,6 +117,7 @@ import org.meshtastic.core.ui.icon.Map
|
|||
import org.meshtastic.core.ui.icon.MeshtasticIcons
|
||||
import org.meshtastic.core.ui.icon.Nodes
|
||||
import org.meshtastic.core.ui.icon.Settings
|
||||
import org.meshtastic.core.ui.qr.ScannedQrCodeDialog
|
||||
import org.meshtastic.core.ui.share.SharedContactDialog
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusBlue
|
||||
import org.meshtastic.core.ui.theme.StatusColors.StatusGreen
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ import androidx.compose.ui.unit.sp
|
|||
import androidx.core.net.toUri
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.geeksville.mesh.ui.common.components.ScannedQrCodeDialog
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
|
|
@ -104,12 +103,13 @@ import org.meshtastic.core.navigation.Route
|
|||
import org.meshtastic.core.service.ConnectionState
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.AdaptiveTwoPane
|
||||
import org.meshtastic.core.ui.component.ChannelSelection
|
||||
import org.meshtastic.core.ui.component.MainAppBar
|
||||
import org.meshtastic.core.ui.component.PreferenceFooter
|
||||
import org.meshtastic.core.ui.qr.ScannedQrCodeDialog
|
||||
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 org.meshtastic.proto.AppOnlyProtos.ChannelSet
|
||||
import org.meshtastic.proto.ChannelProtos
|
||||
|
|
|
|||
|
|
@ -44,4 +44,9 @@ dependencies {
|
|||
implementation(libs.zxing.core)
|
||||
implementation(libs.zxing.android.embedded)
|
||||
implementation(libs.timber)
|
||||
|
||||
debugImplementation(libs.androidx.compose.ui.test.manifest)
|
||||
|
||||
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
|
||||
androidTestImplementation(libs.androidx.test.runner)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
<ID>MagicNumber:EditListPreference.kt$67890</ID>
|
||||
<ID>MagicNumber:LazyColumnDragAndDropDemo.kt$50</ID>
|
||||
<ID>ModifierMissing:AdaptiveTwoPane.kt$AdaptiveTwoPane</ID>
|
||||
<ID>ModifierMissing:ChannelItem.kt$ChannelItem</ID>
|
||||
<ID>ModifierMissing:ChannelSelection.kt$ChannelSelection</ID>
|
||||
<ID>ModifierMissing:ContactSharing.kt$SharedContactDialog</ID>
|
||||
<ID>ModifierMissing:EmojiPicker.kt$EmojiPicker</ID>
|
||||
<ID>ModifierMissing:EmojiPicker.kt$EmojiPickerDialog</ID>
|
||||
|
|
@ -48,6 +50,7 @@
|
|||
<ID>ModifierReused:TextDividerPreference.kt$Row(modifier = modifier.fillMaxWidth().padding(all = 16.dp), verticalAlignment = Alignment.CenterVertically) { Text( text = title, style = MaterialTheme.typography.bodyLarge, color = if (!enabled) { MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f) } else { Color.Unspecified }, ) if (trailingIcon != null) { Icon(trailingIcon, "trailingIcon", modifier = modifier.fillMaxWidth().wrapContentWidth(Alignment.End)) } }</ID>
|
||||
<ID>MultipleEmitters:PreferenceCategory.kt$PreferenceCategory</ID>
|
||||
<ID>ParameterNaming:BitwisePreference.kt$onItemSelected</ID>
|
||||
<ID>ParameterNaming:ChannelSelection.kt$onSelected</ID>
|
||||
<ID>ParameterNaming:ContactSharing.kt$onSharedContactRequested</ID>
|
||||
<ID>ParameterNaming:DropDownPreference.kt$onItemSelected</ID>
|
||||
<ID>ParameterNaming:EditIPv4Preference.kt$onValueChanged</ID>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.compose
|
||||
package org.meshtastic.core.ui.qr
|
||||
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
|
|
@ -23,7 +23,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.common.components.ScannedQrCodeDialog
|
||||
import org.junit.Assert
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.meshtastic.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.AssistChip
|
||||
import androidx.compose.material3.Card
|
||||
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.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun ChannelItem(
|
||||
index: Int,
|
||||
title: String,
|
||||
enabled: Boolean,
|
||||
onClick: () -> Unit = {},
|
||||
content: @Composable RowScope.() -> Unit,
|
||||
) {
|
||||
val fontColor = if (index == 0) MaterialTheme.colorScheme.primary else Color.Unspecified
|
||||
Card(modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp).clickable(enabled = enabled) { onClick() }) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(vertical = 4.dp, horizontal = 4.dp),
|
||||
) {
|
||||
AssistChip(onClick = onClick, label = { Text(text = "$index", color = fontColor) })
|
||||
Text(
|
||||
text = title,
|
||||
modifier = Modifier.weight(1f),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = fontColor,
|
||||
)
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.meshtastic.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.meshtastic.core.model.Channel
|
||||
|
||||
@Composable
|
||||
fun ChannelSelection(
|
||||
index: Int,
|
||||
title: String,
|
||||
enabled: Boolean,
|
||||
isSelected: Boolean,
|
||||
onSelected: (Boolean) -> Unit,
|
||||
channel: Channel,
|
||||
) = ChannelItem(index = index, title = title, enabled = enabled) {
|
||||
SecurityIcon(channel)
|
||||
Spacer(modifier = Modifier.width(10.dp))
|
||||
Checkbox(enabled = enabled, checked = isSelected, onCheckedChange = onSelected)
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.ui.common.components
|
||||
package org.meshtastic.core.ui.qr
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
|
|
@ -53,7 +53,7 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.meshtastic.core.model.Channel
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.feature.settings.radio.component.ChannelSelection
|
||||
import org.meshtastic.core.ui.component.ChannelSelection
|
||||
import org.meshtastic.proto.AppOnlyProtos.ChannelSet
|
||||
import org.meshtastic.proto.ConfigProtos.Config.LoRaConfig.ModemPreset
|
||||
import org.meshtastic.proto.channelSet
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.ui.common.components
|
||||
package org.meshtastic.core.ui.qr
|
||||
|
||||
import android.os.RemoteException
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
|
@ -33,7 +33,6 @@
|
|||
<ID>MagicNumber:EditChannelDialog.kt$16</ID>
|
||||
<ID>MagicNumber:EditChannelDialog.kt$32</ID>
|
||||
<ID>MagicNumber:PacketResponseStateDialog.kt$100</ID>
|
||||
<ID>ModifierMissing:ChannelSettingsItemList.kt$ChannelSelection</ID>
|
||||
<ID>ModifierMissing:CleanNodeDatabaseScreen.kt$CleanNodeDatabaseScreen</ID>
|
||||
<ID>ModifierMissing:MapReportingPreference.kt$MapReportingPreference</ID>
|
||||
<ID>ModifierMissing:NetworkConfigItemList.kt$NetworkConfigScreen</ID>
|
||||
|
|
@ -48,7 +47,6 @@
|
|||
<ID>MultipleEmitters:RadioConfig.kt$RadioConfigItemList</ID>
|
||||
<ID>NestedBlockDepth:RadioConfigViewModel.kt$RadioConfigViewModel$private fun processPacketResponse(packet: MeshProtos.MeshPacket)</ID>
|
||||
<ID>ParameterNaming:ChannelSettingsItemList.kt$onPositiveClicked</ID>
|
||||
<ID>ParameterNaming:ChannelSettingsItemList.kt$onSelected</ID>
|
||||
<ID>ParameterNaming:CleanNodeDatabaseScreen.kt$onCheckedChanged</ID>
|
||||
<ID>ParameterNaming:CleanNodeDatabaseScreen.kt$onDaysChanged</ID>
|
||||
<ID>ParameterNaming:MapReportingPreference.kt$onMapReportingEnabledChanged</ID>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
package org.meshtastic.feature.settings.radio.component
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.assertIsNotDisplayed
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
|
|
@ -61,7 +60,6 @@ class MapReportingPreferenceTest {
|
|||
publishIntervalSecs = positionReportingInterval,
|
||||
onPublishIntervalSecsChanged = positionReportingIntervalChanged,
|
||||
enabled = true,
|
||||
focusManager = LocalFocusManager.current,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,13 +22,11 @@ import androidx.compose.animation.core.FastOutSlowInEasing
|
|||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
|
@ -40,13 +38,9 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
|||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.twotone.Add
|
||||
import androidx.compose.material.icons.twotone.Close
|
||||
import androidx.compose.material3.AssistChip
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -59,11 +53,9 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
|
@ -72,6 +64,7 @@ import androidx.navigation.NavController
|
|||
import org.meshtastic.core.model.Channel
|
||||
import org.meshtastic.core.model.DeviceVersion
|
||||
import org.meshtastic.core.strings.R
|
||||
import org.meshtastic.core.ui.component.ChannelItem
|
||||
import org.meshtastic.core.ui.component.PreferenceCategory
|
||||
import org.meshtastic.core.ui.component.PreferenceFooter
|
||||
import org.meshtastic.core.ui.component.SecurityIcon
|
||||
|
|
@ -83,34 +76,6 @@ import org.meshtastic.proto.ChannelProtos.ChannelSettings
|
|||
import org.meshtastic.proto.ConfigProtos.Config.LoRaConfig
|
||||
import org.meshtastic.proto.channelSettings
|
||||
|
||||
@Composable
|
||||
private fun ChannelItem(
|
||||
index: Int,
|
||||
title: String,
|
||||
enabled: Boolean,
|
||||
onClick: () -> Unit = {},
|
||||
content: @Composable RowScope.() -> Unit,
|
||||
) {
|
||||
val fontColor = if (index == 0) MaterialTheme.colorScheme.primary else Color.Unspecified
|
||||
Card(modifier = Modifier.fillMaxWidth().padding(vertical = 2.dp).clickable(enabled = enabled) { onClick() }) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.padding(vertical = 4.dp, horizontal = 4.dp),
|
||||
) {
|
||||
AssistChip(onClick = onClick, label = { Text(text = "$index", color = fontColor) })
|
||||
Text(
|
||||
text = title,
|
||||
modifier = Modifier.weight(1f),
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = fontColor,
|
||||
)
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ChannelCard(
|
||||
index: Int,
|
||||
|
|
@ -154,20 +119,6 @@ private fun ChannelCard(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ChannelSelection(
|
||||
index: Int,
|
||||
title: String,
|
||||
enabled: Boolean,
|
||||
isSelected: Boolean,
|
||||
onSelected: (Boolean) -> Unit,
|
||||
channel: Channel,
|
||||
) = ChannelItem(index = index, title = title, enabled = enabled) {
|
||||
SecurityIcon(channel)
|
||||
Spacer(modifier = Modifier.width(10.dp))
|
||||
Checkbox(enabled = enabled, checked = isSelected, onCheckedChange = onSelected)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ChannelConfigScreen(navController: NavController, viewModel: RadioConfigViewModel) {
|
||||
val state by viewModel.radioConfigState.collectAsStateWithLifecycle()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue