2015-03-26 03:09:04 +00:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*
|
|
|
|
* @providesModule LinkingIOS
|
|
|
|
* @flow
|
|
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
|
|
|
|
var RCTLinkingManager = require('NativeModules').LinkingManager;
|
|
|
|
var invariant = require('invariant');
|
|
|
|
|
|
|
|
var _notifHandlers = {};
|
|
|
|
var _initialURL = RCTLinkingManager &&
|
|
|
|
RCTLinkingManager.initialURL;
|
|
|
|
|
|
|
|
var DEVICE_NOTIF_EVENT = 'openURL';
|
|
|
|
|
2015-03-31 03:12:32 +00:00
|
|
|
/**
|
|
|
|
* `LinkingIOS` gives you a general interface to interact with both, incoming
|
|
|
|
* and outgoing app links.
|
|
|
|
*
|
|
|
|
* ### Basic Usage
|
|
|
|
*
|
|
|
|
* #### Handling deep links
|
|
|
|
*
|
|
|
|
* If your app was launched from a external url registered to your app you can
|
|
|
|
* access and handle it from any component you want with
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* componentDidMount() {
|
|
|
|
* var url = LinkingIOS.popInitialURL();
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* In case you also want to listen to incoming app links during your app's
|
|
|
|
* execution you'll need to add the following lines to you `*AppDelegate.m`:
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
|
|
|
|
* return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* And then on your React component you'll be able to listen to the events on
|
|
|
|
* `LinkingIOS` as follows
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* componentDidMount() {
|
|
|
|
* LinkingIOS.addEventListener('url', this._handleOpenURL);
|
|
|
|
* },
|
|
|
|
* componentWillUnmount() {
|
|
|
|
* LinkingIOS.removeEventListener('url', this._handleOpenURL);
|
|
|
|
* },
|
|
|
|
* _handleOpenURL(event) {
|
|
|
|
* console.log(event.url);
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* #### Triggering App links
|
|
|
|
*
|
|
|
|
* To trigger an app link (browser, email or custom schemas) you call
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* LinkingIOS.openURL(url)
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* If you want to check if any installed app can handle a given url beforehand you can call
|
|
|
|
* ```
|
|
|
|
* LinkingIOS.canOpenURL(url, (supported) => {
|
|
|
|
* if (!supported) {
|
|
|
|
* AlertIOS.alert('Can\'t handle url: ' + url);
|
|
|
|
* } else {
|
|
|
|
* LinkingIOS.openURL(url);
|
|
|
|
* }
|
|
|
|
* });
|
|
|
|
* ```
|
2015-04-18 23:32:01 +00:00
|
|
|
*
|
|
|
|
* _The iOS simulator does not support the `mailto:` and `tel:` schemas
|
|
|
|
* because the Mail and Phone apps are not installed - you will need to test
|
|
|
|
* them on a device._
|
2015-03-31 03:12:32 +00:00
|
|
|
*/
|
2015-03-26 03:09:04 +00:00
|
|
|
class LinkingIOS {
|
2015-03-31 03:12:32 +00:00
|
|
|
/**
|
|
|
|
* Add a handler to LinkingIOS changes by listening to the `url` event type
|
|
|
|
* and providing the handler
|
|
|
|
*/
|
|
|
|
static addEventListener(type: string, handler: Function) {
|
2015-03-26 03:09:04 +00:00
|
|
|
invariant(
|
|
|
|
type === 'url',
|
|
|
|
'LinkingIOS only supports `url` events'
|
|
|
|
);
|
|
|
|
_notifHandlers[handler] = RCTDeviceEventEmitter.addListener(
|
|
|
|
DEVICE_NOTIF_EVENT,
|
2015-03-31 03:12:32 +00:00
|
|
|
handler
|
2015-03-26 03:09:04 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-03-31 03:12:32 +00:00
|
|
|
/**
|
|
|
|
* Remove a handler by passing the `url` event type and the handler
|
|
|
|
*/
|
|
|
|
static removeEventListener(type: string, handler: Function ) {
|
2015-03-26 03:09:04 +00:00
|
|
|
invariant(
|
|
|
|
type === 'url',
|
|
|
|
'LinkingIOS only supports `url` events'
|
|
|
|
);
|
|
|
|
if (!_notifHandlers[handler]) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_notifHandlers[handler].remove();
|
|
|
|
_notifHandlers[handler] = null;
|
|
|
|
}
|
|
|
|
|
2015-03-31 03:12:32 +00:00
|
|
|
/**
|
|
|
|
* Try to open the given `url` with any of the installed apps.
|
|
|
|
*/
|
|
|
|
static openURL(url: string) {
|
2015-03-26 03:09:04 +00:00
|
|
|
invariant(
|
|
|
|
typeof url === 'string',
|
|
|
|
'Invalid url: should be a string'
|
|
|
|
);
|
|
|
|
RCTLinkingManager.openURL(url);
|
|
|
|
}
|
|
|
|
|
2015-03-31 03:12:32 +00:00
|
|
|
/**
|
|
|
|
* Determine wether or not the an installed app can handle a given `url`
|
|
|
|
* The callback function will be called with `bool supported` as the only argument
|
|
|
|
*/
|
|
|
|
static canOpenURL(url: string, callback: Function) {
|
2015-03-26 03:09:04 +00:00
|
|
|
invariant(
|
|
|
|
typeof url === 'string',
|
|
|
|
'Invalid url: should be a string'
|
|
|
|
);
|
|
|
|
invariant(
|
|
|
|
typeof callback === 'function',
|
|
|
|
'A valid callback function is required'
|
|
|
|
);
|
|
|
|
RCTLinkingManager.canOpenURL(url, callback);
|
|
|
|
}
|
|
|
|
|
2015-03-31 03:12:32 +00:00
|
|
|
/**
|
|
|
|
* If the app launch was triggered by an app link, it will pop the link url,
|
|
|
|
* otherwise it will return `null`
|
|
|
|
*/
|
|
|
|
static popInitialURL(): ?string {
|
2015-03-26 03:09:04 +00:00
|
|
|
var initialURL = _initialURL;
|
|
|
|
_initialURL = null;
|
|
|
|
return initialURL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = LinkingIOS;
|