├── .babelrc ├── .eslintrc ├── .gitignore ├── LICENSE ├── README.md ├── bundle.js ├── docs ├── bundle.js └── index.html ├── package.json ├── rollup.config.js └── src ├── Context.js ├── UserAgent.js ├── index.js ├── launcher ├── Android.js ├── Base.js ├── BrowserBackgroundObserver.js ├── IOS.js ├── PC.js └── index.js └── util.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ "es2015-rollup", "stage-2" ] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "airbnb", 4 | "rules": { 5 | "no-underscore-dangle": 0, 6 | "no-unused-expressions": 0, 7 | "no-inner-declarations": 0, 8 | "no-use-before-define": 0, 9 | "no-undef": 0, 10 | "no-param-reassign": 0 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | tmp 5 | .vscode/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 kwst 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fallback-custom-scheme 2 | 3 | Launcher application (iOS, Android, Windows, Mac) from web page. 4 | Use custom url scheme to launch app. 5 | If not installed the application, fallback (ex. app store, google play store etc). 6 | 7 | | app | handling | 8 | | --- | --- | 9 | | installed | open application | 10 | | not installed | fallback (ex. your store url) | 11 | 12 | ### Demo 13 | [demo page](https://satoshikawabata.github.io/fallback-custom-scheme/) 14 | 15 | ## Install 16 | ### npm 17 | ```shell 18 | npm i fallback-custom-scheme 19 | ``` 20 | 21 | ### download from url 22 | ``` 23 | https://satoshikawabata.github.io/fallback-custom-scheme/bundle.js 24 | ``` 25 | 26 | ## Usage 27 | 28 | ```js 29 | var FallbackCustomScheme = requie('fallback-custom-scheme'); 30 | var fcs = new window.FallbackCustomScheme({ 31 | urlScheme: 'hoge://temp', // your application custom scheme 32 | fallback: 'itunes://hoge', // if not installed the applicaiton, handling (ex. app store, google play store etc) 33 | onFallback: function(){}, // fallback handler 34 | browserback: 'back', // handling on return browser 35 | onBrowserback: function(){}, // browser back handler 36 | query: { // query 37 | a: aaa, 38 | b: bbb 39 | } 40 | }); 41 | ``` 42 | -------------------------------------------------------------------------------- /bundle.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 3 | typeof define === 'function' && define.amd ? define(factory) : 4 | (global.FallbackCustomScheme = factory()); 5 | }(this, (function () { 'use strict'; 6 | 7 | var classCallCheck = function (instance, Constructor) { 8 | if (!(instance instanceof Constructor)) { 9 | throw new TypeError("Cannot call a class as a function"); 10 | } 11 | }; 12 | 13 | var createClass = function () { 14 | function defineProperties(target, props) { 15 | for (var i = 0; i < props.length; i++) { 16 | var descriptor = props[i]; 17 | descriptor.enumerable = descriptor.enumerable || false; 18 | descriptor.configurable = true; 19 | if ("value" in descriptor) descriptor.writable = true; 20 | Object.defineProperty(target, descriptor.key, descriptor); 21 | } 22 | } 23 | 24 | return function (Constructor, protoProps, staticProps) { 25 | if (protoProps) defineProperties(Constructor.prototype, protoProps); 26 | if (staticProps) defineProperties(Constructor, staticProps); 27 | return Constructor; 28 | }; 29 | }(); 30 | 31 | var inherits = function (subClass, superClass) { 32 | if (typeof superClass !== "function" && superClass !== null) { 33 | throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); 34 | } 35 | 36 | subClass.prototype = Object.create(superClass && superClass.prototype, { 37 | constructor: { 38 | value: subClass, 39 | enumerable: false, 40 | writable: true, 41 | configurable: true 42 | } 43 | }); 44 | if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; 45 | }; 46 | 47 | var possibleConstructorReturn = function (self, call) { 48 | if (!self) { 49 | throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 50 | } 51 | 52 | return call && (typeof call === "object" || typeof call === "function") ? call : self; 53 | }; 54 | 55 | var RE_IS_IPHONE = /(iPhone\sOS)\s([\d_]+)/; 56 | var RE_IS_IPAD = /(iPad).*OS\s([\d_]+)/; 57 | var RE_IS_IPOD_TOUCH = /(iPod touch).*OS\s([\d_]+)/; 58 | var RE_IS_ANDROID = /(Android)\s+([\d.]+)/; 59 | var RE_IS_WIN = /Windows/; 60 | var RE_IS_MAC = /Mac OS/; 61 | 62 | var UserAgent = function UserAgent() { 63 | classCallCheck(this, UserAgent); 64 | this.isIOS = null; 65 | this.isAndroid = null; 66 | this.isWin = null; 67 | this.isMac = null; 68 | this.isPC = null; 69 | this.osVer = null; 70 | 71 | var ua = navigator.userAgent; 72 | this.isIOS = !!ua.match(RE_IS_IPHONE) || ua.match(RE_IS_IPAD) || ua.match(RE_IS_IPOD_TOUCH); 73 | this.isAndroid = !!ua.match(RE_IS_ANDROID); 74 | this.isWin = !!ua.match(RE_IS_WIN); 75 | this.isMac = !!ua.match(RE_IS_MAC); 76 | this.isPC = !!(this.isWin || this.isMac); 77 | if (this.isIOS || this.isAndroid) { 78 | var ver = ua.match(/(OS|Android) ([0-9_\.]+){1,3}/); 79 | ver = ver && ver[2].replace(/_/g, '.'); 80 | this.osVer = ver && Number(ver[0]); 81 | } else { 82 | this.osVer = null; 83 | } 84 | }; 85 | 86 | function createCommonjsModule(fn, module) { 87 | return module = { exports: {} }, fn(module, module.exports), module.exports; 88 | } 89 | 90 | var __moduleExports = createCommonjsModule(function (module) { 91 | 'use strict'; 92 | 93 | module.exports = function (str) { 94 | return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { 95 | return '%' + c.charCodeAt(0).toString(16).toUpperCase(); 96 | }); 97 | }; 98 | }); 99 | 100 | var __moduleExports$1 = createCommonjsModule(function (module) { 101 | 'use strict'; 102 | /* eslint-disable no-unused-vars */ 103 | 104 | var hasOwnProperty = Object.prototype.hasOwnProperty; 105 | var propIsEnumerable = Object.prototype.propertyIsEnumerable; 106 | 107 | function toObject(val) { 108 | if (val === null || val === undefined) { 109 | throw new TypeError('Object.assign cannot be called with null or undefined'); 110 | } 111 | 112 | return Object(val); 113 | } 114 | 115 | function shouldUseNative() { 116 | try { 117 | if (!Object.assign) { 118 | return false; 119 | } 120 | 121 | // Detect buggy property enumeration order in older V8 versions. 122 | 123 | // https://bugs.chromium.org/p/v8/issues/detail?id=4118 124 | var test1 = new String('abc'); // eslint-disable-line 125 | test1[5] = 'de'; 126 | if (Object.getOwnPropertyNames(test1)[0] === '5') { 127 | return false; 128 | } 129 | 130 | // https://bugs.chromium.org/p/v8/issues/detail?id=3056 131 | var test2 = {}; 132 | for (var i = 0; i < 10; i++) { 133 | test2['_' + String.fromCharCode(i)] = i; 134 | } 135 | var order2 = Object.getOwnPropertyNames(test2).map(function (n) { 136 | return test2[n]; 137 | }); 138 | if (order2.join('') !== '0123456789') { 139 | return false; 140 | } 141 | 142 | // https://bugs.chromium.org/p/v8/issues/detail?id=3056 143 | var test3 = {}; 144 | 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { 145 | test3[letter] = letter; 146 | }); 147 | if (Object.keys(Object.assign({}, test3)).join('') !== 'abcdefghijklmnopqrst') { 148 | return false; 149 | } 150 | 151 | return true; 152 | } catch (e) { 153 | // We don't expect any of the above to throw, but better to be safe. 154 | return false; 155 | } 156 | } 157 | 158 | module.exports = shouldUseNative() ? Object.assign : function (target, source) { 159 | var from; 160 | var to = toObject(target); 161 | var symbols; 162 | 163 | for (var s = 1; s < arguments.length; s++) { 164 | from = Object(arguments[s]); 165 | 166 | for (var key in from) { 167 | if (hasOwnProperty.call(from, key)) { 168 | to[key] = from[key]; 169 | } 170 | } 171 | 172 | if (Object.getOwnPropertySymbols) { 173 | symbols = Object.getOwnPropertySymbols(from); 174 | for (var i = 0; i < symbols.length; i++) { 175 | if (propIsEnumerable.call(from, symbols[i])) { 176 | to[symbols[i]] = from[symbols[i]]; 177 | } 178 | } 179 | } 180 | } 181 | 182 | return to; 183 | }; 184 | }); 185 | 186 | var index = createCommonjsModule(function (module, exports) { 187 | 'use strict'; 188 | 189 | var strictUriEncode = __moduleExports; 190 | var objectAssign = __moduleExports$1; 191 | 192 | function encode(value, opts) { 193 | if (opts.encode) { 194 | return opts.strict ? strictUriEncode(value) : encodeURIComponent(value); 195 | } 196 | 197 | return value; 198 | } 199 | 200 | exports.extract = function (str) { 201 | return str.split('?')[1] || ''; 202 | }; 203 | 204 | exports.parse = function (str) { 205 | // Create an object with no prototype 206 | // https://github.com/sindresorhus/query-string/issues/47 207 | var ret = Object.create(null); 208 | 209 | if (typeof str !== 'string') { 210 | return ret; 211 | } 212 | 213 | str = str.trim().replace(/^(\?|#|&)/, ''); 214 | 215 | if (!str) { 216 | return ret; 217 | } 218 | 219 | str.split('&').forEach(function (param) { 220 | var parts = param.replace(/\+/g, ' ').split('='); 221 | // Firefox (pre 40) decodes `%3D` to `=` 222 | // https://github.com/sindresorhus/query-string/pull/37 223 | var key = parts.shift(); 224 | var val = parts.length > 0 ? parts.join('=') : undefined; 225 | 226 | key = decodeURIComponent(key); 227 | 228 | // missing `=` should be `null`: 229 | // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters 230 | val = val === undefined ? null : decodeURIComponent(val); 231 | 232 | if (ret[key] === undefined) { 233 | ret[key] = val; 234 | } else if (Array.isArray(ret[key])) { 235 | ret[key].push(val); 236 | } else { 237 | ret[key] = [ret[key], val]; 238 | } 239 | }); 240 | 241 | return ret; 242 | }; 243 | 244 | exports.stringify = function (obj, opts) { 245 | var defaults = { 246 | encode: true, 247 | strict: true 248 | }; 249 | 250 | opts = objectAssign(defaults, opts); 251 | 252 | return obj ? Object.keys(obj).sort().map(function (key) { 253 | var val = obj[key]; 254 | 255 | if (val === undefined) { 256 | return ''; 257 | } 258 | 259 | if (val === null) { 260 | return encode(key, opts); 261 | } 262 | 263 | if (Array.isArray(val)) { 264 | var result = []; 265 | 266 | val.slice().forEach(function (val2) { 267 | if (val2 === undefined) { 268 | return; 269 | } 270 | 271 | if (val2 === null) { 272 | result.push(encode(key, opts)); 273 | } else { 274 | result.push(encode(key, opts) + '=' + encode(val2, opts)); 275 | } 276 | }); 277 | 278 | return result.join('&'); 279 | } 280 | 281 | return encode(key, opts) + '=' + encode(val, opts); 282 | }).filter(function (x) { 283 | return x.length > 0; 284 | }).join('&') : ''; 285 | }; 286 | }); 287 | 288 | var Context = function () { 289 | function Context(context) { 290 | classCallCheck(this, Context); 291 | this._urlScheme = null; 292 | this.query = null; 293 | this.fallback = null; 294 | this.onFallback = null; 295 | this.browserback = null; 296 | this.onBrowserback = null; 297 | 298 | context && this.extend(context); 299 | } 300 | 301 | createClass(Context, [{ 302 | key: 'extend', 303 | value: function extend(target) { 304 | target.urlScheme && (this._urlScheme = target.urlScheme); 305 | target.query && (this.query = target.query); 306 | target.fallback && (this.fallback = target.fallback); 307 | target.onFallback && (this.onFallback = target.onFallback); 308 | target.browserback && (this.browserback = target.browserback); 309 | target.onBrowserback && (this.onBrowserback = target.onBrowserback); 310 | } 311 | }, { 312 | key: 'handleFallback', 313 | value: function handleFallback() { 314 | var fallback = this.fallback; 315 | 316 | if (fallback) { 317 | location.href = fallback; 318 | } 319 | this.onFallback && this.onFallback(); 320 | } 321 | }, { 322 | key: 'handleBrowserBack', 323 | value: function handleBrowserBack() { 324 | var browserback = this.browserback; 325 | 326 | if (browserback === 'back') { 327 | history.back(); 328 | } 329 | this.onBrowserback && this.onBrowserback(); 330 | } 331 | }, { 332 | key: 'urlScheme', 333 | get: function get() { 334 | var query = this.query; 335 | var _urlScheme = this._urlScheme; 336 | 337 | var fullPath = _urlScheme; 338 | if (query) { 339 | var queryStr = index.stringify(query); 340 | var parsed = new URL(fullPath); 341 | parsed.search += (parsed.search ? '&' : '?') + queryStr; 342 | fullPath = parsed.href; 343 | } 344 | 345 | return fullPath; 346 | } 347 | }]); 348 | return Context; 349 | }(); 350 | 351 | var _window = window; 352 | var document$1 = _window.document; 353 | var location$1 = _window.location; 354 | 355 | 356 | var openURLByIFrame = function openURLByIFrame(url) { 357 | var iframe = document$1.createElement('iframe'); 358 | iframe.src = url; 359 | iframe.setAttribute('height', 0); 360 | iframe.setAttribute('width', 0); 361 | iframe.style.display = 'none'; 362 | document$1.body.appendChild(iframe); 363 | return iframe; 364 | }; 365 | 366 | var openURLByHref = function openURLByHref(url, isReplace) { 367 | if (isReplace) { 368 | location$1.replace(url); 369 | } else { 370 | location$1.href = url; 371 | } 372 | }; 373 | 374 | var parseQuery = function parseQuery(str) { 375 | var queries = {}; 376 | var queryStr = str.replace(/^(\?|#|&)/, ''); 377 | var elements = queryStr.split('&'); 378 | for (var i = 0; i < elements.length; i++) { 379 | var param = elements[i]; 380 | var parts = param.replace(/\+/g, ' ').split('='); 381 | var key = parts.shift(); 382 | var val = parts.length > 0 ? parts.join('=') : undefined; 383 | key = decodeURIComponent(key); 384 | val = val === undefined ? null : decodeURIComponent(val); 385 | 386 | if (queries[key] === undefined) { 387 | queries[key] = val; 388 | } else if (Array.isArray(queries[key])) { 389 | queries[key].push(val); 390 | } else { 391 | queries[key] = [queries[key], val]; 392 | } 393 | } 394 | 395 | return queries; 396 | }; 397 | 398 | var util$1 = { 399 | openURLByIFrame: openURLByIFrame, 400 | openURLByHref: openURLByHref, 401 | parseQuery: parseQuery 402 | }; 403 | 404 | var BrowserBackgroundObserver = function () { 405 | function BrowserBackgroundObserver(onReturn, onLeave, useRequestAnimationFrame) { 406 | var _this = this; 407 | 408 | classCallCheck(this, BrowserBackgroundObserver); 409 | this.isReturnBrowser = false; 410 | this.isLeaveBrowser = false; 411 | 412 | this.onReturn = onReturn; 413 | this.onLeave = onLeave; 414 | this.useRequestAnimationFrame = useRequestAnimationFrame; 415 | 416 | this._onLeave = this._onLeave.bind(this); 417 | this._onBlur = this._onBlur.bind(this); 418 | this._onFocus = this._onFocus.bind(this); 419 | this._onVisibilityChange = this._onVisibilityChange.bind(this); 420 | this._onWebkitVisibilityChange = this._onWebkitVisibilityChange.bind(this); 421 | 422 | window.focus(); 423 | window.addEventListener('blur', this._onBlur); 424 | if (document.hidden !== undefined) { 425 | document.addEventListener('visibilitychange', this._onVisibilityChange); 426 | } else if (document.webkitHidden !== undefined) { 427 | document.addEventListener('webkitvisibilitychange', this._onWebkitVisibilityChange); 428 | } 429 | 430 | if (useRequestAnimationFrame) { 431 | (function () { 432 | var observe = function observe() { 433 | _this.rafId = window.requestAnimationFrame(observe); 434 | if (_this.rafTimer !== false) { 435 | clearTimeout(_this.rafTimer); 436 | } 437 | 438 | _this.rafTimer = setTimeout(function () { 439 | if (!isReturnBrowser) { 440 | _onReturn(); 441 | } 442 | 443 | window.cancelAnimationFrame(_this.rafId); 444 | }, 1000); 445 | }; 446 | 447 | observe(); 448 | })(); 449 | } 450 | } 451 | 452 | createClass(BrowserBackgroundObserver, [{ 453 | key: '_onReturn', 454 | value: function _onReturn() { 455 | var rafTimer = this.rafTimer; 456 | var rafId = this.rafId; 457 | 458 | this.isReturnBrowser = true; 459 | document.removeEventListener('visibilitychange', this._onVisibilityChange); 460 | document.removeEventListener('webkitvisibilitychange', this._onWebkitVisibilityChange); 461 | window.removeEventListener('focus', this._onFocus); 462 | clearTimeout(rafTimer); 463 | window.cancelAnimationFrame && window.cancelAnimationFrame(rafId); 464 | 465 | this.onReturn && this.onReturn(); 466 | } 467 | }, { 468 | key: '_onLeave', 469 | value: function _onLeave() { 470 | this.isLeaveBrowser = true; 471 | this.onLeave && this.onLeave(); 472 | } 473 | }, { 474 | key: '_onBlur', 475 | value: function _onBlur() { 476 | var isLeaveBrowser = this.isLeaveBrowser; 477 | 478 | window.removeEventListener('blur', this._onBlur); 479 | window.addEventListener('focus', this._onFocus); 480 | if (!isLeaveBrowser) { 481 | this._onLeave(); 482 | } 483 | } 484 | }, { 485 | key: '_onFocus', 486 | value: function _onFocus() { 487 | var isReturnBrowser = this.isReturnBrowser; 488 | 489 | if (!isReturnBrowser) { 490 | this._onReturn(); 491 | } 492 | } 493 | }, { 494 | key: '_onVisibilityChange', 495 | value: function _onVisibilityChange() { 496 | var isLeaveBrowser = this.isLeaveBrowser; 497 | var isReturnBrowser = this.isReturnBrowser; 498 | 499 | if (!isLeaveBrowser && document.hidden) { 500 | this._onLeave(); 501 | } else if (!isReturnBrowser && !document.hidden) { 502 | this._onReturn(); 503 | } 504 | } 505 | }, { 506 | key: '_onWebkitVisibilityChange', 507 | value: function _onWebkitVisibilityChange() { 508 | var isLeaveBrowser = this.isLeaveBrowser; 509 | var isReturnBrowser = this.isReturnBrowser; 510 | 511 | if (!isLeaveBrowser && document.webkitHidden) { 512 | this._onLeave(); 513 | } else if (!isReturnBrowser && !document.webkitHidden) { 514 | this._onReturn(); 515 | } 516 | } 517 | }]); 518 | return BrowserBackgroundObserver; 519 | }(); 520 | 521 | var BaseLauncher = function () { 522 | function BaseLauncher(context) { 523 | classCallCheck(this, BaseLauncher); 524 | this._context = null; 525 | this._fallbackTime = 500; 526 | 527 | this._context = context; 528 | 529 | this._handleTimeout = this._handleTimeout.bind(this); 530 | this._handleLeaveBrowser = this._handleLeaveBrowser.bind(this); 531 | this._handleBrowserBack = this._handleBrowserBack.bind(this); 532 | } 533 | 534 | createClass(BaseLauncher, [{ 535 | key: 'launch', 536 | value: function launch() { 537 | util$1.openURLByIFrame(this._context.urlScheme); 538 | this._timerId = setTimeout(this._handleTimeout, this._fallbackTime); 539 | this._observer = new BrowserBackgroundObserver(this._handleBrowserBack, this._handleLeaveBrowser, true); 540 | } 541 | }, { 542 | key: '_handleTimeout', 543 | value: function _handleTimeout() { 544 | this._context.handleFallback(); 545 | } 546 | }, { 547 | key: '_handleLeaveBrowser', 548 | value: function _handleLeaveBrowser() { 549 | var _timerId = this._timerId; 550 | 551 | clearTimeout(_timerId); 552 | } 553 | }, { 554 | key: '_handleBrowserBack', 555 | value: function _handleBrowserBack() { 556 | this._context.handleBrowserBack(); 557 | } 558 | }]); 559 | return BaseLauncher; 560 | }(); 561 | 562 | var IOS = function (_BaseLauncher) { 563 | inherits(IOS, _BaseLauncher); 564 | 565 | function IOS() { 566 | classCallCheck(this, IOS); 567 | return possibleConstructorReturn(this, (IOS.__proto__ || Object.getPrototypeOf(IOS)).apply(this, arguments)); 568 | } 569 | 570 | createClass(IOS, [{ 571 | key: 'launch', 572 | value: function launch() { 573 | var _context = this._context; 574 | 575 | if (_context.osVer > 8) { 576 | util$1.openURLByHref(_context.urlScheme); 577 | } else { 578 | util$1.openURLByIFrame(_context.urlScheme); 579 | } 580 | 581 | this._timerId = setTimeout(this._handleTimeout, this._fallbackTime); 582 | this._observer = new BrowserBackgroundObserver(this._handleBrowserBack, this._handleLeaveBrowser, true); 583 | } 584 | }]); 585 | return IOS; 586 | }(BaseLauncher); 587 | 588 | var Android = function (_BaseLauncher) { 589 | inherits(Android, _BaseLauncher); 590 | 591 | function Android() { 592 | classCallCheck(this, Android); 593 | return possibleConstructorReturn(this, (Android.__proto__ || Object.getPrototypeOf(Android)).apply(this, arguments)); 594 | } 595 | 596 | return Android; 597 | }(BaseLauncher); 598 | 599 | var PC = function (_BaseLauncher) { 600 | inherits(PC, _BaseLauncher); 601 | 602 | function PC(context) { 603 | classCallCheck(this, PC); 604 | 605 | var _this = possibleConstructorReturn(this, (PC.__proto__ || Object.getPrototypeOf(PC)).call(this, context)); 606 | 607 | _this._enableEventListener(window); 608 | _this._enableEventListener(document); 609 | return _this; 610 | } 611 | 612 | createClass(PC, [{ 613 | key: 'launch', 614 | value: function launch() { 615 | util$1.openURLByIFrame(this._context.urlScheme); 616 | this._timerId = setTimeout(this._handleTimeout, this._fallbackTime); 617 | this._observer = new BrowserBackgroundObserver(this._handleBrowserBack, this._handleLeaveBrowser, true); 618 | } 619 | }, { 620 | key: '_enableEventListener', 621 | value: function _enableEventListener(target) { 622 | if (!target.addEventListener) { 623 | target.addEventListener = function (type, callback) { 624 | target.attachEvent('on' + type, callback); 625 | }; 626 | } 627 | 628 | if (!target.removeEventListener) { 629 | target.removeEventListener = function (type, callback) { 630 | target.detachEvent('on' + type, callback); 631 | }; 632 | } 633 | } 634 | }]); 635 | return PC; 636 | }(BaseLauncher); 637 | 638 | var util = { 639 | IOS: IOS, 640 | Android: Android, 641 | PC: PC 642 | }; 643 | 644 | var FallbackCustomScheme = function () { 645 | function FallbackCustomScheme(options) { 646 | classCallCheck(this, FallbackCustomScheme); 647 | this._ua = new UserAgent(); 648 | 649 | this._context = new Context(options); 650 | } 651 | 652 | createClass(FallbackCustomScheme, [{ 653 | key: 'launch', 654 | value: function launch(options) { 655 | var _context = this._context; 656 | var _ua = this._ua; 657 | 658 | options && _context.extend(options); 659 | var urlScheme = _context.urlScheme; 660 | var isIOS = _ua.isIOS; 661 | var isAndroid = _ua.isAndroid; 662 | var isPC = _ua.isPC; 663 | 664 | 665 | if (!urlScheme) { 666 | throw new Error('you must set "urlScheme"'); 667 | } 668 | 669 | if (isIOS) { 670 | this._launcher = new IOS(_context); 671 | } else if (isAndroid) { 672 | this._launcher = new Android(_context); 673 | } else if (isPC) { 674 | this._launcher = new PC(_context); 675 | } 676 | if (this._launcher) { 677 | this._launcher.launch(); 678 | } 679 | } 680 | }]); 681 | return FallbackCustomScheme; 682 | }(); 683 | 684 | return FallbackCustomScheme; 685 | 686 | }))); -------------------------------------------------------------------------------- /docs/bundle.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 3 | typeof define === 'function' && define.amd ? define(factory) : 4 | (global.FallbackCustomScheme = factory()); 5 | }(this, (function () { 'use strict'; 6 | 7 | var classCallCheck = function (instance, Constructor) { 8 | if (!(instance instanceof Constructor)) { 9 | throw new TypeError("Cannot call a class as a function"); 10 | } 11 | }; 12 | 13 | var createClass = function () { 14 | function defineProperties(target, props) { 15 | for (var i = 0; i < props.length; i++) { 16 | var descriptor = props[i]; 17 | descriptor.enumerable = descriptor.enumerable || false; 18 | descriptor.configurable = true; 19 | if ("value" in descriptor) descriptor.writable = true; 20 | Object.defineProperty(target, descriptor.key, descriptor); 21 | } 22 | } 23 | 24 | return function (Constructor, protoProps, staticProps) { 25 | if (protoProps) defineProperties(Constructor.prototype, protoProps); 26 | if (staticProps) defineProperties(Constructor, staticProps); 27 | return Constructor; 28 | }; 29 | }(); 30 | 31 | var inherits = function (subClass, superClass) { 32 | if (typeof superClass !== "function" && superClass !== null) { 33 | throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); 34 | } 35 | 36 | subClass.prototype = Object.create(superClass && superClass.prototype, { 37 | constructor: { 38 | value: subClass, 39 | enumerable: false, 40 | writable: true, 41 | configurable: true 42 | } 43 | }); 44 | if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; 45 | }; 46 | 47 | var possibleConstructorReturn = function (self, call) { 48 | if (!self) { 49 | throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 50 | } 51 | 52 | return call && (typeof call === "object" || typeof call === "function") ? call : self; 53 | }; 54 | 55 | var RE_IS_IPHONE = /(iPhone\sOS)\s([\d_]+)/; 56 | var RE_IS_IPAD = /(iPad).*OS\s([\d_]+)/; 57 | var RE_IS_IPOD_TOUCH = /(iPod touch).*OS\s([\d_]+)/; 58 | var RE_IS_ANDROID = /(Android)\s+([\d.]+)/; 59 | var RE_IS_WIN = /Windows/; 60 | var RE_IS_MAC = /Mac OS/; 61 | 62 | var UserAgent = function UserAgent() { 63 | classCallCheck(this, UserAgent); 64 | this.isIOS = null; 65 | this.isAndroid = null; 66 | this.isWin = null; 67 | this.isMac = null; 68 | this.isPC = null; 69 | this.osVer = null; 70 | 71 | var ua = navigator.userAgent; 72 | this.isIOS = !!ua.match(RE_IS_IPHONE) || ua.match(RE_IS_IPAD) || ua.match(RE_IS_IPOD_TOUCH); 73 | this.isAndroid = !!ua.match(RE_IS_ANDROID); 74 | this.isWin = !!ua.match(RE_IS_WIN); 75 | this.isMac = !!ua.match(RE_IS_MAC); 76 | this.isPC = !!(this.isWin || this.isMac); 77 | if (this.isIOS || this.isAndroid) { 78 | var ver = ua.match(/(OS|Android) ([0-9_\.]+){1,3}/); 79 | ver = ver && ver[2].replace(/_/g, '.'); 80 | this.osVer = ver && Number(ver[0]); 81 | } else { 82 | this.osVer = null; 83 | } 84 | }; 85 | 86 | function createCommonjsModule(fn, module) { 87 | return module = { exports: {} }, fn(module, module.exports), module.exports; 88 | } 89 | 90 | var __moduleExports = createCommonjsModule(function (module) { 91 | 'use strict'; 92 | 93 | module.exports = function (str) { 94 | return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { 95 | return '%' + c.charCodeAt(0).toString(16).toUpperCase(); 96 | }); 97 | }; 98 | }); 99 | 100 | var __moduleExports$1 = createCommonjsModule(function (module) { 101 | 'use strict'; 102 | /* eslint-disable no-unused-vars */ 103 | 104 | var hasOwnProperty = Object.prototype.hasOwnProperty; 105 | var propIsEnumerable = Object.prototype.propertyIsEnumerable; 106 | 107 | function toObject(val) { 108 | if (val === null || val === undefined) { 109 | throw new TypeError('Object.assign cannot be called with null or undefined'); 110 | } 111 | 112 | return Object(val); 113 | } 114 | 115 | function shouldUseNative() { 116 | try { 117 | if (!Object.assign) { 118 | return false; 119 | } 120 | 121 | // Detect buggy property enumeration order in older V8 versions. 122 | 123 | // https://bugs.chromium.org/p/v8/issues/detail?id=4118 124 | var test1 = new String('abc'); // eslint-disable-line 125 | test1[5] = 'de'; 126 | if (Object.getOwnPropertyNames(test1)[0] === '5') { 127 | return false; 128 | } 129 | 130 | // https://bugs.chromium.org/p/v8/issues/detail?id=3056 131 | var test2 = {}; 132 | for (var i = 0; i < 10; i++) { 133 | test2['_' + String.fromCharCode(i)] = i; 134 | } 135 | var order2 = Object.getOwnPropertyNames(test2).map(function (n) { 136 | return test2[n]; 137 | }); 138 | if (order2.join('') !== '0123456789') { 139 | return false; 140 | } 141 | 142 | // https://bugs.chromium.org/p/v8/issues/detail?id=3056 143 | var test3 = {}; 144 | 'abcdefghijklmnopqrst'.split('').forEach(function (letter) { 145 | test3[letter] = letter; 146 | }); 147 | if (Object.keys(Object.assign({}, test3)).join('') !== 'abcdefghijklmnopqrst') { 148 | return false; 149 | } 150 | 151 | return true; 152 | } catch (e) { 153 | // We don't expect any of the above to throw, but better to be safe. 154 | return false; 155 | } 156 | } 157 | 158 | module.exports = shouldUseNative() ? Object.assign : function (target, source) { 159 | var from; 160 | var to = toObject(target); 161 | var symbols; 162 | 163 | for (var s = 1; s < arguments.length; s++) { 164 | from = Object(arguments[s]); 165 | 166 | for (var key in from) { 167 | if (hasOwnProperty.call(from, key)) { 168 | to[key] = from[key]; 169 | } 170 | } 171 | 172 | if (Object.getOwnPropertySymbols) { 173 | symbols = Object.getOwnPropertySymbols(from); 174 | for (var i = 0; i < symbols.length; i++) { 175 | if (propIsEnumerable.call(from, symbols[i])) { 176 | to[symbols[i]] = from[symbols[i]]; 177 | } 178 | } 179 | } 180 | } 181 | 182 | return to; 183 | }; 184 | }); 185 | 186 | var index = createCommonjsModule(function (module, exports) { 187 | 'use strict'; 188 | 189 | var strictUriEncode = __moduleExports; 190 | var objectAssign = __moduleExports$1; 191 | 192 | function encode(value, opts) { 193 | if (opts.encode) { 194 | return opts.strict ? strictUriEncode(value) : encodeURIComponent(value); 195 | } 196 | 197 | return value; 198 | } 199 | 200 | exports.extract = function (str) { 201 | return str.split('?')[1] || ''; 202 | }; 203 | 204 | exports.parse = function (str) { 205 | // Create an object with no prototype 206 | // https://github.com/sindresorhus/query-string/issues/47 207 | var ret = Object.create(null); 208 | 209 | if (typeof str !== 'string') { 210 | return ret; 211 | } 212 | 213 | str = str.trim().replace(/^(\?|#|&)/, ''); 214 | 215 | if (!str) { 216 | return ret; 217 | } 218 | 219 | str.split('&').forEach(function (param) { 220 | var parts = param.replace(/\+/g, ' ').split('='); 221 | // Firefox (pre 40) decodes `%3D` to `=` 222 | // https://github.com/sindresorhus/query-string/pull/37 223 | var key = parts.shift(); 224 | var val = parts.length > 0 ? parts.join('=') : undefined; 225 | 226 | key = decodeURIComponent(key); 227 | 228 | // missing `=` should be `null`: 229 | // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters 230 | val = val === undefined ? null : decodeURIComponent(val); 231 | 232 | if (ret[key] === undefined) { 233 | ret[key] = val; 234 | } else if (Array.isArray(ret[key])) { 235 | ret[key].push(val); 236 | } else { 237 | ret[key] = [ret[key], val]; 238 | } 239 | }); 240 | 241 | return ret; 242 | }; 243 | 244 | exports.stringify = function (obj, opts) { 245 | var defaults = { 246 | encode: true, 247 | strict: true 248 | }; 249 | 250 | opts = objectAssign(defaults, opts); 251 | 252 | return obj ? Object.keys(obj).sort().map(function (key) { 253 | var val = obj[key]; 254 | 255 | if (val === undefined) { 256 | return ''; 257 | } 258 | 259 | if (val === null) { 260 | return encode(key, opts); 261 | } 262 | 263 | if (Array.isArray(val)) { 264 | var result = []; 265 | 266 | val.slice().forEach(function (val2) { 267 | if (val2 === undefined) { 268 | return; 269 | } 270 | 271 | if (val2 === null) { 272 | result.push(encode(key, opts)); 273 | } else { 274 | result.push(encode(key, opts) + '=' + encode(val2, opts)); 275 | } 276 | }); 277 | 278 | return result.join('&'); 279 | } 280 | 281 | return encode(key, opts) + '=' + encode(val, opts); 282 | }).filter(function (x) { 283 | return x.length > 0; 284 | }).join('&') : ''; 285 | }; 286 | }); 287 | 288 | var Context = function () { 289 | function Context(context) { 290 | classCallCheck(this, Context); 291 | this._urlScheme = null; 292 | this.query = null; 293 | this.fallback = null; 294 | this.onFallback = null; 295 | this.browserback = null; 296 | this.onBrowserback = null; 297 | 298 | context && this.extend(context); 299 | } 300 | 301 | createClass(Context, [{ 302 | key: 'extend', 303 | value: function extend(target) { 304 | target.urlScheme && (this._urlScheme = target.urlScheme); 305 | target.query && (this.query = target.query); 306 | target.fallback && (this.fallback = target.fallback); 307 | target.onFallback && (this.onFallback = target.onFallback); 308 | target.browserback && (this.browserback = target.browserback); 309 | target.onBrowserback && (this.onBrowserback = target.onBrowserback); 310 | } 311 | }, { 312 | key: 'handleFallback', 313 | value: function handleFallback() { 314 | var fallback = this.fallback; 315 | 316 | if (fallback) { 317 | location.href = fallback; 318 | } 319 | this.onFallback && this.onFallback(); 320 | } 321 | }, { 322 | key: 'handleBrowserBack', 323 | value: function handleBrowserBack() { 324 | var browserback = this.browserback; 325 | 326 | if (browserback === 'back') { 327 | history.back(); 328 | } 329 | this.onBrowserback && this.onBrowserback(); 330 | } 331 | }, { 332 | key: 'urlScheme', 333 | get: function get() { 334 | var query = this.query; 335 | var _urlScheme = this._urlScheme; 336 | 337 | var fullPath = _urlScheme; 338 | if (query) { 339 | var queryStr = index.stringify(query); 340 | var parsed = new URL(fullPath); 341 | parsed.search += (parsed.search ? '&' : '?') + queryStr; 342 | fullPath = parsed.href; 343 | } 344 | 345 | return fullPath; 346 | } 347 | }]); 348 | return Context; 349 | }(); 350 | 351 | var _window = window; 352 | var document$1 = _window.document; 353 | var location$1 = _window.location; 354 | 355 | 356 | var openURLByIFrame = function openURLByIFrame(url) { 357 | var iframe = document$1.createElement('iframe'); 358 | iframe.src = url; 359 | iframe.setAttribute('height', 0); 360 | iframe.setAttribute('width', 0); 361 | iframe.style.display = 'none'; 362 | document$1.body.appendChild(iframe); 363 | return iframe; 364 | }; 365 | 366 | var openURLByHref = function openURLByHref(url, isReplace) { 367 | if (isReplace) { 368 | location$1.replace(url); 369 | } else { 370 | location$1.href = url; 371 | } 372 | }; 373 | 374 | var parseQuery = function parseQuery(str) { 375 | var queries = {}; 376 | var queryStr = str.replace(/^(\?|#|&)/, ''); 377 | var elements = queryStr.split('&'); 378 | for (var i = 0; i < elements.length; i++) { 379 | var param = elements[i]; 380 | var parts = param.replace(/\+/g, ' ').split('='); 381 | var key = parts.shift(); 382 | var val = parts.length > 0 ? parts.join('=') : undefined; 383 | key = decodeURIComponent(key); 384 | val = val === undefined ? null : decodeURIComponent(val); 385 | 386 | if (queries[key] === undefined) { 387 | queries[key] = val; 388 | } else if (Array.isArray(queries[key])) { 389 | queries[key].push(val); 390 | } else { 391 | queries[key] = [queries[key], val]; 392 | } 393 | } 394 | 395 | return queries; 396 | }; 397 | 398 | var util$1 = { 399 | openURLByIFrame: openURLByIFrame, 400 | openURLByHref: openURLByHref, 401 | parseQuery: parseQuery 402 | }; 403 | 404 | var BrowserBackgroundObserver = function () { 405 | function BrowserBackgroundObserver(onReturn, onLeave, useRequestAnimationFrame) { 406 | var _this = this; 407 | 408 | classCallCheck(this, BrowserBackgroundObserver); 409 | this.isReturnBrowser = false; 410 | this.isLeaveBrowser = false; 411 | 412 | this.onReturn = onReturn; 413 | this.onLeave = onLeave; 414 | this.useRequestAnimationFrame = useRequestAnimationFrame; 415 | 416 | this._onLeave = this._onLeave.bind(this); 417 | this._onBlur = this._onBlur.bind(this); 418 | this._onFocus = this._onFocus.bind(this); 419 | this._onVisibilityChange = this._onVisibilityChange.bind(this); 420 | this._onWebkitVisibilityChange = this._onWebkitVisibilityChange.bind(this); 421 | 422 | window.focus(); 423 | window.addEventListener('blur', this._onBlur); 424 | if (document.hidden !== undefined) { 425 | document.addEventListener('visibilitychange', this._onVisibilityChange); 426 | } else if (document.webkitHidden !== undefined) { 427 | document.addEventListener('webkitvisibilitychange', this._onWebkitVisibilityChange); 428 | } 429 | 430 | if (useRequestAnimationFrame) { 431 | (function () { 432 | var observe = function observe() { 433 | _this.rafId = window.requestAnimationFrame(observe); 434 | if (_this.rafTimer !== false) { 435 | clearTimeout(_this.rafTimer); 436 | } 437 | 438 | _this.rafTimer = setTimeout(function () { 439 | if (!isReturnBrowser) { 440 | _onReturn(); 441 | } 442 | 443 | window.cancelAnimationFrame(_this.rafId); 444 | }, 1000); 445 | }; 446 | 447 | observe(); 448 | })(); 449 | } 450 | } 451 | 452 | createClass(BrowserBackgroundObserver, [{ 453 | key: '_onReturn', 454 | value: function _onReturn() { 455 | var rafTimer = this.rafTimer; 456 | var rafId = this.rafId; 457 | 458 | this.isReturnBrowser = true; 459 | document.removeEventListener('visibilitychange', this._onVisibilityChange); 460 | document.removeEventListener('webkitvisibilitychange', this._onWebkitVisibilityChange); 461 | window.removeEventListener('focus', this._onFocus); 462 | clearTimeout(rafTimer); 463 | window.cancelAnimationFrame && window.cancelAnimationFrame(rafId); 464 | 465 | this.onReturn && this.onReturn(); 466 | } 467 | }, { 468 | key: '_onLeave', 469 | value: function _onLeave() { 470 | this.isLeaveBrowser = true; 471 | this.onLeave && this.onLeave(); 472 | } 473 | }, { 474 | key: '_onBlur', 475 | value: function _onBlur() { 476 | var isLeaveBrowser = this.isLeaveBrowser; 477 | 478 | window.removeEventListener('blur', this._onBlur); 479 | window.addEventListener('focus', this._onFocus); 480 | if (!isLeaveBrowser) { 481 | this._onLeave(); 482 | } 483 | } 484 | }, { 485 | key: '_onFocus', 486 | value: function _onFocus() { 487 | var isReturnBrowser = this.isReturnBrowser; 488 | 489 | if (!isReturnBrowser) { 490 | this._onReturn(); 491 | } 492 | } 493 | }, { 494 | key: '_onVisibilityChange', 495 | value: function _onVisibilityChange() { 496 | var isLeaveBrowser = this.isLeaveBrowser; 497 | var isReturnBrowser = this.isReturnBrowser; 498 | 499 | if (!isLeaveBrowser && document.hidden) { 500 | this._onLeave(); 501 | } else if (!isReturnBrowser && !document.hidden) { 502 | this._onReturn(); 503 | } 504 | } 505 | }, { 506 | key: '_onWebkitVisibilityChange', 507 | value: function _onWebkitVisibilityChange() { 508 | var isLeaveBrowser = this.isLeaveBrowser; 509 | var isReturnBrowser = this.isReturnBrowser; 510 | 511 | if (!isLeaveBrowser && document.webkitHidden) { 512 | this._onLeave(); 513 | } else if (!isReturnBrowser && !document.webkitHidden) { 514 | this._onReturn(); 515 | } 516 | } 517 | }]); 518 | return BrowserBackgroundObserver; 519 | }(); 520 | 521 | var BaseLauncher = function () { 522 | function BaseLauncher(context) { 523 | classCallCheck(this, BaseLauncher); 524 | this._context = null; 525 | this._fallbackTime = 500; 526 | 527 | this._context = context; 528 | 529 | this._handleTimeout = this._handleTimeout.bind(this); 530 | this._handleLeaveBrowser = this._handleLeaveBrowser.bind(this); 531 | this._handleBrowserBack = this._handleBrowserBack.bind(this); 532 | } 533 | 534 | createClass(BaseLauncher, [{ 535 | key: 'launch', 536 | value: function launch() { 537 | util$1.openURLByIFrame(this._context.urlScheme); 538 | this._timerId = setTimeout(this._handleTimeout, this._fallbackTime); 539 | this._observer = new BrowserBackgroundObserver(this._handleBrowserBack, this._handleLeaveBrowser, true); 540 | } 541 | }, { 542 | key: '_handleTimeout', 543 | value: function _handleTimeout() { 544 | this._context.handleFallback(); 545 | } 546 | }, { 547 | key: '_handleLeaveBrowser', 548 | value: function _handleLeaveBrowser() { 549 | var _timerId = this._timerId; 550 | 551 | clearTimeout(_timerId); 552 | } 553 | }, { 554 | key: '_handleBrowserBack', 555 | value: function _handleBrowserBack() { 556 | this._context.handleBrowserBack(); 557 | } 558 | }]); 559 | return BaseLauncher; 560 | }(); 561 | 562 | var IOS = function (_BaseLauncher) { 563 | inherits(IOS, _BaseLauncher); 564 | 565 | function IOS() { 566 | classCallCheck(this, IOS); 567 | return possibleConstructorReturn(this, (IOS.__proto__ || Object.getPrototypeOf(IOS)).apply(this, arguments)); 568 | } 569 | 570 | createClass(IOS, [{ 571 | key: 'launch', 572 | value: function launch() { 573 | var _context = this._context; 574 | 575 | if (_context.osVer > 8) { 576 | util$1.openURLByHref(_context.urlScheme); 577 | } else { 578 | util$1.openURLByIFrame(_context.urlScheme); 579 | } 580 | 581 | this._timerId = setTimeout(this._handleTimeout, this._fallbackTime); 582 | this._observer = new BrowserBackgroundObserver(this._handleBrowserBack, this._handleLeaveBrowser, true); 583 | } 584 | }]); 585 | return IOS; 586 | }(BaseLauncher); 587 | 588 | var Android = function (_BaseLauncher) { 589 | inherits(Android, _BaseLauncher); 590 | 591 | function Android() { 592 | classCallCheck(this, Android); 593 | return possibleConstructorReturn(this, (Android.__proto__ || Object.getPrototypeOf(Android)).apply(this, arguments)); 594 | } 595 | 596 | return Android; 597 | }(BaseLauncher); 598 | 599 | var PC = function (_BaseLauncher) { 600 | inherits(PC, _BaseLauncher); 601 | 602 | function PC(context) { 603 | classCallCheck(this, PC); 604 | 605 | var _this = possibleConstructorReturn(this, (PC.__proto__ || Object.getPrototypeOf(PC)).call(this, context)); 606 | 607 | _this._enableEventListener(window); 608 | _this._enableEventListener(document); 609 | return _this; 610 | } 611 | 612 | createClass(PC, [{ 613 | key: 'launch', 614 | value: function launch() { 615 | util$1.openURLByIFrame(this._context.urlScheme); 616 | this._timerId = setTimeout(this._handleTimeout, this._fallbackTime); 617 | this._observer = new BrowserBackgroundObserver(this._handleBrowserBack, this._handleLeaveBrowser, true); 618 | } 619 | }, { 620 | key: '_enableEventListener', 621 | value: function _enableEventListener(target) { 622 | if (!target.addEventListener) { 623 | target.addEventListener = function (type, callback) { 624 | target.attachEvent('on' + type, callback); 625 | }; 626 | } 627 | 628 | if (!target.removeEventListener) { 629 | target.removeEventListener = function (type, callback) { 630 | target.detachEvent('on' + type, callback); 631 | }; 632 | } 633 | } 634 | }]); 635 | return PC; 636 | }(BaseLauncher); 637 | 638 | var util = { 639 | IOS: IOS, 640 | Android: Android, 641 | PC: PC 642 | }; 643 | 644 | var FallbackCustomScheme = function () { 645 | function FallbackCustomScheme(options) { 646 | classCallCheck(this, FallbackCustomScheme); 647 | this._ua = new UserAgent(); 648 | 649 | this._context = new Context(options); 650 | } 651 | 652 | createClass(FallbackCustomScheme, [{ 653 | key: 'launch', 654 | value: function launch(options) { 655 | var _context = this._context; 656 | var _ua = this._ua; 657 | 658 | options && _context.extend(options); 659 | var urlScheme = _context.urlScheme; 660 | var isIOS = _ua.isIOS; 661 | var isAndroid = _ua.isAndroid; 662 | var isPC = _ua.isPC; 663 | 664 | 665 | if (!urlScheme) { 666 | throw new Error('you must set "urlScheme"'); 667 | } 668 | 669 | if (isIOS) { 670 | this._launcher = new IOS(_context); 671 | } else if (isAndroid) { 672 | this._launcher = new Android(_context); 673 | } else if (isPC) { 674 | this._launcher = new PC(_context); 675 | } 676 | if (this._launcher) { 677 | this._launcher.launch(); 678 | } 679 | } 680 | }]); 681 | return FallbackCustomScheme; 682 | }(); 683 | 684 | return FallbackCustomScheme; 685 | 686 | }))); -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |