From bed0565461cdf3de955b9532468b8d2552a44efd Mon Sep 17 00:00:00 2001 From: Manol Donev Date: Tue, 19 Nov 2019 15:50:16 +0200 Subject: [PATCH 1/4] chore: update nativescript.api.md (#8117) --- api-reports/NativeScript.api.md | 73 +++++++++++++++++---------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/api-reports/NativeScript.api.md b/api-reports/NativeScript.api.md index c585fb21b..9e2d5f465 100644 --- a/api-reports/NativeScript.api.md +++ b/api-reports/NativeScript.api.md @@ -170,6 +170,16 @@ export class AndroidApplication extends Observable { nativeApp: any /* android.app.Application */; + on(eventNames: string, callback: (data: AndroidActivityEventData) => void, thisArg?: any); + + on(event: "activityCreated", callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any); + + on(event: "activityDestroyed", callback: (args: AndroidActivityEventData) => void, thisArg?: any); + + on(event: "activityStarted", callback: (args: AndroidActivityEventData) => void, thisArg?: any); + + on(event: "activityPaused", callback: (args: AndroidActivityEventData) => void, thisArg?: any); + on(event: "activityResumed", callback: (args: AndroidActivityEventData) => void, thisArg?: any); on(event: "activityStopped", callback: (args: AndroidActivityEventData) => void, thisArg?: any); @@ -184,16 +194,6 @@ export class AndroidApplication extends Observable { on(event: "activityRequestPermissions", callback: (args: AndroidActivityRequestPermissionsEventData) => void, thisArg?: any); - on(eventNames: string, callback: (data: AndroidActivityEventData) => void, thisArg?: any); - - on(event: "activityCreated", callback: (args: AndroidActivityBundleEventData) => void, thisArg?: any); - - on(event: "activityDestroyed", callback: (args: AndroidActivityEventData) => void, thisArg?: any); - - on(event: "activityStarted", callback: (args: AndroidActivityEventData) => void, thisArg?: any); - - on(event: "activityPaused", callback: (args: AndroidActivityEventData) => void, thisArg?: any); - orientation: "portrait" | "landscape" | "unknown"; packageName: string; @@ -404,15 +404,15 @@ export class ChangeType { // @public export class Color { constructor(knownColor: string); - constructor(alpha: number, red: number, green: number, blue: number); constructor(hex: string); constructor(argb: number); + constructor(alpha: number, red: number, green: number, blue: number); public a: number; android: number; public argb: number; public b: number; - public static equals(value1: Color, value2: Color): boolean; public equals(value: Color): boolean; + public static equals(value1: Color, value2: Color): boolean; public g: number; public hex: string; ios: any /* UIColor */; @@ -1112,9 +1112,9 @@ export class ImageCache extends Observable { enqueue(request: DownloadRequest); get(key: string): any; maxRequests: number; - on(event: "downloadError", callback: (args: DownloadError) => void, thisArg?: any); on(eventNames: string, callback: (args: EventData) => void, thisArg?: any); on(event: "downloaded", callback: (args: DownloadedData) => void, thisArg?: any); + on(event: "downloadError", callback: (args: DownloadError) => void, thisArg?: any); // (undocumented) _onDownloadCompleted(key: string, image: any); // (undocumented) @@ -1144,11 +1144,11 @@ export class ImageSource { static fromBase64Sync(source: string): ImageSource; + static fromData(data: any): Promise; + // @deprecated (undocumented) fromData(data: any): Promise; - static fromData(data: any): Promise; - static fromDataSync(data: any): ImageSource; static fromFile(path: string): Promise; @@ -1372,10 +1372,10 @@ export class ListView extends View { itemTemplates: string | Array; itemTemplateSelector: string | ((item: any, index: number, items: any) => string); public static loadMoreItemsEvent: string; - on(event: "loadMoreItems", callback: (args: EventData) => void, thisArg?: any); - on(event: "itemLoading", callback: (args: ItemEventData) => void, thisArg?: any); on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + on(event: "itemLoading", callback: (args: ItemEventData) => void, thisArg?: any); on(event: "itemTap", callback: (args: ItemEventData) => void, thisArg?: any); + on(event: "loadMoreItems", callback: (args: EventData) => void, thisArg?: any); refresh(); rowHeight: Length; scrollToIndex(index: number); @@ -1482,10 +1482,10 @@ export class Observable { off(eventNames: string, callback?: any, thisArg?: any); - on(event: "propertyChange", callback: (data: EventData) => void, thisArg?: any); - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + on(event: "propertyChange", callback: (data: EventData) => void, thisArg?: any); + once(event: string, callback: (data: EventData) => void, thisArg?: any); public static propertyChangeEvent: string; @@ -1506,10 +1506,10 @@ export class ObservableArray extends Observable { public static changeEvent: string; - concat(...items: T[]): T[]; - concat(...items: U[]): T[]; + concat(...items: T[]): T[]; + every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean; filter(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): T[]; @@ -1558,10 +1558,10 @@ export class ObservableArray extends Observable { sort(compareFn?: (a: T, b: T) => number): T[]; - splice(start: number, deleteCount: number, ...items: T[]): T[]; - splice(start: number): T[]; + splice(start: number, deleteCount: number, ...items: T[]): T[]; + // (undocumented) toLocaleString(): string; @@ -1610,14 +1610,14 @@ export class Page extends ContentView { public on(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void; + public on(event: "navigatingTo", callback: (args: NavigatedData) => void, thisArg?: any): void; + public on(event: "navigatedTo", callback: (args: NavigatedData) => void, thisArg?: any): void; public on(event: "navigatingFrom", callback: (args: NavigatedData) => void, thisArg?: any): void; public on(event: "navigatedFrom", callback: (args: NavigatedData) => void, thisArg?: any): void; - public on(event: "navigatingTo", callback: (args: NavigatedData) => void, thisArg?: any): void; - public onNavigatedFrom(isBackNavigation: boolean): void; public onNavigatedTo(isBackNavigation: boolean): void; @@ -1779,10 +1779,10 @@ export class ScrollView extends ContentView { isScrollEnabled: boolean; - on(event: "scroll", callback: (args: ScrollEventData) => void, thisArg?: any); - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + on(event: "scroll", callback: (args: ScrollEventData) => void, thisArg?: any); + // (undocumented) _onOrientationChanged(); @@ -1816,11 +1816,11 @@ export class SearchBar extends View { ios: any /* UISearchBar */; - on(event: "close", callback: (args: EventData) => void, thisArg?: any); + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); on(event: "submit", callback: (args: EventData) => void, thisArg?: any); - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + on(event: "close", callback: (args: EventData) => void, thisArg?: any); public static submitEvent: string; @@ -2304,6 +2304,9 @@ export class TabStripItem extends View { image: Image; + // (undocumented) + _index: number; + label: Label; on(eventNames: string, callback: (data: EventData) => void); @@ -2678,12 +2681,12 @@ export abstract class View extends ViewBase { // (undocumented) _modalParent?: View; off(eventNames: string | GestureTypes, callback?: (args: EventData) => void, thisArg?: any); - on(event: "showingModally", callback: (args: ShownModallyData) => void, thisArg?: any): void; - on(event: "androidBackPressed", callback: (args: EventData) => void, thisArg?: any); - on(event: "shownModally", callback: (args: ShownModallyData) => void, thisArg?: any); + on(eventNames: string | GestureTypes, callback: (args: EventData) => void, thisArg?: any); on(event: "loaded", callback: (args: EventData) => void, thisArg?: any); on(event: "unloaded", callback: (args: EventData) => void, thisArg?: any); - on(eventNames: string | GestureTypes, callback: (args: EventData) => void, thisArg?: any); + on(event: "androidBackPressed", callback: (args: EventData) => void, thisArg?: any); + on(event: "showingModally", callback: (args: ShownModallyData) => void, thisArg?: any): void; + on(event: "shownModally", callback: (args: ShownModallyData) => void, thisArg?: any); _onAttachedToWindow(): void; onBackPressed(): boolean; _onDetachedFromWindow(): void; @@ -2949,13 +2952,13 @@ export class WebView extends View { public static loadStartedEvent: string; + on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); + // Warning: (ae-forgotten-export) The symbol "LoadEventData" needs to be exported by the entry point index.d.ts on(event: "loadFinished", callback: (args: LoadEventData) => void, thisArg?: any); on(event: "loadStarted", callback: (args: LoadEventData) => void, thisArg?: any); - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); - reload(); src: string; From 60ac4e7a05c9e627eb9fc7a1bdf004c7fca99817 Mon Sep 17 00:00:00 2001 From: Shailesh Lolam Date: Tue, 19 Nov 2019 07:36:08 -0700 Subject: [PATCH 2/4] fix(iOS): Opening alert/confirm on top most of modal dialogs (#7982) This is fix for the issue #6939 where alert() and confirm() does not work in a modal dialog if it's opened on top of an existing modal dialog. --- nativescript-core/ui/dialogs/dialogs.ios.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nativescript-core/ui/dialogs/dialogs.ios.ts b/nativescript-core/ui/dialogs/dialogs.ios.ts index d8276adeb..f7eb1dbe6 100644 --- a/nativescript-core/ui/dialogs/dialogs.ios.ts +++ b/nativescript-core/ui/dialogs/dialogs.ios.ts @@ -205,6 +205,11 @@ function showUIAlertController(alertController: UIAlertController) { if (currentView) { currentView = currentView.modal || currentView; + //get to the top most view controller on the stack + while (currentView && currentView.modal) { + currentView = currentView.modal; + } + let viewController: UIViewController = currentView.ios; if (viewController.presentedViewController) { From c5df2580439c24c57fb364cba91050a00e391c35 Mon Sep 17 00:00:00 2001 From: Alexander Djenkov Date: Wed, 20 Nov 2019 10:00:54 +0200 Subject: [PATCH 3/4] feat(modal-view-ios): handle iOS 13 dismiss modal gesture (#8024) * feat(modal-view): introduce cancelable property on ShowModalOptions * fix(modal-view): handle iOS 13 modal dismiss gesture * chore: address PR comments --- .../ui/core/view-base/view-base.d.ts | 5 ++ .../ui/core/view/view.android.ts | 11 +++- nativescript-core/ui/core/view/view.ios.ts | 60 ++++++++++++++++--- 3 files changed, 67 insertions(+), 9 deletions(-) diff --git a/nativescript-core/ui/core/view-base/view-base.d.ts b/nativescript-core/ui/core/view-base/view-base.d.ts index d0618064e..28023a771 100644 --- a/nativescript-core/ui/core/view-base/view-base.d.ts +++ b/nativescript-core/ui/core/view-base/view-base.d.ts @@ -83,10 +83,15 @@ export interface ShowModalOptions { } android?: { /** + * @deprecated Use ShowModalOptions.cancelable instead. * An optional parameter specifying whether the modal view can be dismissed when not in full-screen mode. */ cancelable?: boolean } + /** + * An optional parameter specifying whether the modal view can be dismissed when not in full-screen mode. + */ + cancelable?: boolean } export abstract class ViewBase extends Observable { diff --git a/nativescript-core/ui/core/view/view.android.ts b/nativescript-core/ui/core/view/view.android.ts index 5b42e0047..c6a3132f2 100644 --- a/nativescript-core/ui/core/view/view.android.ts +++ b/nativescript-core/ui/core/view/view.android.ts @@ -640,12 +640,21 @@ export class View extends ViewCommon { args.putInt(DOMID, this._domId); df.setArguments(args); + let cancelable = true; + + if (options.android && (options).android.cancelable !== undefined) { + cancelable = !!(options).android.cancelable; + console.log("ShowModalOptions.android.cancelable is deprecated. Use ShowModalOptions.cancelable instead."); + } + + cancelable = options.cancelable !== undefined ? !!options.cancelable : cancelable; + const dialogOptions: DialogOptions = { owner: this, fullscreen: !!options.fullscreen, animated: !!options.animated, stretched: !!options.stretched, - cancelable: options.android ? !!options.android.cancelable : true, + cancelable: cancelable, shownCallback: () => this._raiseShownModallyEvent(), dismissCallback: () => this.closeModal() }; diff --git a/nativescript-core/ui/core/view/view.ios.ts b/nativescript-core/ui/core/view/view.ios.ts index 83c5e4ce2..ac9cc56d2 100644 --- a/nativescript-core/ui/core/view/view.ios.ts +++ b/nativescript-core/ui/core/view/view.ios.ts @@ -30,6 +30,7 @@ export class View extends ViewCommon { nativeViewProtected: UIView; viewController: UIViewController; private _popoverPresentationDelegate: ios.UIPopoverPresentationControllerDelegateImp; + private _adaptivePresentationDelegate: ios.UIAdaptivePresentationControllerDelegateImp; private _isLaidOut = false; private _hasTransfrom = false; @@ -422,14 +423,19 @@ export class View extends ViewCommon { controller.modalPresentationStyle = presentationStyle; if (presentationStyle === UIModalPresentationStyle.Popover) { - const popoverPresentationController = controller.popoverPresentationController; - this._popoverPresentationDelegate = ios.UIPopoverPresentationControllerDelegateImp.initWithOwnerAndCallback(new WeakRef(this), this._closeModalCallback); - popoverPresentationController.delegate = this._popoverPresentationDelegate; - const view = parent.nativeViewProtected; - // Note: sourceView and sourceRect are needed to specify the anchor location for the popover. - // Note: sourceView should be the button triggering the modal. If it the Page the popover might appear "behind" the page content - popoverPresentationController.sourceView = view; - popoverPresentationController.sourceRect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height); + this._setupPopoverControllerDelegate(controller, parent); + } + } + + const cancelable = options.cancelable !== undefined ? !!options.cancelable : true; + + if (majorVersion >= 13) { + if (cancelable) { + // Listen for dismiss modal callback. + this._setupAdaptiveControllerDelegate(controller); + } else { + // Prevent users from dismissing the modal. + (controller).modalInPresentation = true; } } @@ -644,6 +650,22 @@ export class View extends ViewCommon { backgroundInternal.hasBorderWidth() || backgroundInternal.hasBorderRadius(); } + + private _setupPopoverControllerDelegate(controller: UIViewController, parent: View) { + const popoverPresentationController = controller.popoverPresentationController; + this._popoverPresentationDelegate = ios.UIPopoverPresentationControllerDelegateImp.initWithOwnerAndCallback(new WeakRef(this), this._closeModalCallback); + popoverPresentationController.delegate = this._popoverPresentationDelegate; + const view = parent.nativeViewProtected; + // Note: sourceView and sourceRect are needed to specify the anchor location for the popover. + // Note: sourceView should be the button triggering the modal. If it the Page the popover might appear "behind" the page content + popoverPresentationController.sourceView = view; + popoverPresentationController.sourceRect = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height); + } + + private _setupAdaptiveControllerDelegate(controller: UIViewController) { + this._adaptivePresentationDelegate = ios.UIAdaptivePresentationControllerDelegateImp.initWithOwnerAndCallback(new WeakRef(this), this._closeModalCallback); + controller.presentationController.delegate = this._adaptivePresentationDelegate; + } } View.prototype._nativeBackgroundState = "unset"; @@ -1019,6 +1041,28 @@ export namespace ios { } } + export class UIAdaptivePresentationControllerDelegateImp extends NSObject implements UIAdaptivePresentationControllerDelegate { + public static ObjCProtocols = [UIAdaptivePresentationControllerDelegate]; + + private owner: WeakRef; + private closedCallback: Function; + + public static initWithOwnerAndCallback(owner: WeakRef, whenClosedCallback: Function): UIAdaptivePresentationControllerDelegateImp { + const instance = super.new(); + instance.owner = owner; + instance.closedCallback = whenClosedCallback; + + return instance; + } + + public presentationControllerDidDismiss(presentationController: UIPresentationController) { + const owner = this.owner.get(); + if (owner && typeof this.closedCallback === "function") { + this.closedCallback(); + } + } + } + export class UIPopoverPresentationControllerDelegateImp extends NSObject implements UIPopoverPresentationControllerDelegate { public static ObjCProtocols = [UIPopoverPresentationControllerDelegate]; From 04f87e37acc0f39796e2d821bfcfbd60b30076ab Mon Sep 17 00:00:00 2001 From: suijaa <56831512+suijaa@users.noreply.github.com> Date: Wed, 20 Nov 2019 13:48:14 +0530 Subject: [PATCH 4/4] docs(changelog): typo (#8121) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 788d329cf..0e56ca170 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1141,7 +1141,7 @@ A full list of breaking changes could be found [here](https://github.com/NativeS - [(#2834)](https://github.com/NativeScript/NativeScript/issues/2834) Animations: scale() syntax does not support only one argument -- [(#2813)](https://github.com/NativeScript/NativeScript/issues/2813) The Camera module in Android doesn't handle pemissions for you +- [(#2813)](https://github.com/NativeScript/NativeScript/issues/2813) The Camera module in Android doesn't handle permissions for you - [(#2789)](https://github.com/NativeScript/NativeScript/issues/2789) CSS border-width causes text to overflow TextView