mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: Implement iOS support and unify Compose Multiplatform infrastructure (#4876)
This commit is contained in:
parent
f04924ded5
commit
d136b162a4
170 changed files with 2208 additions and 2432 deletions
|
|
@ -43,6 +43,7 @@ import androidx.compose.ui.graphics.painter.ColorPainter
|
|||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
@Composable
|
||||
fun <T : Enum<T>> DropDownPreference(
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ fun EditTextPreference(
|
|||
isError = isError,
|
||||
onValueChange = {
|
||||
if (maxSize > 0) {
|
||||
if (it.toByteArray().size <= maxSize) {
|
||||
if (it.encodeToByteArray().size <= maxSize) {
|
||||
onValueChanged(it)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -255,7 +255,7 @@ fun EditTextPreference(
|
|||
if (maxSize > 0 && isFocused) {
|
||||
Box(contentAlignment = Alignment.BottomEnd, modifier = Modifier.fillMaxWidth()) {
|
||||
Text(
|
||||
text = "${value.toByteArray().size}/$maxSize",
|
||||
text = "${value.encodeToByteArray().size}/$maxSize",
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = if (isError) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.onBackground,
|
||||
modifier = Modifier.padding(end = 8.dp, bottom = 4.dp),
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||
import androidx.compose.ui.unit.dp
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.common.util.formatString
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.bad
|
||||
import org.meshtastic.core.resources.fair
|
||||
|
|
@ -153,7 +154,7 @@ fun Snr(snr: Float, modifier: Modifier = Modifier) {
|
|||
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = "%s %.2fdB".format(stringResource(Res.string.snr), snr),
|
||||
text = formatString("%s %.2fdB", stringResource(Res.string.snr), snr),
|
||||
color = color,
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
)
|
||||
|
|
@ -171,7 +172,7 @@ fun Rssi(rssi: Int, modifier: Modifier = Modifier) {
|
|||
}
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = "%s %ddBm".format(stringResource(Res.string.rssi), rssi),
|
||||
text = formatString("%s %ddBm", stringResource(Res.string.rssi), rssi),
|
||||
color = color,
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.common.util.formatString
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.unknown
|
||||
import org.meshtastic.core.ui.icon.BatteryEmpty
|
||||
|
|
@ -60,7 +61,7 @@ fun MaterialBatteryInfo(
|
|||
voltage: Float? = null,
|
||||
contentColor: Color = MaterialTheme.colorScheme.onSurface,
|
||||
) {
|
||||
val levelString = FORMAT.format(level)
|
||||
val levelString = formatString(FORMAT, level)
|
||||
|
||||
Row(
|
||||
modifier = modifier,
|
||||
|
|
@ -130,7 +131,7 @@ fun MaterialBatteryInfo(
|
|||
?.takeIf { it > 0 }
|
||||
?.let {
|
||||
Text(
|
||||
text = "%.2fV".format(it),
|
||||
text = formatString("%.2fV", it),
|
||||
color = contentColor.copy(alpha = 0.8f),
|
||||
style = MaterialTheme.typography.labelMedium.copy(fontSize = 12.sp),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@
|
|||
*/
|
||||
package org.meshtastic.core.ui.component
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
||||
/**
|
||||
* Event emitted when a user re-presses a bottom navigation destination that should trigger a scroll-to-top behaviour on
|
||||
* the corresponding screen.
|
||||
|
|
@ -25,3 +29,5 @@ sealed class ScrollToTopEvent {
|
|||
|
||||
data object ConversationsTabPressed : ScrollToTopEvent()
|
||||
}
|
||||
|
||||
@Composable fun rememberScrollToTopEvents(): MutableSharedFlow<ScrollToTopEvent> = remember { MutableSharedFlow() }
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.meshtastic.core.common.util.formatString
|
||||
import org.meshtastic.core.model.Node
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.signal_quality
|
||||
|
|
@ -63,7 +64,7 @@ fun SignalInfo(
|
|||
tint = signalColor,
|
||||
)
|
||||
Text(
|
||||
text = "%.1fdB · %ddBm · %s".format(node.snr, node.rssi, stringResource(quality.nameRes)),
|
||||
text = formatString("%.1fdB · %ddBm · %s", node.snr, node.rssi, stringResource(quality.nameRes)),
|
||||
style =
|
||||
MaterialTheme.typography.labelSmall.copy(
|
||||
fontWeight = FontWeight.Bold,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.PreviewScreenSizes
|
||||
import androidx.compose.ui.tooling.preview.PreviewLightDark
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
|
|
@ -297,7 +297,7 @@ fun ScannedQrCodeDialog(
|
|||
}
|
||||
}
|
||||
|
||||
@PreviewScreenSizes
|
||||
@PreviewLightDark
|
||||
@Composable
|
||||
private fun ScannedQrCodeDialogPreview() {
|
||||
ScannedQrCodeDialog(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2026 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.runtime.Composable
|
||||
|
||||
@Composable actual fun rememberTimeTickWithLifecycle(): Long = 0L
|
||||
|
||||
internal actual fun <T : Enum<T>> enumEntriesOf(selectedItem: T): List<T> = emptyList()
|
||||
|
||||
internal actual fun Enum<*>.isDeprecatedEnumEntry(): Boolean = false
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2026 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.theme
|
||||
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable actual fun dynamicColorScheme(darkTheme: Boolean): ColorScheme? = null
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2026 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.util
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.ClipEntry
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.TextLinkStyles
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
|
||||
actual fun createClipEntry(text: String, label: String): ClipEntry =
|
||||
throw UnsupportedOperationException("ClipEntry instantiation not supported on iOS stub")
|
||||
|
||||
actual fun annotatedStringFromHtml(html: String, linkStyles: TextLinkStyles?): AnnotatedString = AnnotatedString(html)
|
||||
|
||||
@Composable actual fun rememberOpenNfcSettings(): () -> Unit = {}
|
||||
|
||||
@Composable actual fun rememberShowToast(): suspend (String) -> Unit = { _ -> }
|
||||
|
||||
@Composable actual fun rememberShowToastResource(): suspend (StringResource) -> Unit = { _ -> }
|
||||
|
||||
@Composable actual fun rememberOpenMap(): (latitude: Double, longitude: Double, label: String) -> Unit = { _, _, _ -> }
|
||||
|
||||
@Composable actual fun rememberOpenUrl(): (url: String) -> Unit = { _ -> }
|
||||
|
||||
@Composable actual fun SetScreenBrightness(brightness: Float) {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue