@straitlink/capacitor 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -131,6 +131,7 @@ Debug, release and Play App Signing keys each have their own fingerprint."
131
131
  | `trackEvent(name, { value, currency, linkId, clickId })` | Conversion or revenue event, placed on the tap of the last attributed open (7 days). Resolves `true` when accepted. |
132
132
  | `pendingOpenReports()` / `flushOpenReports()` | Open reports saved while offline (sent again on start and resume). |
133
133
  | `deviceClass()` | `phone` or `tablet` (iPad / 600 dp and up), as sent with open reports. |
134
+ | `openStoreSheet(url, options?)` | The app store inside your app for one of your links (another app to install), deep link kept through the install. Options: `androidPackage`, `listing`, `inline`, `appStoreId`, `providerToken`, `customProductPageId`, `style`. Resolves `{ opened, method, clickId, linkId, referrer, reason }`. |
134
135
  | `doctor()` | Setup check for debug builds (key, endpoint, this app listed in your link domain's files, Android signing certificate). Resolves `{ ok, findings }`. |
135
136
  | `stop()` | Stops delivering events to this object. |
136
137
 
@@ -1,7 +1,9 @@
1
1
  package dev.strait.capacitor;
2
2
 
3
3
  import android.content.Context;
4
+ import android.content.ActivityNotFoundException;
4
5
  import android.content.Intent;
6
+ import android.net.Uri;
5
7
  import android.content.SharedPreferences;
6
8
  import android.content.pm.ApplicationInfo;
7
9
  import android.content.pm.PackageInfo;
@@ -39,6 +41,9 @@ import dev.strait.sdk.DoctorReport;
39
41
  import dev.strait.sdk.KeyValueStore;
40
42
  import dev.strait.sdk.LinkEvent;
41
43
  import dev.strait.sdk.LinkStart;
44
+ import dev.strait.sdk.StoreLauncher;
45
+ import dev.strait.sdk.StoreSheetOptions;
46
+ import dev.strait.sdk.StoreSheetResult;
42
47
  import dev.strait.sdk.StraitClient;
43
48
  import dev.strait.sdk.StraitConfig;
44
49
  import dev.strait.sdk.UrlConnectionTransport;
@@ -184,6 +189,47 @@ public class StraitPlugin extends Plugin {
184
189
  });
185
190
  }
186
191
 
192
+ /** Store sheet: Google Play inside the app for one of the workspace's links, deep link kept. */
193
+ @PluginMethod
194
+ public void openStoreSheet(PluginCall call) {
195
+ StraitClient c = ready(call);
196
+ if (c == null) return;
197
+ String url = call.getString("url", "");
198
+ if (url == null || url.isEmpty()) {
199
+ call.reject("Strait: openStoreSheet needs a url");
200
+ return;
201
+ }
202
+ Context ctx = getContext();
203
+ StoreSheetOptions opts = new StoreSheetOptions(
204
+ call.getString("androidPackage"), ctx.getPackageName(), call.getString("listing"), call.getBoolean("inline", true));
205
+ StoreLauncher launcher = s -> {
206
+ Intent intent = new Intent(s.getAction(), Uri.parse(s.getData()));
207
+ if (s.getPackageName() != null) intent.setPackage(s.getPackageName());
208
+ for (Map.Entry<String, Object> kv : s.getExtras().entrySet()) {
209
+ if (kv.getValue() instanceof Boolean) intent.putExtra(kv.getKey(), (Boolean) kv.getValue());
210
+ else if (kv.getValue() instanceof String) intent.putExtra(kv.getKey(), (String) kv.getValue());
211
+ }
212
+ if (getActivity() == null) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
213
+ try {
214
+ (getActivity() != null ? getActivity() : ctx).startActivity(intent);
215
+ return true;
216
+ } catch (ActivityNotFoundException e) {
217
+ return false;
218
+ }
219
+ };
220
+ executor.execute(() -> {
221
+ StoreSheetResult r = c.openStoreSheet(url, launcher, opts);
222
+ JSObject o = new JSObject();
223
+ o.put("opened", r.getOpened());
224
+ o.put("method", r.getMethod());
225
+ putIf(o, "clickId", r.getClickId());
226
+ putIf(o, "linkId", r.getLinkId());
227
+ putIf(o, "referrer", r.getReferrer());
228
+ putIf(o, "reason", r.getReason());
229
+ call.resolve(o);
230
+ });
231
+ }
232
+
187
233
  /** SHA-256 of this build's signing certificate(s), "AB:CD:…" (what assetlinks.json lists). */
188
234
  @SuppressWarnings("deprecation")
189
235
  private static List<String> signingCerts(Context ctx) {
package/dist/index.d.ts CHANGED
@@ -6,4 +6,4 @@ export declare const StraitNative: StraitNativePlugin;
6
6
  * Android and iOS only; on the web every call resolves a safe default (use @straitlink/web there).
7
7
  */
8
8
  export declare function createStrait(config: CreateStraitConfig, native?: StraitNativePlugin): Strait;
9
- export type { CreateStraitConfig, DeviceClass, DoctorFinding, DoctorReport, LinkEvent, LinkStart, Strait, StraitNativePlugin, TrackEventExtra, } from './strait.js';
9
+ export type { CreateStraitConfig, DeviceClass, DoctorFinding, DoctorReport, LinkEvent, LinkStart, Strait, StoreSheetOptions, StoreSheetResult, StraitNativePlugin, TrackEventExtra, } from './strait.js';
package/dist/strait.d.ts CHANGED
@@ -42,6 +42,32 @@ export interface DoctorFinding {
42
42
  /** What to do; empty for `ok`. */
43
43
  fix: string;
44
44
  }
45
+ /** Store sheet options (same names as @straitlink/react-native). */
46
+ export interface StoreSheetOptions {
47
+ /** Android: the app to install. Default: the workspace's Android package from Strait. */
48
+ androidPackage?: string;
49
+ /** Android: a Play custom store listing name. */
50
+ listing?: string;
51
+ /** Android: false skips Play's inline half-sheet. Default true. */
52
+ inline?: boolean;
53
+ /** iPhone: the app to install. Default: the workspace's App Store ID from Strait. */
54
+ appStoreId?: string;
55
+ providerToken?: string;
56
+ customProductPageId?: string;
57
+ /** iPhone: the full product page (default) or a small card at the bottom. */
58
+ style?: 'product_page' | 'overlay';
59
+ }
60
+ export interface StoreSheetResult {
61
+ opened: boolean;
62
+ /** inline_install | market | web | product_page | overlay | none */
63
+ method: string;
64
+ clickId?: string;
65
+ linkId?: string;
66
+ /** Android: the Play Install Referrer sent. */
67
+ referrer?: string;
68
+ /** not_found, expired, offline, no_package, no_app_store_id, not_shown, unavailable… */
69
+ reason?: string;
70
+ }
45
71
  export interface DoctorReport {
46
72
  /** No `error` finding. */
47
73
  ok: boolean;
@@ -82,6 +108,9 @@ export interface StraitNativePlugin {
82
108
  deviceClass?: DeviceClass;
83
109
  }>;
84
110
  doctor(): Promise<DoctorReport>;
111
+ openStoreSheet(options: {
112
+ url: string;
113
+ } & StoreSheetOptions): Promise<StoreSheetResult>;
85
114
  addListener(event: 'link', cb: (e: LinkEvent) => void): Promise<PluginListenerHandle>;
86
115
  addListener(event: 'linkStart', cb: (s: LinkStart) => void): Promise<PluginListenerHandle>;
87
116
  }
@@ -108,6 +137,11 @@ export interface Strait {
108
137
  * signing certificate). Call after start(). Never throws.
109
138
  */
110
139
  doctor(): Promise<DoctorReport>;
140
+ /**
141
+ * Store sheet: open the app store inside your app for one of your short links (an app you
142
+ * want people to install), keeping the deep link through the install. Never throws.
143
+ */
144
+ openStoreSheet(url: string, options?: StoreSheetOptions): Promise<StoreSheetResult>;
111
145
  /** Stop delivering events to this object. */
112
146
  stop(): void;
113
147
  }
package/dist/strait.js CHANGED
@@ -60,6 +60,7 @@ export function createStrait(config, native) {
60
60
  flushOpenReports: () => safe(() => native.flushOpenReports(), undefined),
61
61
  deviceClass: () => safe(async () => (await native.deviceClass()).deviceClass, undefined),
62
62
  doctor: () => safe(() => native.doctor(), { ok: false, findings: [] }),
63
+ openStoreSheet: (url, options = {}) => safe(() => native.openStoreSheet({ url, ...options }), { opened: false, method: 'none', reason: 'unavailable' }),
63
64
  stop() {
64
65
  linkCbs.clear();
65
66
  startCbs.clear();
@@ -18,6 +18,7 @@ public class StraitPlugin: CAPPlugin, CAPBridgedPlugin {
18
18
  CAPPluginMethod(name: "flushOpenReports", returnType: CAPPluginReturnPromise),
19
19
  CAPPluginMethod(name: "deviceClass", returnType: CAPPluginReturnPromise),
20
20
  CAPPluginMethod(name: "doctor", returnType: CAPPluginReturnPromise),
21
+ CAPPluginMethod(name: "openStoreSheet", returnType: CAPPluginReturnPromise),
21
22
  ]
22
23
 
23
24
  private var links: StraitLinks?
@@ -111,6 +112,36 @@ public class StraitPlugin: CAPPlugin, CAPBridgedPlugin {
111
112
  }
112
113
  }
113
114
 
115
+ /// Store sheet: the App Store inside the app for one of the workspace's links, deep link kept.
116
+ @objc func openStoreSheet(_ call: CAPPluginCall) {
117
+ guard let l = ready(call) else { return }
118
+ guard let url = call.getString("url"), !url.isEmpty else {
119
+ call.reject("Strait: openStoreSheet needs a url")
120
+ return
121
+ }
122
+ DispatchQueue.main.async { [weak self] in
123
+ guard let vc = self?.bridge?.viewController else {
124
+ call.resolve(["opened": false, "method": "none", "reason": "no_view"])
125
+ return
126
+ }
127
+ let options = StoreSheetOptions(
128
+ appStoreId: call.getString("appStoreId"),
129
+ providerToken: call.getString("providerToken"),
130
+ customProductPageId: call.getString("customProductPageId"),
131
+ style: StoreSheetStyle(rawValue: call.getString("style") ?? "") ?? .productPage
132
+ )
133
+ let presenter = SystemStoreSheetPresenter(from: vc)
134
+ l.openStoreSheet(url: url, options: options, presenter: presenter) { r in
135
+ _ = presenter // keep the presenter (the store sheet's delegate) alive until done
136
+ var o: [String: Any] = ["opened": r.opened, "method": r.method]
137
+ if let v = r.clickId { o["clickId"] = v }
138
+ if let v = r.linkId { o["linkId"] = v }
139
+ if let v = r.reason { o["reason"] = v }
140
+ call.resolve(o)
141
+ }
142
+ }
143
+ }
144
+
114
145
  private func ready(_ call: CAPPluginCall) -> StraitLinks? {
115
146
  guard let l = links else {
116
147
  call.reject("Strait: call start() first")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@straitlink/capacitor",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Deep linking for Capacitor and Ionic apps: direct links (App Links, Universal Links, custom schemes), deferred links that survive the install and link-open analytics. Wraps the Strait Android and iOS SDKs.",
5
5
  "keywords": [
6
6
  "capacitor",