- Rename _metadataCache backing property (no public counterpart)
- Break long log lines to satisfy MaxLineLength
- Suppress intentional TooGenericExceptionCaught in error boundaries
- Suppress LongMethod on dispatchAction (when-block, not complex)
- Apply spotless formatting across all modules
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
After rebase, MqttManagerImpl gained a nodeRepository parameter.
Updated test to mock and pass the new dependency.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Parse UTF-8 payload from NODE_STATUS_APP (PortNum=36) and update
the node's nodeStatus field. Already displayed in NodeItem and
NodeDetailsSection.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When ignoring a node, wipe position, deviceMetrics, and publicKey locally
to match what firmware does on the device side. Un-ignoring just clears
the isIgnored flag (device will re-populate on next heard packet).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Change RadioConfigState.route from String to Enum<*>?
- ChannelScreen resolves navigation target via typed cast instead of
string lookup through getNavRouteFrom()
- Delete dead SettingsNavUtils.kt (getNavRouteFrom now unused)
- Eliminates fragile string→enum round-trip that could silently fail
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract self-contained logic into plain coordinator classes:
- MqttProbeCoordinator: MQTT broker probe state + cancellation
- ProfileCoordinator: import/export/install profile file I/O
RadioConfigViewModel delegates to coordinators while retaining
state ownership and config-loading orchestration (its core job).
Reduces VM body by ~60 lines of implementation detail.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The combine(serviceRepository.connectionState, radioConfigState) pattern
subscribed to the ViewModel's own output StateFlow, causing redundant
re-evaluations on every state change. Replace with direct observation
of the source connectionState flow.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Only feature/messaging actually imports from core.service (SendMessageWorker).
The other 5 feature modules (connections, firmware, map, node, settings)
had vestigial dependency declarations from pre-migration.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove getPacketId() from MessageSender interface (SDK owns packet IDs)
- Remove requestId parameter from requestTraceroute/requestNeighborInfo
- Make getPacketId() private in SdkRadioController (still used internally
for delivery tracking correlation)
- Replace radioController.getPacketId() in map with local Random.nextInt()
for waypoint ID generation (only needs uniqueness, not SDK correlation)
- Remove messageSender dependency from CommonNodeRequestActions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- P0: setDeviceAddress now persists address to RadioPrefs before reconnect
- P0: Document nodedbReset firmware limitation (preserveFavorites is local-only)
- P1: Add writeAction helper for AdminException → sendError in RadioConfigViewModel
- P1: Wrap CommonNodeRequestActions scope.launch with runCatching for crash safety
- P1: Create CongestionLevel typealias in core/model to decouple feature modules from SDK
- P1: Cancel prior loadJob in setResponseStateLoading to prevent stale results
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the manual packet-ID tracking and meshPacketFlow subscription in
RadioConfigViewModel with direct typed returns from the SDK via
RadioConfigUseCase. The ViewModel now awaits typed results (User, Config,
ModuleConfig, channels, etc.) from suspend calls and maps AdminException
to UI error states.
Key changes:
- Delete ProcessRadioResponseUseCase (130 lines of manual proto decode)
- Remove requestIds state, registerRequestId, processPacketResponse,
sendAdminRequest, and meshPacketFlow subscription from ViewModel
- Rewrite setResponseStateLoading to use direct coroutine calls
- Admin actions (reboot/shutdown/etc.) fire directly without session key
preflight (SDK handles retryOnSessionExpiry transparently)
- All setters (setConfig, setModuleConfig, setOwner, updateChannels)
no longer return/track packetIds
- Remove messageSender dependency from NodeManagementActions
- Update InstallProfileUseCase to use editSettings {} receiver pattern
- Update all callers: CleanNodeDatabaseUseCase, Esp32OtaUpdateHandler,
NodeManagementActions
- Rewrite RadioConfigViewModelTest for new direct-await semantics
- Update RadioConfigUseCaseTest and InstallProfileUseCaseTest
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace all isLocalNode/sendRemoteAdmin patterns with
client.admin.forNode(NodeId(destNum)).method()
- Use client.sendReaction() instead of manual MeshPacket construction
- Use client.admin.forNode(dest).getDeviceMetadata() for remote metadata
- Delete sendRemoteAdmin() and isLocalNode() helpers
- Remove unused imports (AdminMessage, Data, MeshPacket from SdkStateBridge)
Net: -131 lines, all admin ops now go through SDK's typed API with
proper ACK tracking and session-key retry.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove handler interfaces, implementations, and tests that have zero production
callers after the SDK became authoritative for protocol handling:
- TelemetryPacketHandler/Impl — SDK owns telemetry via NodeChange.Updated
- StoreForwardPacketHandler/Impl — SDK owns S&F lifecycle + SFPP
- NeighborInfoHandler/Impl — SDK owns NeighborInfo model
- TracerouteHandler/Impl — SDK owns traceroute via AdminResult flow
- MeshDataHandler/MessagePersistenceHandler — handleReceivedData was no-op
- HistoryManager/Impl — only caller was deleted StoreForwardPacketHandlerImpl
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SdkStateBridge:
- Wrap handleServiceAction in try/catch to prevent bridge death
- Favorite/Ignore/Mute: only apply local state update on admin
success (eliminates optimistic state inconsistency)
- ImportContact: guard with runCatching, log failures
- Extract dispatchAction for clean separation of concerns
SdkRadioController:
- Wrap sendMessage with try/catch + logging before re-throw
- Wrap sendRemoteAdmin with try/catch + logging before re-throw
- Ensures BLE disconnect errors are visible in logs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eliminate the vestigial NodeManager/NodeRepository interface split.
All runtime node state management methods (handleReceivedUser,
handleReceivedPosition, handleReceivedTelemetry, updateNode, etc.)
now live directly on NodeRepository alongside the query surface.
- Delete NodeManager.kt (82 LOC)
- Extend NodeRepository with NodeIdLookup and add all manager methods
- Update 8 consumers to inject NodeRepository instead of NodeManager
- Remove dead nodeManager param from MeshServiceOrchestrator
- Add NodeManager methods to FakeNodeRepository test double
- Update all tests (mocks, constructor params, verifications)
- SdkNodeRepositoryImpl now binds [NodeRepository, NodeIdLookup]
Build: assembleDebug ✅, desktop:compileKotlin ✅, all jvmTests ✅
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Delete dead methods from NodeManager/NodeRepository interfaces:
- allowNodeDbWrites, setAllowNodeDbWrites (never read)
- loadCachedNodeDB (no-op, zero-value call in orchestrator)
- getNodes(): List<NodeInfo> (deprecated, unused)
- handleReceivedPaxcounter (zero callers)
- handleReceivedNodeStatus, updateNodeStatus (zero callers)
- insertMetadata (zero production callers)
Delete NodeInfo data class (85 LOC):
- All consumers now use Node domain model directly
- Retained MeshUser, Position, DeviceMetrics, EnvironmentMetrics
which have active consumers across feature modules
Remove corresponding implementations from SdkNodeRepositoryImpl,
FakeNodeRepository, and test verifications.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
NodeManager merge and MeshActivity restoration are done.
Only optional VM param slimming and test coverage remain.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Merge NodeManagerImpl logic into SdkNodeRepositoryImpl (single source
of truth for all node state — eliminates duplicate in-memory maps)
- SdkNodeRepositoryImpl now binds NodeRepository, NodeManager, NodeIdLookup
- Delete NodeManagerImpl.kt (377 LOC)
- Add meshActivityFlow to ServiceRepository for nav-bar icon animation
- Emit MeshActivity.Send from SdkPacketHandler and SdkRadioController
- Emit MeshActivity.Receive from ServiceRepositoryImpl.emitMeshPacket()
- Wire UIViewModel.meshActivity to serviceRepository.meshActivityFlow
- Align insertMetadata signature (remove unnecessary suspend)
- Adapt NodeManagerImplTest to test SdkNodeRepositoryImpl directly
- Update FakeServiceRepository with meshActivityFlow stub
All targets compile clean (Android + Desktop), all tests pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove my_node, nodes, metadata tables via AutoMigration with @DeleteTable
- Parameterize all 34 PacketDao queries to accept myNodeNum directly
- Delete NodeInfoDao, NodeEntity, MyNodeEntity, MetadataEntity
- Delete CommonNodeInfoDaoTest (dead)
- Rewrite PacketRepositoryImpl to inject NodeRepository for myNodeNum
- Rewrite CommonPacketDaoTest and CommonPacketRepositoryTest
- Update MigrationTest to remove nodeInfoDao usage
- Update core/database README to reflect current schema
SDK is now sole source of truth for all node data.
Room only stores messages, logs, and user annotations.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MeshLogRepositoryImpl was the sole external consumer of
NodeInfoReadDataSource — it only needed myNodeNum to identify the
local node in logs. Replace with NodeRepository.myNodeInfo (already
SDK-backed via SdkNodeRepositoryImpl).
PacketRepositoryImpl referenced NodeInfoDao.MAX_BIND_PARAMS — inlined
as a private constant since it's just the SQLite bind-param limit.
With zero external consumers remaining, delete:
- NodeInfoReadDataSource interface
- SwitchingNodeInfoReadDataSource implementation
The Room NodeInfoDao/NodeEntity/MyNodeEntity remain in the database
module for now (internal tests + migration history) but have no
external dependents — ready for a future Room migration 40 to DROP.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Constants.kt re-exported MeshtasticIntent constants for the deleted
ServiceBroadcasts system. No consumers remain after broadcast removal.
Also remove MeshService.actionReceived() companion method (no callers).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>