17
17
18
18
import com .diffplug .common .base .Preconditions ;
19
19
import java .util .ArrayList ;
20
- import java .util .List ;
21
20
import java .util .concurrent .atomic .AtomicReference ;
22
21
import java .util .function .Consumer ;
23
22
import org .jetbrains .annotations .Nullable ;
24
23
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
+ */
25
31
public 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 <>();
28
39
29
- static {
30
- // Load the native library - try multiple strategies
40
+ public static void startCapturingBeforeSwt () {
31
41
String libPath = System .getProperty ("durian-swt.library.path" );
32
42
if (libPath != null ) {
33
43
System .load (libPath + "/durian-swt-natives/DeepLinkBridge.dylib" );
34
44
} else {
35
45
throw new IllegalArgumentException ("You need to set 'durian-swt.library.path'" );
36
46
}
37
- }
38
47
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`" );
47
50
nativeBeforeSwt ();
48
51
}
49
52
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
+
52
61
nativeAfterSwt ();
53
- var accumulatedBacklog = backlogUrls .getAndSet (null );
54
- accumulatedBacklog .forEach (urlHandler );
55
62
}
56
63
57
64
// Native method declarations - implemented in DeepLinkBridge.m
@@ -65,12 +72,14 @@ public static void applicationStartAfterSwt() {
65
72
*
66
73
* @param url The URL string received from the operating system
67
74
*/
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 );
72
81
} else {
73
- urlHandler . accept ( url );
82
+ throw new IllegalStateException ( "Expected Consumer or ArrayList, was " + was );
74
83
}
75
84
}
76
85
}
0 commit comments