Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
c52a2cc
Documents api - ini
Feb 6, 2025
dd6907a
Adding documents query in the backend
Feb 8, 2025
cb154fb
Returning ids from a folder
Feb 8, 2025
c85d2c3
Update DocumentsIntegrationTest.kt
Feb 8, 2025
9d0fd93
Name changes
Feb 8, 2025
c66fe7d
Starting integration with app
Feb 8, 2025
3993f8c
Fixing compilation
Feb 25, 2025
950dbcb
Moving classes and merging code
ftrtyfytfjh Apr 4, 2025
e677978
Running backend
ftrtyfytfjh Apr 4, 2025
efe8eeb
making tests run in local database
ftrtyfytfjh Apr 7, 2025
b4eaae2
fixing folder diff
ftrtyfytfjh Apr 8, 2025
3d848f8
sketch of sync for app
ftrtyfytfjh Apr 8, 2025
95f0dc2
structure of the implementation
ftrtyfytfjh Apr 8, 2025
6d87b4e
Fixing DocumentSync implementation
ftrtyfytfjh Apr 10, 2025
78ec6aa
Adding rom implementation
ftrtyfytfjh Apr 10, 2025
53f328e
Ktlint
ftrtyfytfjh Apr 10, 2025
bab42bb
Adding synced info
ftrtyfytfjh Apr 10, 2025
e80601f
Adding correct icon
ftrtyfytfjh Apr 10, 2025
759f29a
Adding correctly icons
ftrtyfytfjh Apr 10, 2025
146471e
fixing logic
ftrtyfytfjh Apr 10, 2025
a2447f4
Update NoteItems.kt
ftrtyfytfjh Apr 10, 2025
44ef447
Adding correctly lastSyncAt
ftrtyfytfjh Apr 10, 2025
9babaa7
Syncing, but favorite is being erased
ftrtyfytfjh Apr 11, 2025
3e8276f
add isFavorite to API
ftrtyfytfjh Apr 14, 2025
809129c
Creating a langchain comunication
ftrtyfytfjh Apr 21, 2025
e9af026
deleting langchain
ftrtyfytfjh Apr 23, 2025
88ae0eb
Sending documents
ftrtyfytfjh Apr 23, 2025
fc0f644
Sending documents
ftrtyfytfjh Apr 23, 2025
65f603a
Search from ktor backend
ftrtyfytfjh Apr 23, 2025
06e1c9a
Changing search feature
ftrtyfytfjh Apr 23, 2025
5526236
Dependency injection working
ftrtyfytfjh Apr 24, 2025
04503e4
semantic search working
ftrtyfytfjh Apr 25, 2025
8bdd48b
Fixing rebase
ftrtyfytfjh Apr 29, 2025
0cc7fe8
Fixing rebase 2
ftrtyfytfjh May 2, 2025
533f2bc
deleting print
ftrtyfytfjh May 2, 2025
4a346b9
Update MainDesktop.kt
ftrtyfytfjh May 2, 2025
290a6bb
commenting out icon
ftrtyfytfjh May 2, 2025
e59e118
Changing room version
ftrtyfytfjh May 2, 2025
a088c9b
fixing tests
ftrtyfytfjh May 2, 2025
6168b63
fixing build for tests
ftrtyfytfjh May 2, 2025
a829379
ktlint
ftrtyfytfjh May 2, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ jobs:
distribution: adopt
java-version: '21'
- name: Build backend
run: ./gradlew backend:documents:documents_spring:assemble backend:editor:api_editor:assemble backend:editor:api_editor:test backend:editor:api_editor_socket:assemble backend:editor:api_editor_socket:test --no-daemon
run: ./gradlew :backend:gateway:test --no-daemon
- name: upload results
uses: actions/upload-artifact@v4
if: failure()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import io.writeopia.notemenu.navigation.NAVIGATION_TYPE
import io.writeopia.notemenu.navigation.navigateToNotes
import io.writeopia.notemenu.ui.screen.menu.EditFileScreen
import io.writeopia.notemenu.ui.screen.menu.RoundedVerticalDivider
import io.writeopia.sdk.network.injector.WriteopiaConnectionInjector
import io.writeopia.sql.WriteopiaDb
import io.writeopia.sqldelight.di.SqlDelightDaoInjector
import io.writeopia.sqldelight.di.WriteopiaDbInjector
Expand All @@ -75,6 +76,8 @@ fun DesktopApp(
toggleMaxScreen: () -> Unit,
startDestination: String = startDestination(),
) {
WriteopiaConnectionInjector.setBaseUrl("http://localhost:8080")

if (writeopiaDb != null) {
WriteopiaDbInjector.initialize(writeopiaDb)
}
Expand All @@ -89,7 +92,7 @@ fun DesktopApp(
val notesMenuInjection = remember {
NotesMenuKmpInjection.desktop(
selectionState = selectionState,
keyboardEventFlow = keyboardEventFlow
keyboardEventFlow = keyboardEventFlow,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import io.writeopia.BuildConfig
import io.writeopia.auth.core.token.AppBearerTokenHandler
import io.writeopia.auth.di.AuthInjection
import io.writeopia.auth.navigation.authNavigation
import io.writeopia.common.utils.Destinations
Expand All @@ -31,7 +30,7 @@ import io.writeopia.persistence.room.WriteopiaApplicationDatabase
import io.writeopia.persistence.room.injection.AppRoomDaosInjection
import io.writeopia.persistence.room.injection.RoomRepositoryInjection
import io.writeopia.persistence.room.injection.WriteopiaRoomInjector
import io.writeopia.sdk.network.injector.ConnectionInjector
import io.writeopia.sdk.network.injector.WriteopiaConnectionInjector
import io.writeopia.ui.image.ImageLoadConfig

class NavigationActivity : ComponentActivity() {
Expand Down Expand Up @@ -75,14 +74,11 @@ fun NavigationGraph(
val uiConfigInjection = UiConfigurationInjector.singleton()

val appDaosInjection = AppRoomDaosInjection.singleton()
val connectionInjector = ConnectionInjector(
bearerTokenHandler = AppBearerTokenHandler,
baseUrl = BuildConfig.BASE_URL
)
WriteopiaConnectionInjector.setBaseUrl(BuildConfig.BASE_URL)
val uiConfigViewModel = uiConfigInjection.provideUiConfigurationViewModel()
val repositoryInjection = RoomRepositoryInjection.singleton()
val authInjection = AuthInjection(connectionInjector, repositoryInjection)
val editorInjector = EditorKmpInjector.mobile(repositoryInjection, connectionInjector)
val authInjection = AuthInjection(repositoryInjection)
val editorInjector = EditorKmpInjector.mobile(repositoryInjection)
val notesMenuInjection = NotesMenuKmpInjection.mobile(repositoryInjection)

val searchInjector = remember {
Expand Down
2 changes: 2 additions & 0 deletions application/core/common_ui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ kotlin {
implementation(compose.material3)
implementation(compose.ui)
implementation(compose.components.uiToolingPreview)

implementation(libs.kotlinx.datetime)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ sealed interface MenuItemUi : Node, Traversable {
val preview: List<StoryStep>,
override var depth: Int = 0,
override val highlighted: Boolean,
override val icon: MenuItem.Icon? = null
override val icon: MenuItem.Icon? = null,
val isSynced: Boolean
) : MenuItemUi {

override val id: String = documentId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ fun MenuItem.toUiCard(
parentId = parentId,
isFavorite = favorite,
highlighted = highlighted,
icon = icon
icon = icon,
isSynced = lastSyncedAt?.let { synced -> lastUpdatedAt <= synced } ?: false
)

else -> throw IllegalArgumentException("MenuItemUi could not me created")
Expand Down
2 changes: 2 additions & 0 deletions application/core/configuration/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation(project(":writeopia_models"))

implementation(project(":application:core:models"))
implementation(project(":application:core:persistence_bridge"))
implementation(project(":application:core:utils"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package io.writeopia.core.configuration.repository

import io.writeopia.core.configuration.models.NotesArrangement
import io.writeopia.models.interfaces.configuration.WorkspaceConfigRepository
import io.writeopia.sdk.persistence.core.sorting.OrderBy
import io.writeopia.sdk.models.sorting.OrderBy
import kotlinx.coroutines.flow.Flow

interface ConfigurationRepository : WorkspaceConfigRepository {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package io.writeopia.core.configuration.repository
import io.writeopia.common.utils.persistence.configuration.NotesConfigurationCommonEntity
import io.writeopia.common.utils.persistence.daos.NotesConfigurationCommonDao
import io.writeopia.core.configuration.models.NotesArrangement
import io.writeopia.sdk.persistence.core.extensions.toEntityField
import io.writeopia.sdk.persistence.core.sorting.OrderBy
import io.writeopia.sdk.models.extensions.toEntityField
import io.writeopia.sdk.models.sorting.OrderBy
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import io.writeopia.app.sql.WorkspaceConfiguration
import io.writeopia.common.utils.extensions.toBoolean
import io.writeopia.common.utils.extensions.toLong
import io.writeopia.core.configuration.models.NotesArrangement
import io.writeopia.sdk.persistence.core.sorting.OrderBy
import io.writeopia.sdk.models.sorting.OrderBy
import io.writeopia.sqldelight.dao.ConfigurationSqlDelightDao
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.writeopia.core.configuration.repository

import io.writeopia.core.configuration.models.NotesArrangement
import io.writeopia.sdk.persistence.core.sorting.OrderBy
import io.writeopia.sdk.models.sorting.OrderBy
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
Expand Down
4 changes: 1 addition & 3 deletions application/core/connection/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ kotlin {
dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.datetime)
implementation(libs.ktor.client.core)
implementation(libs.ktor.client.logging)

implementation(libs.ktor.client.logging)
implementation(libs.ktor.client.core)
implementation(libs.ktor.client.logging)
implementation(libs.ktor.client.content.negotiation)
implementation(libs.ktor.serialization.json)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class AppConnectionInjection private constructor(
ignoreUnknownKeys = true
}
},
private val apiLogger: Logger = Logger.Companion.DEFAULT
private val apiLogger: Logger = Logger.DEFAULT
) {
fun provideJson() = json

Expand Down

This file was deleted.

7 changes: 7 additions & 0 deletions application/core/documents/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
kotlin("multiplatform")
alias(libs.plugins.ktlint)
alias(libs.plugins.androidLibrary)
alias(libs.plugins.kotlinSerialization)
}

kotlin {
Expand Down Expand Up @@ -32,14 +33,20 @@ kotlin {
implementation(project(":writeopia_models"))
implementation(project(":plugins:writeopia_persistence_core"))

implementation(project(":plugins:writeopia_serialization"))

implementation(project(":application:core:utils"))
implementation(project(":application:core:models"))
implementation(project(":application:core:common_ui"))
implementation(project(":application:core:persistence_bridge"))
implementation(project(":application:core:connection"))
implementation(project(":application:core:configuration"))
implementation(project(":application:core:connection"))

implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.datetime)
implementation(libs.ktor.client.core)
implementation(libs.kotlinx.serialization.json)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package io.writeopia.core.folders.api

import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.http.ContentType
import io.ktor.http.contentType
import io.ktor.http.isSuccess
import io.writeopia.common.utils.ResultData
import io.writeopia.sdk.models.api.request.documents.FolderDiffRequest
import io.writeopia.sdk.models.document.Document
import io.writeopia.sdk.serialization.data.DocumentApi
import io.writeopia.sdk.serialization.extensions.toApi
import io.writeopia.sdk.serialization.extensions.toModel
import kotlinx.datetime.Instant

class DocumentsApi(private val client: HttpClient, private val baseUrl: String) {

suspend fun getNewDocuments(folderId: String, lastSync: Instant): ResultData<List<Document>> {
val response = client.post("$baseUrl/api/document/folder/diff") {
contentType(ContentType.Application.Json)
setBody(FolderDiffRequest(folderId, lastSync.toEpochMilliseconds()))
}

return if (response.status.isSuccess()) {
ResultData.Complete(response.body<List<DocumentApi>>().map { it.toModel() })
} else {
println("getNewDocuments status: ${response.status.value}")
ResultData.Error()
}
}

suspend fun sendDocuments(documents: List<Document>): ResultData<Unit> {
val response = client.post("$baseUrl/api/document") {
contentType(ContentType.Application.Json)
setBody(documents.map { it.toApi() })
}

return if (response.status.isSuccess()) {
ResultData.Complete(Unit)
} else {
println("sendDocuments status: ${response.status.value}")
ResultData.Error()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import io.writeopia.sdk.models.document.Document
import io.writeopia.sdk.models.document.Folder
import io.writeopia.sdk.models.document.MenuItem
import io.writeopia.sdk.models.id.GenerateId
import io.writeopia.sdk.persistence.core.sorting.OrderBy
import io.writeopia.sdk.models.sorting.OrderBy
import io.writeopia.sdk.repository.DocumentRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
Expand All @@ -22,7 +22,7 @@ import kotlinx.datetime.Instant
class NotesUseCase private constructor(
private val documentRepository: DocumentRepository,
private val notesConfig: ConfigurationRepository,
private val folderRepository: FolderRepository
private val folderRepository: FolderRepository,
) {

suspend fun createFolder(name: String, userId: String) {
Expand Down Expand Up @@ -69,10 +69,10 @@ class NotesUseCase private constructor(
folderRepository.refreshFolders()
}

suspend fun loadDocumentsForUser(userId: String): List<Document> =
suspend fun loadDocumentsForUserFromDb(userId: String): List<Document> =
documentRepository.loadDocumentsForUser(userId)

suspend fun loadDocumentsForUserAfterTime(userId: String, time: Instant): List<Document> =
suspend fun loadDocumentsForUserAfterTimeFromDb(userId: String, time: Instant): List<Document> =
notesConfig.getOrderPreference(userId)
.let { orderBy ->
documentRepository.loadDocumentsForUserAfterTime(
Expand Down Expand Up @@ -141,7 +141,7 @@ class NotesUseCase private constructor(
duplicateFolders(ids)
}

suspend fun saveDocument(document: Document) {
suspend fun saveDocumentDb(document: Document) {
documentRepository.saveDocument(document)
documentRepository.refreshDocuments()
}
Expand Down Expand Up @@ -269,9 +269,13 @@ class NotesUseCase private constructor(
fun singleton(
documentRepository: DocumentRepository,
notesConfig: ConfigurationRepository,
folderRepository: FolderRepository
folderRepository: FolderRepository,
): NotesUseCase =
instance ?: NotesUseCase(documentRepository, notesConfig, folderRepository).also {
instance ?: NotesUseCase(
documentRepository,
notesConfig,
folderRepository,
).also {
instance = it
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.writeopia.core.folders.sync

import io.writeopia.sdk.models.document.Document
import io.writeopia.sdk.repository.DocumentRepository
import kotlinx.datetime.Clock

class DocumentConflictHandler(private val documentRepository: DocumentRepository) {

/**
* Handle conflicts with documents that were updated both locally and in the backend.
*
* @param localDocuments The documents that should be sent to the backend, because they were updated locally
* @param externalDocuments The documents that should be updated locally, because they were updated in the backend.
*
* @return The documents that are still to be sent to the cloud.
*/
suspend fun handleConflict(
localDocuments: List<Document>,
externalDocuments: List<Document>
): List<Document> {
val now = Clock.System.now()

// Todo: Implement!! Save external documents and remove localDocuments. A more complex
// handling of conflicts can be implemented in the future.
externalDocuments.forEach { document ->
documentRepository.saveDocument(document.copy(lastSyncedAt = now))
}

return (localDocuments.toSet() - externalDocuments.toSet()).toList()
}
}
Loading