@@ -12,6 +12,7 @@ import { useThrottleCallback } from '@react-hook/throttle';
12
12
import * as yorkie from 'yorkie-js-sdk' ;
13
13
import randomColor from 'randomcolor' ;
14
14
import { uniqueNamesGenerator , names } from 'unique-names-generator' ;
15
+ import _ from 'lodash' ;
15
16
16
17
import type { Options , YorkieDocType , YorkiePresenceType } from './types' ;
17
18
@@ -64,30 +65,73 @@ export function useMultiplayerState(roomId: string) {
64
65
) => {
65
66
if ( ! app || client === undefined || doc === undefined ) return ;
66
67
67
- doc . update ( ( root ) => {
68
- Object . entries ( shapes ) . forEach ( ( [ id , shape ] ) => {
68
+ const getUpdatedPropertyList = < T extends object > (
69
+ source : T ,
70
+ target : T ,
71
+ ) => {
72
+ return ( Object . keys ( source ) as Array < keyof T > ) . filter (
73
+ ( key ) => ! _ . isEqual ( source [ key ] , target [ key ] ) ,
74
+ ) ;
75
+ } ;
76
+
77
+ Object . entries ( shapes ) . forEach ( ( [ id , shape ] ) => {
78
+ doc . update ( ( root ) => {
69
79
if ( ! shape ) {
70
80
delete root . shapes [ id ] ;
71
- } else {
81
+ } else if ( ! root . shapes [ id ] ) {
72
82
root . shapes [ id ] = shape ;
83
+ } else {
84
+ const updatedPropertyList = getUpdatedPropertyList (
85
+ shape ,
86
+ root . shapes [ id ] ! . toJS ! ( ) ,
87
+ ) ;
88
+
89
+ updatedPropertyList . forEach ( ( key ) => {
90
+ const newValue = shape [ key ] ;
91
+ ( root . shapes [ id ] [ key ] as typeof newValue ) = newValue ;
92
+ } ) ;
73
93
}
74
94
} ) ;
95
+ } ) ;
75
96
76
- Object . entries ( bindings ) . forEach ( ( [ id , binding ] ) => {
97
+ Object . entries ( bindings ) . forEach ( ( [ id , binding ] ) => {
98
+ doc . update ( ( root ) => {
77
99
if ( ! binding ) {
78
100
delete root . bindings [ id ] ;
79
- } else {
101
+ } else if ( ! root . bindings [ id ] ) {
80
102
root . bindings [ id ] = binding ;
103
+ } else {
104
+ const updatedPropertyList = getUpdatedPropertyList (
105
+ binding ,
106
+ root . bindings [ id ] ! . toJS ! ( ) ,
107
+ ) ;
108
+
109
+ updatedPropertyList . forEach ( ( key ) => {
110
+ const newValue = binding [ key ] ;
111
+ ( root . bindings [ id ] [ key ] as typeof newValue ) = newValue ;
112
+ } ) ;
81
113
}
82
114
} ) ;
115
+ } ) ;
83
116
84
- // Should store app.document.assets which is global asset storage referenced by inner page assets
85
- // Document key for assets should be asset.id (string), not index
86
- Object . entries ( app . assets ) . forEach ( ( [ , asset ] ) => {
117
+ // Should store app.document.assets which is global asset storage referenced by inner page assets
118
+ // Document key for assets should be asset.id (string), not index
119
+ Object . entries ( app . assets ) . forEach ( ( [ , asset ] ) => {
120
+ doc . update ( ( root ) => {
87
121
if ( ! asset . id ) {
88
122
delete root . assets [ asset . id ] ;
89
- } else {
123
+ } else if ( root . assets [ asset . id ] ) {
90
124
root . assets [ asset . id ] = asset ;
125
+ } else {
126
+ const updatedPropertyList = getUpdatedPropertyList (
127
+ asset ,
128
+ root . assets [ asset . id ] ! . toJS ! ( ) ,
129
+ ) ;
130
+
131
+ updatedPropertyList . forEach ( ( key ) => {
132
+ const newValue = asset [ key ] ;
133
+ ( root . assets [ asset . id ] [ key ] as typeof newValue ) = newValue ;
134
+ } ) ;
91
135
}
92
136
} ) ;
93
137
} ) ;
0 commit comments