1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//! Links the application is opened with: a URL in one of its schemes that
//! another application or the system opened, and the deep link of a
//! notification the person tapped.
//!
//! A link that opened the application waits until a screen collects the
//! stream, so the launch link reaches the first collector. A navigation host
//! turns links into routes with `cranpose_navigation::BindDeepLinks`.
use cranpose_core::{EventStream, rememberEventStream};
use crate::inbox::{Inbox, InboxObserver};
static LINKS: Inbox<String> = Inbox::new("opened link");
/// Registers `observer` for opened links, replaying the ones that arrived
/// before there was anywhere to put them.
///
/// Applications collect the stream from [`rememberOpenedLinks`] instead of
/// calling this.
pub fn observe_opened_links(observer: impl Fn(String) + Send + Sync + 'static) -> InboxObserver {
LINKS.observe(observer)
}
/// Publishes a link the application was opened with. Platform hosts call it
/// from any thread; the framework moves each link onto the UI thread before a
/// composition sees it.
pub fn publish_opened_link(link: impl Into<String>) {
LINKS.publish(link.into());
}
/// Discards the links waiting for a collector. Used by tests and host
/// teardown.
pub fn clear_opened_links() {
LINKS.clear();
}
/// Collects the links the application is opened with for as long as this
/// call stays in the composition — what Android's `onNewIntent` and the
/// launch intent's data give an activity.
///
/// ```rust,no_run
/// use cranpose_macros::composable;
/// use cranpose_services::rememberOpenedLinks;
///
/// #[composable]
/// fn Links() {
/// let links = rememberOpenedLinks();
/// cranpose_core::CollectEvents(links, (), |link| {
/// log::info!("opened with {link}");
/// });
/// }
/// ```
#[expect(non_snake_case)]
#[track_caller]
pub fn rememberOpenedLinks() -> EventStream<String> {
rememberEventStream((), |sender| {
observe_opened_links(move |link| sender.send(link))
})
}