@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.
|
|
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",
|