diff --git a/.env b/.env index d795b66..9304a50 100644 --- a/.env +++ b/.env @@ -2,7 +2,7 @@ NEXT_PUBLIC_YORKIE_VERSION='0.4.23' NEXT_PUBLIC_YORKIE_JS_VERSION='0.4.23' NEXT_PUBLIC_YORKIE_IOS_VERSION='0.4.17' -NEXT_PUBLIC_YORKIE_ANDROID_VERSION='0.4.16' +NEXT_PUBLIC_YORKIE_ANDROID_VERSION='0.4.24' NEXT_PUBLIC_DASHBOARD_PATH='/dashboard' NEXT_PUBLIC_JS_SDK_URL='https://cdnjs.cloudflare.com/ajax/libs/yorkie-js-sdk/0.4.23/yorkie-js-sdk.js' diff --git a/docs/android-sdk.mdx b/docs/android-sdk.mdx index abe9a2b..34b2dcc 100644 --- a/docs/android-sdk.mdx +++ b/docs/android-sdk.mdx @@ -79,7 +79,7 @@ This ensures that any modifications made by one client are instantly propagated The second argument is options. - `initialPresence`: Sets the initial presence of the client that attaches the document. The presence is shared with other users participating in the document. It must be serializable to JSON. - - `isRealtimeSync`(Optional): Specifies whether to enable real-time synchronization. The default value is `true`, which means synchronization occurs automatically. If set to `false`, you should manually control the synchronization. +- `syncMode`(Optional): Specifies synchronization modes. The default value is `SyncMode.Realtime`, which automatically pushes and pulls changes. If you set it to `SyncMode.Manual`, you'll need to manually handle synchronization. ```kotlin // Declare your own CoroutineScope @@ -87,12 +87,12 @@ scope.launch { client.attachAsync( document, initialPresences = mapOf("name" to "a"), - isRealtimeSync = true, + syncMode = SyncMode.Manual, ) } ``` -#### Updating presesnce +#### Updating presence The `Document.update()` method allows you to make changes to the state of the current user's presence. @@ -109,28 +109,6 @@ scope.launch { // presence = { "name": "b" } // we can see that the changes made were merged and the final state of the current user's presence is as we desire ``` - -Note, the properties provided will be replaced entirely and not merely updated. - -For example: -```kotlin -// Declare your own CoroutineScope -scope.launch { - client.attachAsync( - document, - initialPresences = mapOf("name" to "a") - ).await() - - document.updateAsync { _, presence -> - presence.put(mapOf("age" to "10")) - }.await() -} - -// final state -// presence = { "age": "10" } -// we can see that the changes made were merged and the final state of the current user's presence is as we desire -``` - #### Getting Presence @@ -147,7 +125,14 @@ document.presences.value.forEach { (clientID, presence) -> ##### Document.Event.PresenceChange It includes all the presence-related events. -By subscribing to it, you can be notified when specific changes occur within the document, such as clients attaching, detaching, or modifying their presence. +By subscribing to it, you can be notified whenever clients watch, unwatch, or modify their presence. + +The `Initialized` event occurs when the client list needs to be initialized. +For example, this happens when you first connect a watch stream to a document, when the connection is lost, or when it is reconnected. + + +Subscribe before attaching the document to ensure you receive the initial `Initialized` event. + ```Kotlin // Declare your own CoroutineScope @@ -163,7 +148,7 @@ scope.launch { } ``` -You can also subscribe to specific types of presence changes. +You can also subscribe to specific types of presence changes to distinguish between your own events and those of others. - `document.event.filterIsInstance`: `Initialized`, `PresenceChanged` - `document.event.filterIsInstance`: `Watched`, `Unwatched`, `PresenceChanged` @@ -208,28 +193,45 @@ Whenever the Document is modified, change events are triggered and we can subscr The events are triggered with an event object, and the event type indicates the source of the change, which can be one of the following values: `LocalChange`, `RemoteChange`, or `Snapshot`. -When the type of the event is `LocalChange` or `RemoteChange`, it has `ChangeInfo` as value. - -For more information about changeInfo for document events, please refer to the [ChangeInfo](https://yorkie.dev/yorkie-android-sdk/yorkie/dev.yorkie.document/-document/-event/-change-info/index.html). ```kotlin // Declare your own CoroutineScope scope.launch { - document.events.collect { event -> - if (event is Document.Event.LocalChange) { - println(event) - } else if (event is Document.Event.RemoteChange) { - event.changeInfo.operations.forEach { op -> - when (op) { - is OperationInfo.IncreaseOpInfo -> { // Do something... } - else -> { return@collect } + document.events.collect { event -> + when (event) { + is Document.Event.Snapshot -> { + // Update with data from the Yorkie Document. + } + + is Document.Event.LocalChange -> { + println(event) + } + + is Document.Event.RemoteChange -> { + event.changeInfo.operations.forEach { op -> + if (op is OperationInfo.IncreaseOpInfo) { + // Do something... + } + } + } } - } } - } } ``` +When the event type is `LocalChange` or `RemoteChange`, it passes changeInfo, which has `operations` and `messages` properties. +For more information about changeInfo for document events, please refer to the [ChangeInfo](https://yorkie.dev/yorkie-js-sdk/api-reference/interfaces/ChangeInfo.html). + +The `Snapshot` event is triggered when a snapshot is received from the server. +This occurs when the changes that a document needs to fetch from the server exceed a certain `SnapshotThreshold`. +Instead of sending numerous changes, the server sends a snapshot of the document. +In such cases, it is essential to update with data from the Yorkie Document. + + +If a client has not synchronized for a prolonged period and then makes a sync request, it might receive a `Snapshot` event. +Ensure your application processes these snapshot events correctly to maintain document synchronization. + + Additionally, you can subscribe to changes for a specific path in the Document using `document.events(path)` with a path argument, such as `$.todos`, where the `$` sign indicates the root of the document. The events are delivered when the target path and its nested values are changed. @@ -246,47 +248,34 @@ scope.launch { ``` -#### Changing Synchronization Setting - -To change the synchronization setting for a document, you can use `Client.pause(document)` and `Client.resume(document)`. - -When you pause a document, the synchronization process will no longer occur in realtime, and you will need to manually execute the synchronization to ensure that the changes are propagated to other clients. +#### Changing Synchronization Mode -To resume the realtime synchronization, you can call `Client.resume(document)`. +To change the synchronization mode for a document, you can use `client.changeSyncMode(doc, syncMode)` -```kotlin -// Pause real-time sync -client.pause(document) +Yorkie offers four SyncModes: +- `SyncMode.Realtime`: Local changes are automatically pushed to the server, and remote changes are pulled from the server. -// Resume real-time sync -client.resume(document) +- `SyncMode.RealtimePushOnly`: Only -``` +- `SyncMode.RealtimeSyncOff`: Changes are not synchronized, but the watch stream remains active. -#### Changing Synchronization Mode +- `SyncMode.Manual`: Synchronization no longer occurs in real-time, and the watch stream is disconneted. -By default, Yorkie synchronizes a document in `PushPull` mode, where local changes are pushed to the server, and remote changes are pulled from the server. +```kotlin +// Enable automatic synchronization of both local and remote changes. +client.changeSyncMode(doc, SyncMode.Realtime) -If you only want to send your changes and not receive remote changes, you can use `PushOnly` mode. +// Only push local changes automatically. +client.changeSyncMode(doc, SyncMode.RealtimePushOnly) -For realtime synchronization, you can use `Client.pauseRemoteChanges(document)` and `Client.resumeRemoteChanges(document)`. +// Synchronization turned off, but the watch stream remains active. +client.changeSyncMode(doc, SyncMode.RealtimeSyncOff) -For manual synchronization, you can pass the desired sync mode to `Client.syncAsync(document, syncMode)`. +// Synchronization turned off, and the watch stream is disconneted. +client.changeSyncMode(doc, SyncMode.Manual) +client.syncAsync(doc).await() // Trigger synchronization manually using the sync function. -```kotlin - // Pause remote changes for realtime sync - client.pauseRemoteChanges(document); - // Resume remote changes for realtime sync - client.resumeRemoteChanges(document); - - // Declare your own CoroutineScope - scope.launch { - // Manual sync in Push-Only mode - client.syncAsync(doc, SyncMode.PushOnly).await(); - // Manual sync in Push-Pull mode - client.syncAsync(doc, SyncMode.PushPull).await(); - } - ``` +``` #### Detaching the Document