1717
1818import com .diffplug .common .base .Preconditions ;
1919import java .util .ArrayList ;
20- import java .util .List ;
2120import java .util .concurrent .atomic .AtomicReference ;
2221import java .util .function .Consumer ;
2322import org .jetbrains .annotations .Nullable ;
2423
24+ /**
25+ * - immediately on app startup, call `MacDeepLink.startCapturingBeforeSwt()`
26+ * - once SWT has initialized, call `MacDeepLink.swtHasInitializedBeginReceiving(Consumer<String>)`
27+ * - all urls which were captured before SWT initialized will be passed immediately (on the SWT thread)
28+ *
29+ * That's all! Don't do anything else.
30+ */
2531public class MacDeepLink {
26- private static volatile @ Nullable Consumer <String > urlHandler ;
27- private static final AtomicReference <@ Nullable List <String >> backlogUrls = new AtomicReference <>();
32+ /**
33+ * state transitions are:
34+ * - `null` on startup
35+ * - `startCapturingBeforeSwt()` transitions to an `ArrayList<String>`, backlog urls get added to it
36+ * - `swtHasInitializedBeginReceiving()` transitions to a `Consumer<String>`, all new urls go there
37+ */
38+ private static final AtomicReference <@ Nullable Object > state = new AtomicReference <>();
2839
29- static {
30- // Load the native library - try multiple strategies
40+ public static void startCapturingBeforeSwt () {
3141 String libPath = System .getProperty ("durian-swt.library.path" );
3242 if (libPath != null ) {
3343 System .load (libPath + "/durian-swt-natives/DeepLinkBridge.dylib" );
3444 } else {
3545 throw new IllegalArgumentException ("You need to set 'durian-swt.library.path'" );
3646 }
37- }
3847
39- public static void setURLHandler (Consumer <String > handler ) {
40- Preconditions .checkArgument (urlHandler == null , "URL handler can only be set once" );
41- urlHandler = handler ;
42- }
43-
44- public static void applicationStartBeforeSwt () {
45- Preconditions .checkArgument (urlHandler != null , "Call `setURLHandler()` first" );
46- backlogUrls .set (new ArrayList <>());
48+ var was = state .getAndSet (new ArrayList <>());
49+ Preconditions .checkArgument (was == null , "`startCapturingBeforeSwt() should be called first`" );
4750 nativeBeforeSwt ();
4851 }
4952
50- public static void applicationStartAfterSwt () {
51- Preconditions .checkArgument (backlogUrls .get () != null , "Call `applicationStartBeforeSwt()` first." );
53+ public static void swtHasInitializedBeginReceiving (Consumer <String > handler ) {
54+ SwtMisc .assertUI ();
55+ var was = state .getAndSet (handler );
56+ Preconditions .checkArgument (was instanceof ArrayList <?>, "Call `applicationStartBeforeSwt()` first." );
57+
58+ var backlog = (ArrayList <String >) was ;
59+ backlog .forEach (handler );
60+
5261 nativeAfterSwt ();
53- var accumulatedBacklog = backlogUrls .getAndSet (null );
54- accumulatedBacklog .forEach (urlHandler );
5562 }
5663
5764 // Native method declarations - implemented in DeepLinkBridge.m
@@ -65,12 +72,14 @@ public static void applicationStartAfterSwt() {
6572 *
6673 * @param url The URL string received from the operating system
6774 */
68- public static void deliverURL (String url ) {
69- var backlog = backlogUrls .get ();
70- if (backlog != null ) {
71- backlog .add (url );
75+ public static void __internal_deliverUrl (String url ) {
76+ var was = state .get ();
77+ if (was instanceof Consumer ) {
78+ ((Consumer <String >) was ).accept (url );
79+ } else if (was instanceof ArrayList <?>) {
80+ ((ArrayList <String >) was ).add (url );
7281 } else {
73- urlHandler . accept ( url );
82+ throw new IllegalStateException ( "Expected Consumer or ArrayList, was " + was );
7483 }
7584 }
7685}
0 commit comments