@@ -112,10 +112,15 @@ def can_be_decorated(x):
112112
113113def _save_field (name , src , dst , encoder = None ):
114114 value = getattr (src , name )
115+
115116 if encoder :
116- dst [name ] = encoder (value )
117- else :
117+ value = encoder (value )
118+
119+ if name not in dst or dst [name ] != value :
118120 dst [name ] = value
121+ return True
122+
123+ return False
119124
120125
121126def _setup_class_fields (owner ):
@@ -145,13 +150,14 @@ class TypeValidation(Enum):
145150
146151
147152class StateDataModel :
148- def __init__ (self , trame_server = None , ** kwargs ):
153+ def __init__ (self , trame_server = None , enable_collaboration = False , ** kwargs ):
149154 self .__id = _next_id ()
150155 self .__trame_server = trame_server
151156
152157 # Register all instances
153158 INSTANCES [self .__id ] = self
154159
160+ self ._enable_collaboration = enable_collaboration
155161 self ._server_state = {}
156162 self ._client_state = {}
157163 self ._dirty_set = set ()
@@ -326,6 +332,9 @@ def client_state(self):
326332 def update_from_client_state (self , partial_state ):
327333 encoders = self .ENCODERS
328334 for k , v in partial_state .items ():
335+ if not self ._enable_collaboration :
336+ self ._client_state [k ] = v
337+
329338 convert = encoders .get (k )
330339 if convert :
331340 setattr (self , k , convert .decoder (v ))
@@ -336,7 +345,12 @@ def update_from_client_state(self, partial_state):
336345 def _id (self ):
337346 return self .__id
338347
339- def flush (self , dirty_set : set [str ] | None = None ):
348+ def dirty (self , * keys ):
349+ """Mark variable dirty and trigger watchers"""
350+ self ._dirty_set .update (keys )
351+ self ._on_dirty ()
352+
353+ def flush (self , dirty_set : set [str ] | None = None , force_push = False ):
340354 """Flush the data to the client."""
341355 if self ._flush_impl is None :
342356 return
@@ -349,19 +363,25 @@ def flush(self, dirty_set: set[str] | None = None):
349363 self ._dirty_set .discard (name )
350364
351365 key_to_send = list (dirty_set & self .CLIENT_NAMES )
366+ modified_keys = []
352367 for name in key_to_send :
353368 encoder = None
354369 if name in self .ENCODERS :
355370 encoder = self .ENCODERS [name ].encoder
356371
357- _save_field (name , self , self ._client_state , encoder )
372+ if _save_field (name , self , self ._client_state , encoder ):
373+ modified_keys .append (name )
374+
375+ if force_push :
376+ modified_keys = list (key_to_send )
358377
359378 # Send data over the network
360- msg = {
361- "id" : self ._id ,
362- "state" : {k : self ._client_state [k ] for k in key_to_send },
363- }
364- self ._flush_impl (msg )
379+ if modified_keys :
380+ msg = {
381+ "id" : self ._id ,
382+ "state" : {k : self ._client_state [k ] for k in modified_keys },
383+ }
384+ self ._flush_impl (msg )
365385
366386
367387# -----------------------------------------------------------------------------
0 commit comments