diff --git a/app/src/main/java/com/m57/hermescontrol/data/remote/ApiClient.kt b/app/src/main/java/com/m57/hermescontrol/data/remote/ApiClient.kt index 04ad2a34..e413181b 100644 --- a/app/src/main/java/com/m57/hermescontrol/data/remote/ApiClient.kt +++ b/app/src/main/java/com/m57/hermescontrol/data/remote/ApiClient.kt @@ -22,9 +22,6 @@ object ApiClient { @Volatile private var service: HermesApiService? = null - @Volatile - private var kanbanService: KanbanApiService? = null - /** The current [HermesApiService] instance. Lazily created on first access. */ val hermesApi: HermesApiService get() { @@ -33,20 +30,15 @@ object ApiClient { } } - /** The current [KanbanApiService] instance. Lazily created on first access. */ + /** The current [KanbanApiService] instance. Reuses [hermesApi]. */ val kanbanApi: KanbanApiService - get() { - return kanbanService ?: synchronized(this) { - kanbanService ?: buildRetrofit().create(KanbanApiService::class.java).also { kanbanService = it } - } - } + get() = hermesApi /** Force-rebuild the Retrofit client (e.g. after settings change). */ fun rebuild() { synchronized(this) { retrofit = null service = null - kanbanService = null } } diff --git a/app/src/main/java/com/m57/hermescontrol/data/remote/HermesApiService.kt b/app/src/main/java/com/m57/hermescontrol/data/remote/HermesApiService.kt index 88abd60a..f6a29028 100644 --- a/app/src/main/java/com/m57/hermescontrol/data/remote/HermesApiService.kt +++ b/app/src/main/java/com/m57/hermescontrol/data/remote/HermesApiService.kt @@ -154,7 +154,7 @@ import retrofit2.http.Path import retrofit2.http.Query import retrofit2.http.Streaming -interface HermesApiService { +interface HermesApiService : KanbanApiService { @GET("api/skills/content") suspend fun getSkillContent( @Query("name") name: String, diff --git a/app/src/main/java/com/m57/hermescontrol/data/remote/KanbanApiService.kt b/app/src/main/java/com/m57/hermescontrol/data/remote/KanbanApiService.kt index ca1a09ea..fc85ec16 100644 --- a/app/src/main/java/com/m57/hermescontrol/data/remote/KanbanApiService.kt +++ b/app/src/main/java/com/m57/hermescontrol/data/remote/KanbanApiService.kt @@ -163,7 +163,7 @@ interface KanbanApiService { ): Response @GET("api/plugins/kanban/profiles") - suspend fun getProfiles(): Response + suspend fun getKanbanProfiles(): Response @PATCH("api/plugins/kanban/profiles/{name}") suspend fun updateProfileDescription( diff --git a/app/src/main/java/com/m57/hermescontrol/data/repository/KanbanRepository.kt b/app/src/main/java/com/m57/hermescontrol/data/repository/KanbanRepository.kt index 456bfd0c..efe3c419 100644 --- a/app/src/main/java/com/m57/hermescontrol/data/repository/KanbanRepository.kt +++ b/app/src/main/java/com/m57/hermescontrol/data/repository/KanbanRepository.kt @@ -323,7 +323,7 @@ class KanbanRepositoryImpl( override suspend fun getProfiles(): NetworkResult = withContext(ioDispatcher) { - safeApiCall { apiProvider().getProfiles() } + safeApiCall { apiProvider().getKanbanProfiles() } } override suspend fun updateProfileDescription( diff --git a/app/src/test/java/com/m57/hermescontrol/E2eIntegrationTest.kt b/app/src/test/java/com/m57/hermescontrol/E2eIntegrationTest.kt index b6cb56e0..8590fa48 100644 --- a/app/src/test/java/com/m57/hermescontrol/E2eIntegrationTest.kt +++ b/app/src/test/java/com/m57/hermescontrol/E2eIntegrationTest.kt @@ -1205,10 +1205,9 @@ class E2eIntegrationTest { runTest { val board = KanbanBoard("board-1", "Backlog", null) val task = KanbanTask("task-1", "Do laundry", null, "todo", null) - coEvery { mockApiService.getKanbanBoards() } returns + coEvery { mockApiService.getBoards(any()) } returns Response.success(KanbanBoardsResponse(listOf(board), "board-1")) - coEvery { mockApiService.switchKanbanBoard("board-1") } returns Response.success(Unit) - coEvery { mockApiService.getKanbanBoard() } returns + coEvery { mockApiService.getBoard("board-1", any(), any()) } returns Response.success(KanbanBoardResponse(listOf(KanbanColumn("todo", listOf(task))), null, null)) val viewModel = KanbanViewModel(eventsClientProvider = { mockk(relaxed = true) }) @@ -1230,11 +1229,16 @@ class E2eIntegrationTest { // Desktop-style transition: todo -> ready is a direct write the // backend accepts; the VM PATCHes the target status. coEvery { - mockApiService.updateKanbanTask( - "task-1", - mapOf("status" to "ready"), + mockApiService.updateTask( + eq("task-1"), + eq("board-1"), + any(), + ) + } returns + Response.success( + com.m57.hermescontrol.data.model + .UpdateTaskResponse(task = task.copy(status = "ready")), ) - } returns Response.success(Unit) viewModel.moveTask(viewModel.uiState.value.tasks[0], KanbanTaskAction.READY) advanceUntilIdle() assertEquals( @@ -1243,9 +1247,13 @@ class E2eIntegrationTest { .status, ) - // Create path: the wrapped {"task": ...} response must not - // break deserialization — the API layer reads it as Unit. - coEvery { mockApiService.createKanbanTask(any(), any()) } returns Response.success(Unit) + // Create path: returns CreateTaskResponse + coEvery { mockApiService.createTask(any(), any()) } returns + Response.success( + com.m57.hermescontrol.data.model.CreateTaskResponse( + task = KanbanTask("task-2", "Fresh task", status = "todo"), + ), + ) viewModel.createTask("Fresh task", null, "todo") advanceUntilIdle() assertEquals("Task created successfully", viewModel.uiState.value.toastMessage)