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 ;
2015-06-06 02:00:17 +00:00
var Map = require ( 'Map' ) ;
2015-03-26 03:09:04 +00:00
var invariant = require ( 'invariant' ) ;
2015-06-06 02:00:17 +00:00
var _notifHandlers = new Map ( ) ;
2015-03-26 03:09:04 +00:00
var _initialURL = RCTLinkingManager &&
RCTLinkingManager . initialURL ;
var DEVICE _NOTIF _EVENT = 'openURL' ;
2015-03-31 03:12:32 +00:00
/ * *
2015-11-12 20:35:44 +00:00
* ` LinkingIOS ` gives you a general interface to interact with both incoming
2015-03-31 03:12:32 +00:00
* and outgoing app links .
*
* # # # Basic Usage
*
* # # # # Handling deep links
*
2015-09-01 15:21:35 +00:00
* If your app was launched from an external url registered to your app you can
2015-03-31 03:12:32 +00:00
* 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 ` :
*
* ` ` `
2015-12-04 16:05:11 +00:00
* - ( BOOL ) application : ( UIApplication * ) application openURL : ( NSURL * ) url
* sourceApplication : ( NSString * ) sourceApplication annotation : ( id ) annotation
* {
* return [ RCTLinkingManager application : application openURL : url
* sourceApplication : sourceApplication annotation : annotation ] ;
2015-03-31 03:12:32 +00:00
* }
2015-12-04 16:05:11 +00:00
*
* // Only if your app is using [Universal Links](https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/AppSearch/UniversalLinks.html).
* - ( BOOL ) application : ( UIApplication * ) application continueUserActivity : ( NSUserActivity * ) userActivity
* restorationHandler : ( void ( ^ ) ( NSArray * _Nullable ) ) restorationHandler
* {
* return [ RCTLinkingManager application : application
* continueUserActivity : userActivity
* restorationHandler : restorationHandler ] ;
* }
*
2015-03-31 03:12:32 +00:00
* ` ` `
*
* 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
*
2015-11-12 20:35:44 +00:00
* To trigger an app link ( browser , email or custom schemas ) , call
2015-03-31 03:12:32 +00:00
*
* ` ` `
* LinkingIOS . openURL ( url )
* ` ` `
*
2015-12-04 16:05:11 +00:00
* If you want to check if any installed app can handle a given URL beforehand , call
2015-03-31 03:12:32 +00:00
* ` ` `
* LinkingIOS . canOpenURL ( url , ( supported ) => {
* if ( ! supported ) {
* AlertIOS . alert ( 'Can\'t handle url: ' + url ) ;
* } else {
* LinkingIOS . openURL ( url ) ;
* }
* } ) ;
* ` ` `
* /
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'
) ;
2015-06-06 02:00:17 +00:00
var listener = RCTDeviceEventEmitter . addListener (
2015-03-26 03:09:04 +00:00
DEVICE _NOTIF _EVENT ,
2015-03-31 03:12:32 +00:00
handler
2015-03-26 03:09:04 +00:00
) ;
2015-06-06 02:00:17 +00:00
_notifHandlers . set ( handler , listener ) ;
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'
) ;
2015-06-06 02:00:17 +00:00
var listener = _notifHandlers . get ( handler ) ;
if ( ! listener ) {
2015-03-26 03:09:04 +00:00
return ;
}
2015-06-06 02:00:17 +00:00
listener . remove ( ) ;
_notifHandlers . delete ( handler ) ;
2015-03-26 03:09:04 +00:00
}
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
/ * *
2015-11-12 20:35:44 +00:00
* Determine whether or not an installed app can handle a given URL .
2015-03-31 03:12:32 +00:00
* The callback function will be called with ` bool supported ` as the only argument
2015-10-12 15:03:02 +00:00
*
2015-12-04 16:05:11 +00:00
* NOTE : As of iOS 9 , your app needs to provide the ` LSApplicationQueriesSchemes ` key
2015-10-12 15:03:02 +00:00
* inside ` Info.plist ` .
2015-03-31 03:12:32 +00:00
* /
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 ;