diff --git a/.gitignore b/.gitignore index ef597a6..d41bbf7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ xcuserdata/ build/ /android/dist ios/titanium-web-dialog.xcodeproj/project.xcworkspace/xcuserdata +android/libs diff --git a/README.md b/README.md index 80ec411..a69c511 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Titanium Web Dialog -Use the SFSafariViewController (iOS) and Chrome Pages (Android) together. +Use the native `SFSafariViewController` (iOS) and `Chrome Pages` (Android) within Axway Titanium. Titanium Web Dialog @@ -9,13 +9,10 @@ Use the SFSafariViewController (iOS) and Chrome Pages (Android) together. - Titanium SDK 7.0.0 or later (or use the [SDK-6-compatibility](https://github.com/appcelerator-modules/titanium-web-dialog/tree/SDK-6-compatibility) Titanium SDK 6.x) - iOS 9+ and Android 4.1+ -## Roadmap +## iOS Note -- [x] Find suitable module name -- [x] Create both modules on the same namespace (right now [Ti.SafariDialog](https://github.com/appcelerator-modules/ti.safaridialog) vs [Ti.ChromeTabs](https://github.com/prashantsaini1/ti-chrometabs)) -- [x] Adjust existing docs from Ti.SafariDialog to support Android as well -- [x] Write cross-platform example and tests -- [x] Release module +The iOS part of this module is based on Ti.SafariDialog, which has been deprecated for a cross-platform solution. All API's of Ti.SafariDialog +still work here and have been extended by more features over time. ## Android Legacy Support @@ -33,7 +30,7 @@ If you want to use this module in Titanium SDK 6.x, please use the [this version * `barColor` (String) * `animated` (Boolean, iOS only) * `entersReaderIfAvailable` (Boolean, iOS only) - * `barCollapsingEnabled` (Boolean, iOS only) + * `barCollapsingEnabled` (Boolean) * `title` (String, iOS only) * `tintColor` (String, iOS only)    * `dismissButtonStyle` (`DISMISS_BUTTON_STYLE_*`, iOS only) @@ -52,6 +49,13 @@ If you want to use this module in Titanium SDK 6.x, please use the [this version * `DISMISS_BUTTON_STYLE_CLOSE` (iOS only) * `DISMISS_BUTTON_STYLE_CANCEL` (iOS only) +#### Events + +* `open` -> `success` (Boolean), `url` (String) +* `close` -> `success` (Boolean), `url` (String) - iOS only +* `load` -> `success` (Boolean), `url` (String) - iOS only +* `redirect` -> `url` (String) - iOS only + ### `AuthenticationSession` (iOS only) ## License diff --git a/android/.clang-format b/android/.clang-format new file mode 100644 index 0000000..3e6a508 --- /dev/null +++ b/android/.clang-format @@ -0,0 +1,26 @@ +--- +Language: Java +AccessModifierOffset: -4 +AllowShortBlocksOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +# class, constructor, method should be next line +BreakBeforeBraces: Linux +# Keep '=' at end of line when wrapping, but move things like '&&', '||' to beginning of newline +BreakBeforeBinaryOperators: NonAssignment +# FIXME: break for brace after synchronized block, anonymous class declarations +BreakAfterJavaFieldAnnotations: true +ColumnLimit: 120 +IndentCaseLabels: true +IndentWidth: 4 +MaxEmptyLinesToKeep: 1 +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpacesInParentheses: false +TabWidth: 4 +UseTab: ForContinuationAndIndentation +SpaceAfterCStyleCast: true +# Spaces inside {} for array literals, i.e. "new Object[] { args }" +Cpp11BracedListStyle: false +ReflowComments: false diff --git a/android/libs/arm64-v8a/libti.webdialog.so b/android/libs/arm64-v8a/libti.webdialog.so deleted file mode 100644 index e16cf65..0000000 Binary files a/android/libs/arm64-v8a/libti.webdialog.so and /dev/null differ diff --git a/android/libs/armeabi-v7a/libti.webdialog.so b/android/libs/armeabi-v7a/libti.webdialog.so deleted file mode 100644 index 92733ce..0000000 Binary files a/android/libs/armeabi-v7a/libti.webdialog.so and /dev/null differ diff --git a/android/libs/x86/libti.webdialog.so b/android/libs/x86/libti.webdialog.so deleted file mode 100644 index 5032eb3..0000000 Binary files a/android/libs/x86/libti.webdialog.so and /dev/null differ diff --git a/android/manifest b/android/manifest index 65288d2..547134b 100644 --- a/android/manifest +++ b/android/manifest @@ -2,7 +2,7 @@ # this is your module manifest and used by Titanium # during compilation, packaging, distribution, etc. # -version: 1.0.0 +version: 1.1.0 apiversion: 4 architectures: arm64-v8a armeabi-v7a x86 description: titanium-web-dialog diff --git a/android/src/ti/webdialog/Params.java b/android/src/ti/webdialog/Params.java old mode 100755 new mode 100644 index ddb3552..3d21a4c --- a/android/src/ti/webdialog/Params.java +++ b/android/src/ti/webdialog/Params.java @@ -1,6 +1,7 @@ package ti.webdialog; -public class Params { +public class Params +{ public static final String LCAT = "TiChromeDialog"; public static final String SHOW_TITLE = "showTitle"; public static final String URL = "url"; @@ -8,4 +9,5 @@ public class Params { public static final String FADE_TRANSITION = "fadeTransition"; public static final String ENABLE_SHARING = "enableSharing"; public static final String CLOSE_ICON = "closeIcon"; + public static final String BAR_COLLAPSING_ENABLED = "barCollapsingEnabled"; } diff --git a/android/src/ti/webdialog/TitaniumWebDialogModule.java b/android/src/ti/webdialog/TitaniumWebDialogModule.java old mode 100755 new mode 100644 index c0f2133..81f7873 --- a/android/src/ti/webdialog/TitaniumWebDialogModule.java +++ b/android/src/ti/webdialog/TitaniumWebDialogModule.java @@ -34,132 +34,150 @@ import android.support.customtabs.CustomTabsService; import android.util.DisplayMetrics; - -@Kroll.module(name="TitaniumWebDialog", id="ti.webdialog") +@Kroll.module(name = "TitaniumWebDialog", id = "ti.webdialog") public class TitaniumWebDialogModule extends KrollModule { - // Standard Debugging variables - private static final String LCAT = "TiWebDialog"; - - private List getCustomTabBrowsers(Context context, List browsersList) { - List customTabBrowsers = new ArrayList(); - - for (ResolveInfo info : browsersList) { - String packageName = info.activityInfo.packageName; - - Intent intent = new Intent(); - intent.setAction(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION); - intent.setPackage(packageName); - - if (context.getPackageManager().resolveService(intent, 0) != null) { - customTabBrowsers.add(packageName); - } - } - - return customTabBrowsers; - } - - private void openCustomTab(Context context, List customTabBrowsers, KrollDict options) { - String URL = options.getString(Params.URL); - CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); - builder.setShowTitle(Utils.getBool(options, Params.SHOW_TITLE)); - - int barColor = Utils.getColor(options, Params.BAR_COLOR); - if (barColor != -1) { - builder.setToolbarColor(barColor); - } - - // set start and exit animations - if (Utils.getBool(options, Params.FADE_TRANSITION)) { - builder.setStartAnimations(context, android.R.anim.fade_in, android.R.anim.fade_out); - builder.setExitAnimations(context, android.R.anim.fade_in, android.R.anim.fade_out); - } - - //enable Share link option - if (Utils.getBool(options, Params.ENABLE_SHARING)) { - builder.addDefaultShareMenuItem(); - } - - String closeIcon = Utils.getString(options, Params.CLOSE_ICON); - if (!closeIcon.isEmpty()) { - builder.setCloseButtonIcon( getIcon(closeIcon) ); - } - - CustomTabsIntent tabIntent = builder.build(); - - for(String s:customTabBrowsers) { - tabIntent.intent.setPackage(s); - } - - tabIntent.launchUrl(context, Uri.parse(URL)); - } - - - private Bitmap getIcon(String path) { - Bitmap resultBitmap = null; - - if (path != null && !path.trim().equalsIgnoreCase("")) { - String resourceIcon = path.replaceAll(".png", ""); - resourceIcon = "drawable." + resourceIcon; - - int resource = Utils.getR(resourceIcon); - - if (resource == 0) { - TiUrl imageUrl = new TiUrl(path); - TiFileHelper tfh = new TiFileHelper(TiApplication.getInstance()); - Drawable d = tfh.loadDrawable(imageUrl.resolve(), false); - - resultBitmap = ((BitmapDrawable) d).getBitmap(); - - } else { - resultBitmap = BitmapFactory.decodeResource(TiApplication.getAppRootOrCurrentActivity().getResources(), resource); - } - } - - // important step to show close icon - // rescale bitmap to 24dp(Height) x 48dp(Width) as mentioned here, otherwise it won't work - // https://developer.chrome.com/multidevice/android/customtabs#choosing-an icon for the action button - if (resultBitmap != null) { - resultBitmap = Utils.rescaleBitmap(TiApplication.getAppRootOrCurrentActivity(), resultBitmap, 24, 48); - } - - return resultBitmap; - } - - - @Kroll.method - public void open(KrollDict options) { - if ((options != null) && options.containsKeyAndNotNull(Params.URL)) { - Context context = TiApplication.getAppCurrentActivity(); - List browsersList = Utils.allBrowsers(context); - - if (!browsersList.isEmpty()) { - List customTabBrowsers = getCustomTabBrowsers(context, browsersList); - - // show supported browsers list or open directly if only 1 supported browser is available - openCustomTab(context, customTabBrowsers, options); - } else { - Log.i(Params.LCAT, "No browsers available in this device."); - } - } - } - - @Kroll.method - public boolean isSupported() { - Context context = TiApplication.getAppCurrentActivity(); - List browsersList = Utils.allBrowsers(context); - - return !browsersList.isEmpty(); - } - - @Kroll.method - public void close(KrollDict options) { - Log.e(Params.LCAT, "The \"close\" method is not implemented, yet!"); - } - - @Kroll.method - public boolean isOpen(KrollDict options) { - Log.e(Params.LCAT, "The \"isOpen\" method is not implemented, yet!"); - return false; - } + // Standard Debugging variables + private static final String LCAT = "TiWebDialog"; + + private List getCustomTabBrowsers(Context context, List browsersList) + { + List customTabBrowsers = new ArrayList(); + + for (ResolveInfo info : browsersList) { + String packageName = info.activityInfo.packageName; + + Intent intent = new Intent(); + intent.setAction(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION); + intent.setPackage(packageName); + + if (context.getPackageManager().resolveService(intent, 0) != null) { + customTabBrowsers.add(packageName); + } + } + + return customTabBrowsers; + } + + private void openCustomTab(Context context, List customTabBrowsers, KrollDict options) + { + String URL = options.getString(Params.URL); + CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); + builder.setShowTitle(Utils.getBool(options, Params.SHOW_TITLE)); + + int barColor = Utils.getColor(options, Params.BAR_COLOR); + if (barColor != -1) { + builder.setToolbarColor(barColor); + } + + // set start and exit animations + if (Utils.getBool(options, Params.FADE_TRANSITION)) { + builder.setStartAnimations(context, android.R.anim.fade_in, android.R.anim.fade_out); + builder.setExitAnimations(context, android.R.anim.fade_in, android.R.anim.fade_out); + } + + // hide navigation bar on scroll + if (Utils.getBool(options, Params.BAR_COLLAPSING_ENABLED)) { + builder.enableUrlBarHiding(); + } + + //enable Share link option + if (Utils.getBool(options, Params.ENABLE_SHARING)) { + builder.addDefaultShareMenuItem(); + } + + String closeIcon = Utils.getString(options, Params.CLOSE_ICON); + if (!closeIcon.isEmpty()) { + builder.setCloseButtonIcon(getIcon(closeIcon)); + } + + CustomTabsIntent tabIntent = builder.build(); + + for (String s : customTabBrowsers) { + tabIntent.intent.setPackage(s); + } + + tabIntent.launchUrl(context, Uri.parse(URL)); + } + + private Bitmap getIcon(String path) + { + Bitmap resultBitmap = null; + + if (path != null && !path.trim().equalsIgnoreCase("")) { + String resourceIcon = path.replaceAll(".png", ""); + resourceIcon = "drawable." + resourceIcon; + + int resource = Utils.getR(resourceIcon); + + if (resource == 0) { + TiUrl imageUrl = new TiUrl(path); + TiFileHelper tfh = new TiFileHelper(TiApplication.getInstance()); + Drawable d = tfh.loadDrawable(imageUrl.resolve(), false); + + resultBitmap = ((BitmapDrawable) d).getBitmap(); + + } else { + resultBitmap = + BitmapFactory.decodeResource(TiApplication.getAppRootOrCurrentActivity().getResources(), resource); + } + } + + // important step to show close icon + // rescale bitmap to 24dp(Height) x 48dp(Width) as mentioned here, otherwise it won't work + // https://developer.chrome.com/multidevice/android/customtabs#choosing-an icon for the action button + if (resultBitmap != null) { + resultBitmap = Utils.rescaleBitmap(TiApplication.getAppRootOrCurrentActivity(), resultBitmap, 24, 48); + } + + return resultBitmap; + } + + @Kroll.method + public void open(KrollDict options) + { + if ((options != null) && options.containsKeyAndNotNull(Params.URL)) { + Context context = TiApplication.getAppCurrentActivity(); + List browsersList = Utils.allBrowsers(context); + + KrollDict event = new KrollDict(); + + event.put("success", !browsersList.isEmpty()); + event.put("url", options.getString(Params.URL)); + + if (!browsersList.isEmpty()) { + List customTabBrowsers = getCustomTabBrowsers(context, browsersList); + + // show supported browsers list or open directly if only 1 supported browser is available + openCustomTab(context, customTabBrowsers, options); + + } else { + Log.i(Params.LCAT, "No browsers available in this device."); + } + + fireEvent("open", event); + } + } + + @Kroll.method + public boolean isSupported() + { + Context context = TiApplication.getAppCurrentActivity(); + List browsersList = Utils.allBrowsers(context); + + return !browsersList.isEmpty(); + } + + @Kroll.method + public void close(KrollDict options) + { + Log.e(Params.LCAT, "The \"close\" method is not implemented on Android, yet!"); + } + + @Kroll.method + public boolean isOpen(KrollDict options) + { + Log.e(Params.LCAT, "The \"isOpen\" method is not implemented on Android, yet!"); + return false; + } } diff --git a/android/src/ti/webdialog/Utils.java b/android/src/ti/webdialog/Utils.java old mode 100755 new mode 100644 index 9078186..bf2c2fd --- a/android/src/ti/webdialog/Utils.java +++ b/android/src/ti/webdialog/Utils.java @@ -16,107 +16,113 @@ import android.net.Uri; import android.util.DisplayMetrics; -public class Utils { - public static int getR(String path) { +public class Utils +{ + public static int getR(String path) + { // TiRHelper maintains a cache system & uses 0 for not-found resources try { return TiRHelper.getResource(path); - + } catch (ResourceNotFoundException e) { return 0; } } - - public static int[] getStyleableIntArray(String packageName, String name) { - try { - Field[] fields2 = Class.forName(packageName + ".R$styleable" ).getFields(); - - for (Field f : fields2) { - if ( f.getName().equals( name ) ) { - int[] ret = (int[])f.get( null ); - return ret; - } - } - } catch ( Throwable t ) {} - - return null; - } - + + public static int[] getStyleableIntArray(String packageName, String name) + { + try { + Field[] fields2 = Class.forName(packageName + ".R$styleable").getFields(); + + for (Field f : fields2) { + if (f.getName().equals(name)) { + int[] ret = (int[]) f.get(null); + return ret; + } + } + } catch (Throwable t) { + } + + return null; + } + // return the list of all available & enabled browsers in device - public static List allBrowsers(Context context) { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.testingurl.com")); + public static List allBrowsers(Context context) + { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.testingurl.com")); return context.getPackageManager().queryIntentActivities(intent, 0); } - - public static String getString(KrollDict options, String key) { + + public static String getString(KrollDict options, String key) + { String value = "" + (options.containsKeyAndNotNull(key) ? options.get(key) : ""); return value.trim(); } - - public static boolean getBool(KrollDict options, String key) { + + public static boolean getBool(KrollDict options, String key) + { return (Boolean) (options.containsKeyAndNotNull(key) ? options.get(key) : false); } - - public static int getColor(KrollDict options, String key) { + + public static int getColor(KrollDict options, String key) + { if (options.containsKeyAndNotNull(key)) { - return TiConvert.toColor( (String) options.get(key)); - + return TiConvert.toColor((String) options.get(key)); + } else { return getR("color.colorPrimary"); } } - + // takes MAX_HEIGHT & MAX_WIDTH in terms of dp - public static Bitmap rescaleBitmap(Context context, Bitmap bm, final int MAX_HEIGHT, final int MAX_WIDTH) { + public static Bitmap rescaleBitmap(Context context, Bitmap bm, final int MAX_HEIGHT, final int MAX_WIDTH) + { DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); float density = displayMetrics.density; - + final int REQ_HEIGHT = (int) density * MAX_HEIGHT; final int REQ_WIDTH = (int) density * MAX_WIDTH; - + final int bitmapW = bm.getWidth(); final int bitmapH = bm.getHeight(); - + if (bitmapH <= REQ_HEIGHT && bitmapW <= REQ_WIDTH) { return bm; } - + int finalH = 0, finalW = 0; float ratioWH = (float) bitmapW / bitmapH; - + if (bitmapH > REQ_HEIGHT) { finalH = REQ_HEIGHT; finalW = (int) (finalH * ratioWH); - + // check if width is in 48dp bound if (finalW > REQ_WIDTH) { finalW = REQ_WIDTH; } - + } else if (bitmapW > REQ_WIDTH) { finalW = REQ_WIDTH; finalH = (int) (finalW / ratioWH); - + // check if height is in 24dp bound if (finalH > REQ_HEIGHT) { finalH = REQ_HEIGHT; } } - + if (finalH != 0 && finalW != 0) { final Bitmap resultBitmap = Bitmap.createScaledBitmap(bm, finalW, finalH, false); - + if (bm != null && !bm.isRecycled()) { bm.recycle(); } - + return resultBitmap; - + } else { return bm; } } } - - - diff --git a/apidoc/WebDialog.yml b/apidoc/WebDialog.yml index 303c8c3..350a57c 100644 --- a/apidoc/WebDialog.yml +++ b/apidoc/WebDialog.yml @@ -109,7 +109,7 @@ events: The open event is fired after the web dialog has opened. properties: - name: url - summary: The URL provided when opening the web dialog + summary: The URL provided when opening the web dialog. type: String platforms: [iphone, ipad] @@ -119,7 +119,7 @@ events: or programmatically. properties: - name: url - summary: The URL provided when opening the web dialog + summary: The URL provided when opening the web dialog. type: String platforms: [iphone, ipad] @@ -133,12 +133,20 @@ events: Note: This event is available in Titanium SDK 6.0.0 and later. properties: - name: url - summary: The URL provided when opening the web dialog + summary: The URL provided when opening the web dialog. type: String - name: success summary: Returns `true` if loading completed successfully, `false` otherwise. type: Boolean platforms: [iphone, ipad] + + - name: redirect + summary: Fired when the browser is redirected to another URL before the first page load finishes. + properties: + - name: url + summary: The URL provided when opening the web dialog. + type: String + platforms: [iphone, ipad] --- name: WebDialogOpenParams @@ -179,7 +187,7 @@ properties: optional: true type: Number constants: [Modules.WebDialog.DISMISS_BUTTON_STYLE_*] - platforms: [iphone, ipad] + platforms: [iphone, ipad] - name: barCollapsingEnabled summary: | @@ -189,4 +197,4 @@ properties: optional: true default: true type: Boolean - platforms: [iphone, ipad] + platforms: [iphone, ipad, android] diff --git a/ios/.clang-format b/ios/.clang-format new file mode 100644 index 0000000..155e5a1 --- /dev/null +++ b/ios/.clang-format @@ -0,0 +1,96 @@ +--- +# BasedOnStyle: WebKit +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +BreakBeforeBinaryOperators: All +BreakBeforeBraces: WebKit +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +BreakBeforeInheritanceComma: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '$' +IndentCaseLabels: false +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: Inner +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 8 +UseTab: Never +... diff --git a/ios/Classes/TiWebdialogAuthenticationSessionProxy.h b/ios/Classes/TiWebdialogAuthenticationSessionProxy.h index aa0ae4e..f8d0075 100644 --- a/ios/Classes/TiWebdialogAuthenticationSessionProxy.h +++ b/ios/Classes/TiWebdialogAuthenticationSessionProxy.h @@ -26,4 +26,3 @@ @end #endif - diff --git a/ios/Classes/TiWebdialogAuthenticationSessionProxy.m b/ios/Classes/TiWebdialogAuthenticationSessionProxy.m index 45d8f17..cf13813 100644 --- a/ios/Classes/TiWebdialogAuthenticationSessionProxy.m +++ b/ios/Classes/TiWebdialogAuthenticationSessionProxy.m @@ -18,26 +18,26 @@ - (SFAuthenticationSession *)authSession if (_authSession == nil) { NSString *url = [TiUtils stringValue:[self valueForKey:@"url"]]; NSString *scheme = [TiUtils stringValue:[self valueForKey:@"scheme"]]; - + _authSession = [[SFAuthenticationSession alloc] initWithURL:[TiUtils toURL:url proxy:self] callbackURLScheme:[TiUtils stringValue:scheme] completionHandler:^(NSURL *callbackURL, NSError *error) { NSMutableDictionary *event = [NSMutableDictionary dictionaryWithDictionary:@{ - @"success": NUMBOOL(error == nil) + @"success" : NUMBOOL(error == nil) }]; - + if (error != nil) { [event setObject:[error localizedDescription] forKey:@"error"]; } else { [event setObject:[callbackURL absoluteString] forKey:@"callbackURL"]; } - + if ([self _hasListeners:@"callback"]) { [self fireEvent:@"callback" withObject:event]; } }]; } - + return _authSession; } diff --git a/ios/Classes/TiWebdialogModule.h b/ios/Classes/TiWebdialogModule.h index d00580e..8c35e4c 100644 --- a/ios/Classes/TiWebdialogModule.h +++ b/ios/Classes/TiWebdialogModule.h @@ -9,8 +9,8 @@ #import "TiModule.h" #import -@interface TiWebdialogModule: TiModule { -@private +@interface TiWebdialogModule : TiModule { + @private SFSafariViewController *_safariController; NSString *_url; BOOL _isOpen; diff --git a/ios/Classes/TiWebdialogModule.m b/ios/Classes/TiWebdialogModule.m index 6b10a63..32ab897 100644 --- a/ios/Classes/TiWebdialogModule.m +++ b/ios/Classes/TiWebdialogModule.m @@ -7,10 +7,10 @@ */ #import "TiWebdialogModule.h" +#import "TiApp.h" #import "TiBase.h" #import "TiHost.h" #import "TiUtils.h" -#import "TiApp.h" @implementation TiWebdialogModule @@ -42,14 +42,15 @@ - (void)teardown [_safariController setDelegate:nil]; _safariController = nil; } - + _isOpen = NO; - + if ([self _hasListeners:@"close"]) { - [self fireEvent:@"close" withObject:@{ - @"success": NUMINT(YES), - @"url": [_url stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] - }]; + [self fireEvent:@"close" + withObject:@{ + @"success" : NUMINT(YES), + @"url" : [_url stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] + }]; } } @@ -67,7 +68,7 @@ - (SFSafariViewController *)safariController:(NSString *)url withEntersReaderIfA SFSafariViewControllerConfiguration *config = [[SFSafariViewControllerConfiguration alloc] init]; config.entersReaderIfAvailable = entersReaderIfAvailable; config.barCollapsingEnabled = barCollapsingEnabled; - + _safariController = [[SFSafariViewController alloc] initWithURL:safariURL configuration:config]; } else { @@ -77,20 +78,31 @@ - (SFSafariViewController *)safariController:(NSString *)url withEntersReaderIfA #if IS_IOS_11 } #endif - + [_safariController setDelegate:self]; } - + return _safariController; } - (void)safariViewController:(SFSafariViewController *)controller didCompleteInitialLoad:(BOOL)didLoadSuccessfully { if ([self _hasListeners:@"load"]) { - [self fireEvent:@"load" withObject:@{ - @"url": [_url stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding], - @"success": NUMBOOL(didLoadSuccessfully) - }]; + [self fireEvent:@"load" + withObject:@{ + @"url" : [_url stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding], + @"success" : NUMBOOL(didLoadSuccessfully) + }]; + } +} + +- (void)safariViewController:(SFSafariViewController *)controller initialLoadDidRedirectToURL:(NSURL *)URL +{ + if ([self _hasListeners:@"redirect"]) { + [self fireEvent:@"redirect" + withObject:@{ + @"url" : [_url stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] + }]; } } @@ -108,8 +120,8 @@ - (NSNumber *)isSupported:(id)unused - (void)close:(id)unused { - ENSURE_UI_THREAD(close,unused); - + ENSURE_UI_THREAD(close, unused); + if (_safariController != nil) { [[TiApp app] hideModalController:_safariController animated:YES]; [self teardown]; @@ -119,39 +131,39 @@ - (void)close:(id)unused - (void)open:(id)args { - ENSURE_SINGLE_ARG(args,NSDictionary); - ENSURE_UI_THREAD(open,args); - + ENSURE_SINGLE_ARG(args, NSDictionary); + ENSURE_UI_THREAD(open, args); + if (![args objectForKey:@"url"]) { NSLog(@"[ERROR] url is required"); return; } - + _url = [TiUtils stringValue:@"url" properties:args]; BOOL animated = [TiUtils boolValue:@"animated" properties:args def:YES]; BOOL entersReaderIfAvailable = [TiUtils boolValue:@"entersReaderIfAvailable" properties:args def:YES]; BOOL barCollapsingEnabled = NO; - + #if IS_IOS_11 barCollapsingEnabled = [TiUtils boolValue:@"barCollapsingEnabled" properties:args def:YES]; #endif - + SFSafariViewController *safari = [self safariController:_url withEntersReaderIfAvailable:entersReaderIfAvailable andBarCollapsingEnabled:barCollapsingEnabled]; - + if ([args objectForKey:@"title"]) { [safari setTitle:[TiUtils stringValue:@"title" properties:args]]; } - + if ([args objectForKey:@"tintColor"]) { TiColor *newColor = [TiUtils colorValue:@"tintColor" properties:args]; - + if ([TiUtils isIOS10OrGreater]) { [safari setPreferredControlTintColor:[newColor _color]]; } else { [[safari view] setTintColor:[newColor _color]]; } } - + if ([args objectForKey:@"barColor"]) { if ([TiUtils isIOS10OrGreater]) { [safari setPreferredBarTintColor:[[TiUtils colorValue:@"barColor" properties:args] _color]]; @@ -159,7 +171,7 @@ - (void)open:(id)args NSLog(@"[ERROR] Ti.WebDialog: The barColor property is only available in iOS 10 and later"); } } - + #if IS_IOS_11 if ([args objectForKey:@"dismissButtonStyle"]) { if (@available(iOS 11.0, *)) { @@ -169,17 +181,17 @@ - (void)open:(id)args } } #endif - - [[TiApp app] showModalController:safari animated:animated]; - + + [[TiApp app] showModalController:safari + animated:animated]; + _isOpen = YES; - + if ([self _hasListeners:@"open"]) { NSDictionary *event = [NSDictionary dictionaryWithObjectsAndKeys: - NUMINT(YES),@"success", - _url,@"url", - nil - ]; + NUMINT(YES), @"success", + _url, @"url", + nil]; [self fireEvent:@"open" withObject:event]; } } diff --git a/ios/Classes/TiWebdialogModuleAssets.h b/ios/Classes/TiWebdialogModuleAssets.h index 2ac3978..2c96bbc 100644 --- a/ios/Classes/TiWebdialogModuleAssets.h +++ b/ios/Classes/TiWebdialogModuleAssets.h @@ -3,10 +3,9 @@ */ @interface TiWebdialogModuleAssets : NSObject { - } - (NSData *)moduleAsset; -- (NSData *)resolveModuleAsset:(NSString*)path; +- (NSData *)resolveModuleAsset:(NSString *)path; @end diff --git a/ios/manifest b/ios/manifest index e511d26..5cd237c 100644 --- a/ios/manifest +++ b/ios/manifest @@ -2,7 +2,7 @@ # this is your module manifest and used by Titanium # during compilation, packaging, distribution, etc. # -version: 1.0.0 +version: 1.1.0 apiversion: 2 architectures: armv7 arm64 i386 x86_64 description: titanium-web-dialog