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.domain.di
import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.Module
@Module
@ComponentScan("org.meshtastic.core.domain")
class CoreDomainModule

View file

@ -16,9 +16,9 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.model.RadioController
import org.meshtastic.core.repository.NodeRepository
import javax.inject.Inject
/**
* Use case for performing administrative and destructive actions on mesh nodes.
@ -26,8 +26,8 @@ import javax.inject.Inject
* This component provides methods for rebooting, shutting down, or resetting nodes within the mesh. It also handles
* local database synchronization when these actions are performed on the locally connected device.
*/
@Single
open class AdminActionsUseCase
@Inject
constructor(
private val radioController: RadioController,
private val nodeRepository: NodeRepository,

View file

@ -16,15 +16,15 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.model.Node
import org.meshtastic.core.model.RadioController
import org.meshtastic.core.repository.NodeRepository
import javax.inject.Inject
import kotlin.time.Duration.Companion.days
/** Use case for cleaning up nodes from the database. */
@Single
open class CleanNodeDatabaseUseCase
@Inject
constructor(
private val nodeRepository: NodeRepository,
private val radioController: RadioController,

View file

@ -21,18 +21,18 @@ import kotlinx.datetime.Instant
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime
import okio.BufferedSink
import org.koin.core.annotation.Single
import org.meshtastic.core.model.Position
import org.meshtastic.core.model.util.positionToMeter
import org.meshtastic.core.repository.MeshLogRepository
import org.meshtastic.core.repository.NodeRepository
import org.meshtastic.proto.PortNum
import javax.inject.Inject
import kotlin.math.roundToInt
import org.meshtastic.proto.Position as ProtoPosition
/** Use case for exporting persisted packet data to a CSV format. */
@Single
open class ExportDataUseCase
@Inject
constructor(
private val nodeRepository: NodeRepository,
private val meshLogRepository: MeshLogRepository,

View file

@ -17,11 +17,12 @@
package org.meshtastic.core.domain.usecase.settings
import okio.BufferedSink
import org.koin.core.annotation.Single
import org.meshtastic.proto.DeviceProfile
import javax.inject.Inject
/** Use case for exporting a device profile to an output stream. */
open class ExportProfileUseCase @Inject constructor() {
@Single
open class ExportProfileUseCase {
/**
* Exports the provided [DeviceProfile] to the given [BufferedSink].
*

View file

@ -19,12 +19,13 @@ package org.meshtastic.core.domain.usecase.settings
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import okio.BufferedSink
import org.koin.core.annotation.Single
import org.meshtastic.core.common.util.nowMillis
import org.meshtastic.proto.Config
import javax.inject.Inject
/** Use case for exporting security configuration to a JSON format. */
open class ExportSecurityConfigUseCase @Inject constructor() {
@Single
open class ExportSecurityConfigUseCase {
/**
* Exports the provided [Config.SecurityConfig] as a JSON string to the given [BufferedSink].
*

View file

@ -17,11 +17,12 @@
package org.meshtastic.core.domain.usecase.settings
import okio.BufferedSource
import org.koin.core.annotation.Single
import org.meshtastic.proto.DeviceProfile
import javax.inject.Inject
/** Use case for importing a device profile from an input stream. */
open class ImportProfileUseCase @Inject constructor() {
@Single
open class ImportProfileUseCase {
/**
* Imports a [DeviceProfile] from the provided [BufferedSource].
*

View file

@ -16,6 +16,7 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.model.Position
import org.meshtastic.core.model.RadioController
import org.meshtastic.proto.Config
@ -24,10 +25,10 @@ import org.meshtastic.proto.LocalConfig
import org.meshtastic.proto.LocalModuleConfig
import org.meshtastic.proto.ModuleConfig
import org.meshtastic.proto.User
import javax.inject.Inject
/** Use case for installing a device profile onto a radio. */
open class InstallProfileUseCase @Inject constructor(private val radioController: RadioController) {
@Single
open class InstallProfileUseCase constructor(private val radioController: RadioController) {
/**
* Installs the provided [DeviceProfile] onto the radio at [destNum].
*

View file

@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import org.koin.core.annotation.Single
import org.meshtastic.core.model.ConnectionState
import org.meshtastic.core.model.Node
import org.meshtastic.core.model.RadioController
@ -29,11 +30,10 @@ import org.meshtastic.core.repository.RadioPrefs
import org.meshtastic.core.repository.isBle
import org.meshtastic.core.repository.isSerial
import org.meshtastic.core.repository.isTcp
import javax.inject.Inject
/** Use case to determine if the currently connected device is capable of over-the-air (OTA) updates. */
@Single
open class IsOtaCapableUseCase
@Inject
constructor(
private val nodeRepository: NodeRepository,
private val radioController: RadioController,

View file

@ -16,11 +16,12 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.model.RadioController
import javax.inject.Inject
/** Use case for controlling location sharing with the mesh. */
open class MeshLocationUseCase @Inject constructor(private val radioController: RadioController) {
@Single
open class MeshLocationUseCase constructor(private val radioController: RadioController) {
/** Starts providing the phone's location to the mesh. */
fun startProvidingLocation() {
radioController.startProvideLocation()

View file

@ -17,6 +17,7 @@
package org.meshtastic.core.domain.usecase.settings
import co.touchlab.kermit.Logger
import org.koin.core.annotation.Single
import org.meshtastic.core.model.getStringResFrom
import org.meshtastic.core.resources.UiText
import org.meshtastic.proto.AdminMessage
@ -28,7 +29,6 @@ import org.meshtastic.proto.MeshPacket
import org.meshtastic.proto.PortNum
import org.meshtastic.proto.Routing
import org.meshtastic.proto.User
import javax.inject.Inject
/** Sealed class representing the result of processing a radio response packet. */
sealed class RadioResponseResult {
@ -54,7 +54,8 @@ sealed class RadioResponseResult {
}
/** Use case for processing incoming [MeshPacket]s that are responses to admin requests. */
open class ProcessRadioResponseUseCase @Inject constructor() {
@Single
open class ProcessRadioResponseUseCase {
/**
* Decodes and processes the provided [packet].
*

View file

@ -16,16 +16,17 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.model.Position
import org.meshtastic.core.model.RadioController
import org.meshtastic.proto.Config
import org.meshtastic.proto.ModuleConfig
import org.meshtastic.proto.User
import javax.inject.Inject
/** Use case for interacting with radio configuration components. */
@Suppress("TooManyFunctions")
open class RadioConfigUseCase @Inject constructor(private val radioController: RadioController) {
@Single
open class RadioConfigUseCase constructor(private val radioController: RadioController) {
/**
* Updates the owner information on the radio.
*

View file

@ -16,15 +16,12 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.datastore.UiPreferencesDataSource
import javax.inject.Inject
/** Use case for setting whether the application intro has been completed. */
open class SetAppIntroCompletedUseCase
@Inject
constructor(
private val uiPreferencesDataSource: UiPreferencesDataSource,
) {
@Single
open class SetAppIntroCompletedUseCase constructor(private val uiPreferencesDataSource: UiPreferencesDataSource) {
operator fun invoke(completed: Boolean) {
uiPreferencesDataSource.setAppIntroCompleted(completed)
}

View file

@ -16,12 +16,13 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.common.database.DatabaseManager
import org.meshtastic.core.database.DatabaseConstants
import javax.inject.Inject
/** Use case for setting the database cache limit. */
open class SetDatabaseCacheLimitUseCase @Inject constructor(private val databaseManager: DatabaseManager) {
@Single
open class SetDatabaseCacheLimitUseCase constructor(private val databaseManager: DatabaseManager) {
operator fun invoke(limit: Int) {
val clamped = limit.coerceIn(DatabaseConstants.MIN_CACHE_LIMIT, DatabaseConstants.MAX_CACHE_LIMIT)
databaseManager.setCacheLimit(clamped)

View file

@ -16,13 +16,13 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.repository.MeshLogPrefs
import org.meshtastic.core.repository.MeshLogRepository
import javax.inject.Inject
/** Use case for managing mesh log settings. */
@Single
open class SetMeshLogSettingsUseCase
@Inject
constructor(
private val meshLogRepository: MeshLogRepository,
private val meshLogPrefs: MeshLogPrefs,

View file

@ -16,11 +16,12 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.repository.UiPrefs
import javax.inject.Inject
/** Use case for setting whether to provide the node location to the mesh. */
open class SetProvideLocationUseCase @Inject constructor(private val uiPrefs: UiPrefs) {
@Single
open class SetProvideLocationUseCase constructor(private val uiPrefs: UiPrefs) {
operator fun invoke(myNodeNum: Int, provideLocation: Boolean) {
uiPrefs.setShouldProvideNodeLocation(myNodeNum, provideLocation)
}

View file

@ -16,11 +16,12 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.datastore.UiPreferencesDataSource
import javax.inject.Inject
/** Use case for setting the application theme. */
open class SetThemeUseCase @Inject constructor(private val uiPreferencesDataSource: UiPreferencesDataSource) {
@Single
open class SetThemeUseCase constructor(private val uiPreferencesDataSource: UiPreferencesDataSource) {
operator fun invoke(themeMode: Int) {
uiPreferencesDataSource.setTheme(themeMode)
}

View file

@ -16,11 +16,12 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.repository.AnalyticsPrefs
import javax.inject.Inject
/** Use case for toggling the analytics preference. */
open class ToggleAnalyticsUseCase @Inject constructor(private val analyticsPrefs: AnalyticsPrefs) {
@Single
open class ToggleAnalyticsUseCase constructor(private val analyticsPrefs: AnalyticsPrefs) {
operator fun invoke() {
analyticsPrefs.setAnalyticsAllowed(!analyticsPrefs.analyticsAllowed.value)
}

View file

@ -16,11 +16,12 @@
*/
package org.meshtastic.core.domain.usecase.settings
import org.koin.core.annotation.Single
import org.meshtastic.core.repository.HomoglyphPrefs
import javax.inject.Inject
/** Use case for toggling the homoglyph encoding preference. */
open class ToggleHomoglyphEncodingUseCase @Inject constructor(private val homoglyphEncodingPrefs: HomoglyphPrefs) {
@Single
open class ToggleHomoglyphEncodingUseCase constructor(private val homoglyphEncodingPrefs: HomoglyphPrefs) {
operator fun invoke() {
homoglyphEncodingPrefs.setHomoglyphEncodingEnabled(!homoglyphEncodingPrefs.homoglyphEncodingEnabled.value)
}