Skip to content

Commit 7b5d34c

Browse files
leandroBorgesFerreiraLeandro Ferreira
andauthored
Fixing persistence of documents (#523)
* Fixing persistence of documents * ktlint * z * fixing tests --------- Co-authored-by: Leandro Ferreira <[email protected]>
1 parent de2c039 commit 7b5d34c

5 files changed

Lines changed: 67 additions & 53 deletions

File tree

application/core/auth_core/src/commonMain/kotlin/io/writeopia/auth/core/manager/AuthRepository.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ interface AuthRepository : UserRepository {
1111

1212
override fun listenForUser(): Flow<WriteopiaUser> = flow { emit(getUser()) }
1313

14-
fun listenForWorkspace(): Flow<Workspace> =
15-
flow { emit(getWorkspace() ?: Workspace.disconnectedWorkspace()) }
14+
override fun listenForWorkspace(): Flow<Workspace> = flow {
15+
emit(getWorkspace() ?: Workspace.disconnectedWorkspace())
16+
}
1617

1718
override suspend fun getUser(): WriteopiaUser
1819

plugins/writeopia_persistence_core/src/commonMain/kotlin/io/writeopia/sdk/persistence/core/tracker/OnUpdateDocumentTracker.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import io.writeopia.sdk.models.story.StoryStep
1313
import io.writeopia.sdk.models.story.StoryTypes
1414
import kotlinx.coroutines.flow.Flow
1515
import kotlinx.coroutines.flow.collectLatest
16+
import kotlinx.coroutines.flow.combine
1617
import kotlinx.datetime.Clock
1718

1819
class OnUpdateDocumentTracker(
@@ -24,9 +25,14 @@ class OnUpdateDocumentTracker(
2425

2526
override suspend fun saveOnStoryChanges(
2627
documentEditionFlow: Flow<Pair<StoryState, DocumentInfo>>,
27-
workspaceId: String
28+
workspaceIdFlow: Flow<String>,
2829
) {
29-
documentEditionFlow.collectLatest { (storyState, documentInfo) ->
30+
combine(
31+
documentEditionFlow,
32+
workspaceIdFlow
33+
) { (storyState, documentInfo), workspaceId ->
34+
Triple(storyState, documentInfo, workspaceId)
35+
}.collectLatest { (storyState, documentInfo, workspaceId) ->
3036
when (val lastEdit = storyState.lastEdit) {
3137
is LastEdit.LineEdition -> {
3238
if (lastEdit.storyStep.ephemeral) return@collectLatest

writeopia/src/commonMain/kotlin/io/writeopia/sdk/manager/DocumentTracker.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ interface DocumentTracker {
1515
*/
1616
suspend fun saveOnStoryChanges(
1717
documentEditionFlow: Flow<Pair<StoryState, DocumentInfo>>,
18-
workspaceId: String
18+
workspaceIdFlow: Flow<String>
1919
)
2020
}

writeopia/src/commonMain/kotlin/io/writeopia/sdk/repository/UserRepository.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import kotlinx.coroutines.flow.flow
88
interface UserRepository {
99
fun listenForUser(): Flow<WriteopiaUser> = flow { emit(getUser()) }
1010

11+
fun listenForWorkspace(): Flow<Workspace> =
12+
flow { emit(getWorkspace() ?: Workspace.disconnectedWorkspace()) }
13+
1114
suspend fun getUser(): WriteopiaUser
1215

1316
suspend fun getWorkspace(): Workspace?

writeopia_ui/src/commonMain/kotlin/io/writeopia/ui/manager/WriteopiaStateManager.kt

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import io.writeopia.sdk.models.story.StoryTypes
2323
import io.writeopia.sdk.models.story.Tag
2424
import io.writeopia.sdk.models.story.TagInfo
2525
import io.writeopia.sdk.models.user.WriteopiaUser
26+
import io.writeopia.sdk.models.workspace.Workspace
2627
import io.writeopia.sdk.normalization.builder.StepsMapNormalizationBuilder
2728
import io.writeopia.sdk.repository.DocumentRepository
2829
import io.writeopia.sdk.repository.UserRepository
@@ -104,7 +105,7 @@ class WriteopiaStateManager(
104105
if (isEditable) {
105106
when (event) {
106107
KeyboardEvent.DELETE -> {
107-
if (_positionsOnEdit.value.isNotEmpty()) {
108+
if (_onEditPositions.value.isNotEmpty()) {
108109
deleteSelection()
109110
}
110111
}
@@ -147,16 +148,14 @@ class WriteopiaStateManager(
147148
getCurrentStory()?.let { story ->
148149
val position = currentPosition()
149150

150-
if (position != null) {
151-
changeStoryState(
152-
Action.StoryStateChange(
153-
storyStep = story.copy(
154-
type = StoryTypes.EQUATION.type
155-
),
156-
position
157-
)
151+
changeStoryState(
152+
Action.StoryStateChange(
153+
storyStep = story.copy(
154+
type = StoryTypes.EQUATION.type
155+
),
156+
position
158157
)
159-
}
158+
)
160159
}
161160
}
162161

@@ -178,10 +177,13 @@ class WriteopiaStateManager(
178177

179178
private var localUserId: String? = null
180179

181-
private val _dragPosition = MutableStateFlow(-1)
182-
private val _isDragging = MutableStateFlow(false)
180+
private val dragPosition = MutableStateFlow(-1)
181+
private val isDragging = MutableStateFlow(false)
183182

184-
private val dragRealPosition = combine(_dragPosition, _isDragging) { position, isDragging ->
183+
private val dragRealPosition = combine(
184+
dragPosition,
185+
isDragging
186+
) { position, isDragging ->
185187
if (isDragging) position else -1
186188
}
187189

@@ -203,8 +205,8 @@ class WriteopiaStateManager(
203205

204206
val documentInfo: StateFlow<DocumentInfo> = _documentInfo.asStateFlow()
205207

206-
private val _positionsOnEdit = MutableStateFlow(setOf<Int>())
207-
val onEditPositions = _positionsOnEdit.asStateFlow()
208+
private val _onEditPositions = MutableStateFlow(setOf<Int>())
209+
val onEditPositions = _onEditPositions.asStateFlow()
208210

209211
private var sharedEditionManager: SharedEditionManager? = null
210212

@@ -220,12 +222,12 @@ class WriteopiaStateManager(
220222
parseDocument(info, state)
221223
}.stateIn(coroutineScope, SharingStarted.Lazily, null)
222224

223-
private val _documentEditionState: Flow<Pair<StoryState, DocumentInfo>> =
225+
private val documentEditionState: Flow<Pair<StoryState, DocumentInfo>> =
224226
combine(currentStory, _documentInfo, ::Pair)
225227

226228
val toDraw: Flow<DrawState> =
227229
combine(
228-
_positionsOnEdit,
230+
_onEditPositions,
229231
currentStory,
230232
dragRealPosition
231233
) { positions, storyState, dragPosition ->
@@ -247,7 +249,7 @@ class WriteopiaStateManager(
247249
DrawState(toDrawStories, focus)
248250
}
249251

250-
private var _initialized = false
252+
private var initialized = false
251253

252254
val selectionMetadataState: Flow<Set<SelectionMetadata>> = _currentStory.map { storyState ->
253255
val selection = storyState.selection.position
@@ -290,7 +292,7 @@ class WriteopiaStateManager(
290292
}
291293

292294
val isOnSelection: Boolean
293-
get() = _positionsOnEdit.value.isNotEmpty()
295+
get() = _onEditPositions.value.isNotEmpty()
294296

295297
/**
296298
* Saves the document automatically as it is changed. It uses the [DocumentTracker] passed
@@ -299,8 +301,10 @@ class WriteopiaStateManager(
299301
fun saveOnStoryChanges(documentTracker: DocumentTracker) {
300302
coroutineScope.launch(dispatcher) {
301303
documentTracker.saveOnStoryChanges(
302-
_documentEditionState,
303-
userRepository?.getWorkspace()?.id ?: ""
304+
documentEditionState,
305+
userRepository?.listenForWorkspace()?.map { workspace ->
306+
workspace.id
307+
} ?: MutableStateFlow(Workspace.disconnectedWorkspace().id)
304308
)
305309
}
306310
}
@@ -311,13 +315,13 @@ class WriteopiaStateManager(
311315
fun liveSync(sharedEditionManager: SharedEditionManager) {
312316
coroutineScope.launch(dispatcher) {
313317
sharedEditionManager.startLiveEdition(
314-
inFlow = _documentEditionState,
318+
inFlow = documentEditionState,
315319
outFlow = _currentStory,
316320
)
317321
}
318322
}
319323

320-
fun isInitialized(): Boolean = _initialized
324+
fun isInitialized(): Boolean = initialized
321325

322326
/**
323327
* Creates a new story. Use this when you wouldn't like to load a documented previously saved.
@@ -333,7 +337,7 @@ class WriteopiaStateManager(
333337
) {
334338
if (isInitialized() && !forceRestart) return
335339

336-
_initialized = true
340+
initialized = true
337341
val (documentInfo, storyState) = writeopiaManager.newDocument(
338342
documentId,
339343
title,
@@ -355,7 +359,7 @@ class WriteopiaStateManager(
355359
fun loadDocument(document: Document) {
356360
if (isInitialized()) return
357361

358-
_initialized = true
362+
initialized = true
359363

360364
val stories = document.content
361365
val state =
@@ -398,10 +402,10 @@ class WriteopiaStateManager(
398402

399403
backStackManager.addState(_currentStory.value)
400404

401-
if (_positionsOnEdit.value.contains(fixedMove.positionFrom)) {
405+
if (_onEditPositions.value.contains(fixedMove.positionFrom)) {
402406
val bulkMove = Action.BulkMove(
403407
storyStep = selectedStories(),
404-
positionFrom = _positionsOnEdit.value,
408+
positionFrom = _onEditPositions.value,
405409
positionTo = fixedMove.positionTo
406410
)
407411

@@ -445,7 +449,7 @@ class WriteopiaStateManager(
445449
*/
446450
fun onCheckItemClicked() {
447451
if (!isEditable) return
448-
val onEdit = _positionsOnEdit.value
452+
val onEdit = _onEditPositions.value
449453

450454
if (onEdit.isNotEmpty()) {
451455
toggleStateForStories(onEdit, StoryTypes.CHECK_ITEM)
@@ -459,7 +463,7 @@ class WriteopiaStateManager(
459463
*/
460464
fun onListItemClicked() {
461465
if (!isEditable) return
462-
val onEdit = _positionsOnEdit.value
466+
val onEdit = _onEditPositions.value
463467

464468
if (onEdit.isNotEmpty()) {
465469
toggleStateForStories(onEdit, StoryTypes.UNORDERED_LIST_ITEM)
@@ -470,7 +474,7 @@ class WriteopiaStateManager(
470474

471475
fun toggleHighLightBlock() {
472476
if (!isEditable) return
473-
val onEdit = _positionsOnEdit.value
477+
val onEdit = _onEditPositions.value
474478

475479
if (onEdit.isNotEmpty()) {
476480
toggleTagForStories(onEdit, TagInfo(Tag.HIGH_LIGHT_BLOCK))
@@ -671,9 +675,9 @@ class WriteopiaStateManager(
671675
if (!isEditable) return
672676
if (_currentStory.value.stories[position] != null) {
673677
if (isSelected) {
674-
_positionsOnEdit.value += position
678+
_onEditPositions.value += position
675679
} else {
676-
_positionsOnEdit.value -= position
680+
_onEditPositions.value -= position
677681
}
678682
}
679683
}
@@ -689,7 +693,7 @@ class WriteopiaStateManager(
689693

690694
fun onSectionSelected(position: Int) {
691695
if (!isEditable) return
692-
val isSelected = _positionsOnEdit.value.contains(position)
696+
val isSelected = _onEditPositions.value.contains(position)
693697
val stories = getStories()
694698

695699
val lastPosition = getStories().asSequence()
@@ -705,15 +709,15 @@ class WriteopiaStateManager(
705709
}
706710

707711
if (isSelected) {
708-
_positionsOnEdit.value -= newSelected
712+
_onEditPositions.value -= newSelected
709713
} else {
710-
_positionsOnEdit.value += newSelected
714+
_onEditPositions.value += newSelected
711715
}
712716
}
713717

714718
fun toggleSelection(position: Int) {
715719
if (!isEditable) return
716-
onSelected(!_positionsOnEdit.value.contains(position), position)
720+
onSelected(!_onEditPositions.value.contains(position), position)
717721
}
718722

719723
/**
@@ -847,11 +851,11 @@ class WriteopiaStateManager(
847851
if (!isEditable) return
848852
coroutineScope.launch(dispatcher) {
849853
val (newStories, _) = writeopiaManager.bulkDelete(
850-
_positionsOnEdit.value,
854+
_onEditPositions.value,
851855
_currentStory.value.stories
852856
)
853857

854-
_positionsOnEdit.value = emptySet()
858+
_onEditPositions.value = emptySet()
855859

856860
backStackManager.addState(_currentStory.value)
857861
val state = _currentStory.value.copy(stories = newStories, lastEdit = LastEdit.Whole)
@@ -860,19 +864,19 @@ class WriteopiaStateManager(
860864
}
861865

862866
fun onDragHover(position: Int) {
863-
_dragPosition.value = position
867+
dragPosition.value = position
864868
}
865869

866870
fun onDragStart() {
867-
_isDragging.value = true
871+
isDragging.value = true
868872
}
869873

870874
fun onDragStop() {
871875
coroutineScope.launch {
872876
// It is necessary to delay the stop dragging event to wait for the move request to
873877
// be received.
874878
delay(100)
875-
_isDragging.value = false
879+
isDragging.value = false
876880
}
877881
}
878882

@@ -915,7 +919,7 @@ class WriteopiaStateManager(
915919

916920
fun toggleSpan(span: Span, extra: String? = null) {
917921
if (isEditable) {
918-
val onEdit = _positionsOnEdit.value
922+
val onEdit = _onEditPositions.value
919923

920924
if (onEdit.isNotEmpty()) {
921925
_currentStory.value =
@@ -1021,7 +1025,7 @@ class WriteopiaStateManager(
10211025
* Cancels the current selection.
10221026
*/
10231027
fun clearSelection() {
1024-
_positionsOnEdit.value = emptySet()
1028+
_onEditPositions.value = emptySet()
10251029
}
10261030

10271031
fun receiveExternalFiles(files: List<ExternalFile>, position: Int) {
@@ -1045,7 +1049,7 @@ class WriteopiaStateManager(
10451049
* that is selected
10461050
*/
10471051
private fun getSelectionInfo(): List<SelectionInfo> {
1048-
val selected = _positionsOnEdit.value
1052+
val selected = _onEditPositions.value
10491053

10501054
return if (selected.isNotEmpty()) {
10511055
// TODO: Fix this to accept multiple clusters of selection!
@@ -1075,7 +1079,7 @@ class WriteopiaStateManager(
10751079
if (!isEditable) return
10761080
if (documentRepository == null) return
10771081

1078-
val lastSelection = _positionsOnEdit.value.max()
1082+
val lastSelection = _onEditPositions.value.max()
10791083

10801084
val text = getStories()[lastSelection]?.text?.let {
10811085
it.take(max(it.length, 30))
@@ -1111,7 +1115,7 @@ class WriteopiaStateManager(
11111115

11121116
fun getSelectedStories(): List<StoryStep> {
11131117
val stories = getStories()
1114-
return _positionsOnEdit.value
1118+
return _onEditPositions.value
11151119
.sorted()
11161120
.mapNotNull { position ->
11171121
stories[position]
@@ -1353,7 +1357,7 @@ class WriteopiaStateManager(
13531357
private fun getCurrentStory(): StoryStep? = currentPosition().let(::getStory)
13541358

13551359
private fun selectAll() {
1356-
_positionsOnEdit.value = getStories().keys - setOf(0)
1360+
_onEditPositions.value = getStories().keys - setOf(0)
13571361
}
13581362

13591363
private fun parseDocument(info: DocumentInfo, state: StoryState): Document {
@@ -1377,7 +1381,7 @@ class WriteopiaStateManager(
13771381
)
13781382
}
13791383

1380-
private fun selectedStories(): List<StoryStep> = _positionsOnEdit.value.mapNotNull(::getStory)
1384+
private fun selectedStories(): List<StoryStep> = _onEditPositions.value.mapNotNull(::getStory)
13811385

13821386
companion object {
13831387
fun create(

0 commit comments

Comments
 (0)