1414# {values} -> dict (where as in R is an environment) 
1515# √ values is a dict! 
1616# {exclude} -> Requires `session.setBookmarkExclude(names)`, `session.getBookmarkExclude()` 
17- # * `session.setBookmarkExclude(names)` TODO: 
18- # * `session.getBookmarkExclude()` 
19- # * `session.bookmark_exclude` value? 
17+ # √ `session.bookmark_exclude: list[str]` value! 
18+ # √ `session._get_bookmark_exclude()` & `session._bookmark_exclude_fn` 
2019# Using a `.bookmark_exclude = []` and `._get_bookmark_exclude()` helper that accesses a `._bookmark_exclude_fns` list of functions which return scoped bookmark excluded values 
2120# Enable bookmarking hooks: 
22- # * types: `url`, `server`, `disable` 
23- # * where to store it? `session` object feels too late. `App` may not exist yet. 
21+ # * √ `session.bookmark_store`: `url`, `server`, `disable` 
2422# Session hooks -> `onBookmark()`, `onBookmarked()`, `onRestore(), `onRestored()` 
25- # * `session.onBookmark ()` TODO:  
26- # * `session.onBookmarked ()` TODO:  
23+ # * √  `session.on_bookmark ()` # Takes the save state  
24+ # * √  `session.on_bookmarked ()` # Takes a url  
2725# * `session.onRestore()` 
2826# * `session.onRestored()` 
2927# Session hooks -> Require list of callback functions for each 
30- # Session hooks -> Calling hooks in proper locations with info 
31- # Session hook -> Call bookmark "right now": `doBookmark()` 
32- # * `session.doBookmark ()` 
28+ # * √  Session hooks -> Calling hooks in proper locations with info 
29+ # * √  Session hook -> Call bookmark "right now": `doBookmark()` 
30+ # * √  `session.do_bookmark ()` 
3331# Session updates -> Require updates for `SessionProxy` object 
34- # `doBookmark()` -> Update query string 
35- # * Update query string 
32+ # * √  `doBookmark()` -> Update query string 
33+ # * √  Update query string 
3634
3735# bookmark -> restore state 
3836# restore state -> {inputs, values, exclude} 
3937# restore {inputs} -> Update all inputs given restored value 
4038
39+ # Shinylive! 
40+ # Get query string from parent frame / tab 
41+ # * Ignore the code itself 
42+ # * May need to escape (all?) the parameters to avoid collisions with `h=` or `code=`. 
43+ # Set query string to parent frame / tab 
44+ 
4145import  pickle 
4246from  pathlib  import  Path 
43- from  typing  import  Any , Callable 
47+ from  typing  import  Any , Awaitable ,  Callable 
4448from  urllib .parse  import  urlencode  as  urllib_urlencode 
4549
4650from  .. import  Inputs 
@@ -57,8 +61,9 @@ class ShinySaveState:
5761    input : Inputs 
5862    values : dict [str , Any ]
5963    exclude : list [str ]
64+     # _bookmark_: A special value that is always excluded from the bookmark. 
6065    on_save : (
61-         Callable [["ShinySaveState" ], None ] |  None 
66+         Callable [["ShinySaveState" ], Awaitable [ None ] ] |  None 
6267    )  # A callback to invoke during the saving process. 
6368
6469    # These are set not in initialize(), but by external functions that modify 
@@ -69,20 +74,22 @@ def __init__(
6974        self ,
7075        input : Inputs ,
7176        exclude : list [str ],
72-         on_save : Callable [["ShinySaveState" ], None ] |  None ,
77+         on_save : Callable [["ShinySaveState" ], Awaitable [ None ] ] |  None ,
7378    ):
7479        self .input  =  input 
7580        self .exclude  =  exclude 
7681        self .on_save  =  on_save 
7782        self .dir  =  None   # This will be set by external functions. 
7883        self .values  =  {}
7984
80-     def  _call_on_save (self ):
81-         # Allow user-supplied onSave function to do things like add state$values, or 
85+         self ._always_exclude : list [str ] =  ["._bookmark_" ]
86+ 
87+     async  def  _call_on_save (self ):
88+         # Allow user-supplied save function to do things like add state$values, or 
8289        # save data to state dir. 
8390        if  self .on_save :
8491            with  isolate ():
85-                 self .on_save (self )
92+                 await   self .on_save (self )
8693
8794    def  _exclude_bookmark_value (self ):
8895        # If the bookmark value is not in the exclude list, add it. 
@@ -98,19 +105,19 @@ async def _save_state(self) -> str:
98105        str 
99106            A query string which can be used to restore the session. 
100107        """ 
101-         id  =  private_random_id (prefix = "" , bytes = 3 )
108+         id  =  private_random_id (prefix = "" , bytes = 8 )
102109
103110        # TODO: barret move code to single call location 
104111        # A function for saving the state object to disk, given a directory to save 
105112        # to. 
106113        async  def  save_state_to_dir (state_dir : Path ) ->  None :
107114            self .dir  =  state_dir 
108115
109-             self ._call_on_save ()
116+             await   self ._call_on_save ()
110117
111118            self ._exclude_bookmark_value ()
112119
113-             input_values_json  =  self .input ._serialize (
120+             input_values_json  =  await   self .input ._serialize (
114121                exclude = self .exclude ,
115122                state_dir = self .dir ,
116123            )
@@ -165,7 +172,7 @@ async def _encode_state(self) -> str:
165172            A query string which can be used to restore the session. 
166173        """ 
167174        # Allow user-supplied onSave function to do things like add state$values. 
168-         self ._call_on_save ()
175+         await   self ._call_on_save ()
169176
170177        self ._exclude_bookmark_value ()
171178
0 commit comments