refactor: migrate from Hilt to Koin and expand KMP common modules (#4746)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-03-09 20:19:46 -05:00 committed by GitHub
parent a5390a80e7
commit 875cf1cff2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
440 changed files with 3738 additions and 3508 deletions

View file

@ -0,0 +1,24 @@
/*
* 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.di
import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.Module
@Module
@ComponentScan("org.meshtastic.core.ui")
class CoreUiModule

View file

@ -26,12 +26,12 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import androidx.emoji2.emojipicker.RecentEmojiProviderAdapter
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import org.koin.compose.viewmodel.koinViewModel
import org.meshtastic.core.ui.component.BottomSheetDialog
@Composable
fun EmojiPicker(
viewModel: EmojiPickerViewModel = hiltViewModel(),
viewModel: EmojiPickerViewModel = koinViewModel(),
onDismiss: () -> Unit = {},
onConfirm: (String) -> Unit,
) {

View file

@ -17,12 +17,11 @@
package org.meshtastic.core.ui.emoji
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import org.koin.core.annotation.KoinViewModel
import org.meshtastic.core.repository.CustomEmojiPrefs
import javax.inject.Inject
@HiltViewModel
class EmojiPickerViewModel @Inject constructor(private val customEmojiPrefs: CustomEmojiPrefs) : ViewModel() {
@KoinViewModel
class EmojiPickerViewModel(private val customEmojiPrefs: CustomEmojiPrefs) : ViewModel() {
var customEmojiFrequency: String?
get() = customEmojiPrefs.customEmojiFrequency.value

View file

@ -47,9 +47,9 @@ import androidx.compose.ui.tooling.preview.PreviewScreenSizes
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel
import org.meshtastic.core.model.Channel
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.accept
@ -66,7 +66,7 @@ import org.meshtastic.proto.ChannelSet
fun ScannedQrCodeDialog(
incoming: ChannelSet,
onDismiss: () -> Unit,
viewModel: ScannedQrCodeViewModel = hiltViewModel(),
viewModel: ScannedQrCodeViewModel = koinViewModel(),
) {
val channels by viewModel.channels.collectAsStateWithLifecycle()

View file

@ -18,8 +18,8 @@ package org.meshtastic.core.ui.qr
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import org.koin.core.annotation.KoinViewModel
import org.meshtastic.core.model.RadioController
import org.meshtastic.core.repository.RadioConfigRepository
import org.meshtastic.core.ui.util.getChannelList
@ -28,12 +28,9 @@ import org.meshtastic.proto.Channel
import org.meshtastic.proto.ChannelSet
import org.meshtastic.proto.Config
import org.meshtastic.proto.LocalConfig
import javax.inject.Inject
@HiltViewModel
class ScannedQrCodeViewModel
@Inject
constructor(
@KoinViewModel
class ScannedQrCodeViewModel(
private val radioConfigRepository: RadioConfigRepository,
private val radioController: RadioController,
) : ViewModel() {

View file

@ -22,9 +22,9 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel
import org.meshtastic.core.model.util.compareUsers
import org.meshtastic.core.model.util.userFieldsToString
import org.meshtastic.core.resources.Res
@ -42,7 +42,7 @@ import org.meshtastic.proto.User
fun SharedContactDialog(
sharedContact: SharedContact,
onDismiss: () -> Unit,
viewModel: SharedContactViewModel = hiltViewModel(),
viewModel: SharedContactViewModel = koinViewModel(),
) {
val unfilteredNodes by viewModel.unfilteredNodes.collectAsStateWithLifecycle()

View file

@ -18,24 +18,19 @@ package org.meshtastic.core.ui.share
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import org.koin.core.annotation.KoinViewModel
import org.meshtastic.core.model.Node
import org.meshtastic.core.model.service.ServiceAction
import org.meshtastic.core.repository.NodeRepository
import org.meshtastic.core.repository.ServiceRepository
import org.meshtastic.core.ui.viewmodel.stateInWhileSubscribed
import org.meshtastic.proto.SharedContact
import javax.inject.Inject
@HiltViewModel
class SharedContactViewModel
@Inject
constructor(
nodeRepository: NodeRepository,
private val serviceRepository: ServiceRepository,
) : ViewModel() {
@KoinViewModel
class SharedContactViewModel(nodeRepository: NodeRepository, private val serviceRepository: ServiceRepository) :
ViewModel() {
val unfilteredNodes: StateFlow<List<Node>> =
nodeRepository.getNodes().stateInWhileSubscribed(initialValue = emptyList())

View file

@ -21,8 +21,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import org.jetbrains.compose.resources.StringResource
import javax.inject.Inject
import javax.inject.Singleton
import org.koin.core.annotation.Single
fun interface ComposableContent {
@Composable fun Content()
@ -32,8 +31,8 @@ fun interface ComposableContent {
* A global manager for displaying alerts across the application. This allows ViewModels to trigger alerts without
* direct dependencies on UI components.
*/
@Singleton
class AlertManager @Inject constructor() {
@Single
class AlertManager {
data class AlertData(
val title: String? = null,
val titleRes: StringResource? = null,

View file

@ -0,0 +1,24 @@
/*
* 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.runtime.compositionLocalOf
import androidx.compose.ui.Modifier
import org.meshtastic.core.model.Node
val LocalInlineMapProvider = compositionLocalOf<@Composable (node: Node, modifier: Modifier) -> Unit> { { _, _ -> } }

View file

@ -0,0 +1,30 @@
/*
* 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.foundation.layout.PaddingValues
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.unit.dp
data class TracerouteMapOverlayInsets(
val overlayAlignment: Alignment = Alignment.BottomCenter,
val overlayPadding: PaddingValues = PaddingValues(bottom = 16.dp),
val contentHorizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
)
val LocalTracerouteMapOverlayInsetsProvider = compositionLocalOf { TracerouteMapOverlayInsets() }