web-launch-kit 0.0.1 → 0.0.2
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 +55 -43
- package/dist/index.d.ts +15 -1
- package/dist/launch-kit.cjs +169 -14
- package/dist/launch-kit.cjs.map +1 -1
- package/dist/launch-kit.min.cjs +1 -1
- package/dist/launch-kit.min.cjs.map +1 -1
- package/dist/launch-kit.min.mjs +1 -1
- package/dist/launch-kit.min.mjs.map +1 -1
- package/dist/launch-kit.mjs +169 -14
- package/dist/launch-kit.mjs.map +1 -1
- package/dist/launch-kit.umd.js +169 -14
- package/dist/launch-kit.umd.js.map +1 -1
- package/dist/launch-kit.umd.min.js +1 -1
- package/dist/launch-kit.umd.min.js.map +1 -1
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -28,14 +28,13 @@ The bundle is self-contained (OS/locale detection is inlined) — no peer script
|
|
|
28
28
|
| `LaunchKit.telephone(options?)` | `Promise<void>` | Open the dialer (`tel:`) |
|
|
29
29
|
| `LaunchKit.message(options?)` | `Promise<void>` | Open the SMS composer (`sms:`) |
|
|
30
30
|
| `LaunchKit.mail(options?)` | `Promise<void>` | Open the mail composer (`mailto:`) |
|
|
31
|
+
| `LaunchKit.map(options?)` | `Promise<void>` | Open a map by query, coordinate, or directions; native app per-OS with a Google Maps web fallback |
|
|
31
32
|
| `LaunchKit.filepicker(options?)` | `Promise<File[]>` | Pick files or a directory (File System Access API, with input fallback) |
|
|
32
33
|
| `LaunchKit.setting(type?)` | `Promise<void>` | Open a system-settings pane where supported |
|
|
33
34
|
| `LaunchKit.utils` | object | `canOpenIntent` / `canOpenUniversal` / `canOpenSetting` getters, plus async `getTrackId` / `getProductId` |
|
|
34
35
|
|
|
35
36
|
`AppOpenedBy` is one of: `"scheme"`, `"universal"`, `"intent"`, `"fallback"`, `"store"`.
|
|
36
37
|
|
|
37
|
-
Named exports `getProductId` / `getTrackId` (synchronous store-id lookups) are also available.
|
|
38
|
-
|
|
39
38
|
---
|
|
40
39
|
|
|
41
40
|
## Launching an app
|
|
@@ -43,7 +42,6 @@ Named exports `getProductId` / `getTrackId` (synchronous store-id lookups) are a
|
|
|
43
42
|
`app()` takes per-platform options and only acts on the block matching the current
|
|
44
43
|
OS. It builds an ordered list of candidates and tries each until one launches the
|
|
45
44
|
app, resolving with the route that worked.
|
|
46
|
-
|
|
47
45
|
```mermaid
|
|
48
46
|
flowchart TD
|
|
49
47
|
A([LaunchKit.app called]) --> B{Detect OS via PlatformKit}
|
|
@@ -60,14 +58,14 @@ flowchart TD
|
|
|
60
58
|
A2 --> A3{"scheme given, but intent missing?"}
|
|
61
59
|
A3 -->|yes| A4["createIntentURL:<br/>scheme + packageName + fallback"]
|
|
62
60
|
A3 -->|no| A5
|
|
63
|
-
A4 --> A5["Priority list:<br/>intent (if canOpenIntent) ⭢ scheme
|
|
61
|
+
A4 --> A5["Priority list:<br/>intent (if canOpenIntent) ⭢ scheme (if canOpenScheme)<br/>⭢ fallback ⭢ app store (if canOpenScheme) ⭢ web store"]
|
|
64
62
|
end
|
|
65
63
|
|
|
66
64
|
subgraph IOS["ios · resolveOptions"]
|
|
67
65
|
I1{"bundleId given, but trackId missing?"}
|
|
68
66
|
I1 -->|yes| I2["getTrackId:<br/>iTunes lookup API (bundleId ⭢ trackId)"]
|
|
69
67
|
I1 -->|no| I3
|
|
70
|
-
I2 --> I3["Priority list:<br/>universal (if
|
|
68
|
+
I2 --> I3["Priority list:<br/>universal (if canOpenUniversal) ⭢ scheme (if canOpenScheme)<br/>⭢ fallback ⭢ app store (if canOpenScheme) ⭢ web store"]
|
|
71
69
|
end
|
|
72
70
|
|
|
73
71
|
subgraph WIN["windows · resolveOptions"]
|
|
@@ -123,43 +121,18 @@ flowchart TD
|
|
|
123
121
|
import LaunchKit from 'web-launch-kit'
|
|
124
122
|
|
|
125
123
|
const openedBy = await LaunchKit.app({
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
trackId: '586683407',
|
|
139
|
-
universal: 'https://1drv.ms/x/c/7f3d9a02c81b4e65/IQBk2wYfN8pTQ5vHmR9xLzUcAeXtP0jWnK4oD3iFgZs7bQY?e=Rk9mZ2',
|
|
140
|
-
fallback: 'https://www.microsoft.com/ko-kr/microsoft-365/excel',
|
|
141
|
-
allowAppStore: true,
|
|
142
|
-
allowWebStore: false,
|
|
143
|
-
timeout: 2000,
|
|
144
|
-
},
|
|
145
|
-
windows: {
|
|
146
|
-
scheme: 'ms-excel://',
|
|
147
|
-
packageFamilyName: 'Microsoft.Office.Desktop_8wekyb3d8bbwe',
|
|
148
|
-
productId: 'cfq7ttc0pr28',
|
|
149
|
-
fallback: 'https://www.microsoft.com/ko-kr/microsoft-365/excel',
|
|
150
|
-
allowAppStore: true,
|
|
151
|
-
allowWebStore: false,
|
|
152
|
-
timeout: 750,
|
|
153
|
-
},
|
|
154
|
-
macos: {
|
|
155
|
-
scheme: 'ms-excel://',
|
|
156
|
-
bundleId: 'com.microsoft.Excel',
|
|
157
|
-
trackId: '462058435',
|
|
158
|
-
fallback: 'https://www.microsoft.com/ko-kr/microsoft-365/excel',
|
|
159
|
-
allowAppStore: true,
|
|
160
|
-
allowWebStore: false,
|
|
161
|
-
timeout: 750,
|
|
162
|
-
}
|
|
124
|
+
android: {
|
|
125
|
+
scheme: 'myapp://profile/42',
|
|
126
|
+
packageName: 'com.example.myapp',
|
|
127
|
+
allowAppStore: true,
|
|
128
|
+
allowWebStore: true,
|
|
129
|
+
},
|
|
130
|
+
ios: {
|
|
131
|
+
universal: 'https://example.com/profile/42',
|
|
132
|
+
scheme: 'myapp://profile/42',
|
|
133
|
+
bundleId: 'com.example.myapp', // resolved to a trackId for the store fallback
|
|
134
|
+
allowAppStore: true,
|
|
135
|
+
},
|
|
163
136
|
})
|
|
164
137
|
|
|
165
138
|
console.log(openedBy) // "universal" | "scheme" | "intent" | "fallback" | "store"
|
|
@@ -169,7 +142,12 @@ Per-platform fields: Android accepts `intent` / `scheme` / `packageName` / `fall
|
|
|
169
142
|
(scheme ⇄ intent are derived from each other); iOS accepts `universal` / `scheme` /
|
|
170
143
|
`bundleId` / `trackId`; Windows accepts `scheme` / `packageFamilyName` / `productId`;
|
|
171
144
|
macOS accepts `scheme` / `bundleId` / `trackId`. All accept `fallback`, `timeout`,
|
|
172
|
-
`allowAppStore`, `allowWebStore`.
|
|
145
|
+
`allowAppStore`, `allowWebStore`.
|
|
146
|
+
|
|
147
|
+
Android and iOS additionally accept
|
|
148
|
+
`assumeAllowedInApp` — declare it `true` only when your app is whitelisted by a
|
|
149
|
+
partner-gated in-app browser (e.g. Weibo) so scheme / universal-link candidates are
|
|
150
|
+
kept there; it never bypasses hard-blocked webviews or OS version requirements.
|
|
173
151
|
|
|
174
152
|
## Communication intents
|
|
175
153
|
|
|
@@ -200,6 +178,33 @@ const files = await LaunchKit.filepicker({ accept: ['image/*', '.pdf'], multiple
|
|
|
200
178
|
const tree = await LaunchKit.filepicker({ directory: true })
|
|
201
179
|
```
|
|
202
180
|
|
|
181
|
+
## Maps
|
|
182
|
+
|
|
183
|
+
`map()` takes an intent — a search query, a coordinate, or a route — and builds the
|
|
184
|
+
right URL for the current OS (`maps://` on iOS/macOS, `geo:` on Android, `bingmaps:`
|
|
185
|
+
on Windows), falling back to Google Maps on the web.
|
|
186
|
+
|
|
187
|
+
```js
|
|
188
|
+
import LaunchKit from 'web-launch-kit'
|
|
189
|
+
|
|
190
|
+
// Search for a place
|
|
191
|
+
await LaunchKit.map({ query: 'Seoul City Hall' })
|
|
192
|
+
|
|
193
|
+
// Show a coordinate with a labelled pin
|
|
194
|
+
await LaunchKit.map({ coordinate: [37.5665, 126.9780], label: 'Seoul City Hall', zoom: 15 })
|
|
195
|
+
|
|
196
|
+
// Directions (origin defaults to current location when omitted)
|
|
197
|
+
await LaunchKit.map({ directions: { destination: 'Seoul Station', origin: [37.5665, 126.9780] } })
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Provide exactly one of `query` / `coordinate` / `directions`; when several are set,
|
|
201
|
+
`directions` wins, then `coordinate`, then `query`. A `label` with `coordinate`
|
|
202
|
+
renders a named pin on iOS/macOS/Windows and is ignored on Android, where `geo:`
|
|
203
|
+
handlers other than Google Maps misread the labelled form as a search. Android's
|
|
204
|
+
`geo:` scheme also has no standard directions support, so routes use the Google Maps
|
|
205
|
+
fallback there, and on Windows the discontinued Maps app means `bingmaps:` usually
|
|
206
|
+
defers to the web fallback too.
|
|
207
|
+
|
|
203
208
|
## System settings
|
|
204
209
|
|
|
205
210
|
```js
|
|
@@ -239,3 +244,10 @@ const { default: LaunchKit } = require('web-launch-kit')
|
|
|
239
244
|
exports are synchronous (blocking XHR) and intended for internal/legacy use.
|
|
240
245
|
- **Store-id lookups depend on remote APIs** (iTunes Lookup, Microsoft display catalog)
|
|
241
246
|
and are cached for one hour; failures resolve to `undefined` rather than throwing.
|
|
247
|
+
- **In-app browsers are gated per candidate.** Inside webviews that block launches
|
|
248
|
+
(WeChat, QQ, Qzone, Baidu; Weibo unless partnered), dead candidates — custom schemes,
|
|
249
|
+
`intent://`, and store schemes like `market://` — are skipped up front instead of
|
|
250
|
+
burning their timeouts, so the chain falls straight through to `fallback` / web store
|
|
251
|
+
(the only routes that work there). Whitelisted partner apps opt back in with
|
|
252
|
+
`assumeAllowedInApp: true`.
|
|
253
|
+
- **`map()` uses the per-OS timeout** for each candidate.
|
package/dist/index.d.ts
CHANGED
|
@@ -82,11 +82,13 @@ declare interface AppInfo {
|
|
|
82
82
|
declare interface AndroidAppInfo extends AppInfo {
|
|
83
83
|
intent?: URLCandidate;
|
|
84
84
|
packageName?: string;
|
|
85
|
+
assumeAllowedInApp?: boolean;
|
|
85
86
|
}
|
|
86
87
|
declare interface IOSAppInfo extends AppInfo {
|
|
87
88
|
universal?: URLCandidate;
|
|
88
89
|
bundleId?: string;
|
|
89
90
|
trackId?: string;
|
|
91
|
+
assumeAllowedInApp?: boolean;
|
|
90
92
|
}
|
|
91
93
|
declare interface WindowsAppInfo extends AppInfo {
|
|
92
94
|
packageFamilyName?: string;
|
|
@@ -123,6 +125,17 @@ declare interface FilepickerOptions {
|
|
|
123
125
|
multiple?: boolean;
|
|
124
126
|
startIn?: OpenPickerStartIn;
|
|
125
127
|
}
|
|
128
|
+
declare interface MapOptions {
|
|
129
|
+
query?: string;
|
|
130
|
+
coordinate?: [number, number];
|
|
131
|
+
label?: string;
|
|
132
|
+
directions?: {
|
|
133
|
+
destination: string | [number, number];
|
|
134
|
+
origin?: string | [number, number];
|
|
135
|
+
};
|
|
136
|
+
zoom?: number;
|
|
137
|
+
fallback?: URLStringOrFallback;
|
|
138
|
+
}
|
|
126
139
|
interface LaunchKitUtils {
|
|
127
140
|
get canOpenIntent(): boolean;
|
|
128
141
|
get canOpenUniversal(): boolean;
|
|
@@ -138,10 +151,11 @@ interface LaunchKitInstance {
|
|
|
138
151
|
telephone(options?: TelephoneOptions): Promise<void>;
|
|
139
152
|
message(options?: MessageOptions): Promise<void>;
|
|
140
153
|
mail(options?: MailOptions): Promise<void>;
|
|
154
|
+
map(options?: MapOptions): Promise<void>;
|
|
141
155
|
filepicker(options?: FilepickerOptions): Promise<File[]>;
|
|
142
156
|
setting(type?: SettingType): Promise<void>;
|
|
143
157
|
}
|
|
144
158
|
declare const LaunchKit: LaunchKitInstance;
|
|
145
159
|
|
|
146
160
|
export { SettingType, LaunchKit as default };
|
|
147
|
-
export type { AndroidAppInfo, AppInfo, AppOpenOptions, AppOpenedBy, FilepickerOptions, IOSAppInfo, LaunchKitInstance, MacOSAppInfo, MailOptions, MessageOptions, OpenPickerStartIn, TelephoneOptions, URLCandidate, URLCandidateOrFallback, URLStringOrFallback, WindowsAppInfo };
|
|
161
|
+
export type { AndroidAppInfo, AppInfo, AppOpenOptions, AppOpenedBy, FilepickerOptions, IOSAppInfo, LaunchKitInstance, MacOSAppInfo, MailOptions, MapOptions, MessageOptions, OpenPickerStartIn, TelephoneOptions, URLCandidate, URLCandidateOrFallback, URLStringOrFallback, WindowsAppInfo };
|
package/dist/launch-kit.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var version$1 = "0.0.
|
|
5
|
+
var version$1 = "0.0.2";
|
|
6
6
|
var packageJSON$1 = {
|
|
7
7
|
version: version$1};
|
|
8
8
|
|
|
@@ -940,7 +940,7 @@ var ANDROID_DEFAULT_TIMEOUT = 1000;
|
|
|
940
940
|
var IOS_DEFAULT_TIMEOUT = 2000;
|
|
941
941
|
var WINDOWS_DEFAULT_TIMEOUT = 750;
|
|
942
942
|
var MACOS_DEFAULT_TIMEOUT = 750;
|
|
943
|
-
var
|
|
943
|
+
var DEFAULT_TIMEOUT = 750;
|
|
944
944
|
var NAVIGATOR = globalThis.navigator;
|
|
945
945
|
var CLEANUP_INPUT_ELEMENT = null;
|
|
946
946
|
function createTypeGuard(tag) {
|
|
@@ -974,7 +974,7 @@ function getDefaultTimeout() {
|
|
|
974
974
|
case 'macos':
|
|
975
975
|
return MACOS_DEFAULT_TIMEOUT;
|
|
976
976
|
default:
|
|
977
|
-
return
|
|
977
|
+
return DEFAULT_TIMEOUT;
|
|
978
978
|
}
|
|
979
979
|
}
|
|
980
980
|
function isDocumentHidden() {
|
|
@@ -1080,7 +1080,7 @@ function restoreFocus() {
|
|
|
1080
1080
|
return hasFocus(topDocument);
|
|
1081
1081
|
}
|
|
1082
1082
|
function stripURL(value) {
|
|
1083
|
-
return
|
|
1083
|
+
return isURL(value) ? value.toString() : value;
|
|
1084
1084
|
}
|
|
1085
1085
|
function resolveFocusEventConfig() {
|
|
1086
1086
|
var top = getTopmostWindow();
|
|
@@ -1294,6 +1294,8 @@ function resolveOptions(option) {
|
|
|
1294
1294
|
var fallback;
|
|
1295
1295
|
var allowAppStore;
|
|
1296
1296
|
var allowWebStore;
|
|
1297
|
+
var allowScheme;
|
|
1298
|
+
var assumeAllowedInApp;
|
|
1297
1299
|
var timeout;
|
|
1298
1300
|
var intent;
|
|
1299
1301
|
var packageName;
|
|
@@ -1310,8 +1312,10 @@ function resolveOptions(option) {
|
|
|
1310
1312
|
scheme = stripURL(option.android.scheme);
|
|
1311
1313
|
fallback = stripURL(option.android.fallback);
|
|
1312
1314
|
packageName = option.android.packageName;
|
|
1315
|
+
assumeAllowedInApp = option.android.assumeAllowedInApp === true;
|
|
1313
1316
|
allowAppStore = option.android.allowAppStore;
|
|
1314
1317
|
allowWebStore = option.android.allowWebStore;
|
|
1318
|
+
allowScheme = canOpenScheme(assumeAllowedInApp);
|
|
1315
1319
|
timeout = option.android.timeout;
|
|
1316
1320
|
if (typeof intent !== 'undefined' && (typeof scheme === 'undefined' || typeof packageName === 'undefined' || typeof fallback === 'undefined')) {
|
|
1317
1321
|
var parsed = parseIntentURL(intent);
|
|
@@ -1328,12 +1332,12 @@ function resolveOptions(option) {
|
|
|
1328
1332
|
timeout = ANDROID_DEFAULT_TIMEOUT;
|
|
1329
1333
|
if (typeof intent !== 'undefined' && canOpenIntent())
|
|
1330
1334
|
resolved.push(['intent', intent]);
|
|
1331
|
-
if (typeof scheme !== 'undefined')
|
|
1335
|
+
if (typeof scheme !== 'undefined' && allowScheme)
|
|
1332
1336
|
resolved.push(['scheme', scheme]);
|
|
1333
1337
|
if (typeof fallback !== 'undefined')
|
|
1334
1338
|
resolved.push(['fallback', fallback]);
|
|
1335
1339
|
if (typeof packageName !== 'undefined') {
|
|
1336
|
-
if (allowAppStore)
|
|
1340
|
+
if (allowAppStore && allowScheme)
|
|
1337
1341
|
resolved.push(['store', createAppStoreURL(packageName, os)]);
|
|
1338
1342
|
if (allowWebStore)
|
|
1339
1343
|
resolved.push(['store', createWebStoreURL(packageName, os)]);
|
|
@@ -1347,21 +1351,23 @@ function resolveOptions(option) {
|
|
|
1347
1351
|
fallback = stripURL(option.ios.fallback);
|
|
1348
1352
|
bundleId = option.ios.bundleId;
|
|
1349
1353
|
trackId = option.ios.trackId;
|
|
1354
|
+
assumeAllowedInApp = option.ios.assumeAllowedInApp === true;
|
|
1350
1355
|
allowAppStore = option.ios.allowAppStore;
|
|
1351
1356
|
allowWebStore = option.ios.allowWebStore;
|
|
1357
|
+
allowScheme = canOpenScheme(assumeAllowedInApp);
|
|
1352
1358
|
timeout = option.ios.timeout;
|
|
1353
1359
|
if (typeof bundleId !== 'undefined' && typeof trackId === 'undefined')
|
|
1354
1360
|
trackId = getTrackId(bundleId);
|
|
1355
1361
|
if (typeof timeout === 'undefined')
|
|
1356
1362
|
timeout = IOS_DEFAULT_TIMEOUT;
|
|
1357
|
-
if (typeof universal !== 'undefined' && canOpenUniversal())
|
|
1363
|
+
if (typeof universal !== 'undefined' && canOpenUniversal(assumeAllowedInApp))
|
|
1358
1364
|
resolved.push(['universal', universal]);
|
|
1359
|
-
if (typeof scheme !== 'undefined')
|
|
1365
|
+
if (typeof scheme !== 'undefined' && allowScheme)
|
|
1360
1366
|
resolved.push(['scheme', scheme]);
|
|
1361
1367
|
if (typeof fallback !== 'undefined')
|
|
1362
1368
|
resolved.push(['fallback', fallback]);
|
|
1363
1369
|
if (typeof trackId !== 'undefined') {
|
|
1364
|
-
if (allowAppStore)
|
|
1370
|
+
if (allowAppStore && allowScheme)
|
|
1365
1371
|
resolved.push(['store', createAppStoreURL(trackId, os)]);
|
|
1366
1372
|
if (allowWebStore)
|
|
1367
1373
|
resolved.push(['store', createWebStoreURL(trackId, os)]);
|
|
@@ -1434,10 +1440,41 @@ function canOpenIntent() {
|
|
|
1434
1440
|
return false;
|
|
1435
1441
|
if (browser === 'opera' && PlatformKit.compareVersion(version, '14.0') < 0)
|
|
1436
1442
|
return false;
|
|
1437
|
-
|
|
1443
|
+
if (isFullyBlockedInAppBrowser() || isPartnerAppOnly())
|
|
1444
|
+
return false;
|
|
1445
|
+
return !(/(?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/[\w.]+;/i.test(PlatformKit.userAgent) || /instagram[\/ ][-\w.]+/i.test(PlatformKit.userAgent) || /musical_ly(?:.+app_?version\/|_)[\w.]+/i.test(PlatformKit.userAgent) || /ultralite app_version\/[\w.]+/i.test(PlatformKit.userAgent));
|
|
1446
|
+
}
|
|
1447
|
+
function canOpenUniversal(assumeAllowedInApp) {
|
|
1448
|
+
if (assumeAllowedInApp === void 0) { assumeAllowedInApp = false; }
|
|
1449
|
+
if (PlatformKit.os.name !== 'ios' || PlatformKit.compareVersion(PlatformKit.os.version, '9.0') < 0)
|
|
1450
|
+
return false;
|
|
1451
|
+
if (isPartnerAppOnly() && !assumeAllowedInApp)
|
|
1452
|
+
return false;
|
|
1453
|
+
var userAgent = PlatformKit.userAgent;
|
|
1454
|
+
var wechat = userAgent.match(/micromessenger\/(\d+(?:\.\d+)*)/i);
|
|
1455
|
+
if (wechat !== null && PlatformKit.compareVersion(wechat[1], '7.0.5') < 0)
|
|
1456
|
+
return false;
|
|
1457
|
+
if (/ qq\/[\d.]+/i.test(userAgent) || /m?qqbrowser\/[\d.]+/i.test(userAgent) || /ucbrowser\/[\d.]+/i.test(userAgent))
|
|
1458
|
+
return false;
|
|
1459
|
+
return !/qzone\/.*_qz_[\d.]+/i.test(userAgent);
|
|
1460
|
+
}
|
|
1461
|
+
function canOpenScheme(assumeAllowedInApp) {
|
|
1462
|
+
if (assumeAllowedInApp === void 0) { assumeAllowedInApp = false; }
|
|
1463
|
+
var os = PlatformKit.os.name;
|
|
1464
|
+
if (os === 'android')
|
|
1465
|
+
return !isFullyBlockedInAppBrowser() && (!isPartnerAppOnly() || assumeAllowedInApp);
|
|
1466
|
+
if (os === 'ios')
|
|
1467
|
+
return !/micromessenger\/[\w.]+/i.test(PlatformKit.userAgent) && (!isPartnerAppOnly() || assumeAllowedInApp);
|
|
1468
|
+
return true;
|
|
1469
|
+
}
|
|
1470
|
+
function isFullyBlockedInAppBrowser() {
|
|
1471
|
+
if (PlatformKit.os.name !== 'android')
|
|
1472
|
+
return false;
|
|
1473
|
+
var userAgent = PlatformKit.userAgent;
|
|
1474
|
+
return /micromessenger\/[\w.]+/i.test(userAgent) || / qq\/[\d.]+/i.test(userAgent) || /qzone\/.*_qz_[\d.]+/i.test(userAgent) || /baiduboxapp\/[\d.]+/i.test(userAgent);
|
|
1438
1475
|
}
|
|
1439
|
-
function
|
|
1440
|
-
return
|
|
1476
|
+
function isPartnerAppOnly() {
|
|
1477
|
+
return /weibo.*weibo__[\d.]+/i.test(PlatformKit.userAgent);
|
|
1441
1478
|
}
|
|
1442
1479
|
function canOpenSetting() {
|
|
1443
1480
|
var os = PlatformKit.os.name;
|
|
@@ -1544,6 +1581,18 @@ function escapeURIComponentMailAddressString(value) {
|
|
|
1544
1581
|
function encodeMailBody(value) {
|
|
1545
1582
|
return escapeURIComponentString(value.replace(/\r\n|\n|\r/g, '\r\n'));
|
|
1546
1583
|
}
|
|
1584
|
+
function encodeMapValue(value) {
|
|
1585
|
+
if (isArray(value))
|
|
1586
|
+
return value[0] + ',' + value[1];
|
|
1587
|
+
return escapeURIComponentString(value);
|
|
1588
|
+
}
|
|
1589
|
+
function encodeBingRoutePoint(value) {
|
|
1590
|
+
if (typeof value === 'undefined')
|
|
1591
|
+
return '';
|
|
1592
|
+
if (isArray(value))
|
|
1593
|
+
return 'pos.' + value[0] + '_' + value[1];
|
|
1594
|
+
return escapeURIComponentString(value);
|
|
1595
|
+
}
|
|
1547
1596
|
function toArray(value) {
|
|
1548
1597
|
return typeof value === 'undefined' ? [] : typeof value === 'string' ? [value] : value;
|
|
1549
1598
|
}
|
|
@@ -1790,12 +1839,12 @@ var LaunchKit = {
|
|
|
1790
1839
|
catch (error) {
|
|
1791
1840
|
return Promise.reject(error);
|
|
1792
1841
|
}
|
|
1793
|
-
var tried = [];
|
|
1794
1842
|
var urls = resolved[0];
|
|
1795
1843
|
var timeout = resolved[1];
|
|
1796
1844
|
if (urls.length === 0)
|
|
1797
1845
|
return Promise.reject(new Error('No openable URL candidates were resolved for the current OS ("' + PlatformKit.os.name + '"). Provide at least one of: scheme, intent, universal, fallback, or store id for this platform.'));
|
|
1798
1846
|
return new Promise(function (resolve, reject) {
|
|
1847
|
+
var tried = [];
|
|
1799
1848
|
function openURLSequential(index) {
|
|
1800
1849
|
if (index === void 0) { index = 0; }
|
|
1801
1850
|
if (index >= urls.length)
|
|
@@ -1867,6 +1916,112 @@ var LaunchKit = {
|
|
|
1867
1916
|
url += '?' + joining(params, undefined, '&');
|
|
1868
1917
|
return openURL(0, url, getDefaultTimeout());
|
|
1869
1918
|
},
|
|
1919
|
+
map: function (options) {
|
|
1920
|
+
if (options === void 0) { options = {}; }
|
|
1921
|
+
var params = [];
|
|
1922
|
+
var urls = [];
|
|
1923
|
+
var url = '';
|
|
1924
|
+
switch (PlatformKit.os.name) {
|
|
1925
|
+
case 'android':
|
|
1926
|
+
if (typeof options.coordinate !== 'undefined') {
|
|
1927
|
+
url = 'geo:' + options.coordinate[0] + ',' + options.coordinate[1];
|
|
1928
|
+
}
|
|
1929
|
+
else if (typeof options.query !== 'undefined') {
|
|
1930
|
+
url = 'geo:0,0';
|
|
1931
|
+
params.push('q=' + escapeURIComponentString(options.query));
|
|
1932
|
+
}
|
|
1933
|
+
else {
|
|
1934
|
+
url = 'geo:0,0';
|
|
1935
|
+
}
|
|
1936
|
+
if (typeof options.zoom !== 'undefined')
|
|
1937
|
+
params.push('z=' + options.zoom);
|
|
1938
|
+
if (params.length > 0)
|
|
1939
|
+
url = url + '?' + joining(params, undefined, '&');
|
|
1940
|
+
urls.push(url);
|
|
1941
|
+
break;
|
|
1942
|
+
case 'ios':
|
|
1943
|
+
case 'macos':
|
|
1944
|
+
if (typeof options.directions !== 'undefined') {
|
|
1945
|
+
if (typeof options.directions.destination !== 'undefined')
|
|
1946
|
+
params.push('daddr=' + encodeMapValue(options.directions.destination));
|
|
1947
|
+
if (typeof options.directions.origin !== 'undefined')
|
|
1948
|
+
params.push('saddr=' + encodeMapValue(options.directions.origin));
|
|
1949
|
+
}
|
|
1950
|
+
else if (typeof options.coordinate !== 'undefined') {
|
|
1951
|
+
params.push('ll=' + options.coordinate[0] + ',' + options.coordinate[1]);
|
|
1952
|
+
if (typeof options.label !== 'undefined')
|
|
1953
|
+
params.push('q=' + escapeURIComponentString(options.label));
|
|
1954
|
+
}
|
|
1955
|
+
else if (typeof options.query !== 'undefined') {
|
|
1956
|
+
params.push('q=' + escapeURIComponentString(options.query));
|
|
1957
|
+
}
|
|
1958
|
+
if (typeof options.zoom !== 'undefined')
|
|
1959
|
+
params.push('z=' + options.zoom);
|
|
1960
|
+
urls.push('maps://?' + joining(params, undefined, '&'));
|
|
1961
|
+
break;
|
|
1962
|
+
case 'windows':
|
|
1963
|
+
if (typeof options.directions !== 'undefined') {
|
|
1964
|
+
params.push('rtp=' + encodeBingRoutePoint(options.directions.origin) + '~' + encodeBingRoutePoint(options.directions.destination));
|
|
1965
|
+
}
|
|
1966
|
+
else if (typeof options.coordinate !== 'undefined') {
|
|
1967
|
+
params.push('cp=' + options.coordinate[0] + '~' + options.coordinate[1]);
|
|
1968
|
+
if (typeof options.label !== 'undefined')
|
|
1969
|
+
params.push('q=' + escapeURIComponentString(options.label));
|
|
1970
|
+
}
|
|
1971
|
+
else if (typeof options.query !== 'undefined') {
|
|
1972
|
+
params.push('where=' + escapeURIComponentString(options.query));
|
|
1973
|
+
}
|
|
1974
|
+
if (typeof options.zoom !== 'undefined')
|
|
1975
|
+
params.push('lvl=' + options.zoom);
|
|
1976
|
+
urls.push('bingmaps:?' + joining(params, undefined, '&'));
|
|
1977
|
+
}
|
|
1978
|
+
if (typeof options.fallback !== 'undefined') {
|
|
1979
|
+
urls.push(stripURL(options.fallback));
|
|
1980
|
+
}
|
|
1981
|
+
else {
|
|
1982
|
+
var params_1 = ['api=1'];
|
|
1983
|
+
if (typeof options.directions !== 'undefined') {
|
|
1984
|
+
params_1.push('destination=' + encodeMapValue(options.directions.destination));
|
|
1985
|
+
if (typeof options.directions.origin !== 'undefined')
|
|
1986
|
+
params_1.push('origin=' + encodeMapValue(options.directions.origin));
|
|
1987
|
+
urls.push('https://www.google.com/maps/dir/?' + joining(params_1, undefined, '&'));
|
|
1988
|
+
}
|
|
1989
|
+
else {
|
|
1990
|
+
if (typeof options.coordinate !== 'undefined')
|
|
1991
|
+
params_1.push('query=' + options.coordinate[0] + ',' + options.coordinate[1]);
|
|
1992
|
+
else if (typeof options.query !== 'undefined')
|
|
1993
|
+
params_1.push('query=' + escapeURIComponentString(options.query));
|
|
1994
|
+
if (typeof options.zoom !== 'undefined')
|
|
1995
|
+
params_1.push('zoom=' + options.zoom);
|
|
1996
|
+
urls.push('https://www.google.com/maps/search/?' + joining(params_1, undefined, '&'));
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
return new Promise(function (resolve, reject) {
|
|
2000
|
+
var tried = [];
|
|
2001
|
+
function openURLSequential(index) {
|
|
2002
|
+
if (index === void 0) { index = 0; }
|
|
2003
|
+
if (index >= urls.length)
|
|
2004
|
+
return reject(new Error('Failed to open a map using all available URLs.\n\nAttempted URLs:\n' + joining(tried, undefined, '\n↓\n')));
|
|
2005
|
+
var url = urls[index];
|
|
2006
|
+
if (typeof url === 'string') {
|
|
2007
|
+
tried[index] = url;
|
|
2008
|
+
return openURL(index, url, getDefaultTimeout())
|
|
2009
|
+
.then(function () {
|
|
2010
|
+
resolve();
|
|
2011
|
+
})
|
|
2012
|
+
.catch(function () {
|
|
2013
|
+
openURLSequential(index + 1);
|
|
2014
|
+
});
|
|
2015
|
+
}
|
|
2016
|
+
else {
|
|
2017
|
+
tried[index] = '[function fallback]';
|
|
2018
|
+
url();
|
|
2019
|
+
resolve();
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
return openURLSequential();
|
|
2023
|
+
});
|
|
2024
|
+
},
|
|
1870
2025
|
filepicker: function (options) {
|
|
1871
2026
|
if (options === void 0) { options = {}; }
|
|
1872
2027
|
var module;
|
|
@@ -1969,7 +2124,7 @@ var LaunchKit = {
|
|
|
1969
2124
|
if (index === void 0) { index = 0; }
|
|
1970
2125
|
if (index >= urls.length)
|
|
1971
2126
|
return reject(new Error('Failed to open the "' + type + '" settings pane using all available URLs.\n\nAttempted URLs:\n' + joining(urls, undefined, '\n↓\n')));
|
|
1972
|
-
return openURL(index, urls[index],
|
|
2127
|
+
return openURL(index, urls[index], DEFAULT_TIMEOUT)
|
|
1973
2128
|
.then(function () {
|
|
1974
2129
|
resolve();
|
|
1975
2130
|
})
|