@@ -180,6 +180,26 @@ async def update_query_string(
180
180
"""
181
181
...
182
182
183
+ @abstractmethod
184
+ async def get_bookmark_url (self ) -> str | None :
185
+ """
186
+ Get the URL of the current bookmark state
187
+
188
+ This method should return the full URL, including the query string.
189
+
190
+ As a side effect, all `on_bookmark` callbacks will be invoked to allow the
191
+ bookmark state to be modified before it is serialized. This will cause the
192
+ bookmark state to be serialized to disk when `session.bookmark.store ==
193
+ "server"`.
194
+
195
+ Returns
196
+ -------
197
+ :
198
+ The full URL of the current bookmark state, including the query string.
199
+ `None` if bookmarking is not enabled.
200
+ """
201
+ ...
202
+
183
203
@abstractmethod
184
204
async def do_bookmark (self ) -> None :
185
205
"""
@@ -385,66 +405,76 @@ def _get_bookmark_exclude(self) -> list[str]:
385
405
# Remove duplicates
386
406
return list (set ([* self .exclude , * scoped_excludes ]))
387
407
408
+ async def get_bookmark_url (self ) -> str | None :
409
+ if self .store == "disable" :
410
+ return None
411
+
412
+ # ?withLogErrors
413
+ from ..bookmark ._bookmark import BookmarkState
414
+ from ..session import session_context
415
+
416
+ async def root_state_on_save (state : BookmarkState ) -> None :
417
+ with session_context (self ._session ):
418
+ await self ._on_bookmark_callbacks .invoke (state )
419
+
420
+ root_state = BookmarkState (
421
+ input = self ._session .input ,
422
+ exclude = self ._get_bookmark_exclude (),
423
+ on_save = root_state_on_save ,
424
+ )
425
+
426
+ if self .store == "server" :
427
+ query_string = await root_state ._save_state (app = self ._session .app )
428
+ elif self .store == "url" :
429
+ query_string = await root_state ._encode_state ()
430
+ # # Can we have browser storage?
431
+ # elif self.store == "browser":
432
+ # get_json object
433
+ # get consistent storage value (not session id)
434
+ # send object to browser storage
435
+ # return server-like-id url value
436
+ else :
437
+ raise ValueError ("Unknown bookmark store: " + self .store )
438
+
439
+ clientdata = self ._session .clientdata
440
+
441
+ port = str (clientdata .url_port ())
442
+ full_url = "" .join (
443
+ [
444
+ clientdata .url_protocol (),
445
+ "//" ,
446
+ clientdata .url_hostname (),
447
+ ":" if port else "" ,
448
+ port ,
449
+ clientdata .url_pathname (),
450
+ "?" ,
451
+ query_string ,
452
+ ]
453
+ )
454
+
455
+ return full_url
456
+
388
457
async def do_bookmark (self ) -> None :
389
458
390
- if self .store == "disable" :
391
- # If you have a bookmark button or request a bookmark to be saved,
392
- # then it should be saved. (Present a warning telling author how to fix it)
393
- warnings .warn (
394
- "Saving the bookmark state has been requested. "
395
- 'However, bookmarking is current set to `"disable"`. '
396
- "Please enable bookmarking by setting "
397
- "`shiny.App(bookmark_store=)` or "
398
- "`shiny.express.app_opts(bookmark_store=)`" ,
399
- stacklevel = 2 ,
400
- )
401
- return
459
+ from ..session import session_context
402
460
403
461
try :
404
- # ?withLogErrors
405
- from ..bookmark ._bookmark import BookmarkState
406
- from ..session import session_context
462
+ full_url = await self .get_bookmark_url ()
463
+
464
+ if full_url is None :
465
+ # If you have a bookmark button or request a bookmark to be saved,
466
+ # then it should be saved. (Present a warning telling author how to fix it)
467
+ warnings .warn (
468
+ "Saving the bookmark state has been requested. "
469
+ 'However, bookmarking is current set to `"disable"`. '
470
+ "Please enable bookmarking by setting "
471
+ "`shiny.App(bookmark_store=)` or "
472
+ "`shiny.express.app_opts(bookmark_store=)`" ,
473
+ stacklevel = 2 ,
474
+ )
475
+ return
407
476
408
- async def root_state_on_save (state : BookmarkState ) -> None :
409
- with session_context (self ._session ):
410
- await self ._on_bookmark_callbacks .invoke (state )
411
-
412
- root_state = BookmarkState (
413
- input = self ._session .input ,
414
- exclude = self ._get_bookmark_exclude (),
415
- on_save = root_state_on_save ,
416
- )
417
-
418
- if self .store == "server" :
419
- query_string = await root_state ._save_state (app = self ._session .app )
420
- elif self .store == "url" :
421
- query_string = await root_state ._encode_state ()
422
- # # Can we have browser storage?
423
- # elif self.store == "browser":
424
- # get_json object
425
- # get consistent storage value (not session id)
426
- # send object to browser storage
427
- # return server-like-id url value
428
- else :
429
- raise ValueError ("Unknown bookmark store: " + self .store )
430
-
431
- clientdata = self ._session .clientdata
432
-
433
- port = str (clientdata .url_port ())
434
- full_url = "" .join (
435
- [
436
- clientdata .url_protocol (),
437
- "//" ,
438
- clientdata .url_hostname (),
439
- ":" if port else "" ,
440
- port ,
441
- clientdata .url_pathname (),
442
- "?" ,
443
- query_string ,
444
- ]
445
- )
446
-
447
- # If onBookmarked callback was provided, invoke it; if not call
477
+ # If on_bookmarked callback was provided, invoke it; if not call
448
478
# the default.
449
479
if self ._on_bookmarked_callbacks .count () > 0 :
450
480
with session_context (self ._session ):
@@ -573,6 +603,9 @@ async def update_query_string(
573
603
) -> None :
574
604
await self ._session ._parent .bookmark .update_query_string (query_string , mode )
575
605
606
+ async def get_bookmark_url (self ) -> str | None :
607
+ return await self ._session ._parent .bookmark .get_bookmark_url ()
608
+
576
609
async def do_bookmark (self ) -> None :
577
610
await self ._session ._parent .bookmark .do_bookmark ()
578
611
@@ -617,6 +650,9 @@ async def update_query_string(
617
650
# no-op within ExpressStub
618
651
return None
619
652
653
+ async def get_bookmark_url (self ) -> str | None :
654
+ return None
655
+
620
656
async def do_bookmark (self ) -> None :
621
657
# no-op within ExpressStub
622
658
return None
0 commit comments