Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ val appModule = module {
single<ProjectRepository> { SqlDelightProjectRepository(get(), get()) }
single<ServerRepositoryV2> { SqlDelightServerRepository(get(), get()) }
single<MessageRepositoryV2> { SqlDelightMessageRepository(get(), get()) }
single<SynchronizationServiceV2> { DefaultSynchronizationService(get(), get(), get(), get()) }
single<SynchronizationServiceV2> { DefaultSynchronizationService(get(), get(), get()) }
single<ServerServiceV2> { DefaultServerService(get(), get(), get()) }
single<ProjectServiceV2> { DefaultProjectService(get()) }
single<SessionServiceV2> { DefaultSessionService(get()) }
single<ProjectServiceV2> { DefaultProjectService(get(), get()) }
single<SessionServiceV2> { DefaultSessionService(get(), get()) }
single<MessageServiceV2> { DefaultMessageService(get()) }
single<ConnectionGateway> { get<ServerRepository>() }
single<ProjectGateway> { get<ServerRepository>() }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package de.chennemann.opencode.mobile.domain.v2

import de.chennemann.opencode.mobile.domain.v2.projects.ProjectRepository
import de.chennemann.opencode.mobile.domain.v2.projects.LocalProjectInfo
import de.chennemann.opencode.mobile.domain.v2.projects.ProjectService
import de.chennemann.opencode.mobile.domain.v2.servers.ServerRepository
import de.chennemann.opencode.mobile.domain.v2.session.LocalSessionRecord
import de.chennemann.opencode.mobile.domain.v2.session.SessionRepository
import de.chennemann.opencode.mobile.domain.v2.session.SessionService

interface SynchronizationService {
suspend fun syncServer(serverId: String)
}

class DefaultSynchronizationService(
private val serverRepository: ServerRepository,
private val projectRepository: ProjectRepository,
private val sessionRepository: SessionRepository,
private val adapter: OpenCodeServerAdapter,
private val projectService: ProjectService,
private val sessionService: SessionService,
) : SynchronizationService {
override suspend fun syncServer(serverId: String) {
val id = serverId.trim()
Expand All @@ -23,64 +20,13 @@ class DefaultSynchronizationService(
val url = server.url.trim()
if (url.isBlank()) return

syncProjectsForServer(id, url)
}

private suspend fun syncProjectsForServer(serverId: String, url: String) {
val remoteProjects = adapter.allProjects(url)
remoteProjects.forEach { remote ->
val projectId = remote.id.trim()
val projectPath = remote.worktree.trim()
if (projectId.isBlank() || projectPath.isBlank()) return@forEach

val existing = projectRepository.selectProject(projectId)
val local = LocalProjectInfo(
id = projectId,
serverId = serverId,
name = remote.name.trim().ifBlank { projectPath },
path = projectPath,
pinned = existing?.pinned ?: false,
val projects = projectService.syncServerProjects(id, url)
projects.forEach { project ->
sessionService.syncSessionsOfProject(
projectId = project.id,
projectPath = project.path,
baseUrl = url,
)

if (existing == null) {
projectRepository.insertProject(local)
} else {
projectRepository.updateProject(local)
}

syncSessionsForProject(projectId, url)
}
}

private suspend fun syncSessionsForProject(projectId: String, url: String) {
val id = projectId.trim()
if (id.isBlank()) return
val baseUrl = url.trim()
if (baseUrl.isBlank()) return
val project = projectRepository.selectProject(id) ?: return
val projectPath = project.path.trim()
if (projectPath.isBlank()) return

val remoteSessions = adapter.allSessionsOfAGivenProject(baseUrl, projectPath)
remoteSessions.forEach { remote ->
val sessionId = remote.id.trim()
val sessionPath = remote.directory.trim()
if (sessionId.isBlank() || sessionPath.isBlank()) return@forEach

val existing = sessionRepository.selectStoredSession(sessionId)
val local = LocalSessionRecord(
id = sessionId,
projectId = id,
title = remote.title.trim().ifBlank { sessionPath },
path = sessionPath,
pinned = existing?.pinned ?: false,
)

if (existing == null) {
sessionRepository.insertStoredSession(local)
} else {
sessionRepository.updateStoredSession(local)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package de.chennemann.opencode.mobile.domain.v2.projects

import de.chennemann.opencode.mobile.domain.v2.OpenCodeServerAdapter
import kotlinx.coroutines.flow.Flow

interface ProjectService {
fun observeProjects(serverId: String? = null): Flow<List<LocalProjectInfo>>

suspend fun togglePinnedById(projectId: String): Boolean

suspend fun syncServerProjects(serverId: String, baseUrl: String): List<LocalProjectInfo>
}

class DefaultProjectService(
private val projectRepository: ProjectRepository,
private val adapter: OpenCodeServerAdapter,
) : ProjectService {
override fun observeProjects(serverId: String?): Flow<List<LocalProjectInfo>> {
return projectRepository.observeProjects(serverId)
Expand All @@ -24,4 +28,35 @@ class DefaultProjectService(
)
return true
}

override suspend fun syncServerProjects(serverId: String, baseUrl: String): List<LocalProjectInfo> {
val sid = serverId.trim()
val url = baseUrl.trim()
if (sid.isBlank() || url.isBlank()) return emptyList()

val remoteProjects = adapter.allProjects(url)
val synced = mutableListOf<LocalProjectInfo>()
remoteProjects.forEach { remote ->
val projectId = remote.id.trim()
val projectPath = remote.worktree.trim()
if (projectId.isBlank() || projectPath.isBlank()) return@forEach

val existing = projectRepository.selectProject(projectId)
val local = LocalProjectInfo(
id = projectId,
serverId = sid,
name = remote.name.trim().ifBlank { projectPath },
path = projectPath,
pinned = existing?.pinned ?: false,
)

if (existing == null) {
projectRepository.insertProject(local)
} else {
projectRepository.updateProject(local)
}
synced += local
}
return synced
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,56 @@
package de.chennemann.opencode.mobile.domain.v2.session

import de.chennemann.opencode.mobile.domain.v2.OpenCodeServerAdapter
import kotlinx.coroutines.flow.Flow

interface SessionService {
fun sessionsOfProject(projectKey: String): Flow<List<LocalSessionInfo>>

suspend fun syncSessionsOfProject(
projectId: String,
projectPath: String,
baseUrl: String,
)
}

class DefaultSessionService(
private val sessionRepository: SessionRepository,
private val adapter: OpenCodeServerAdapter,
) : SessionService {
override fun sessionsOfProject(projectKey: String): Flow<List<LocalSessionInfo>> {
return sessionRepository.sessionsOfProject(projectKey)
}

override suspend fun syncSessionsOfProject(
projectId: String,
projectPath: String,
baseUrl: String,
) {
val pid = projectId.trim()
val path = projectPath.trim()
val url = baseUrl.trim()
if (pid.isBlank() || path.isBlank() || url.isBlank()) return

val remoteSessions = adapter.allSessionsOfAGivenProject(url, path)
remoteSessions.forEach { remote ->
val sessionId = remote.id.trim()
val sessionPath = remote.directory.trim()
if (sessionId.isBlank() || sessionPath.isBlank()) return@forEach

val existing = sessionRepository.selectStoredSession(sessionId)
val local = LocalSessionRecord(
id = sessionId,
projectId = pid,
title = remote.title.trim().ifBlank { sessionPath },
path = sessionPath,
pinned = existing?.pinned ?: false,
)

if (existing == null) {
sessionRepository.insertStoredSession(local)
} else {
sessionRepository.updateStoredSession(local)
}
}
}
}
Loading