2019-10-26 02:42:50 +00:00
import ' dart:async ' ;
2019-11-04 00:39:23 +00:00
import ' dart:io ' ;
2019-10-26 02:42:50 +00:00
2019-11-10 13:11:30 +00:00
import ' package:flutter/foundation.dart ' ;
2019-10-26 02:42:50 +00:00
import ' package:flutter/services.dart ' ;
import ' types.dart ' ;
import ' in_app_browser.dart ' ;
///ChromeSafariBrowser class.
///
///This class uses native [Chrome Custom Tabs](https://developer.android.com/reference/android/support/customtabs/package-summary) on Android
///and [SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) on iOS.
///
2019-11-10 13:11:30 +00:00
///[browserFallback] represents the [InAppBrowser] instance fallback in case `Chrome Custom Tabs`/`SFSafariViewController` is not available.
2019-10-26 02:42:50 +00:00
class ChromeSafariBrowser {
String uuid ;
InAppBrowser browserFallback ;
bool _isOpened = false ;
2019-12-18 20:34:40 +00:00
MethodChannel _channel ;
static const MethodChannel _sharedChannel = const MethodChannel ( ' com.pichillilorenzo/flutter_chromesafaribrowser ' ) ;
2019-10-26 02:42:50 +00:00
///Initialize the [ChromeSafariBrowser] instance with an [InAppBrowser] fallback instance or `null`.
2019-12-01 11:55:06 +00:00
ChromeSafariBrowser ( { bFallback } ) {
2019-10-26 02:42:50 +00:00
uuid = uuidGenerator . v4 ( ) ;
2019-11-10 13:11:30 +00:00
browserFallback = bFallback ;
2019-12-18 20:34:40 +00:00
this . _channel =
MethodChannel ( ' com.pichillilorenzo/flutter_chromesafaribrowser_ $ uuid ' ) ;
this . _channel . setMethodCallHandler ( handleMethod ) ;
2019-10-26 02:42:50 +00:00
_isOpened = false ;
}
Future < dynamic > handleMethod ( MethodCall call ) async {
2019-12-01 11:55:06 +00:00
switch ( call . method ) {
2019-10-26 02:42:50 +00:00
case " onChromeSafariBrowserOpened " :
onOpened ( ) ;
break ;
2019-12-18 00:56:21 +00:00
case " onChromeSafariBrowserCompletedInitialLoad " :
onCompletedInitialLoad ( ) ;
2019-10-26 02:42:50 +00:00
break ;
case " onChromeSafariBrowserClosed " :
onClosed ( ) ;
this . _isOpened = false ;
break ;
default :
throw UnimplementedError ( " Unimplemented ${ call . method } method " ) ;
}
}
///Opens an [url] in a new [ChromeSafariBrowser] instance.
///
2019-11-10 13:11:30 +00:00
///[url]: The [url] to load. Call [encodeUriComponent()] on this if the [url] contains Unicode characters.
2019-10-26 02:42:50 +00:00
///
2019-11-10 13:11:30 +00:00
///[options]: Options for the [ChromeSafariBrowser].
2019-10-26 02:42:50 +00:00
///
2019-11-10 13:11:30 +00:00
///[headersFallback]: The additional header of the [InAppBrowser] instance fallback to be used in the HTTP request for this URL, specified as a map from name to value.
2019-10-26 02:42:50 +00:00
///
2019-11-10 13:11:30 +00:00
///[optionsFallback]: Options used by the [InAppBrowser] instance fallback.
2019-12-01 11:55:06 +00:00
Future < void > open (
{ @ required String url ,
ChromeSafariBrowserClassOptions options ,
Map < String , String > headersFallback = const { } ,
InAppBrowserClassOptions optionsFallback } ) async {
2019-10-26 02:42:50 +00:00
assert ( url ! = null & & url . isNotEmpty ) ;
this . throwIsAlreadyOpened ( message: ' Cannot open $ url ! ' ) ;
2019-10-27 03:35:05 +00:00
Map < String , dynamic > optionsMap = { } ;
2019-11-04 00:39:23 +00:00
if ( Platform . isAndroid )
2019-12-16 22:58:10 +00:00
optionsMap . addAll ( options . android ? . toMap ( ) ? ? { } ) ;
2019-11-04 00:39:23 +00:00
else if ( Platform . isIOS )
2019-12-16 22:58:10 +00:00
optionsMap . addAll ( options . ios ? . toMap ( ) ? ? { } ) ;
2019-10-27 03:35:05 +00:00
Map < String , dynamic > optionsFallbackMap = { } ;
2019-11-04 00:39:23 +00:00
if ( optionsFallback ! = null ) {
2019-12-01 11:55:06 +00:00
optionsFallbackMap
2019-12-16 22:58:10 +00:00
. addAll ( optionsFallback . crossPlatform ? . toMap ( ) ? ? { } ) ;
2019-12-01 11:55:06 +00:00
optionsFallbackMap . addAll ( optionsFallback
2019-12-16 22:58:10 +00:00
. inAppWebViewWidgetOptions ? . crossPlatform
2019-12-01 11:55:06 +00:00
? . toMap ( ) ? ?
{ } ) ;
2019-11-04 00:39:23 +00:00
if ( Platform . isAndroid ) {
2019-12-01 11:55:06 +00:00
optionsFallbackMap
2019-12-16 22:58:10 +00:00
. addAll ( optionsFallback . android ? . toMap ( ) ? ? { } ) ;
2019-12-01 11:55:06 +00:00
optionsFallbackMap . addAll ( optionsFallback
2019-12-16 22:58:10 +00:00
. inAppWebViewWidgetOptions ? . android
2019-12-01 11:55:06 +00:00
? . toMap ( ) ? ?
{ } ) ;
} else if ( Platform . isIOS ) {
optionsFallbackMap
2019-12-16 22:58:10 +00:00
. addAll ( optionsFallback . ios ? . toMap ( ) ? ? { } ) ;
2019-12-01 11:55:06 +00:00
optionsFallbackMap . addAll ( optionsFallback
2019-12-16 22:58:10 +00:00
. inAppWebViewWidgetOptions ? . ios
2019-12-01 11:55:06 +00:00
? . toMap ( ) ? ?
{ } ) ;
2019-11-04 00:39:23 +00:00
}
}
2019-10-27 03:35:05 +00:00
2019-10-26 02:42:50 +00:00
Map < String , dynamic > args = < String , dynamic > { } ;
args . putIfAbsent ( ' uuid ' , ( ) = > uuid ) ;
args . putIfAbsent ( ' url ' , ( ) = > url ) ;
2019-10-27 03:35:05 +00:00
args . putIfAbsent ( ' options ' , ( ) = > optionsMap ) ;
2019-12-18 20:34:40 +00:00
args . putIfAbsent ( ' uuidFallback ' ,
( ) = > ( browserFallback ! = null ) ? browserFallback . uuid : ' ' ) ;
args . putIfAbsent ( ' headersFallback ' , ( ) = > headersFallback ) ;
2019-10-27 03:35:05 +00:00
args . putIfAbsent ( ' optionsFallback ' , ( ) = > optionsFallbackMap ) ;
2019-12-18 20:34:40 +00:00
await _sharedChannel . invokeMethod ( ' open ' , args ) ;
2019-10-26 02:42:50 +00:00
this . _isOpened = true ;
}
///Event fires when the [ChromeSafariBrowser] is opened.
2019-12-01 11:55:06 +00:00
void onOpened ( ) { }
2019-10-26 02:42:50 +00:00
2019-12-18 00:56:21 +00:00
///Event fires when the initial URL load is complete.
void onCompletedInitialLoad ( ) { }
2019-10-26 02:42:50 +00:00
///Event fires when the [ChromeSafariBrowser] is closed.
2019-12-01 11:55:06 +00:00
void onClosed ( ) { }
2019-10-26 02:42:50 +00:00
2019-11-25 22:04:17 +00:00
///Returns `true` if the [ChromeSafariBrowser] instance is opened, otherwise `false`.
2019-10-26 02:42:50 +00:00
bool isOpened ( ) {
return this . _isOpened ;
}
void throwIsAlreadyOpened ( { String message = ' ' } ) {
if ( this . isOpened ( ) ) {
2019-12-01 11:55:06 +00:00
throw Exception ( [
' Error: ${ ( message . isEmpty ) ? ' ' : message + ' ' } The browser is already opened. '
] ) ;
2019-10-26 02:42:50 +00:00
}
}
void throwIsNotOpened ( { String message = ' ' } ) {
if ( ! this . isOpened ( ) ) {
2019-12-01 11:55:06 +00:00
throw Exception ( [
' Error: ${ ( message . isEmpty ) ? ' ' : message + ' ' } The browser is not opened. '
] ) ;
2019-10-26 02:42:50 +00:00
}
}
2019-12-01 11:55:06 +00:00
}