From 0ff21d7e5e0004b1251f79bd2b5ce160c00e462d Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Thu, 27 Aug 2020 09:19:59 +0200 Subject: [PATCH 001/363] onListenerAdded and onListenerRemoved --- packages/core/data/observable/index.d.ts | 13 +++++++++++++ packages/core/data/observable/index.ts | 7 ++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/core/data/observable/index.d.ts b/packages/core/data/observable/index.d.ts index 77c0f19ed7..b972635bf9 100644 --- a/packages/core/data/observable/index.d.ts +++ b/packages/core/data/observable/index.d.ts @@ -163,6 +163,19 @@ export class Observable { */ public _isViewBase: boolean; //@endprivate + + /** + * This method is intended to be overriden by inheritors to be notified when a new listener is added + * count is the number of listeners for that event after addition + */ + onListenerAdded(eventName: string, count: number); + + /** + * This method is intended to be overriden by inheritors to be notified when a new listener is removed + * count is the number of listeners for that event after removal + */ + onListenerRemoved(eventName: string, count: number); + } /** diff --git a/packages/core/data/observable/index.ts b/packages/core/data/observable/index.ts index fcd38e9f30..87c2a6d582 100644 --- a/packages/core/data/observable/index.ts +++ b/packages/core/data/observable/index.ts @@ -98,7 +98,9 @@ export class Observable implements ObservableDefinition { public off(eventNames: string, callback?: any, thisArg?: any): void { this.removeEventListener(eventNames, callback, thisArg); } - + onListenerAdded(eventName: string, count: number) {} + onListenerRemoved(eventName: string, count: number) {} + public addEventListener(eventNames: string, callback: (data: EventData) => void, thisArg?: any): void { if (typeof eventNames !== 'string') { throw new TypeError('Events name(s) must be string.'); @@ -117,6 +119,7 @@ export class Observable implements ObservableDefinition { callback: callback, thisArg: thisArg, }); + this.onListenerAdded(event, list.length ); } } @@ -143,9 +146,11 @@ export class Observable implements ObservableDefinition { delete this._observers[event]; } } + this.onListenerRemoved(event, list ? list.length : 0); } else { this._observers[event] = undefined; delete this._observers[event]; + this.onListenerRemoved(event, 0); } } } From 3fbeacec41ff5068d1395e4366dda8ee65539321 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Thu, 27 Aug 2020 09:21:34 +0200 Subject: [PATCH 002/363] fix(android): dont dispose fragment on onloaded rely on android logic --- packages/core/ui/frame/index.android.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/core/ui/frame/index.android.ts b/packages/core/ui/frame/index.android.ts index 91cd684088..d11f8fcca7 100644 --- a/packages/core/ui/frame/index.android.ts +++ b/packages/core/ui/frame/index.android.ts @@ -241,11 +241,6 @@ export class Frame extends FrameBase { onUnloaded() { super.onUnloaded(); - - // calling dispose fragment after super.onUnloaded() means we are not relying on the built-in Android logic - // to automatically remove child fragments when parent fragment is removed; - // this fixes issue with missing nested fragment on app suspend / resume; - this.disposeCurrentFragment(); } private disposeCurrentFragment(): void { From 582f5fa6eb7dc00333bffd4c4db254fda20b059f Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Fri, 7 Aug 2020 11:33:26 +0200 Subject: [PATCH 003/363] dont use replace transaction anymore. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That way we dont “unload” and “load” fragments. This fixes black screens and slow transitions with opengl or cameras # Conflicts: # packages/core/ui/frame/fragment.transitions.android.ts # packages/core/ui/frame/frame-common.ts # packages/core/ui/frame/index.android.ts --- .../ui/frame/fragment.transitions.android.ts | 3 +- packages/core/ui/frame/frame-common.ts | 4 --- packages/core/ui/frame/index.android.ts | 30 +++++++++++++++++-- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/packages/core/ui/frame/fragment.transitions.android.ts b/packages/core/ui/frame/fragment.transitions.android.ts index 83fe2dd1a1..cea73620d6 100644 --- a/packages/core/ui/frame/fragment.transitions.android.ts +++ b/packages/core/ui/frame/fragment.transitions.android.ts @@ -143,13 +143,12 @@ export function _setAndroidFragmentTransitions(animated: boolean, navigationTran if (currentFragmentNeedsDifferentAnimation) { setupCurrentFragmentFadeTransition(navigationTransition, currentEntry); } - } else if (name === 'explode') { + } else if (name === 'explode') { setupNewFragmentExplodeTransition(navigationTransition, newEntry); if (currentFragmentNeedsDifferentAnimation) { setupCurrentFragmentExplodeTransition(navigationTransition, currentEntry); } } else if (name.indexOf('flip') === 0) { - navigationTransition = { duration: 3000, curve: null }; const direction = name.substr('flip'.length) || 'right'; //Extract the direction from the string const flipTransition = new FlipTransition(direction, navigationTransition.duration, navigationTransition.curve); diff --git a/packages/core/ui/frame/frame-common.ts b/packages/core/ui/frame/frame-common.ts index e89038db25..f8b98e87e6 100644 --- a/packages/core/ui/frame/frame-common.ts +++ b/packages/core/ui/frame/frame-common.ts @@ -296,10 +296,6 @@ export class FrameBase extends CustomLayoutView { private raiseCurrentPageNavigatedEvents(isBack: boolean) { const page = this.currentPage; if (page) { - if (page.isLoaded) { - // Forward navigation does not remove page from frame so we raise unloaded manually. - page.callUnloaded(); - } page.onNavigatedFrom(isBack); } } diff --git a/packages/core/ui/frame/index.android.ts b/packages/core/ui/frame/index.android.ts index 91cd684088..40d1af1990 100644 --- a/packages/core/ui/frame/index.android.ts +++ b/packages/core/ui/frame/index.android.ts @@ -324,6 +324,8 @@ export class Frame extends FrameBase { // If we had real navigation process queue. this._processNavigationQueue(entry.resolvedPage); + + } else { // Otherwise currentPage was recreated so this wasn't real navigation. // Continue with next item in the queue. @@ -436,7 +438,7 @@ export class Frame extends FrameBase { //transaction.setTransition(androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN); } - transaction.replace(this.containerViewId, newFragment, newFragmentTag); + transaction.add(this.containerViewId, newFragment, newFragmentTag); transaction.commitAllowingStateLoss(); } @@ -458,8 +460,30 @@ export class Frame extends FrameBase { _reverseTransitions(backstackEntry, this._currentEntry); - transaction.replace(this.containerViewId, backstackEntry.fragment, backstackEntry.fragmentTag); - + const currentIndex =this.backStack.length; + const gotBackToIndex = this.backStack.indexOf(backstackEntry); + + for (let index = gotBackToIndex + 1; index < currentIndex; index++) { + transaction.remove(this.backStack[index].fragment); + } + if (this._currentEntry !== backstackEntry) { + // if we are going back we need to store where we are backing to + // so that we can set the current entry + if ((this._currentEntry as any).exitTransitionListener) { + (this._currentEntry as any).exitTransitionListener.backEntry = backstackEntry; + } + if ((this._currentEntry as any).returnTransitionListener) { + (this._currentEntry as any).returnTransitionListener.backEntry = backstackEntry; + } + if ((this._currentEntry as any).enterTransitionListener) { + (this._currentEntry as any).enterTransitionListener.backEntry = backstackEntry; + } + if ((this._currentEntry as any).reenterTransitionListener) { + (this._currentEntry as any).reenterTransitionListener.backEntry = backstackEntry; + } + transaction.remove((this._currentEntry).fragment); + + } transaction.commitAllowingStateLoss(); } From b127f12bbbf7d8f6f97b5d06f621377d3205a509 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Thu, 27 Aug 2020 09:25:01 +0200 Subject: [PATCH 004/363] another try at fixing transitions --- .../ui/frame/fragment.transitions.android.ts | 18 +++++++++---- packages/core/ui/frame/index.android.ts | 26 ++++++++----------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/packages/core/ui/frame/fragment.transitions.android.ts b/packages/core/ui/frame/fragment.transitions.android.ts index cea73620d6..8840733b9b 100644 --- a/packages/core/ui/frame/fragment.transitions.android.ts +++ b/packages/core/ui/frame/fragment.transitions.android.ts @@ -26,6 +26,7 @@ let AnimationListener: android.animation.Animator.AnimatorListener; interface ExpandedTransitionListener extends androidx.transition.Transition.TransitionListener { entry: ExpandedEntry; + backEntry?: BackstackEntry; transition: androidx.transition.Transition; } @@ -223,6 +224,7 @@ function getAnimationListener(): android.animation.Animator.AnimatorListener { onAnimationStart(animator: ExpandedAnimator): void { const entry = animator.entry; + const backEntry = animator.backEntry; addToWaitingQueue(entry); if (Trace.isEnabled()) { Trace.write(`START ${animator.transitionType} for ${entry.fragmentTag}`, Trace.categories.Transition); @@ -236,10 +238,13 @@ function getAnimationListener(): android.animation.Animator.AnimatorListener { } onAnimationEnd(animator: ExpandedAnimator): void { + const entry = animator.entry; + const backEntry = animator.backEntry; if (Trace.isEnabled()) { - Trace.write(`END ${animator.transitionType} for ${animator.entry.fragmentTag}`, Trace.categories.Transition); + Trace.write(`END ${animator.transitionType} for ${entry.fragmentTag} backEntry:${backEntry ? backEntry.fragmentTag : 'none'}`, Trace.categories.Transition); } - transitionOrAnimationCompleted(animator.entry, animator.backEntry); + transitionOrAnimationCompleted(entry, backEntry); + animator.backEntry = null; } onAnimationCancel(animator: ExpandedAnimator): void { @@ -345,10 +350,12 @@ function getTransitionListener(entry: ExpandedEntry, transition: androidx.transi onTransitionEnd(transition: androidx.transition.Transition): void { const entry = this.entry; + const backEntry = this.backEntry; if (Trace.isEnabled()) { - Trace.write(`END ${toShortString(transition)} transition for ${entry.fragmentTag}`, Trace.categories.Transition); + Trace.write(`END ${toShortString(transition)} transition for ${entry.fragmentTag} backEntry:${backEntry ? backEntry.fragmentTag : 'none'}`, Trace.categories.Transition); } - transitionOrAnimationCompleted(entry, this.backEntry); + transitionOrAnimationCompleted(entry, backEntry); + this.backEntry = null; } onTransitionResume(transition: androidx.transition.Transition): void { @@ -497,7 +504,7 @@ function setEnterTransition(navigationTransition: NavigationTransition, entry: E fragment.setEnterTransition(transition); } -function setExitTransition(navigationTransition: NavigationTransition, entry: ExpandedEntry, transition: androidx.transition.Transition): void { +function xsetExitTransition(navigationTransition: NavigationTransition, entry: ExpandedEntry, transition: androidx.transition.Transition): void { setUpNativeTransition(navigationTransition, transition); const listener = addNativeTransitionListener(entry, transition); @@ -660,6 +667,7 @@ function transitionOrAnimationCompleted(entry: ExpandedEntry, backEntry: Backsta if (!entries) { return; } + console.log('transitionOrAnimationCompleted', frameId, backEntry && backEntry.fragmentTag, waitingQueue.size, entries.size, completedEntries.size ); entries.delete(entry); if (entries.size === 0) { diff --git a/packages/core/ui/frame/index.android.ts b/packages/core/ui/frame/index.android.ts index 40d1af1990..ef82d67438 100644 --- a/packages/core/ui/frame/index.android.ts +++ b/packages/core/ui/frame/index.android.ts @@ -19,6 +19,7 @@ import { Builder } from '../builder'; import { CSSUtils } from '../../css/system-classes'; import { Device } from '../../platform'; import { profile } from '../../profiling'; +import { ExpandedEntry } from './fragment.transitions.android'; export * from './frame-common'; @@ -463,26 +464,21 @@ export class Frame extends FrameBase { const currentIndex =this.backStack.length; const gotBackToIndex = this.backStack.indexOf(backstackEntry); - for (let index = gotBackToIndex + 1; index < currentIndex; index++) { - transaction.remove(this.backStack[index].fragment); - } + // the order is important so that the transition listener called be + // the one from the current entry we are going back from if (this._currentEntry !== backstackEntry) { + const entry = this._currentEntry as ExpandedEntry; // if we are going back we need to store where we are backing to // so that we can set the current entry - if ((this._currentEntry as any).exitTransitionListener) { - (this._currentEntry as any).exitTransitionListener.backEntry = backstackEntry; - } - if ((this._currentEntry as any).returnTransitionListener) { - (this._currentEntry as any).returnTransitionListener.backEntry = backstackEntry; - } - if ((this._currentEntry as any).enterTransitionListener) { - (this._currentEntry as any).enterTransitionListener.backEntry = backstackEntry; + // it only needs to be done on the return transition + if (entry.returnTransitionListener) { + entry.returnTransitionListener.backEntry = backstackEntry; } - if ((this._currentEntry as any).reenterTransitionListener) { - (this._currentEntry as any).reenterTransitionListener.backEntry = backstackEntry; - } - transaction.remove((this._currentEntry).fragment); + transaction.remove((this._currentEntry).fragment); + } + for (let index = gotBackToIndex + 1; index < currentIndex; index++) { + transaction.remove(this.backStack[index].fragment); } transaction.commitAllowingStateLoss(); } From c1e710a614470333b5ec0244cab514579136b388 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 24 Aug 2020 11:07:29 +0200 Subject: [PATCH 005/363] use replace when navigating with clearHistory --- packages/core/ui/frame/index.android.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/core/ui/frame/index.android.ts b/packages/core/ui/frame/index.android.ts index ef82d67438..6143a24167 100644 --- a/packages/core/ui/frame/index.android.ts +++ b/packages/core/ui/frame/index.android.ts @@ -439,7 +439,11 @@ export class Frame extends FrameBase { //transaction.setTransition(androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN); } - transaction.add(this.containerViewId, newFragment, newFragmentTag); + if (clearHistory) { + transaction.replace(this.containerViewId, newFragment, newFragmentTag); + } else { + transaction.add(this.containerViewId, newFragment, newFragmentTag); + } transaction.commitAllowingStateLoss(); } From 392e2c8d59551c4183538234d8c63a3d747e72e1 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 24 Aug 2020 11:14:36 +0200 Subject: [PATCH 006/363] still unload page if navigation is replace or is back or clearHistory is used --- packages/core/ui/frame/frame-common.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/core/ui/frame/frame-common.ts b/packages/core/ui/frame/frame-common.ts index f8b98e87e6..6f4a5c5260 100644 --- a/packages/core/ui/frame/frame-common.ts +++ b/packages/core/ui/frame/frame-common.ts @@ -259,7 +259,7 @@ export class FrameBase extends CustomLayoutView { public _updateBackstack(entry: BackstackEntry, navigationType: NavigationType): void { const isBack = navigationType === NavigationType.back; const isReplace = navigationType === NavigationType.replace; - this.raiseCurrentPageNavigatedEvents(isBack); + this.raiseCurrentPageNavigatedEvents(isBack, isReplace, entry.entry.clearHistory); const current = this._currentEntry; // Do nothing for Hot Module Replacement @@ -293,9 +293,14 @@ export class FrameBase extends CustomLayoutView { return false; } - private raiseCurrentPageNavigatedEvents(isBack: boolean) { + private raiseCurrentPageNavigatedEvents(isBack: boolean, isReplace: boolean, clearHistory: boolean) { const page = this.currentPage; if (page) { + if ((isBack || isReplace || clearHistory) && page.isLoaded) { + console.log('unloading current page'); + // Forward navigation does not remove page from frame so we raise unloaded manually. + page.callUnloaded(); + } page.onNavigatedFrom(isBack); } } From 9a5d99e241a0453a347d76fcf1aab00eb591f2ad Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 24 Aug 2020 11:14:50 +0200 Subject: [PATCH 007/363] also use replace when replacing frame page --- packages/core/ui/frame/index.android.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/ui/frame/index.android.ts b/packages/core/ui/frame/index.android.ts index 6143a24167..0c876dc065 100644 --- a/packages/core/ui/frame/index.android.ts +++ b/packages/core/ui/frame/index.android.ts @@ -439,7 +439,7 @@ export class Frame extends FrameBase { //transaction.setTransition(androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN); } - if (clearHistory) { + if (clearHistory || isReplace) { transaction.replace(this.containerViewId, newFragment, newFragmentTag); } else { transaction.add(this.containerViewId, newFragment, newFragmentTag); From d41195e3f97ffc1e71a2625c9dc1a53993efd2f7 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 24 Aug 2020 11:25:02 +0200 Subject: [PATCH 008/363] in fact this does not seem to be necessary anymore --- packages/core/ui/frame/frame-common.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/core/ui/frame/frame-common.ts b/packages/core/ui/frame/frame-common.ts index 6f4a5c5260..f8b98e87e6 100644 --- a/packages/core/ui/frame/frame-common.ts +++ b/packages/core/ui/frame/frame-common.ts @@ -259,7 +259,7 @@ export class FrameBase extends CustomLayoutView { public _updateBackstack(entry: BackstackEntry, navigationType: NavigationType): void { const isBack = navigationType === NavigationType.back; const isReplace = navigationType === NavigationType.replace; - this.raiseCurrentPageNavigatedEvents(isBack, isReplace, entry.entry.clearHistory); + this.raiseCurrentPageNavigatedEvents(isBack); const current = this._currentEntry; // Do nothing for Hot Module Replacement @@ -293,14 +293,9 @@ export class FrameBase extends CustomLayoutView { return false; } - private raiseCurrentPageNavigatedEvents(isBack: boolean, isReplace: boolean, clearHistory: boolean) { + private raiseCurrentPageNavigatedEvents(isBack: boolean) { const page = this.currentPage; if (page) { - if ((isBack || isReplace || clearHistory) && page.isLoaded) { - console.log('unloading current page'); - // Forward navigation does not remove page from frame so we raise unloaded manually. - page.callUnloaded(); - } page.onNavigatedFrom(isBack); } } From be15327dccd37d87715a2b52b06d15eff1dcdd42 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 24 Aug 2020 17:02:42 +0200 Subject: [PATCH 009/363] typo fix --- packages/core/ui/frame/fragment.transitions.android.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/ui/frame/fragment.transitions.android.ts b/packages/core/ui/frame/fragment.transitions.android.ts index 8840733b9b..76cf449242 100644 --- a/packages/core/ui/frame/fragment.transitions.android.ts +++ b/packages/core/ui/frame/fragment.transitions.android.ts @@ -504,7 +504,7 @@ function setEnterTransition(navigationTransition: NavigationTransition, entry: E fragment.setEnterTransition(transition); } -function xsetExitTransition(navigationTransition: NavigationTransition, entry: ExpandedEntry, transition: androidx.transition.Transition): void { +function setExitTransition(navigationTransition: NavigationTransition, entry: ExpandedEntry, transition: androidx.transition.Transition): void { setUpNativeTransition(navigationTransition, transition); const listener = addNativeTransitionListener(entry, transition); From 5fcfb753509c9ca72c1a805afba3eb42e8f2b56b Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Thu, 27 Aug 2020 09:07:25 +0200 Subject: [PATCH 010/363] android fragment transitions fully working now --- packages/core/ui/frame/frame-common.ts | 2 +- packages/core/ui/frame/index.android.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/core/ui/frame/frame-common.ts b/packages/core/ui/frame/frame-common.ts index f8b98e87e6..f52530aa3e 100644 --- a/packages/core/ui/frame/frame-common.ts +++ b/packages/core/ui/frame/frame-common.ts @@ -259,8 +259,8 @@ export class FrameBase extends CustomLayoutView { public _updateBackstack(entry: BackstackEntry, navigationType: NavigationType): void { const isBack = navigationType === NavigationType.back; const isReplace = navigationType === NavigationType.replace; - this.raiseCurrentPageNavigatedEvents(isBack); const current = this._currentEntry; + this.raiseCurrentPageNavigatedEvents(isBack); // Do nothing for Hot Module Replacement if (isBack) { diff --git a/packages/core/ui/frame/index.android.ts b/packages/core/ui/frame/index.android.ts index 0c876dc065..6cc4af7ff6 100644 --- a/packages/core/ui/frame/index.android.ts +++ b/packages/core/ui/frame/index.android.ts @@ -444,6 +444,9 @@ export class Frame extends FrameBase { } else { transaction.add(this.containerViewId, newFragment, newFragmentTag); } + if (this._currentEntry && this._currentEntry.entry.backstackVisible === false) { + transaction.remove(this._currentEntry.fragment); + } transaction.commitAllowingStateLoss(); } @@ -466,7 +469,7 @@ export class Frame extends FrameBase { _reverseTransitions(backstackEntry, this._currentEntry); const currentIndex =this.backStack.length; - const gotBackToIndex = this.backStack.indexOf(backstackEntry); + const goBackToIndex = this.backStack.indexOf(backstackEntry); // the order is important so that the transition listener called be // the one from the current entry we are going back from @@ -481,9 +484,10 @@ export class Frame extends FrameBase { transaction.remove((this._currentEntry).fragment); } - for (let index = gotBackToIndex + 1; index < currentIndex; index++) { + for (let index = goBackToIndex + 1; index < currentIndex; index++) { transaction.remove(this.backStack[index].fragment); } + transaction.commitAllowingStateLoss(); } From 53c8234b23457b144785acd9b47df0dfc4b8395a Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Thu, 27 Aug 2020 09:08:05 +0200 Subject: [PATCH 011/363] test fix for new navigation event order --- apps/automated/app/ui/page/page-tests-common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/automated/app/ui/page/page-tests-common.ts b/apps/automated/app/ui/page/page-tests-common.ts index 74ef945430..08ee90412c 100644 --- a/apps/automated/app/ui/page/page-tests-common.ts +++ b/apps/automated/app/ui/page/page-tests-common.ts @@ -181,7 +181,7 @@ function _test_PageNavigation_EventSequence(withTransition: boolean) { helper.navigateWithEntry(navigationEntry); helper.goBack(); - const expectedEventSequence = ['navigatingTo', 'loaded', 'navigatedTo', 'navigatingFrom', 'unloaded', 'navigatedFrom']; + const expectedEventSequence = ['navigatingTo', 'loaded', 'navigatedTo', 'navigatingFrom', 'navigatedFrom', 'unloaded']; TKUnit.arrayAssert(eventSequence, expectedEventSequence, 'Actual event sequence is not equal to expected. Actual: ' + eventSequence + '; Expected: ' + expectedEventSequence); } From d2382a5790405698f69f0b82800f8a817e03655c Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 7 Sep 2020 14:09:22 +0200 Subject: [PATCH 012/363] chore: allow the use of npm/pnpm to build --- package.json | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e3698a46f6..76a10d0d45 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,36 @@ "version": "7.0.0-rc.54", "license": "MIT", "scripts": { - "setup": "npx rimraf -- hooks node_modules package-lock.json && npm i && ts-patch install && nx run core:setup", - "start": "nps" + "setup": "rimraf -- hooks node_modules package-lock.json && ${NPM:npm} i && ts-patch install && npm run core:setup", + "start": "nps", + "clean":"rimraf -- hooks node_modules platforms package-lock.json webpack.config.js", + "apps-automated:ios":"cd apps/automated && tns debug ios --no-hmr --emulator --env.testing", + "apps-automated:android":"cd apps/automated && tns debug android --no-hmr --emulator --env.testing", + "apps-automated:clean":"cd apps/automated && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && ${NPM:npm} i && rimraf -- package-lock.json", + "apps-toolbox:ios":"cd apps/toolbox && tns debug ios --no-hmr --emulator --env.testing", + "apps-toolbox:android":"cd apps/toolbox && tns debug android --no-hmr --emulator --env.testing", + "apps-toolbox:clean":"cd apps/toolbox && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && ${NPM:npm} i && rimraf -- package-lock.json", + "apps-ui:ios":"cd apps/ui && tns debug ios --no-hmr --emulator --env.testing", + "apps-ui:android":"cd apps/ui && tns debug android --no-hmr --emulator --env.testing", + "apps-ui:clean":"cd apps/ui && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && ${NPM:npm} i && rimraf -- package-lock.json", + "core:lint":"cd packages/core && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/core/**", + "core:test":"cd packages/core && jest --config jest.config.js", + "core:setup":"cd packages/core && nx run webpack:build", + "core:build":"tsc --build packages/core/tsconfig.lib.json --outDir dist/packages/core && copyfiles -u packages/core/*.md dist/packages/core", + "core:build.npm":"npm run core:build && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/**/*.d.ts\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/js-libs/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/cli-hooks/**/*.js\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/platforms/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/fetch/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/css/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/css-value/**/*\" dist && cd dist/packages/core && npm pack && mv *.tgz ..", + "core:unit":"tsc -p packages/core/__tests__ && mocha --config=packages/core/__tests__/.mocharc.yml", + "core:unit.watch":"tsc -p packages/core/__tests__ && mocha --watch --config=packages/core/__tests__/.mocharc.yml", + "core-compat:build":"cd packages/core-compat && rimraf -- node_modules package-lock.json && ${NPM:npm} i && tsc -p tsconfig.json && mv \"$(npm pack | tail -n 1)\" ../../dist/packages/tns-core-modules.tgz", + "types-ios:lint":"cd packages/types-ios && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-ios/**", + "types-ios:test":"cd packages/types-ios && jest --config jest.config.js --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-ios/**", + "types-ios:build":"cd packages/types-ios && tsc -p tsconfig.lib.json && copyfiles package.json *.md ../dist/packages/types-ios", + "types-android:lint":"cd packages/types-android && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-android/**", + "types-android:test":"cd packages/types-android && jest --config jest.config.js --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-android/**", + "types-android:build":"cd packages/types-android && tsc -p tsconfig.lib.json && copyfiles package.json *.md ../dist/packages/types-android", + "ui-mobile-base:build":"cd packages/ui-mobile-base && ./build.sh && copyfiles dist/package/platforms/* ../../packages/core/platforms", + "webpack:lint":"cd packages/webpack && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/webpack/**", + "webpack:test":"cd packages/webpack && npm run tsc && npm run jasmine", + "webpack:build":"npm run setup && mkdir -p ../../dist/packages && mv \"$(npm pack | tail -n 1)\" ../../dist/packages/nativescript-webpack.tgz" }, "private": true, "dependencies": { From 6e274675be76c6d0219e6cd1ae5562936734263c Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 7 Sep 2020 15:18:29 +0200 Subject: [PATCH 013/363] chore: fixed npm scripts --- package.json | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 76a10d0d45..eecd9da3f5 100644 --- a/package.json +++ b/package.json @@ -16,23 +16,23 @@ "apps-ui:android":"cd apps/ui && tns debug android --no-hmr --emulator --env.testing", "apps-ui:clean":"cd apps/ui && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && ${NPM:npm} i && rimraf -- package-lock.json", "core:lint":"cd packages/core && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/core/**", - "core:test":"cd packages/core && jest --config jest.config.js", - "core:setup":"cd packages/core && nx run webpack:build", - "core:build":"tsc --build packages/core/tsconfig.lib.json --outDir dist/packages/core && copyfiles -u packages/core/*.md dist/packages/core", + "core:test":"cd packages/core && jest", + "core:setup":"npm run webpack:build", + "core:build":"tsc -p packages/core/tsconfig.lib.json --outDir dist/packages/core && copyfiles -u packages/core/*.md packages/core/package.json dist/packages/core", "core:build.npm":"npm run core:build && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/**/*.d.ts\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/js-libs/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/cli-hooks/**/*.js\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/platforms/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/fetch/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/css/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/css-value/**/*\" dist && cd dist/packages/core && npm pack && mv *.tgz ..", - "core:unit":"tsc -p packages/core/__tests__ && mocha --config=packages/core/__tests__/.mocharc.yml", - "core:unit.watch":"tsc -p packages/core/__tests__ && mocha --watch --config=packages/core/__tests__/.mocharc.yml", - "core-compat:build":"cd packages/core-compat && rimraf -- node_modules package-lock.json && ${NPM:npm} i && tsc -p tsconfig.json && mv \"$(npm pack | tail -n 1)\" ../../dist/packages/tns-core-modules.tgz", + "core:unit":"cd packages/core/__tests__ && tsc && mocha", + "core:unit.watch":"cd packages/core/__tests__ && tsc && mocha --watch", + "core-compat:build":"cd packages/core-compat && rimraf node_modules package-lock.json && $npm_package_config_npm_alias i && tsc -p tsconfig.json && mv \"$(npm pack | tail -n 1)\" ../../dist/packages/tns-core-modules.tgz", "types-ios:lint":"cd packages/types-ios && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-ios/**", "types-ios:test":"cd packages/types-ios && jest --config jest.config.js --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-ios/**", - "types-ios:build":"cd packages/types-ios && tsc -p tsconfig.lib.json && copyfiles package.json *.md ../dist/packages/types-ios", + "types-ios:build":"rimraf dist/packages/types-ios && cpy '**/*' '../../../dist/packages/types-ios' --cwd=packages/types-ios/src --parents && cpy 'package.json' '*.md' '../../dist/packages/types-ios' --cwd=packages/types-ios --parents", "types-android:lint":"cd packages/types-android && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-android/**", "types-android:test":"cd packages/types-android && jest --config jest.config.js --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-android/**", - "types-android:build":"cd packages/types-android && tsc -p tsconfig.lib.json && copyfiles package.json *.md ../dist/packages/types-android", + "types-android:build":"rimraf dist/packages/types-android && cpy '**/*' '../../../dist/packages/types-android' --cwd=packages/types-android/src --parents && cpy 'package.json' '*.md' '../../dist/packages/types-android' --cwd=packages/types-android --parents", "ui-mobile-base:build":"cd packages/ui-mobile-base && ./build.sh && copyfiles dist/package/platforms/* ../../packages/core/platforms", "webpack:lint":"cd packages/webpack && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/webpack/**", "webpack:test":"cd packages/webpack && npm run tsc && npm run jasmine", - "webpack:build":"npm run setup && mkdir -p ../../dist/packages && mv \"$(npm pack | tail -n 1)\" ../../dist/packages/nativescript-webpack.tgz" + "webpack:build":"cd packages/webpack npm run setup && mkdir -p ../../dist/packages && mv \"$(npm pack | tail -n 1)\" ../../dist/packages/nativescript-webpack.tgz" }, "private": true, "dependencies": { @@ -55,6 +55,7 @@ "chai": "^4.2.0", "conventional-changelog-cli": "^2.0.34", "copyfiles": "^2.3.0", + "cpy-cli": "^3.1.1", "css": "^3.0.0", "css-tree": "^1.0.0-alpha.39", "dotenv": "~8.2.0", @@ -78,7 +79,8 @@ "ts-jest": "~26.1.1", "ts-node": "~8.10.2", "ts-patch": "^1.2.5", - "tslint": "~6.1.2", + "tslib": "~2.0.1", + "tslint": "~6.1.3", "typescript": "~3.9.7", "webpack": "~4.44.1", "webpack-cli": "~3.3.12" From 6c2cfa101b1aa7066e30b2bace920ad60fbe96d1 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 7 Sep 2020 15:18:44 +0200 Subject: [PATCH 014/363] chore(webpack): allow use of pnpm / yarn --- packages/webpack/package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/webpack/package.json b/packages/webpack/package.json index 7584c179cd..180b802081 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -28,8 +28,11 @@ "type": "git", "url": "https://github.com/NativeScript/nativescript-dev-webpack.git" }, + "config": { + "npm_alias":"npm" + }, "scripts": { - "clean": "npx rimraf -- node_modules package-lock.json && npm i --ignore-scripts", + "clean": "npx rimraf -- node_modules package-lock.json && $npm_package_config_npm_alias i --ignore-scripts", "tsc": "tsc", "postinstall": "node postinstall.js", "preuninstall": "node preuninstall.js", From c09c091345eb720667fc132d638578ea5c2a6be5 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 7 Sep 2020 15:18:53 +0200 Subject: [PATCH 015/363] chore: fix transformer path --- packages/core/tsconfig.lib.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/tsconfig.lib.json b/packages/core/tsconfig.lib.json index 1a082d817f..4417a2893e 100644 --- a/packages/core/tsconfig.lib.json +++ b/packages/core/tsconfig.lib.json @@ -17,7 +17,7 @@ "rootDir": "./", "types": ["node"], "plugins": [ - { "transform": "../../../packages/webpack/transformers/ns-transform-native-classes.ts", "type": "raw" } + { "transform": "../webpack/transformers/ns-transform-native-classes.ts", "type": "raw" } ] }, "exclude": ["**/*.spec.ts", "dist", "__tests__"], From b65a1d3c9c4af3d2f80e58928a2acd8cdd5e00af Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 7 Sep 2020 15:27:46 +0200 Subject: [PATCH 016/363] nps should be included --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index f036a53b66..07af9add53 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "module-alias": "^2.2.2", "nativescript": "~7.0.6", "node-sass": "~4.14.1", + "nps":"5.10.0", "parse-css": "git+https://github.com/tabatkins/parse-css.git", "parserlib": "^1.1.1", "prettier": "~2.0.5", From f6e1ab709fe9cd0be5016f27bf16625ca2fcc4e7 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Mon, 7 Sep 2020 16:22:45 +0200 Subject: [PATCH 017/363] chore: lint --- package.json | 58 ++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 07af9add53..8f1676e044 100644 --- a/package.json +++ b/package.json @@ -3,38 +3,38 @@ "version": "7.0.0", "license": "MIT", "config": { - "npm_alias":"npm" + "npm_alias": "npm" }, "scripts": { "setup": "npx rimraf hooks node_modules package-lock.json && $npm_package_config_npm_alias i && ts-patch install && npm run core:setup", "start": "nps", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", - "clean":"rimraf -- hooks node_modules platforms package-lock.json webpack.config.js", - "apps-automated:ios":"cd apps/automated && tns debug ios --no-hmr --emulator --env.testing", - "apps-automated:android":"cd apps/automated && tns debug android --no-hmr --emulator --env.testing", - "apps-automated:clean":"cd apps/automated && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && $npm_package_config_npm_alias i && rimraf -- package-lock.json", - "apps-toolbox:ios":"cd apps/toolbox && tns debug ios --no-hmr --emulator --env.testing", - "apps-toolbox:android":"cd apps/toolbox && tns debug android --no-hmr --emulator --env.testing", - "apps-toolbox:clean":"cd apps/toolbox && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && $npm_package_config_npm_alias i && rimraf -- package-lock.json", - "apps-ui:ios":"cd apps/ui && tns debug ios --no-hmr --emulator --env.testing", - "apps-ui:android":"cd apps/ui && tns debug android --no-hmr --emulator --env.testing", - "apps-ui:clean":"cd apps/ui && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && $npm_package_config_npm_alias i && rimraf -- package-lock.json", - "core:lint":"cd packages/core && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/core/**", - "core:setup":"npm run webpack:build", - "core:build":"tsc -p packages/core/tsconfig.lib.json --outDir dist/packages/core && copyfiles -u packages/core/*.md packages/core/package.json dist/packages/core", - "core:build.npm":"npm run core:build && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/**/*.d.ts\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/js-libs/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/cli-hooks/**/*.js\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/platforms/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/fetch/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/css/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/css-value/**/*\" dist && cd dist/packages/core && npm pack && mv *.tgz ..", - "core:unit":"cd packages/core/__tests__ && tsc && mocha", - "core:unit.watch":"cd packages/core/__tests__ && tsc && mocha --watch", - "core-compat:build":"cd packages/core-compat && rimraf node_modules package-lock.json && $npm_package_config_npm_alias i && tsc -p tsconfig.json && mv \"$(npm pack | tail -n 1)\" ../../dist/packages/tns-core-modules.tgz", - "types-ios:lint":"cd packages/types-ios && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-ios/**", - "types-ios:build":"rimraf dist/packages/types-ios && cpy '**/*' '../../../dist/packages/types-ios' --cwd=packages/types-ios/src --parents && cpy 'package.json' '*.md' '../../dist/packages/types-ios' --cwd=packages/types-ios --parents", - "types-android:lint":"cd packages/types-android && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-android/**", - "types-android:test":"cd packages/types-android && jest --config jest.config.js --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-android/**", - "types-android:build":"rimraf dist/packages/types-android && cpy '**/*' '../../../dist/packages/types-android' --cwd=packages/types-android/src --parents && cpy 'package.json' '*.md' '../../dist/packages/types-android' --cwd=packages/types-android --parents", - "ui-mobile-base:build":"cd packages/ui-mobile-base && ./build.sh && copyfiles dist/package/platforms/* ../../packages/core/platforms", - "webpack:lint":"cd packages/webpack && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/webpack/**", - "webpack:test":"cd packages/webpack && npm run tsc && npm run jasmine", - "webpack:build":"cd packages/webpack npm run setup && mkdir -p ../../dist/packages && mv \"$(npm pack | tail -n 1)\" ../../dist/packages/nativescript-webpack.tgz" + "clean": "rimraf -- hooks node_modules platforms package-lock.json webpack.config.js", + "apps-automated:ios": "cd apps/automated && tns debug ios --no-hmr --emulator --env.testing", + "apps-automated:android": "cd apps/automated && tns debug android --no-hmr --emulator --env.testing", + "apps-automated:clean": "cd apps/automated && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && $npm_package_config_npm_alias i && rimraf -- package-lock.json", + "apps-toolbox:ios": "cd apps/toolbox && tns debug ios --no-hmr --emulator --env.testing", + "apps-toolbox:android": "cd apps/toolbox && tns debug android --no-hmr --emulator --env.testing", + "apps-toolbox:clean": "cd apps/toolbox && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && $npm_package_config_npm_alias i && rimraf -- package-lock.json", + "apps-ui:ios": "cd apps/ui && tns debug ios --no-hmr --emulator --env.testing", + "apps-ui:android": "cd apps/ui && tns debug android --no-hmr --emulator --env.testing", + "apps-ui:clean": "cd apps/ui && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && $npm_package_config_npm_alias i && rimraf -- package-lock.json", + "core:lint": "cd packages/core && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/core/**", + "core:setup": "npm run webpack:build", + "core:build": "tsc -p packages/core/tsconfig.lib.json --outDir dist/packages/core && copyfiles -u packages/core/*.md packages/core/package.json dist/packages/core", + "core:build.npm": "npm run core:build && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/**/*.d.ts\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/js-libs/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/cli-hooks/**/*.js\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/platforms/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/fetch/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/css/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/css-value/**/*\" dist && cd dist/packages/core && npm pack && mv *.tgz ..", + "core:unit": "cd packages/core/__tests__ && tsc && mocha", + "core:unit.watch": "cd packages/core/__tests__ && tsc && mocha --watch", + "core-compat:build": "cd packages/core-compat && rimraf node_modules package-lock.json && $npm_package_config_npm_alias i && tsc -p tsconfig.json && mv \"$(npm pack | tail -n 1)\" ../../dist/packages/tns-core-modules.tgz", + "types-ios:lint": "cd packages/types-ios && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-ios/**", + "types-ios:build": "rimraf dist/packages/types-ios && cpy '**/*' '../../../dist/packages/types-ios' --cwd=packages/types-ios/src --parents && cpy 'package.json' '*.md' '../../dist/packages/types-ios' --cwd=packages/types-ios --parents", + "types-android:lint": "cd packages/types-android && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-android/**", + "types-android:test": "cd packages/types-android && jest --config jest.config.js --ignore-pattern **/node_modules/** --ignore-pattern !packages/types-android/**", + "types-android:build": "rimraf dist/packages/types-android && cpy '**/*' '../../../dist/packages/types-android' --cwd=packages/types-android/src --parents && cpy 'package.json' '*.md' '../../dist/packages/types-android' --cwd=packages/types-android --parents", + "ui-mobile-base:build": "cd packages/ui-mobile-base && ./build.sh && copyfiles dist/package/platforms/* ../../packages/core/platforms", + "webpack:lint": "cd packages/webpack && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/webpack/**", + "webpack:test": "cd packages/webpack && npm run tsc && npm run jasmine", + "webpack:build": "cd packages/webpack npm run setup && mkdir -p ../../dist/packages && mv \"$(npm pack | tail -n 1)\" ../../dist/packages/nativescript-webpack.tgz" }, "private": true, "dependencies": { @@ -72,12 +72,12 @@ "module-alias": "^2.2.2", "nativescript": "~7.0.6", "node-sass": "~4.14.1", - "nps":"5.10.0", + "nps": "5.10.0", "parse-css": "git+https://github.com/tabatkins/parse-css.git", "parserlib": "^1.1.1", "prettier": "~2.0.5", "reduce-css-calc": "~2.1.7", - "rimraf":"3.0.2", + "rimraf": "3.0.2", "shady-css-parser": "^0.1.0", "terser-webpack-plugin": "~3.0.6", "ts-jest": "~26.1.1", From b8df0b3ac051a3e4437e87ed87c9659652255e6c Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Tue, 8 Sep 2020 14:22:22 +0200 Subject: [PATCH 018/363] feat: boolean to disable systemAppearanceChanged (theme) --- packages/core/application/application-common.ts | 4 ++-- packages/core/application/index.d.ts | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/core/application/application-common.ts b/packages/core/application/application-common.ts index 2a083eb320..c7cbc0385b 100644 --- a/packages/core/application/application-common.ts +++ b/packages/core/application/application-common.ts @@ -148,9 +148,9 @@ export function orientationChanged(rootView: View, newOrientation: 'portrait' | applyCssClass(rootModalView, ORIENTATION_CSS_CLASSES, newOrientationCssClass); }); } - +export let autoSystemAppearanceChanged = true; export function systemAppearanceChanged(rootView: View, newSystemAppearance: 'dark' | 'light'): void { - if (!rootView) { + if (!rootView || !autoSystemAppearanceChanged) { return; } diff --git a/packages/core/application/index.d.ts b/packages/core/application/index.d.ts index 9b14fe31ce..217efbecf9 100644 --- a/packages/core/application/index.d.ts +++ b/packages/core/application/index.d.ts @@ -54,6 +54,10 @@ export const orientationChangedEvent: string; */ export const systemAppearanceChangedEvent: string; +/** + * Boolean to enable/disable systemAppearanceChanged + */ +export let autoSystemAppearanceChanged = true; /** * Updates root view classes including those of modals * @param rootView the root view From eee862650d42f854a7f19297c6e01ac8e020a682 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Tue, 8 Sep 2020 14:23:06 +0200 Subject: [PATCH 019/363] chore: renamed core --- packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index 16bc1fa8ae..a83573b0ae 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,5 +1,5 @@ { - "name": "@nativescript/core", + "name": "@akylas/nativescript", "main": "index", "types": "index.d.ts", "description": "NativeScript Core Modules", From 43f1d50a36fb337148b355670b1b880537034c97 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Tue, 8 Sep 2020 14:43:54 +0200 Subject: [PATCH 020/363] fix: need to be a function to work --- packages/core/application/application-common.ts | 5 +++++ packages/core/application/index.d.ts | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/packages/core/application/application-common.ts b/packages/core/application/application-common.ts index c7cbc0385b..d27dee9c5f 100644 --- a/packages/core/application/application-common.ts +++ b/packages/core/application/application-common.ts @@ -149,6 +149,11 @@ export function orientationChanged(rootView: View, newOrientation: 'portrait' | }); } export let autoSystemAppearanceChanged = true; + +export function setAutoSystemAppearanceChanged(value: boolean) { + autoSystemAppearanceChanged = value; +} + export function systemAppearanceChanged(rootView: View, newSystemAppearance: 'dark' | 'light'): void { if (!rootView || !autoSystemAppearanceChanged) { return; diff --git a/packages/core/application/index.d.ts b/packages/core/application/index.d.ts index 217efbecf9..9d0106c3aa 100644 --- a/packages/core/application/index.d.ts +++ b/packages/core/application/index.d.ts @@ -58,6 +58,12 @@ export const systemAppearanceChangedEvent: string; * Boolean to enable/disable systemAppearanceChanged */ export let autoSystemAppearanceChanged = true; + +/** + * enable/disable systemAppearanceChanged + */ +export function setAutoSystemAppearanceChanged (value: boolean); + /** * Updates root view classes including those of modals * @param rootView the root view From 6729bfbbb04a9a5ab7d9f41ae841d7dab81a9c2e Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Wed, 9 Sep 2020 15:12:47 +0200 Subject: [PATCH 021/363] clean up log --- packages/core/ui/frame/fragment.transitions.android.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/ui/frame/fragment.transitions.android.ts b/packages/core/ui/frame/fragment.transitions.android.ts index 76cf449242..9dacfaa009 100644 --- a/packages/core/ui/frame/fragment.transitions.android.ts +++ b/packages/core/ui/frame/fragment.transitions.android.ts @@ -667,7 +667,6 @@ function transitionOrAnimationCompleted(entry: ExpandedEntry, backEntry: Backsta if (!entries) { return; } - console.log('transitionOrAnimationCompleted', frameId, backEntry && backEntry.fragmentTag, waitingQueue.size, entries.size, completedEntries.size ); entries.delete(entry); if (entries.size === 0) { From 64594bc4d228b876b5451dfad38be6e1e8c5353d Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Wed, 9 Sep 2020 21:33:07 +0200 Subject: [PATCH 022/363] remove global events should be done in a plugin --- packages/core/data/observable/index.ts | 110 +------------------------ 1 file changed, 1 insertion(+), 109 deletions(-) diff --git a/packages/core/data/observable/index.ts b/packages/core/data/observable/index.ts index 87c2a6d582..dfc60573f3 100644 --- a/packages/core/data/observable/index.ts +++ b/packages/core/data/observable/index.ts @@ -37,9 +37,6 @@ export class WrappedValue implements WrappedValueDefinition { const _wrappedValues = [new WrappedValue(null), new WrappedValue(null), new WrappedValue(null), new WrappedValue(null), new WrappedValue(null)]; -const _globalEventHandlers = {}; - - export class Observable implements ObservableDefinition { public static propertyChangeEvent = 'propertyChange'; public _isViewBase: boolean; @@ -155,120 +152,15 @@ export class Observable implements ObservableDefinition { } } - public static on(eventName: string, callback: any, thisArg?: any): void { - this.addEventListener(eventName, callback, thisArg); - } - - public static once(eventName: string, callback: any, thisArg?: any): void { - if (typeof eventName !== 'string') { - throw new TypeError('Event must be string.'); - } - - if (typeof callback !== 'function') { - throw new TypeError('callback must be function.'); - } - - const eventClass = this.name; - if (!_globalEventHandlers[eventClass]) { - _globalEventHandlers[eventClass] = {}; - } - if (!Array.isArray(_globalEventHandlers[eventClass][eventName])) { - _globalEventHandlers[eventClass][eventName] = []; - } - _globalEventHandlers[eventClass][eventName].push({callback, thisArg, once: true}); - } - - public static off(eventName: string, callback?: any, thisArg?: any): void { - this.removeEventListener(eventName, callback, thisArg); - } - - public static removeEventListener(eventName: string, callback?: any, thisArg?: any): void { - if (typeof eventName !== 'string') { - throw new TypeError('Event must be string.'); - } - - if (callback && typeof callback !== 'function') { - throw new TypeError('callback must be function.'); - } - - const eventClass = this.name; - - // Short Circuit if no handlers exist.. - if (!_globalEventHandlers[eventClass] || !Array.isArray(_globalEventHandlers[eventClass][eventName])) { return; } - - const events = _globalEventHandlers[eventClass][eventName]; - if (thisArg) { - for (let i = 0; i < events.length; i++) { - if (events[i].callback === callback && events[i].thisArg === thisArg) { - events.splice(i, 1); - i--; - } - } - } else if (callback) { - for (let i = 0; i < events.length; i++) { - if (events[i].callback === callback) { - events.splice(i, 1); - i--; - } - } - } else { - // Clear all events of this type - delete _globalEventHandlers[eventClass][eventName]; - } - - if (events.length === 0) { - // Clear all events of this type - delete _globalEventHandlers[eventClass][eventName]; - } - - // Clear the primary class grouping if no events are left - const keys = Object.keys(_globalEventHandlers[eventClass]); - if (keys.length === 0) { - delete _globalEventHandlers[eventClass]; - } - - } - - public static addEventListener(eventName: string, callback: any, thisArg?: any): void { - if (typeof eventName !== 'string') { - throw new TypeError('Event must be string.'); - } - - if (typeof callback !== 'function') { - throw new TypeError('callback must be function.'); - } - - const eventClass = this.name; - if (!_globalEventHandlers[eventClass]) { - _globalEventHandlers[eventClass] = {}; - } - if (!Array.isArray(_globalEventHandlers[eventClass][eventName])) { - _globalEventHandlers[eventClass][eventName] = []; - } - _globalEventHandlers[eventClass][eventName].push({callback, thisArg}); - } - public notify(data: T): void { const eventClass = this.constructor.name; - if (_globalEventHandlers[eventClass]) { - const event = data.eventName + "First"; - const events = _globalEventHandlers[eventClass][event]; - if (events) { - Observable._handleEvent(events, data); - } - } + const observers = >this._observers[data.eventName]; if (observers) { Observable._handleEvent(observers, data); } - if (_globalEventHandlers[eventClass]) { - const events = _globalEventHandlers[eventClass][data.eventName]; - if (events) { - Observable._handleEvent(events, data); - } - } } private static _handleEvent(observers: Array, data: T): void { From c30a9c3e3569e0367056bfd80fa730ae79e29066 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Wed, 9 Sep 2020 22:47:26 +0200 Subject: [PATCH 023/363] fix(core): autoSystemAppearanceChanged typings in ambient context fix --- packages/core/application/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/application/index.d.ts b/packages/core/application/index.d.ts index 9d0106c3aa..909627aa39 100644 --- a/packages/core/application/index.d.ts +++ b/packages/core/application/index.d.ts @@ -57,7 +57,7 @@ export const systemAppearanceChangedEvent: string; /** * Boolean to enable/disable systemAppearanceChanged */ -export let autoSystemAppearanceChanged = true; +export let autoSystemAppearanceChanged: boolean; /** * enable/disable systemAppearanceChanged From df86162d3ee10b5c07ca7ce073cb71ad12f4bc26 Mon Sep 17 00:00:00 2001 From: tarunama Date: Thu, 10 Sep 2020 10:28:13 +0900 Subject: [PATCH 024/363] chore: add repository --- apps/automated/package.json | 7 +++++-- apps/toolbox/package.json | 7 +++++-- apps/ui/package.json | 7 +++++-- package.json | 6 +++++- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/apps/automated/package.json b/apps/automated/package.json index dd43297b80..dac032e77f 100644 --- a/apps/automated/package.json +++ b/apps/automated/package.json @@ -1,8 +1,11 @@ { "main": "main.js", "description": "NativeScript Application", - "license": "SEE LICENSE IN ", - "repository": "", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/NativeScript/NativeScript.git" + }, "scripts": { "clean": "npx rimraf hooks node_modules platforms package-lock.json && npm i" }, diff --git a/apps/toolbox/package.json b/apps/toolbox/package.json index 6e9b5ae7eb..16167ec773 100644 --- a/apps/toolbox/package.json +++ b/apps/toolbox/package.json @@ -1,8 +1,11 @@ { "main": "main.js", "description": "NativeScript Application", - "license": "SEE LICENSE IN ", - "repository": "", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/NativeScript/NativeScript.git" + }, "dependencies": { "nativescript-theme-core": "file:../../node_modules/nativescript-theme-core", "@nativescript/core": "file:../../packages/core" diff --git a/apps/ui/package.json b/apps/ui/package.json index a47721bdf4..100413761e 100644 --- a/apps/ui/package.json +++ b/apps/ui/package.json @@ -1,8 +1,11 @@ { "main": "main.js", "description": "NativeScript Application", - "license": "SEE LICENSE IN ", - "repository": "", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/NativeScript/NativeScript.git" + }, "dependencies": { "nativescript-theme-core": "file:../../node_modules/nativescript-theme-core", "@nativescript/core": "file:../../packages/core" diff --git a/package.json b/package.json index 8758ffa40c..201033255c 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,11 @@ "start": "nps", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s" }, - "private": true, + "private": true, + "repository": { + "type": "git", + "url": "https://github.com/NativeScript/NativeScript.git" + }, "dependencies": { "nativescript-theme-core": "^1.0.4" }, From f7713c40a63959c2b5934a25bd3577f07d0401c0 Mon Sep 17 00:00:00 2001 From: Ken Southerland Date: Wed, 9 Sep 2020 15:01:39 -0700 Subject: [PATCH 025/363] fix(webpack): verify now works properly closes https://github.com/NativeScript/NativeScript/issues/8840 --- packages/webpack/verify/update.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webpack/verify/update.js b/packages/webpack/verify/update.js index fe0e43c76e..cceb756f8e 100644 --- a/packages/webpack/verify/update.js +++ b/packages/webpack/verify/update.js @@ -5,7 +5,7 @@ const { getPackageJson, getProjectDir, writePackageJson, -} = require("../projectHelpers"); +} = require("../helpers/projectHelpers"); const { forceUpdateProjectFiles } = require("../helpers/projectFilesManager"); const { forceUpdateProjectDeps } = require("../helpers/dependencyManager"); From bd04a4710fa108de69b8099af0e98107801d12e6 Mon Sep 17 00:00:00 2001 From: tarunama Date: Thu, 10 Sep 2020 12:27:07 +0900 Subject: [PATCH 026/363] chore: cleanup navigation-helper.ts (#8834) --- apps/ui/e2e/helpers/navigation-helper.ts | 64 +++++++++++++++--------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/apps/ui/e2e/helpers/navigation-helper.ts b/apps/ui/e2e/helpers/navigation-helper.ts index d93ce73225..a0d1c36b1d 100644 --- a/apps/ui/e2e/helpers/navigation-helper.ts +++ b/apps/ui/e2e/helpers/navigation-helper.ts @@ -1,4 +1,10 @@ -import { AppiumDriver, IRectangle, logInfo, logWarn, Point } from "nativescript-dev-appium"; +import { + AppiumDriver, + IRectangle, + logInfo, + logWarn, + Point +} from "nativescript-dev-appium"; export enum ElementCacheStrategy { allAtOnce, @@ -18,12 +24,15 @@ export class NavigationHelper { private _cachedElements: ICachedElement; private _currentSuite: ICachedElement; - constructor(protected _driver: AppiumDriver, protected _suitMainPageNavigationLinks: Array, private _elemtsCacheStrategy: ElementCacheStrategy = ElementCacheStrategy.onload) { - } + constructor( + protected _driver: AppiumDriver, + protected _suitMainPageNavigationLinks: Array, + private _elementsCacheStrategy: ElementCacheStrategy = ElementCacheStrategy.onload + ) {} - async initSuite() { - if (this._elemtsCacheStrategy === ElementCacheStrategy.allAtOnce - || this._elemtsCacheStrategy === ElementCacheStrategy.onload) { + async initSuite(): Promise { + if (this._elementsCacheStrategy === ElementCacheStrategy.allAtOnce + || this._elementsCacheStrategy === ElementCacheStrategy.onload) { if (this._currentSuite) { while (this._currentSuite.parent) { this._currentSuite = this._currentSuite.parent; @@ -31,7 +40,7 @@ export class NavigationHelper { } else { if (!this._cachedElements || this._cachedElements.children.size === 0) { this._cachedElements = { name: "initSuite", children: new Map() }; - if (this._elemtsCacheStrategy === ElementCacheStrategy.allAtOnce) { + if (this._elementsCacheStrategy === ElementCacheStrategy.allAtOnce) { await this.cacheAllElements(this._cachedElements); } } @@ -43,12 +52,12 @@ export class NavigationHelper { await this.navigateToSuitMainPage(); } - async endSuite() { - logInfo("End of suit 'button' tests!"); + async endSuite(): Promise { + logInfo(`End of suit 'button' tests!`); await this._driver.takeScreenshot("end_button_suit"); } - async navigateToSuitMainPage() { + async navigateToSuitMainPage(): Promise { for (let index = 0; index < this._suitMainPageNavigationLinks.length; index++) { const mainPage = this._suitMainPageNavigationLinks[index]; await this.navigateToSample(mainPage); @@ -59,7 +68,7 @@ export class NavigationHelper { logInfo(`Navigate to ${sample}`); const sampleName = sample.toLowerCase(); - if (this._elemtsCacheStrategy === ElementCacheStrategy.allAtOnce) { + if (this._elementsCacheStrategy === ElementCacheStrategy.allAtOnce) { if (!this._currentSuite.children.has(sampleName)) { await this.cacheAllElements(this._currentSuite); } @@ -69,7 +78,7 @@ export class NavigationHelper { const sampleElement = this._currentSuite.children.get(sampleName).rect; await this._driver.clickPoint(sampleElement.x + (sampleElement.width / 2), sampleElement.y + (sampleElement.height / 2)); this._currentSuite = this._currentSuite.children.get(sampleName); - } else if (this._elemtsCacheStrategy === ElementCacheStrategy.onload) { + } else if (this._elementsCacheStrategy === ElementCacheStrategy.onload) { if (this._currentSuite.children.has(sampleName)) { const sampleElement = this._currentSuite.children.get(sampleName).rect; await this._driver.clickPoint(sampleElement.x + (sampleElement.width / 2), sampleElement.y + (sampleElement.height / 2)); @@ -94,14 +103,14 @@ export class NavigationHelper { async navigateBackToSuitMainPage() { logInfo(`Navigate to back`); - if (this._elemtsCacheStrategy === ElementCacheStrategy.allAtOnce - || this._elemtsCacheStrategy === ElementCacheStrategy.onload) { + if (this._elementsCacheStrategy === ElementCacheStrategy.allAtOnce + || this._elementsCacheStrategy === ElementCacheStrategy.onload) { this._currentSuite = this._currentSuite && this._currentSuite.parent; } await this._driver.navBack(); } - async swipeBackToSuitMainPage() { + async swipeBackToSuitMainPage(): Promise { logInfo(`Swipe to back`); const startPoint = {}; const endPoint = {}; @@ -115,20 +124,29 @@ export class NavigationHelper { await this._driver.swipe(startPoint, endPoint); } else { - logWarn("Swipe back is not supported from android!"); + logWarn(`Swipe back is not supported from android!`); } } - private async cacheAllElements(cachedElements: ICachedElement) { - const allSamples = await this._driver.findElementsByClassName(this._driver.locators.button); + private async cacheAllElements(cachedElements: ICachedElement): Promise { + const allSamples = await this._driver.findElementsByClassName(this._driver.locators.button); for (let index = 0; index < allSamples.length; index++) { const element = allSamples[index]; const rect = await element.getRectangle(); - const text = (await element.text()).toLowerCase(); - if (!cachedElements.children.has(text)) { - console.log(text); - cachedElements.children.set(text, { parent: cachedElements, name: text, rect: rect, children: new Map() }); - } + const text = (await element.text()).toLowerCase(); + + if (cachedElements.children.has(text)) continue + + logInfo(text); + cachedElements.children.set( + text, + { + parent: cachedElements, + name: text, + rect: rect, + children: new Map() + } + ); } } } From 1623a567b6eaa195d075936103d2f7d829e1fa07 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Thu, 10 Sep 2020 05:46:50 +0200 Subject: [PATCH 027/363] fix(core): bundle-config-loader global handling (#8838) --- packages/core/globals/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/globals/index.ts b/packages/core/globals/index.ts index 9ccbf5fba9..d477336358 100644 --- a/packages/core/globals/index.ts +++ b/packages/core/globals/index.ts @@ -358,3 +358,6 @@ export function initGlobal() { }; } } +if (!global.NativeScriptHasInitGlobal) { + initGlobal(); +} From 8753605788b98b504f8b0075fae5a66d8ce83317 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Wed, 9 Sep 2020 20:57:49 -0700 Subject: [PATCH 028/363] chore(release): @nativescript/core 7.0.2, @nativescript/webpack 3.0.4 (#8842) --- CHANGELOG.md | 11 +++++++++++ package.json | 2 +- packages/core/package.json | 2 +- packages/webpack/package.json | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee4e97446d..7b68251ee3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [7.0.2](https://github.com/NativeScript/NativeScript/compare/7.0.0...7.0.2) (2020-09-10) + + +### Bug Fixes + +* **core:** autoSystemAppearanceChanged typings in ambient context fix ([c30a9c3](https://github.com/NativeScript/NativeScript/commit/c30a9c3e3569e0367056bfd80fa730ae79e29066)) +* **core:** bundle-config-loader global handling ([#8838](https://github.com/NativeScript/NativeScript/issues/8838)) ([1623a56](https://github.com/NativeScript/NativeScript/commit/1623a567b6eaa195d075936103d2f7d829e1fa07)) +* **webpack:** verify now works properly ([f7713c4](https://github.com/NativeScript/NativeScript/commit/f7713c40a63959c2b5934a25bd3577f07d0401c0)) + + + ## [7.0.1](https://github.com/NativeScript/NativeScript/compare/7.0.0...7.0.1) (2020-09-09) diff --git a/package.json b/package.json index 201033255c..445162952b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nativescript", - "version": "7.0.1", + "version": "7.0.2", "license": "MIT", "scripts": { "setup": "npx rimraf hooks node_modules package-lock.json && npm i && ts-patch install && nx run core:setup", diff --git a/packages/core/package.json b/packages/core/package.json index b415771423..d2a2b886a7 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -3,7 +3,7 @@ "main": "index", "types": "index.d.ts", "description": "NativeScript Core Modules", - "version": "7.0.1", + "version": "7.0.2", "homepage": "https://nativescript.org", "repository": { "type": "git", diff --git a/packages/webpack/package.json b/packages/webpack/package.json index 4a0e2d8c7d..af66a52813 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -1,6 +1,6 @@ { "name": "@nativescript/webpack", - "version": "3.0.3", + "version": "3.0.4", "main": "index", "description": "Webpack plugin for NativeScript", "homepage": "https://nativescript.org", From 172e10269bca72548920ba27c165747f827ed222 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Thu, 10 Sep 2020 16:25:38 +0200 Subject: [PATCH 029/363] fixed core:build --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 262369454d..724fe968b9 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "apps-ui:clean": "cd apps/ui && rimraf -- hooks node_modules platforms package-lock.json webpack.config.js && $npm_package_config_npm_alias i && rimraf -- package-lock.json", "core:lint": "cd packages/core && eslint -c .eslintrc --ignore-pattern **/node_modules/** --ignore-pattern !packages/core/**", "core:setup": "npm run webpack:build", - "core:build": "tsc -p packages/core/tsconfig.lib.json --outDir dist/packages/core && copyfiles -u packages/core/*.md packages/core/package.json dist/packages/core", + "core:build": "tsc -p packages/core/tsconfig.lib.json --outDir dist/packages/core && cpy 'packages/core/*.md' 'packages/core/package.json' 'dist/packages/core'", "core:build.npm": "npm run core:build && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/**/*.d.ts\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/js-libs/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/cli-hooks/**/*.js\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/platforms/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/fetch/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/css/**/*\" dist && copyfiles -e \"packages/core/__tests__/**/*\" \"packages/core/css-value/**/*\" dist && cd dist/packages/core && npm pack && mv *.tgz ..", "core:unit": "cd packages/core/__tests__ && tsc && mocha", "core:unit.watch": "cd packages/core/__tests__ && tsc && mocha --watch", From cdad0cf16f313495f02ac9c1b47c290508d1a709 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Sat, 12 Sep 2020 15:10:42 +0200 Subject: [PATCH 030/363] remove tabs from N moved to @nativescript-community/ui-material-tabs This removes the requirement for the podfile --- packages/core/platforms/ios/Podfile | 4 - packages/core/ui/tabs/index.android.ts | 1006 ------------------- packages/core/ui/tabs/index.d.ts | 100 -- packages/core/ui/tabs/index.ios.ts | 1236 ------------------------ packages/core/ui/tabs/tabs-common.ts | 53 - 5 files changed, 2399 deletions(-) delete mode 100644 packages/core/platforms/ios/Podfile delete mode 100644 packages/core/ui/tabs/index.android.ts delete mode 100644 packages/core/ui/tabs/index.d.ts delete mode 100644 packages/core/ui/tabs/index.ios.ts delete mode 100644 packages/core/ui/tabs/tabs-common.ts diff --git a/packages/core/platforms/ios/Podfile b/packages/core/platforms/ios/Podfile deleted file mode 100644 index 7ba729baa5..0000000000 --- a/packages/core/platforms/ios/Podfile +++ /dev/null @@ -1,4 +0,0 @@ -platform :ios, '9.0' -use_frameworks! - -pod 'MaterialComponents/Tabs', '~> 94.5' \ No newline at end of file diff --git a/packages/core/ui/tabs/index.android.ts b/packages/core/ui/tabs/index.android.ts deleted file mode 100644 index a7842f0332..0000000000 --- a/packages/core/ui/tabs/index.android.ts +++ /dev/null @@ -1,1006 +0,0 @@ -// Types -import { TabContentItem } from '../tab-navigation-base/tab-content-item'; -import { TabStrip } from '../tab-navigation-base/tab-strip'; -import { TabStripItem } from '../tab-navigation-base/tab-strip-item'; -import { TextTransform } from '../text-base'; - -// Requires -import * as application from '../../application'; -import { ImageSource } from '../../image-source'; -import { ad, isFontIconURI, layout, RESOURCE_PREFIX } from '../../utils/utils'; -import { Color } from '../../color'; -import { Frame } from '../frame'; -import { Font } from '../styling/font'; -import { getIconSpecSize, itemsProperty, selectedIndexProperty, tabStripProperty } from '../tab-navigation-base/tab-navigation-base'; -import { getTransformedText } from '../text-base'; -import { offscreenTabLimitProperty, swipeEnabledProperty, animationEnabledProperty, TabsBase } from './tabs-common'; - -export * from './tabs-common'; - -const ACCENT_COLOR = 'colorAccent'; -const PRIMARY_COLOR = 'colorPrimary'; -const DEFAULT_ELEVATION = 4; - -const TABID = '_tabId'; -const INDEX = '_index'; - -interface PagerAdapter { - new (owner: Tabs): androidx.viewpager.widget.PagerAdapter; -} - -let PagerAdapter: PagerAdapter; -let TabsBar: any; -let appResources: android.content.res.Resources; - -function makeFragmentName(viewId: number, id: number): string { - return 'android:viewpager:' + viewId + ':' + id; -} - -function getTabById(id: number): Tabs { - const ref = tabs.find((ref) => { - const tab = ref.get(); - - return tab && tab._domId === id; - }); - - return ref && ref.get(); -} - -function initializeNativeClasses() { - if (PagerAdapter) { - return; - } - - @NativeClass - class TabFragmentImplementation extends org.nativescript.widgets.FragmentBase { - private owner: Tabs; - private index: number; - private backgroundBitmap: android.graphics.Bitmap = null; - - constructor() { - super(); - - return global.__native(this); - } - - static newInstance(tabId: number, index: number): TabFragmentImplementation { - const args = new android.os.Bundle(); - args.putInt(TABID, tabId); - args.putInt(INDEX, index); - const fragment = new TabFragmentImplementation(); - fragment.setArguments(args); - - return fragment; - } - - public onCreate(savedInstanceState: android.os.Bundle): void { - super.onCreate(savedInstanceState); - const args = this.getArguments(); - this.owner = getTabById(args.getInt(TABID)); - this.index = args.getInt(INDEX); - if (!this.owner) { - throw new Error(`Cannot find TabView`); - } - } - - public onCreateView(inflater: android.view.LayoutInflater, container: android.view.ViewGroup, savedInstanceState: android.os.Bundle): android.view.View { - const tabItem = this.owner.items[this.index]; - - return tabItem.nativeViewProtected; - } - - public onDestroyView() { - const hasRemovingParent = this.getRemovingParentFragment(); - - // Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments. - // TODO: Consider removing it when update to androidx.fragment:1.2.0 - if (hasRemovingParent && this.owner.selectedIndex === this.index) { - const bitmapDrawable = new android.graphics.drawable.BitmapDrawable(appResources, this.backgroundBitmap); - this.owner._originalBackground = this.owner.backgroundColor || new Color('White'); - this.owner.nativeViewProtected.setBackgroundDrawable(bitmapDrawable); - this.backgroundBitmap = null; - } - - super.onDestroyView(); - } - - public onPause(): void { - const hasRemovingParent = this.getRemovingParentFragment(); - - // Get view as bitmap and set it as background. This is workaround for the disapearing nested fragments. - // TODO: Consider removing it when update to androidx.fragment:1.2.0 - if (hasRemovingParent && this.owner.selectedIndex === this.index) { - this.backgroundBitmap = this.loadBitmapFromView(this.owner.nativeViewProtected); - } - - super.onPause(); - } - - private loadBitmapFromView(view: android.view.View): android.graphics.Bitmap { - // Another way to get view bitmap. Test performance vs setDrawingCacheEnabled - // const width = view.getWidth(); - // const height = view.getHeight(); - // const bitmap = android.graphics.Bitmap.createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888); - // const canvas = new android.graphics.Canvas(bitmap); - // view.layout(0, 0, width, height); - // view.draw(canvas); - - view.setDrawingCacheEnabled(true); - const bitmap = android.graphics.Bitmap.createBitmap(view.getDrawingCache()); - view.setDrawingCacheEnabled(false); - - return bitmap; - } - } - - const POSITION_UNCHANGED = -1; - const POSITION_NONE = -2; - - @NativeClass - class FragmentPagerAdapter extends androidx.viewpager.widget.PagerAdapter { - public items: Array; - private mCurTransaction: androidx.fragment.app.FragmentTransaction; - private mCurrentPrimaryItem: androidx.fragment.app.Fragment; - - constructor(public owner: Tabs) { - super(); - - return global.__native(this); - } - - getCount() { - const items = this.items; - - return items ? items.length : 0; - } - - getPageTitle(index: number) { - const items = this.items; - if (index < 0 || index >= items.length) { - return ''; - } - - return ''; // items[index].title; - } - - startUpdate(container: android.view.ViewGroup): void { - if (container.getId() === android.view.View.NO_ID) { - throw new Error(`ViewPager with adapter ${this} requires a view containerId`); - } - } - - instantiateItem(container: android.view.ViewGroup, position: number): java.lang.Object { - const fragmentManager = this.owner._getFragmentManager(); - if (!this.mCurTransaction) { - this.mCurTransaction = fragmentManager.beginTransaction(); - } - - const itemId = this.getItemId(position); - const name = makeFragmentName(container.getId(), itemId); - - let fragment: androidx.fragment.app.Fragment = fragmentManager.findFragmentByTag(name); - if (fragment != null) { - this.mCurTransaction.attach(fragment); - } else { - fragment = TabFragmentImplementation.newInstance(this.owner._domId, position); - this.mCurTransaction.add(container.getId(), fragment, name); - } - - if (fragment !== this.mCurrentPrimaryItem) { - fragment.setMenuVisibility(false); - fragment.setUserVisibleHint(false); - } - - const tabItems = this.owner.items; - const tabItem = tabItems ? tabItems[position] : null; - if (tabItem) { - tabItem.canBeLoaded = true; - } - - return fragment; - } - - getItemPosition(object: java.lang.Object): number { - return this.items ? POSITION_UNCHANGED : POSITION_NONE; - } - - destroyItem(container: android.view.ViewGroup, position: number, object: java.lang.Object): void { - if (!this.mCurTransaction) { - const fragmentManager = this.owner._getFragmentManager(); - this.mCurTransaction = fragmentManager.beginTransaction(); - } - - const fragment: androidx.fragment.app.Fragment = object; - this.mCurTransaction.detach(fragment); - - if (this.mCurrentPrimaryItem === fragment) { - this.mCurrentPrimaryItem = null; - } - - const tabItems = this.owner.items; - const tabItem = tabItems ? tabItems[position] : null; - if (tabItem) { - tabItem.canBeLoaded = false; - } - } - - setPrimaryItem(container: android.view.ViewGroup, position: number, object: java.lang.Object): void { - const fragment = object; - if (fragment !== this.mCurrentPrimaryItem) { - if (this.mCurrentPrimaryItem != null) { - this.mCurrentPrimaryItem.setMenuVisibility(false); - this.mCurrentPrimaryItem.setUserVisibleHint(false); - } - - if (fragment != null) { - fragment.setMenuVisibility(true); - fragment.setUserVisibleHint(true); - } - - this.mCurrentPrimaryItem = fragment; - this.owner.selectedIndex = position; - - const tab = this.owner; - const tabItems = tab.items; - const newTabItem = tabItems ? tabItems[position] : null; - - if (newTabItem) { - tab._loadUnloadTabItems(tab.selectedIndex); - } - } - } - - finishUpdate(container: android.view.ViewGroup): void { - this._commitCurrentTransaction(); - } - - isViewFromObject(view: android.view.View, object: java.lang.Object): boolean { - return (object).getView() === view; - } - - saveState(): android.os.Parcelable { - // Commit the current transaction on save to prevent "No view found for id 0xa" exception on restore. - // Related to: https://github.com/NativeScript/NativeScript/issues/6466 - this._commitCurrentTransaction(); - - return null; - } - - restoreState(state: android.os.Parcelable, loader: java.lang.ClassLoader): void { - // - } - - getItemId(position: number): number { - return position; - } - - private _commitCurrentTransaction() { - if (this.mCurTransaction != null) { - this.mCurTransaction.commitNowAllowingStateLoss(); - this.mCurTransaction = null; - } - } - } - - @NativeClass - class TabsBarImplementation extends org.nativescript.widgets.TabsBar { - constructor(context: android.content.Context, public owner: Tabs) { - super(context); - - return global.__native(this); - } - - public onSelectedPositionChange(position: number, prevPosition: number): void { - const owner = this.owner; - if (!owner) { - return; - } - - const tabStripItems = owner.tabStrip && owner.tabStrip.items; - - if (position >= 0 && tabStripItems && tabStripItems[position]) { - tabStripItems[position]._emit(TabStripItem.selectEvent); - owner._setItemColor(tabStripItems[position]); - } - - if (prevPosition >= 0 && tabStripItems && tabStripItems[prevPosition]) { - tabStripItems[prevPosition]._emit(TabStripItem.unselectEvent); - owner._setItemColor(tabStripItems[prevPosition]); - } - } - - public onTap(position: number): boolean { - const owner = this.owner; - if (!owner) { - return false; - } - - const tabStrip = owner.tabStrip; - const tabStripItems = tabStrip && tabStrip.items; - - if (position >= 0 && tabStripItems[position]) { - tabStripItems[position]._emit(TabStripItem.tapEvent); - tabStrip.notify({ - eventName: TabStrip.itemTapEvent, - object: tabStrip, - index: position, - }); - } - - if (!owner.items[position]) { - return false; - } - - return true; - } - } - - PagerAdapter = FragmentPagerAdapter; - TabsBar = TabsBarImplementation; - appResources = application.android.context.getResources(); -} - -let defaultAccentColor: number = undefined; -function getDefaultAccentColor(context: android.content.Context): number { - if (defaultAccentColor === undefined) { - //Fallback color: https://developer.android.com/samples/SlidingTabsColors/src/com.example.android.common/view/SlidingTabStrip.html - defaultAccentColor = ad.resources.getPaletteColor(ACCENT_COLOR, context) || 0xff33b5e5; - } - - return defaultAccentColor; -} - -function setElevation(grid: org.nativescript.widgets.GridLayout, tabsBar: org.nativescript.widgets.TabsBar, tabsPosition: string) { - const compat = androidx.core.view.ViewCompat; - if (compat.setElevation) { - const val = DEFAULT_ELEVATION * layout.getDisplayDensity(); - - if (tabsPosition === 'top') { - compat.setElevation(grid, val); - } - - compat.setElevation(tabsBar, val); - } -} - -export const tabs = new Array>(); - -function iterateIndexRange(index: number, eps: number, lastIndex: number, callback: (i) => void) { - const rangeStart = Math.max(0, index - eps); - const rangeEnd = Math.min(index + eps, lastIndex); - for (let i = rangeStart; i <= rangeEnd; i++) { - callback(i); - } -} - -export class Tabs extends TabsBase { - private _tabsBar: org.nativescript.widgets.TabsBar; - private _viewPager: androidx.viewpager.widget.ViewPager; - private _pagerAdapter: androidx.viewpager.widget.PagerAdapter; - private _androidViewId: number = -1; - public _originalBackground: any; - private _textTransform: TextTransform = 'uppercase'; - private _selectedItemColor: Color; - private _unSelectedItemColor: Color; - public animationEnabled: boolean; - - constructor() { - super(); - tabs.push(new WeakRef(this)); - } - - get _hasFragments(): boolean { - return true; - } - - public onItemsChanged(oldItems: TabContentItem[], newItems: TabContentItem[]): void { - super.onItemsChanged(oldItems, newItems); - - if (oldItems) { - oldItems.forEach((item: TabContentItem, i, arr) => { - (item).index = 0; - (item).tabItemSpec = null; - item.setNativeView(null); - }); - } - } - - public createNativeView() { - initializeNativeClasses(); - // TODO - // if (Trace.isEnabled()) { - // Trace.write("TabView._createUI(" + this + ");", traceCategory); - // } - - const context: android.content.Context = this._context; - const nativeView = new org.nativescript.widgets.GridLayout(context); - const viewPager = new org.nativescript.widgets.TabViewPager(context); - const tabsBar = new TabsBar(context, this); - const lp = new org.nativescript.widgets.CommonLayoutParams(); - const primaryColor = ad.resources.getPaletteColor(PRIMARY_COLOR, context); - let accentColor = getDefaultAccentColor(context); - - lp.row = 1; - - if (this.tabsPosition === 'top') { - nativeView.addRow(new org.nativescript.widgets.ItemSpec(1, org.nativescript.widgets.GridUnitType.auto)); - nativeView.addRow(new org.nativescript.widgets.ItemSpec(1, org.nativescript.widgets.GridUnitType.star)); - - viewPager.setLayoutParams(lp); - } else { - nativeView.addRow(new org.nativescript.widgets.ItemSpec(1, org.nativescript.widgets.GridUnitType.star)); - nativeView.addRow(new org.nativescript.widgets.ItemSpec(1, org.nativescript.widgets.GridUnitType.auto)); - - tabsBar.setLayoutParams(lp); - } - - nativeView.addView(viewPager); - (nativeView).viewPager = viewPager; - - const adapter = new PagerAdapter(this); - viewPager.setAdapter(adapter); - (viewPager).adapter = adapter; - - nativeView.addView(tabsBar); - (nativeView).tabsBar = tabsBar; - - setElevation(nativeView, tabsBar, this.tabsPosition); - - if (accentColor) { - tabsBar.setSelectedIndicatorColors([accentColor]); - } - - if (primaryColor) { - tabsBar.setBackgroundColor(primaryColor); - } - - return nativeView; - } - - public initNativeView(): void { - super.initNativeView(); - if (this._androidViewId < 0) { - this._androidViewId = android.view.View.generateViewId(); - } - - const nativeView: any = this.nativeViewProtected; - this._tabsBar = (nativeView).tabsBar; - - const viewPager = (nativeView).viewPager; - viewPager.setId(this._androidViewId); - this._viewPager = viewPager; - this._pagerAdapter = (viewPager).adapter; - (this._pagerAdapter).owner = this; - } - - public _loadUnloadTabItems(newIndex: number) { - const items = this.items; - if (!items) { - return; - } - - const lastIndex = items.length - 1; - const offsideItems = this.offscreenTabLimit; - - let toUnload = []; - let toLoad = []; - - iterateIndexRange(newIndex, offsideItems, lastIndex, (i) => toLoad.push(i)); - - items.forEach((item, i) => { - const indexOfI = toLoad.indexOf(i); - if (indexOfI < 0) { - toUnload.push(i); - } - }); - - toUnload.forEach((index) => { - const item = items[index]; - if (items[index]) { - item.unloadView(item.content); - } - }); - - const newItem = items[newIndex]; - const selectedView = newItem && newItem.content; - if (selectedView instanceof Frame) { - (selectedView)._pushInFrameStackRecursive(); - } - - toLoad.forEach((index) => { - const item = items[index]; - if (this.isLoaded && items[index]) { - item.loadView(item.content); - } - }); - } - - public onLoaded(): void { - super.onLoaded(); - - if (this._originalBackground) { - this.backgroundColor = null; - this.backgroundColor = this._originalBackground; - this._originalBackground = null; - } - - this.setItems(this.items); - - if (this.tabStrip) { - this.setTabStripItems(this.tabStrip.items); - } - - // this.setAdapterItems(this.items); - } - - public onUnloaded(): void { - super.onUnloaded(); - - this.setItems(null); - this.setTabStripItems(null); - - // this.setAdapterItems(null); - } - - public disposeNativeView() { - this._tabsBar.setItems(null, null); - (this._pagerAdapter).owner = null; - this._pagerAdapter = null; - - this._tabsBar = null; - this._viewPager = null; - super.disposeNativeView(); - } - - public _onRootViewReset(): void { - super._onRootViewReset(); - - // call this AFTER the super call to ensure descendants apply their rootview-reset logic first - // i.e. in a scenario with tab frames let the frames cleanup their fragments first, and then - // cleanup the tab fragments to avoid - // android.content.res.Resources$NotFoundException: Unable to find resource ID #0xfffffff6 - this.disposeCurrentFragments(); - } - - private disposeCurrentFragments(): void { - const fragmentManager = this._getFragmentManager(); - const transaction = fragmentManager.beginTransaction(); - let fragments = >fragmentManager.getFragments().toArray(); - for (let i=0;i) { - if (!this._pagerAdapter) { - return false; - } - - const currentPagerAdapterItems = (this._pagerAdapter).items; - - // if both values are null, should not update - if (!items && !currentPagerAdapterItems) { - return false; - } - - // if one value is null, should update - if (!items || !currentPagerAdapterItems) { - return true; - } - - // if both are Arrays but length doesn't match, should update - if (items.length !== currentPagerAdapterItems.length) { - return true; - } - - const matchingItems = currentPagerAdapterItems.filter((currentItem) => { - return !!items.filter((item) => { - return item._domId === currentItem._domId; - })[0]; - }); - - // if both are Arrays and length matches, but not all items are the same, should update - if (matchingItems.length !== items.length) { - return true; - } - - // if both are Arrays and length matches and all items are the same, should not update - return false; - } - - private setItems(items: Array) { - if (this.shouldUpdateAdapter(items)) { - (this._pagerAdapter).items = items; - - if (items && items.length) { - items.forEach((item: TabContentItem, i) => { - (item).index = i; - }); - } - - this._pagerAdapter.notifyDataSetChanged(); - } - } - - private setTabStripItems(items: Array) { - const length = items ? items.length : 0; - if (length === 0) { - this._tabsBar.setItems(null, null); - - return; - } - - const tabItems = new Array(); - items.forEach((tabStripItem: TabStripItem, i, arr) => { - tabStripItem._index = i; - const tabItemSpec = this.createTabItemSpec(tabStripItem); - (tabStripItem).tabItemSpec = tabItemSpec; - tabItems.push(tabItemSpec); - }); - - const tabsBar = this._tabsBar; - tabsBar.setItems(tabItems, this._viewPager); - this.tabStrip.setNativeView(tabsBar); - items.forEach((item, i, arr) => { - const tv = tabsBar.getTextViewForItemAt(i); - item.setNativeView(tv); - this._setItemColor(item); - }); - } - - private getItemLabelTextTransform(tabStripItem: TabStripItem): TextTransform { - const nestedLabel = tabStripItem.label; - let textTransform: TextTransform = null; - if (nestedLabel && nestedLabel.style.textTransform !== 'initial') { - textTransform = nestedLabel.style.textTransform; - } else if (tabStripItem.style.textTransform !== 'initial') { - textTransform = tabStripItem.style.textTransform; - } - - return textTransform || this._textTransform; - } - - private createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec { - const tabItemSpec = new org.nativescript.widgets.TabItemSpec(); - - if (tabStripItem.isLoaded) { - const nestedLabel = tabStripItem.label; - let title = nestedLabel.text; - - // TEXT-TRANSFORM - const textTransform = this.getItemLabelTextTransform(tabStripItem); - title = getTransformedText(title, textTransform); - tabItemSpec.title = title; - - // BACKGROUND-COLOR - const backgroundColor = tabStripItem.style.backgroundColor; - tabItemSpec.backgroundColor = backgroundColor ? backgroundColor.android : this.getTabBarBackgroundArgbColor(); - - // COLOR - let itemColor = this.selectedIndex === tabStripItem._index ? this._selectedItemColor : this._unSelectedItemColor; - const color = itemColor || nestedLabel.style.color; - tabItemSpec.color = color && color.android; - - // FONT - const fontInternal = nestedLabel.style.fontInternal; - if (fontInternal) { - tabItemSpec.fontSize = fontInternal.fontSize; - tabItemSpec.typeFace = fontInternal.getAndroidTypeface(); - } - - // ICON - const iconSource = tabStripItem.image && tabStripItem.image.src; - if (iconSource) { - const icon = this.getIcon(tabStripItem, itemColor); - - if (icon) { - // TODO: Make this native call that accepts string so that we don't load Bitmap in JS. - // tslint:disable-next-line:deprecation - tabItemSpec.iconDrawable = icon; - } else { - // TODO: - // traceMissingIcon(iconSource); - } - } - } - - return tabItemSpec; - } - - private getIcon(tabStripItem: TabStripItem, color?: Color): android.graphics.drawable.BitmapDrawable { - const iconSource = tabStripItem.image && tabStripItem.image.src; - if (!iconSource) { - return null; - } - - let is: ImageSource; - if (isFontIconURI(iconSource)) { - const fontIconCode = iconSource.split('//')[1]; - const target = tabStripItem.image ? tabStripItem.image : tabStripItem; - const font = target.style.fontInternal; - if (!color) { - color = target.style.color; - } - is = ImageSource.fromFontIconCodeSync(fontIconCode, font, color); - } else { - is = ImageSource.fromFileOrResourceSync(iconSource); - } - - let imageDrawable: android.graphics.drawable.BitmapDrawable; - if (is && is.android) { - let image = is.android; - - if (this.tabStrip && this.tabStrip.isIconSizeFixed) { - image = this.getFixedSizeIcon(image); - } - - imageDrawable = new android.graphics.drawable.BitmapDrawable(appResources, image); - } else { - // TODO - // traceMissingIcon(iconSource); - } - - return imageDrawable; - } - - private getFixedSizeIcon(image: android.graphics.Bitmap): android.graphics.Bitmap { - const inWidth = image.getWidth(); - const inHeight = image.getHeight(); - - const iconSpecSize = getIconSpecSize({ width: inWidth, height: inHeight }); - - const widthPixels = iconSpecSize.width * layout.getDisplayDensity(); - const heightPixels = iconSpecSize.height * layout.getDisplayDensity(); - - const scaledImage = android.graphics.Bitmap.createScaledBitmap(image, widthPixels, heightPixels, true); - - return scaledImage; - } - - // private setAdapterItems(items: Array) { - // if (this.shouldUpdateAdapter(items)) { - // (this._pagerAdapter).items = items; - - // const length = items ? items.length : 0; - // if (length === 0) { - // this._tabLayout.setItems(null, null); - // this._pagerAdapter.notifyDataSetChanged(); - // return; - // } - - // const tabItems = new Array(); - // items.forEach((item: TabStripItem, i, arr) => { - // const tabItemSpec = createTabItemSpec(item); - // (item).index = i; - // (item).tabItemSpec = tabItemSpec; - // tabItems.push(tabItemSpec); - // }); - - // const tabLayout = this._tabLayout; - // tabLayout.setItems(tabItems, this._viewPager); - // items.forEach((item, i, arr) => { - // const tv = tabLayout.getTextViewForItemAt(i); - // item.setNativeView(tv); - // }); - - // this._pagerAdapter.notifyDataSetChanged(); - // } - // } - - public updateAndroidItemAt(index: number, spec: org.nativescript.widgets.TabItemSpec) { - this._tabsBar.updateItemAt(index, spec); - } - - public getTabBarBackgroundColor(): android.graphics.drawable.Drawable { - return this._tabsBar.getBackground(); - } - - public setTabBarBackgroundColor(value: android.graphics.drawable.Drawable | Color): void { - if (value instanceof Color) { - this._tabsBar.setBackgroundColor(value.android); - } else { - this._tabsBar.setBackground(tryCloneDrawable(value, this.nativeViewProtected.getResources())); - } - - this.updateTabStripItems(); - } - - private updateTabStripItems(): void { - this.tabStrip.items.forEach((tabStripItem: TabStripItem) => { - if (tabStripItem.nativeView) { - const tabItemSpec = this.createTabItemSpec(tabStripItem); - this.updateAndroidItemAt(tabStripItem._index, tabItemSpec); - } - }); - } - - public getTabBarHighlightColor(): number { - return getDefaultAccentColor(this._context); - } - - public setTabBarHighlightColor(value: number | Color) { - const color = value instanceof Color ? value.android : value; - this._tabsBar.setSelectedIndicatorColors([color]); - } - - private setItemsColors(items: Array): void { - items.forEach((item) => { - if (item.nativeView) { - this._setItemColor(item); - } - }); - } - - public getTabBarSelectedItemColor(): Color { - return this._selectedItemColor; - } - - public setTabBarSelectedItemColor(value: Color) { - this._selectedItemColor = value; - this.setItemsColors(this.tabStrip.items); - } - - public getTabBarUnSelectedItemColor(): Color { - return this._unSelectedItemColor; - } - - public setTabBarUnSelectedItemColor(value: Color) { - this._unSelectedItemColor = value; - this.setItemsColors(this.tabStrip.items); - } - - private updateItem(tabStripItem: TabStripItem): void { - // TODO: Should figure out a way to do it directly with the the nativeView - const tabStripItemIndex = this.tabStrip.items.indexOf(tabStripItem); - const tabItemSpec = this.createTabItemSpec(tabStripItem); - this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec); - } - - public setTabBarItemTitle(tabStripItem: TabStripItem, value: string): void { - this.updateItem(tabStripItem); - } - - public setTabBarItemBackgroundColor(tabStripItem: TabStripItem, value: android.graphics.drawable.Drawable | Color): void { - this.updateItem(tabStripItem); - } - - public _setItemColor(tabStripItem: TabStripItem) { - const itemColor = tabStripItem._index === this.selectedIndex ? this._selectedItemColor : this._unSelectedItemColor; - if (!itemColor) { - return; - } - - // set label color - tabStripItem.nativeViewProtected.setTextColor(itemColor.android); - - // set icon color - this.setIconColor(tabStripItem, itemColor); - } - - private setIconColor(tabStripItem: TabStripItem, color?: Color) { - const tabBarItem = this._tabsBar.getViewForItemAt(tabStripItem._index); - - const drawable = this.getIcon(tabStripItem, color); - const imgView = tabBarItem.getChildAt(0); - imgView.setImageDrawable(drawable); - if (color) { - imgView.setColorFilter(color.android); - } - } - - public setTabBarItemColor(tabStripItem: TabStripItem, value: number | Color): void { - const itemColor = tabStripItem._index === this.selectedIndex ? this._selectedItemColor : this._unSelectedItemColor; - if (itemColor) { - // the itemColor is set through the selectedItemColor and unSelectedItemColor properties - // so it does not respect the css color - return; - } - - const androidColor = value instanceof Color ? value.android : value; - tabStripItem.nativeViewProtected.setTextColor(androidColor); - } - - public setTabBarIconColor(tabStripItem: TabStripItem, value: number | Color): void { - const itemColor = tabStripItem._index === this.selectedIndex ? this._selectedItemColor : this._unSelectedItemColor; - if (itemColor) { - // the itemColor is set through the selectedItemColor and unSelectedItemColor properties - // so it does not respect the css color - return; - } - - this.setIconColor(tabStripItem); - } - - public setTabBarIconSource(tabStripItem: TabStripItem, value: number | Color): void { - this.updateItem(tabStripItem); - } - - public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font): void { - if (value.fontSize) { - tabStripItem.nativeViewProtected.setTextSize(value.fontSize); - } - tabStripItem.nativeViewProtected.setTypeface(value.getAndroidTypeface()); - } - - public getTabBarItemTextTransform(tabStripItem: TabStripItem): TextTransform { - return this.getItemLabelTextTransform(tabStripItem); - } - - public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform): void { - const nestedLabel = tabStripItem.label; - const title = getTransformedText(nestedLabel.text, value); - tabStripItem.nativeViewProtected.setText(title); - } - - public getTabBarTextTransform(): TextTransform { - return this._textTransform; - } - - public setTabBarTextTransform(value: TextTransform): void { - let items = this.tabStrip && this.tabStrip.items; - if (items) { - items.forEach((tabStripItem) => { - if (tabStripItem.label && tabStripItem.nativeViewProtected) { - const nestedLabel = tabStripItem.label; - const title = getTransformedText(nestedLabel.text, value); - tabStripItem.nativeViewProtected.setText(title); - } - }); - } - this._textTransform = value; - } - - [selectedIndexProperty.setNative](value: number) { - // TODO - // if (Trace.isEnabled()) { - // Trace.write("TabView this._viewPager.setCurrentItem(" + value + ", " + smoothScroll + ");", traceCategory); - // } - this._viewPager.setCurrentItem(value, this.animationEnabled); - } - - [itemsProperty.getDefault](): TabContentItem[] { - return null; - } - [itemsProperty.setNative](value: TabContentItem[]) { - this.setItems(value); - selectedIndexProperty.coerce(this); - } - - [tabStripProperty.getDefault](): TabStrip { - return null; - } - [tabStripProperty.setNative](value: TabStrip) { - this.setTabStripItems(value.items); - } - - [swipeEnabledProperty.getDefault](): boolean { - // TODO: create native method and get native? - return true; - } - [swipeEnabledProperty.setNative](value: boolean) { - (this._viewPager).setSwipePageEnabled(value); - } - - [offscreenTabLimitProperty.getDefault](): number { - return this._viewPager.getOffscreenPageLimit(); - } - [offscreenTabLimitProperty.setNative](value: number) { - this._viewPager.setOffscreenPageLimit(value); - } - - [animationEnabledProperty.setNative](value: number) { - (this._viewPager).setAnimationEnabled(value); - } -} - -function tryCloneDrawable(value: android.graphics.drawable.Drawable, resources: android.content.res.Resources): android.graphics.drawable.Drawable { - if (value) { - const constantState = value.getConstantState(); - if (constantState) { - return constantState.newDrawable(resources); - } - } - - return value; -} diff --git a/packages/core/ui/tabs/index.d.ts b/packages/core/ui/tabs/index.d.ts deleted file mode 100644 index e2f4a83e7c..0000000000 --- a/packages/core/ui/tabs/index.d.ts +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Contains the Tabs class, which represents a tab navigation component. - */ - -import { Property } from '../core/properties'; -import { EventData } from '../../data/observable'; -import { TabContentItem } from '../tab-navigation-base/tab-content-item'; -import { SelectedIndexChangedEventData, TabNavigationBase } from '../tab-navigation-base/tab-navigation-base'; -import { TabStrip } from '../tab-navigation-base/tab-strip'; - -export * from '../tab-navigation-base/tab-content-item'; -export * from '../tab-navigation-base/tab-navigation-base'; -export * from '../tab-navigation-base/tab-strip'; -export * from '../tab-navigation-base/tab-strip-item'; - -/** - * Represents a swipeable tabs view. - */ -export class Tabs extends TabNavigationBase { - /** - * Gets or sets the items of the Tabs. - */ - items: Array; - - /** - * Gets or sets the tab strip of the Tabs. - */ - tabStrip: TabStrip; - - /** - * Gets or sets the selectedIndex of the Tabs. - */ - selectedIndex: number; - - /** - * Gets or sets the swipe enabled state of the Tabs. - */ - swipeEnabled: boolean; - - /** - * Gets or sets the number of offscreen preloaded tabs of the Tabs. - */ - offscreenTabLimit: number; - - /** - * Gets or sets the position state of the Tabs. - */ - tabsPosition: 'top' | 'bottom'; - - /** - * Gets or set the MDCTabBarAlignment of the tab bar icons in iOS. Defaults to "justified" - * Valid values are: - * - leading - * - justified - * - center - * - centerSelected - */ - iOSTabBarItemsAlignment: IOSTabBarItemsAlignment; - - /** - * Gets the native [android widget](http://developer.android.com/reference/android/support/v4/view/ViewPager.html) that represents the user interface for this component. Valid only when running on Android OS. - */ - android: any /* android.view.View */; //android.support.v4.view.ViewPager; - - /** - * Gets the native iOS [UITabBarController](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITabBarController_Class/) that represents the user interface for this component. Valid only when running on iOS. - */ - ios: any /* UITabBarController */; - - /** - * String value used when hooking to the selectedIndexChanged event. - */ - public static selectedIndexChangedEvent: string; - - /** - * A basic method signature to hook an event listener (shortcut alias to the addEventListener method). - * @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change"). - * @param callback - Callback function which will be executed when event is raised. - * @param thisArg - An optional parameter which will be used as `this` context for callback execution. - */ - on(eventNames: string, callback: (data: EventData) => void, thisArg?: any); - - /** - * Raised when the selected index changes. - */ - on(event: 'selectedIndexChanged', callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any); -} - -export const itemsProperty: Property; -export const tabStripProperty: Property; -export const selectedIndexProperty: Property; - -/** - * IOS Alignment of the Tabs TabStrip to use. - * - `leading` - tab items are aligned to the left - * - `justified` - tab strip is split equally to all the tab items - * - `center` - tabs items are aligned in the center - * - `centerSelected` - tab items move to make the selected tab in the center - */ -export type IOSTabBarItemsAlignment = 'leading' | 'justified' | 'center' | 'centerSelected'; diff --git a/packages/core/ui/tabs/index.ios.ts b/packages/core/ui/tabs/index.ios.ts deleted file mode 100644 index 9213b803b0..0000000000 --- a/packages/core/ui/tabs/index.ios.ts +++ /dev/null @@ -1,1236 +0,0 @@ -// Types -import { TabContentItem } from '../tab-navigation-base/tab-content-item'; -import { TabStrip } from '../tab-navigation-base/tab-strip'; -import { TabStripItem } from '../tab-navigation-base/tab-strip-item'; -import { TextTransform } from '../text-base'; - -// Requires -import { Color } from '../../color'; -import { ImageSource } from '../../image-source'; -import { Device } from '../../platform'; -import { iOSNativeHelper, isFontIconURI, layout } from '../../utils'; -import { IOSHelper, View } from '../core/view'; -import { ViewBase } from '../core/view-base'; -import { Frame } from '../frame'; -import { Font } from '../styling/font'; -import { getIconSpecSize, itemsProperty, selectedIndexProperty, tabStripProperty } from '../tab-navigation-base/tab-navigation-base'; -import { swipeEnabledProperty, TabsBase, IOSTabBarItemsAlignment, iOSTabBarItemsAlignmentProperty } from './tabs-common'; - -// TODO -// import { profile } from "../../profiling"; - -export * from './tabs-common'; - -const majorVersion = iOSNativeHelper.MajorVersion; -const isPhone = Device.deviceType === 'Phone'; - -// Equivalent to dispatch_async(dispatch_get_main_queue(...)) call -const invokeOnRunLoop = (function () { - const runloop = CFRunLoopGetMain(); - - return (action: () => any) => { - CFRunLoopPerformBlock(runloop, kCFRunLoopDefaultMode, action); - CFRunLoopWakeUp(runloop); - }; -})(); - -@NativeClass -class MDCTabBarDelegateImpl extends NSObject implements MDCTabBarDelegate { - public static ObjCProtocols = [MDCTabBarDelegate]; - - private _owner: WeakRef; - - public static initWithOwner(owner: WeakRef): MDCTabBarDelegateImpl { - let delegate = MDCTabBarDelegateImpl.new(); - delegate._owner = owner; - - return delegate; - } - - public tabBarShouldSelectItem(tabBar: MDCTabBar, item: UITabBarItem): boolean { - const owner = this._owner.get(); - const shouldSelectItem = owner._canSelectItem; - const selectedIndex = owner.tabBarItems.indexOf(item); - - if (owner.selectedIndex !== selectedIndex) { - owner._canSelectItem = false; - } - - const tabStrip = owner.tabStrip; - const tabStripItems = tabStrip && tabStrip.items; - - if (tabStripItems && tabStripItems[selectedIndex]) { - tabStripItems[selectedIndex]._emit(TabStripItem.tapEvent); - tabStrip.notify({ - eventName: TabStrip.itemTapEvent, - object: tabStrip, - index: selectedIndex, - }); - } - - return shouldSelectItem; - } - - public tabBarDidSelectItem(tabBar: MDCTabBar, selectedItem: UITabBarItem): void { - const owner = this._owner.get(); - const tabBarItems = owner.tabBarItems; - const selectedIndex = tabBarItems.indexOf(selectedItem); - - owner.selectedIndex = selectedIndex; - } -} - -@NativeClass -class BackgroundIndicatorTemplate extends NSObject implements MDCTabBarIndicatorTemplate { - public static ObjCProtocols = [MDCTabBarIndicatorTemplate]; - - public indicatorAttributesForContext(context: MDCTabBarIndicatorContext): MDCTabBarIndicatorAttributes { - let attributes = new MDCTabBarIndicatorAttributes(); - attributes.path = UIBezierPath.bezierPathWithRect(context.bounds); - - return attributes; - } -} - -@NativeClass -class UIPageViewControllerImpl extends UIPageViewController { - tabBar: MDCTabBar; - scrollView: UIScrollView; - tabBarDelegate: MDCTabBarDelegateImpl; - - private _owner: WeakRef; - - public static initWithOwner(owner: WeakRef): UIPageViewControllerImpl { - const handler = UIPageViewControllerImpl.alloc().initWithTransitionStyleNavigationOrientationOptions(UIPageViewControllerTransitionStyle.Scroll, UIPageViewControllerNavigationOrientation.Horizontal, null); - handler._owner = owner; - - return handler; - } - - public viewDidLoad(): void { - const owner = this._owner.get(); - - const tabBarItems = owner.tabBarItems; - const tabBar = MDCTabBar.alloc().initWithFrame(this.view.bounds); - - if (tabBarItems && tabBarItems.length) { - tabBar.items = NSArray.arrayWithArray(tabBarItems); - } - - tabBar.delegate = this.tabBarDelegate = MDCTabBarDelegateImpl.initWithOwner(new WeakRef(owner)); - - if (majorVersion <= 12 || !UIColor.labelColor) { - tabBar.tintColor = UIColor.blueColor; - tabBar.barTintColor = UIColor.whiteColor; - tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Normal); - tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Selected); - } else { - tabBar.tintColor = UIColor.systemBlueColor; - tabBar.barTintColor = UIColor.systemBackgroundColor; - tabBar.setTitleColorForState(UIColor.labelColor, MDCTabBarItemState.Normal); - tabBar.setTitleColorForState(UIColor.labelColor, MDCTabBarItemState.Selected); - tabBar.inkColor = UIColor.clearColor; - } - - tabBar.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleBottomMargin; - tabBar.alignment = MDCTabBarAlignment.Justified; - tabBar.sizeToFit(); - - this.tabBar = tabBar; - this.view.addSubview(tabBar); - } - - public viewWillAppear(animated: boolean): void { - super.viewWillAppear(animated); - const owner = this._owner.get(); - if (!owner) { - return; - } - - IOSHelper.updateAutoAdjustScrollInsets(this, owner); - - // Tabs can be reset as a root view. Call loaded here in this scenario. - if (!owner.isLoaded) { - owner.callLoaded(); - } - } - - public viewDidLayoutSubviews(): void { - super.viewDidLayoutSubviews(); - const owner = this._owner.get(); - if (!owner) { - return; - } - - let safeAreaInsetsBottom = 0; - let safeAreaInsetsTop = 0; - - if (majorVersion > 10) { - safeAreaInsetsBottom = this.view.safeAreaInsets.bottom; - safeAreaInsetsTop = this.view.safeAreaInsets.top; - } else { - safeAreaInsetsTop = this.topLayoutGuide.length; - } - - let scrollViewTop = 0; - let scrollViewHeight = this.view.bounds.size.height + safeAreaInsetsBottom; - - if (owner.tabStrip) { - scrollViewTop = this.tabBar.frame.size.height; - scrollViewHeight = this.view.bounds.size.height - this.tabBar.frame.size.height + safeAreaInsetsBottom; - let tabBarTop = safeAreaInsetsTop; - let tabBarHeight = this.tabBar.frame.size.height; - - const tabsPosition = owner.tabsPosition; - if (tabsPosition === 'bottom') { - tabBarTop = this.view.frame.size.height - this.tabBar.frame.size.height - safeAreaInsetsBottom; - scrollViewTop = this.view.frame.origin.y; - scrollViewHeight = this.view.frame.size.height - safeAreaInsetsBottom; - } - - let parent = owner.parent; - - // Handle Angular scenario where Tabs is in a ProxyViewContainer - // It is possible to wrap components in ProxyViewContainers indefinitely - while (parent && !parent.nativeViewProtected) { - parent = parent.parent; - } - - if (parent && majorVersion > 10) { - // TODO: Figure out a better way to handle ViewController nesting/Safe Area nesting - tabBarTop = Math.max(tabBarTop, parent.nativeView.safeAreaInsets.top); - } - - this.tabBar.frame = CGRectMake(0, tabBarTop, this.tabBar.frame.size.width, tabBarHeight); - } else { - this.tabBar.hidden = true; - } - - const subViews: NSArray = this.view.subviews; - let scrollView: UIScrollView = null; - - for (let i = 0; i < subViews.count; i++) { - const view: UIView = subViews[i]; - if (view instanceof UIScrollView) { - scrollView = view; - } - } - - if (scrollView) { - // The part of the UIPageViewController that is changing the pages is a UIScrollView - // We want to expand it to the size of the UIPageViewController as it is not so by default - this.scrollView = scrollView; - - if (!owner.swipeEnabled) { - scrollView.scrollEnabled = false; - } - - scrollView.frame = CGRectMake(0, scrollViewTop, this.view.bounds.size.width, scrollViewHeight); //this.view.bounds; - } - } - - // Mind implementation for other controllers - public traitCollectionDidChange(previousTraitCollection: UITraitCollection): void { - super.traitCollectionDidChange(previousTraitCollection); - - if (majorVersion >= 13) { - const owner = this._owner.get(); - if (owner && this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection && this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection(previousTraitCollection)) { - owner.notify({ - eventName: IOSHelper.traitCollectionColorAppearanceChangedEvent, - object: owner, - }); - } - } - } - - public viewWillTransitionToSizeWithTransitionCoordinator(size: CGSize, coordinator: UIViewControllerTransitionCoordinator): void { - super.viewWillTransitionToSizeWithTransitionCoordinator(size, coordinator); - coordinator.animateAlongsideTransitionCompletion(() => { - const owner = this._owner.get(); - if (owner && owner.tabStrip && owner.tabStrip.items) { - const tabStrip = owner.tabStrip; - tabStrip.items.forEach((tabStripItem) => { - updateBackgroundPositions(tabStrip, tabStripItem, this.tabBar.alignment !== MDCTabBarAlignment.Justified || owner.selectedIndex !== tabStripItem._index ? owner._defaultItemBackgroundColor : null); - - const index = tabStripItem._index; - const tabBarItemController = owner.viewControllers[index]; - updateTitleAndIconPositions(tabStripItem, tabBarItemController.tabBarItem, tabBarItemController); - }); - } - }, null); - } -} - -@NativeClass -class UIPageViewControllerDataSourceImpl extends NSObject implements UIPageViewControllerDataSource { - public static ObjCProtocols = [UIPageViewControllerDataSource]; - - private _owner: WeakRef; - - public static initWithOwner(owner: WeakRef): UIPageViewControllerDataSourceImpl { - let dataSource = UIPageViewControllerDataSourceImpl.new(); - dataSource._owner = owner; - - return dataSource; - } - - public pageViewControllerViewControllerBeforeViewController(pageViewController: UIPageViewController, viewController: UIViewController): UIViewController { - // TODO - // if (Trace.isEnabled()) { - // Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug); - // } - - const owner = this._owner.get(); - let selectedIndex = owner.selectedIndex; - - if (selectedIndex === 0) { - return null; - } - - selectedIndex--; - const prevItem = owner.items[selectedIndex]; - let prevViewController = (prevItem).__controller; - - // if (!prevViewController) { - // prevViewController = owner.getViewController(prevItem); - // } - - owner._setCanBeLoaded(selectedIndex); - owner._loadUnloadTabItems(selectedIndex); - - return prevViewController; - } - - public pageViewControllerViewControllerAfterViewController(pageViewController: UIPageViewController, viewController: UIViewController): UIViewController { - // TODO - // if (Trace.isEnabled()) { - // Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug); - // } - - const owner = this._owner.get(); - let selectedIndex = owner.selectedIndex; - - if (selectedIndex === owner.items.length - 1) { - return null; - } - - selectedIndex++; - const nextItem = owner.items[selectedIndex]; - let nextViewController = (nextItem).__controller; - - // if (!nextViewController) { - // nextViewController = owner.getViewController(nextItem); - // } - - owner._setCanBeLoaded(selectedIndex); - owner._loadUnloadTabItems(selectedIndex); - // nextItem.loadView(nextItem.view); - - return nextViewController; - } - - public presentationCountForPageViewController(pageViewController: UIPageViewController): number { - // TODO - // if (Trace.isEnabled()) { - // Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug); - // } - - return 0; - } - - public presentationIndexForPageViewController(pageViewController: UIPageViewController): number { - // TODO - // if (Trace.isEnabled()) { - // Trace.write("TabView.delegate.SHOULD_select(" + tabBarController + ", " + viewController + ");", Trace.categories.Debug); - // } - - return 0; - } -} - -@NativeClass -class UIPageViewControllerDelegateImpl extends NSObject implements UIPageViewControllerDelegate { - public static ObjCProtocols = [UIPageViewControllerDelegate]; - - private _owner: WeakRef; - - public static initWithOwner(owner: WeakRef): UIPageViewControllerDelegateImpl { - let delegate = UIPageViewControllerDelegateImpl.new(); - delegate._owner = owner; - - return delegate; - } - - public pageViewControllerWillTransitionToViewControllers(pageViewController: UIPageViewController, viewControllers: NSArray): void { - // const owner = this._owner.get(); - // const ownerViewControllers = owner.viewControllers; - // const selectedIndex = owner.selectedIndex; - // const nextViewController = viewControllers[0]; - // const nextViewControllerIndex = ownerViewControllers.indexOf(nextViewController); - // if (selectedIndex > nextViewControllerIndex) { - // owner.selectedIndex--; - // } else { - // owner.selectedIndex++; - // } - } - - public pageViewControllerDidFinishAnimatingPreviousViewControllersTransitionCompleted(pageViewController: UIPageViewController, didFinishAnimating: boolean, previousViewControllers: NSArray, transitionCompleted: boolean): void { - if (!transitionCompleted) { - return; - } - - const owner = this._owner.get(); - const ownerViewControllers = owner.viewControllers; - const selectedIndex = owner.selectedIndex; - const nextViewController = pageViewController.viewControllers[0]; - const nextViewControllerIndex = ownerViewControllers.indexOf(nextViewController); - - if (selectedIndex !== nextViewControllerIndex) { - owner.selectedIndex = nextViewControllerIndex; - owner._canSelectItem = true; - } - } -} - -function iterateIndexRange(index: number, eps: number, lastIndex: number, callback: (i) => void) { - const rangeStart = Math.max(0, index - eps); - const rangeEnd = Math.min(index + eps, lastIndex); - for (let i = rangeStart; i <= rangeEnd; i++) { - callback(i); - } -} - -function updateBackgroundPositions(tabStrip: TabStrip, tabStripItem: TabStripItem, color: UIColor = null) { - let bgView = (tabStripItem).bgView; - const index = tabStripItem._index; - let width = tabStrip.nativeView.frame.size.width / tabStrip.items.length; - const frame = CGRectMake(width * index, 0, width, tabStrip.nativeView.frame.size.width); - if (!bgView) { - bgView = UIView.alloc().initWithFrame(frame); - tabStrip.nativeView.insertSubviewAtIndex(bgView, 0); - (tabStripItem).bgView = bgView; - } else { - bgView.frame = frame; - } - - const backgroundColor = tabStripItem.style.backgroundColor; - bgView.backgroundColor = color || (backgroundColor instanceof Color ? backgroundColor.ios : backgroundColor); -} - -function updateTitleAndIconPositions(tabStripItem: TabStripItem, tabBarItem: UITabBarItem, controller: UIViewController) { - if (!tabStripItem || !tabBarItem) { - return; - } - - // For iOS <11 icon is *always* above the text. - // For iOS 11 icon is above the text *only* on phones in portrait mode. - const orientation = controller.interfaceOrientation; - const isPortrait = orientation !== UIInterfaceOrientation.LandscapeLeft && orientation !== UIInterfaceOrientation.LandscapeRight; - const isIconAboveTitle = majorVersion < 11 || (isPhone && isPortrait); - - if (!tabStripItem.iconSource) { - if (isIconAboveTitle) { - tabBarItem.titlePositionAdjustment = { - horizontal: 0, - vertical: -20, - }; - } else { - tabBarItem.titlePositionAdjustment = { horizontal: 0, vertical: 0 }; - } - } - - if (!tabStripItem.title) { - if (isIconAboveTitle) { - tabBarItem.imageInsets = new UIEdgeInsets({ - top: 6, - left: 0, - bottom: -6, - right: 0, - }); - } else { - tabBarItem.imageInsets = new UIEdgeInsets({ - top: 0, - left: 0, - bottom: 0, - right: 0, - }); - } - } -} - -export class Tabs extends TabsBase { - public nativeViewProtected: UIView; - public selectedIndex: number; - // public swipeEnabled: boolean; - // public offscreenTabLimit: number; - // public tabsPosition: "top" | "bottom"; - public _canSelectItem: boolean; - public isLoaded: boolean; - public viewController: UIPageViewControllerImpl; - public items: TabContentItem[]; - public _ios: UIPageViewControllerImpl; - public viewControllers: UIViewController[]; - public tabBarItems: UITabBarItem[]; - private _currentNativeSelectedIndex: number; - private _dataSource: UIPageViewControllerDataSourceImpl; - private _delegate: UIPageViewControllerDelegateImpl; - // private _moreNavigationControllerDelegate: UINavigationControllerDelegateImpl; - private _iconsCache = {}; - private _backgroundIndicatorColor: UIColor; - public _defaultItemBackgroundColor: UIColor; - private _selectedItemColor: Color; - private _unSelectedItemColor: Color; - public animationEnabled: boolean; - - constructor() { - super(); - - this.viewController = this._ios = UIPageViewControllerImpl.initWithOwner(new WeakRef(this)); //alloc().initWithTransitionStyleNavigationOrientationOptions(UIPageViewControllerTransitionStyle.Scroll, UIPageViewControllerNavigationOrientation.Horizontal, null);; - } - - createNativeView() { - return this._ios.view; - } - - initNativeView() { - super.initNativeView(); - this._dataSource = UIPageViewControllerDataSourceImpl.initWithOwner(new WeakRef(this)); - this._delegate = UIPageViewControllerDelegateImpl.initWithOwner(new WeakRef(this)); - } - - disposeNativeView() { - this._dataSource = null; - this._delegate = null; - this._ios.tabBarDelegate = null; - this._ios.tabBar = null; - super.disposeNativeView(); - } - - // TODO - // @profile() - public onLoaded() { - super.onLoaded(); - - this.setViewControllers(this.items); - - const selectedIndex = this.selectedIndex; - const selectedView = this.items && this.items[selectedIndex] && this.items[selectedIndex].content; - if (selectedView instanceof Frame) { - selectedView._pushInFrameStackRecursive(); - } - - this._ios.dataSource = this._dataSource; - this._ios.delegate = this._delegate; - } - - public onUnloaded() { - this._ios.dataSource = null; - this._ios.delegate = null; - super.onUnloaded(); - } - - get ios(): UIPageViewController { - return this._ios; - } - - public layoutNativeView(left: number, top: number, right: number, bottom: number): void { - // - } - - public _setNativeViewFrame(nativeView: UIView, frame: CGRect) { - // - } - - public onSelectedIndexChanged(oldIndex: number, newIndex: number): void { - const items = this.items; - if (!items) { - return; - } - - const oldItem = items[oldIndex]; - if (oldItem) { - oldItem.canBeLoaded = false; - oldItem.unloadView(oldItem.content); - } - - const newItem = items[newIndex]; - if (newItem && this.isLoaded) { - const selectedView = items[newIndex].content; - if (selectedView instanceof Frame) { - selectedView._pushInFrameStackRecursive(); - } - - newItem.canBeLoaded = true; - newItem.loadView(newItem.content); - } - - const tabStripItems = this.tabStrip && this.tabStrip.items; - if (tabStripItems) { - if (tabStripItems[newIndex]) { - tabStripItems[newIndex]._emit(TabStripItem.selectEvent); - this.updateItemColors(tabStripItems[newIndex]); - } - - if (tabStripItems[oldIndex]) { - tabStripItems[oldIndex]._emit(TabStripItem.unselectEvent); - this.updateItemColors(tabStripItems[oldIndex]); - } - } - - this._loadUnloadTabItems(newIndex); - - super.onSelectedIndexChanged(oldIndex, newIndex); - } - - public _loadUnloadTabItems(newIndex: number) { - const items = this.items; - if (!items) { - return; - } - - const lastIndex = items.length - 1; - const offsideItems = this.offscreenTabLimit; - - let toUnload = []; - let toLoad = []; - - iterateIndexRange(newIndex, offsideItems, lastIndex, (i) => toLoad.push(i)); - - items.forEach((item, i) => { - const indexOfI = toLoad.indexOf(i); - if (indexOfI < 0) { - toUnload.push(i); - } - }); - - toUnload.forEach((index) => { - const item = items[index]; - if (items[index]) { - item.unloadView(item.content); - } - }); - - const newItem = items[newIndex]; - const selectedView = newItem && newItem.content; - if (selectedView instanceof Frame) { - selectedView._pushInFrameStackRecursive(); - } - - toLoad.forEach((index) => { - const item = items[index]; - if (this.isLoaded && items[index]) { - item.loadView(item.content); - } - }); - } - - public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void { - const width = layout.getMeasureSpecSize(widthMeasureSpec); - const widthMode = layout.getMeasureSpecMode(widthMeasureSpec); - - const height = layout.getMeasureSpecSize(heightMeasureSpec); - const heightMode = layout.getMeasureSpecMode(heightMeasureSpec); - - const widthAndState = View.resolveSizeAndState(width, width, widthMode, 0); - const heightAndState = View.resolveSizeAndState(height, height, heightMode, 0); - - this.setMeasuredDimension(widthAndState, heightAndState); - } - - public _onViewControllerShown(viewController: UIViewController) { - // This method could be called with the moreNavigationController or its list controller, so we have to check. - // TODO - // if (Trace.isEnabled()) { - // Trace.write("TabView._onViewControllerShown(" + viewController + ");", Trace.categories.Debug); - // } - if (this._ios.viewControllers && this._ios.viewControllers.containsObject(viewController)) { - this.selectedIndex = this._ios.viewControllers.indexOfObject(viewController); - } else { - // TODO - // if (Trace.isEnabled()) { - // Trace.write("TabView._onViewControllerShown: viewController is not one of our viewControllers", Trace.categories.Debug); - // } - } - } - - private getViewController(item: TabContentItem): UIViewController { - let newController: UIViewController = item.content ? item.content.viewController : null; - - if (newController) { - (item).setViewController(newController, newController.view); - - return newController; - } - - if (item.content.ios instanceof UIViewController) { - newController = item.content.ios; - (item).setViewController(newController, newController.view); - } else if (item.content.ios && item.content.ios.controller instanceof UIViewController) { - newController = item.content.ios.controller; - (item).setViewController(newController, newController.view); - } else { - newController = IOSHelper.UILayoutViewController.initWithOwner(new WeakRef(item.content)) as UIViewController; - newController.view.addSubview(item.content.nativeViewProtected); - item.content.viewController = newController; - (item).setViewController(newController, item.content.nativeViewProtected); - } - - return newController; - } - - public _setCanBeLoaded(index: number) { - const items = this.items; - if (!this.items) { - return; - } - - const lastIndex = items.length - 1; - const offsideItems = this.offscreenTabLimit; - - iterateIndexRange(index, offsideItems, lastIndex, (i) => { - if (items[i]) { - (items[i]).canBeLoaded = true; - } - }); - } - - private setViewControllers(items: TabContentItem[]) { - const length = items ? items.length : 0; - if (length === 0) { - this.viewControllers = null; - - return; - } - - const viewControllers = []; - const tabBarItems = []; - - if (this.tabStrip) { - this.tabStrip.setNativeView(this._ios.tabBar); - } - - const tabStripItems = this.tabStrip && this.tabStrip.items; - if (tabStripItems) { - if (tabStripItems[this.selectedIndex]) { - tabStripItems[this.selectedIndex]._emit(TabStripItem.selectEvent); - } - } - - items.forEach((item, i) => { - const controller = this.getViewController(item); - - if (this.tabStrip && this.tabStrip.items && this.tabStrip.items[i]) { - const tabStripItem = this.tabStrip.items[i]; - const tabBarItem = this.createTabBarItem(tabStripItem, i); - updateTitleAndIconPositions(tabStripItem, tabBarItem, controller); - - this.setViewTextAttributes(tabStripItem.label, i === this.selectedIndex); - - controller.tabBarItem = tabBarItem; - tabStripItem._index = i; - tabBarItems.push(tabBarItem); - tabStripItem.setNativeView(tabBarItem); - } - - item.canBeLoaded = true; - viewControllers.push(controller); - }); - - this.setItemImages(); - - this.viewControllers = viewControllers; - this.tabBarItems = tabBarItems; - - if (this.viewController && this.viewController.tabBar) { - this.viewController.tabBar.itemAppearance = this.getTabBarItemAppearance(); - this.viewController.tabBar.items = NSArray.arrayWithArray(this.tabBarItems); - // TODO: investigate why this call is necessary to actually toggle item appearance - this.viewController.tabBar.sizeToFit(); - if (this.selectedIndex) { - this.viewController.tabBar.setSelectedItemAnimated(this.tabBarItems[this.selectedIndex], false); - } - } - } - - private setItemImages() { - if (this._selectedItemColor || this._unSelectedItemColor) { - if (this.tabStrip && this.tabStrip.items) { - this.tabStrip.items.forEach((item) => { - if (this._unSelectedItemColor && item.nativeView) { - item.nativeView.image = this.getIcon(item, this._unSelectedItemColor); - } - if (this._selectedItemColor && item.nativeView) { - if (this.selectedIndex === item._index) { - item.nativeView.image = this.getIcon(item, this._selectedItemColor); - } - } - }); - } - } - } - - private updateAllItemsColors() { - this._defaultItemBackgroundColor = null; - this.setItemColors(); - if (this.tabStrip && this.tabStrip.items) { - this.tabStrip.items.forEach((tabStripItem) => { - this.updateItemColors(tabStripItem); - }); - } - } - - private updateItemColors(tabStripItem: TabStripItem): void { - updateBackgroundPositions(this.tabStrip, tabStripItem); - this.setIconColor(tabStripItem, true); - } - - private createTabBarItem(item: TabStripItem, index: number): UITabBarItem { - let image: UIImage; - let title: string; - - if (item.isLoaded) { - image = this.getIcon(item); - title = item.label.text; - - if (!this.tabStrip._hasImage) { - this.tabStrip._hasImage = !!image; - } - - if (!this.tabStrip._hasTitle) { - this.tabStrip._hasTitle = !!title; - } - } - - const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(title, image, index); - - return tabBarItem; - } - - private getTabBarItemAppearance(): MDCTabBarItemAppearance { - let itemAppearance; - if (this.tabStrip && this.tabStrip._hasImage && this.tabStrip._hasTitle) { - itemAppearance = MDCTabBarItemAppearance.TitledImages; - } else if (this.tabStrip && this.tabStrip._hasImage) { - itemAppearance = MDCTabBarItemAppearance.Images; - } else { - itemAppearance = MDCTabBarItemAppearance.Titles; - } - - return itemAppearance; - } - - private getIconRenderingMode(): UIImageRenderingMode { - switch (this.tabStrip && this.tabStrip.iosIconRenderingMode) { - case 'alwaysOriginal': - return UIImageRenderingMode.AlwaysOriginal; - case 'alwaysTemplate': - return UIImageRenderingMode.AlwaysTemplate; - case 'automatic': - default: - const hasItemColor = this._selectedItemColor || this._unSelectedItemColor; - - return hasItemColor ? UIImageRenderingMode.AlwaysTemplate : UIImageRenderingMode.AlwaysOriginal; - } - } - - private getIcon(tabStripItem: TabStripItem, color?: Color): UIImage { - // Image and Label children of TabStripItem - // take priority over its `iconSource` and `title` properties - const iconSource = tabStripItem.image && tabStripItem.image.src; - if (!iconSource) { - return null; - } - - const target = tabStripItem.image; - const font = target.style.fontInternal || Font.default; - if (!color) { - color = target.style.color; - } - const iconTag = [iconSource, font.fontStyle, font.fontWeight, font.fontSize, font.fontFamily, color].join(';'); - - let isFontIcon = false; - let image: UIImage = this._iconsCache[iconTag]; - if (!image) { - let is = new ImageSource(); - if (isFontIconURI(iconSource)) { - isFontIcon = true; - const fontIconCode = iconSource.split('//')[1]; - is = ImageSource.fromFontIconCodeSync(fontIconCode, font, color); - } else { - is = ImageSource.fromFileOrResourceSync(iconSource); - } - - if (is && is.ios) { - image = is.ios; - - if (this.tabStrip && this.tabStrip.isIconSizeFixed) { - image = this.getFixedSizeIcon(image); - } - - let renderingMode: UIImageRenderingMode = UIImageRenderingMode.Automatic; - if (!isFontIcon) { - renderingMode = this.getIconRenderingMode(); - } - const originalRenderedImage = image.imageWithRenderingMode(renderingMode); - this._iconsCache[iconTag] = originalRenderedImage; - image = originalRenderedImage; - } - } - - return image; - } - - private getFixedSizeIcon(image: UIImage): UIImage { - const inWidth = image.size.width; - const inHeight = image.size.height; - - const iconSpecSize = getIconSpecSize({ width: inWidth, height: inHeight }); - - const widthPts = iconSpecSize.width; - const heightPts = iconSpecSize.height; - - UIGraphicsBeginImageContextWithOptions({ width: widthPts, height: heightPts }, false, layout.getDisplayDensity()); - image.drawInRect(CGRectMake(0, 0, widthPts, heightPts)); - let resultImage = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return resultImage; - } - - public getTabBarBackgroundColor(): UIColor { - return this._ios.tabBar.barTintColor; - } - - public setTabBarBackgroundColor(value: UIColor | Color): void { - this._ios.tabBar.barTintColor = value instanceof Color ? value.ios : value; - this.updateAllItemsColors(); - } - - public setTabBarItemTitle(tabStripItem: TabStripItem, value: string): void { - tabStripItem.nativeView.title = value; - } - - private equalUIColor(first: UIColor, second: UIColor): boolean { - if (!first && !second) { - return true; - } - if (!first || !second) { - return false; - } - const firstComponents = CGColorGetComponents(first.CGColor); - const secondComponents = CGColorGetComponents(second.CGColor); - - return firstComponents[0] === secondComponents[0] && firstComponents[1] === secondComponents[1] && firstComponents[2] === secondComponents[2] && firstComponents[3] === secondComponents[3]; - } - - private isSelectedAndHightlightedItem(tabStripItem: TabStripItem): boolean { - // to find out whether the current tab strip item is active (has style with :active selector applied) - // we need to check whether its _visualState is equal to "highlighted" as when changing tabs - // we first go through setTabBarItemBackgroundColor thice, once before setting the "highlighted" state - // and once after that, but if the "highlighted" state is not set we cannot get the backgroundColor - // set using :active selector - return tabStripItem._index === this.selectedIndex && tabStripItem['_visualState'] === 'highlighted'; - } - - public setTabBarItemBackgroundColor(tabStripItem: TabStripItem, value: UIColor | Color): void { - if (!this.tabStrip || !tabStripItem) { - return; - } - - let newColor = value instanceof Color ? value.ios : value; - const itemSelectedAndHighlighted = this.isSelectedAndHightlightedItem(tabStripItem); - - // As we cannot implement selected item background color in Tabs we are using the Indicator for this - // To be able to detect that there are two different background colors (one for selected and one for not selected item) - // we are checking whether the current item is not selected and higlighted and we store the value of its - // background color to _defaultItemBackgroundColor and later if we need to process a selected and highlighted item - // we are comparing it's backgroun color to the default one and if there's a difference - // we are changing the selectionIndicatorTemplate from underline to the whole item - // in that mode we are not able to show the indicator as it is used for the background of the selected item - - if (!this._defaultItemBackgroundColor && !itemSelectedAndHighlighted) { - this._defaultItemBackgroundColor = newColor; - } - - if (this.viewController.tabBar.alignment !== MDCTabBarAlignment.Justified && itemSelectedAndHighlighted && !this.equalUIColor(this._defaultItemBackgroundColor, newColor)) { - if (!this._backgroundIndicatorColor) { - this._backgroundIndicatorColor = newColor; - this._ios.tabBar.selectionIndicatorTemplate = new BackgroundIndicatorTemplate(); - this._ios.tabBar.tintColor = newColor; - } - } else { - updateBackgroundPositions(this.tabStrip, tabStripItem, newColor); - } - } - - public setTabBarItemColor(tabStripItem: TabStripItem, value: UIColor | Color): void { - this.setViewTextAttributes(tabStripItem.label); - } - - private setItemColors(): void { - if (this._selectedItemColor) { - this.viewController.tabBar.selectedItemTintColor = this._selectedItemColor.ios; - } - if (this._unSelectedItemColor) { - this.viewController.tabBar.unselectedItemTintColor = this._unSelectedItemColor.ios; - } - } - - private setIconColor(tabStripItem: TabStripItem, forceReload: boolean = false): void { - // if there is no change in the css color and there is no item color set - // we don't need to reload the icon - if (!forceReload && !this._selectedItemColor && !this._unSelectedItemColor) { - return; - } - - let image: UIImage; - - // if selectedItemColor or unSelectedItemColor is set we don't respect the color from the style - const tabStripColor = this.selectedIndex === tabStripItem._index ? this._selectedItemColor : this._unSelectedItemColor; - image = this.getIcon(tabStripItem, tabStripColor); - - tabStripItem.nativeView.image = image; - } - - public setTabBarIconColor(tabStripItem: TabStripItem, value: UIColor | Color): void { - this.setIconColor(tabStripItem, true); - } - - public setTabBarIconSource(tabStripItem: TabStripItem, value: UIColor | Color): void { - this.updateItemColors(tabStripItem); - } - - public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font): void { - this.setViewTextAttributes(tabStripItem.label); - } - - public getTabBarFontInternal(): UIFont { - return this._ios.tabBar.unselectedItemTitleFont; - } - - public setTabBarFontInternal(value: Font): void { - const defaultTabItemFontSize = 10; - const tabItemFontSize = this.tabStrip.style.fontSize || defaultTabItemFontSize; - const font: UIFont = (this.tabStrip.style.fontInternal || Font.default).getUIFont(UIFont.systemFontOfSize(tabItemFontSize)); - - this._ios.tabBar.unselectedItemTitleFont = font; - this._ios.tabBar.selectedItemTitleFont = font; - } - - public getTabBarTextTransform(): TextTransform { - switch (this._ios.tabBar.titleTextTransform) { - case MDCTabBarTextTransform.None: - return 'none'; - case MDCTabBarTextTransform.Automatic: - return 'initial'; - case MDCTabBarTextTransform.Uppercase: - default: - return 'uppercase'; - } - } - - public setTabBarTextTransform(value: TextTransform): void { - if (value === 'none') { - this._ios.tabBar.titleTextTransform = MDCTabBarTextTransform.None; - } else if (value === 'uppercase') { - this._ios.tabBar.titleTextTransform = MDCTabBarTextTransform.Uppercase; - } else if (value === 'initial') { - this._ios.tabBar.titleTextTransform = MDCTabBarTextTransform.Automatic; - } - } - - public getTabBarColor(): UIColor { - return this._ios.tabBar.titleColorForState(MDCTabBarItemState.Normal); - } - - public setTabBarColor(value: UIColor | Color): void { - const nativeColor = value instanceof Color ? value.ios : value; - this._ios.tabBar.setTitleColorForState(nativeColor, MDCTabBarItemState.Normal); - this._ios.tabBar.setTitleColorForState(nativeColor, MDCTabBarItemState.Selected); - } - - public getTabBarHighlightColor(): UIColor { - return this._ios.tabBar.tintColor; - } - - public setTabBarHighlightColor(value: UIColor | Color) { - const nativeColor = value instanceof Color ? value.ios : value; - this._ios.tabBar.tintColor = nativeColor; - } - - public getTabBarSelectedItemColor(): Color { - return this._selectedItemColor; - } - - public setTabBarSelectedItemColor(value: Color) { - this._selectedItemColor = value; - this.updateAllItemsColors(); - } - - public getTabBarUnSelectedItemColor(): Color { - return this._unSelectedItemColor; - } - - public setTabBarUnSelectedItemColor(value: Color) { - this._unSelectedItemColor = value; - this.updateAllItemsColors(); - } - - private visitFrames(view: ViewBase, operation: (frame: Frame) => {}) { - if (view instanceof Frame) { - operation(view); - } - view.eachChild((child) => { - this.visitFrames(child, operation); - - return true; - }); - } - - [selectedIndexProperty.setNative](value: number) { - // TODO - // if (Trace.isEnabled()) { - // Trace.write("TabView._onSelectedIndexPropertyChangedSetNativeValue(" + value + ")", Trace.categories.Debug); - // } - - if (value > -1) { - const item = this.items[value]; - const controllers = NSMutableArray.alloc().initWithCapacity(1); - - let itemController = (item).__controller; - - // if (!itemController) { - // itemController = this.getViewController(item); - // } - - controllers.addObject(itemController); - - let navigationDirection = UIPageViewControllerNavigationDirection.Forward; - - if (this._currentNativeSelectedIndex && this._currentNativeSelectedIndex > value) { - navigationDirection = UIPageViewControllerNavigationDirection.Reverse; - } - - this._currentNativeSelectedIndex = value; - - // do not make layout changes while the animation is in progress https://stackoverflow.com/a/47031524/613113 - this.visitFrames(item, (frame) => (frame._animationInProgress = true)); - - invokeOnRunLoop(() => - this.viewController.setViewControllersDirectionAnimatedCompletion(controllers, navigationDirection, this.animationEnabled, (finished: boolean) => { - this.visitFrames(item, (frame) => (frame._animationInProgress = false)); - if (finished) { - // HACK: UIPageViewController fix; see https://stackoverflow.com/a/17330606 - invokeOnRunLoop(() => this.viewController.setViewControllersDirectionAnimatedCompletion(controllers, navigationDirection, false, null)); - - this._canSelectItem = true; - this._setCanBeLoaded(value); - this._loadUnloadTabItems(value); - } - }) - ); - - if (this.tabBarItems && this.tabBarItems.length && this.viewController && this.viewController.tabBar) { - this.viewController.tabBar.setSelectedItemAnimated(this.tabBarItems[value], this.animationEnabled); - } - // TODO: - // (this._ios)._willSelectViewController = this._ios.viewControllers[value]; - // this._ios.selectedIndex = value; - } - } - - [itemsProperty.getDefault](): TabContentItem[] { - return null; - } - [itemsProperty.setNative](value: TabContentItem[]) { - if (value) { - value.forEach((item: TabContentItem, i) => { - (item).index = i; - }); - } - - this.setViewControllers(value); - selectedIndexProperty.coerce(this); - } - - [tabStripProperty.getDefault](): TabStrip { - return null; - } - [tabStripProperty.setNative](value: TabStrip) { - this.setViewControllers(this.items); - selectedIndexProperty.coerce(this); - } - - [swipeEnabledProperty.getDefault](): boolean { - return true; - } - [swipeEnabledProperty.setNative](value: boolean) { - if (this.viewController && this.viewController.scrollView) { - this.viewController.scrollView.scrollEnabled = value; - } - } - - [iOSTabBarItemsAlignmentProperty.getDefault](): IOSTabBarItemsAlignment { - if (!this.viewController || !this.viewController.tabBar) { - return 'justified'; - } - - let alignment = this.viewController.tabBar.alignment.toString(); - - return (alignment.charAt(0).toLowerCase() + alignment.substring(1)); - } - [iOSTabBarItemsAlignmentProperty.setNative](value: IOSTabBarItemsAlignment) { - if (!this.viewController || !this.viewController.tabBar) { - return; - } - - let alignment = MDCTabBarAlignment.Justified; - switch (value) { - case 'leading': - alignment = MDCTabBarAlignment.Leading; - break; - case 'center': - alignment = MDCTabBarAlignment.Center; - break; - case 'centerSelected': - alignment = MDCTabBarAlignment.CenterSelected; - break; - } - - this.viewController.tabBar.alignment = alignment; - } - - private setViewTextAttributes(view: View, setSelected: boolean = false): any { - if (!view) { - return null; - } - - const defaultTabItemFontSize = 10; - const tabItemFontSize = view.style.fontSize || defaultTabItemFontSize; - const font: UIFont = (view.style.fontInternal || Font.default).getUIFont(UIFont.systemFontOfSize(tabItemFontSize)); - - this.viewController.tabBar.unselectedItemTitleFont = font; - this.viewController.tabBar.selectedItemTitleFont = font; - - const tabItemTextColor = view.style.color; - const textColor = tabItemTextColor instanceof Color ? tabItemTextColor.ios : null; - - if (textColor) { - this.viewController.tabBar.setTitleColorForState(textColor, MDCTabBarItemState.Normal); - this.viewController.tabBar.setImageTintColorForState(textColor, MDCTabBarItemState.Normal); - - if (setSelected) { - this.viewController.tabBar.setTitleColorForState(textColor, MDCTabBarItemState.Selected); - this.viewController.tabBar.setImageTintColorForState(textColor, MDCTabBarItemState.Selected); - } - } - - if (this._selectedItemColor) { - this.viewController.tabBar.selectedItemTintColor = this._selectedItemColor.ios; - } - if (this._unSelectedItemColor) { - this.viewController.tabBar.unselectedItemTintColor = this._unSelectedItemColor.ios; - } - } -} diff --git a/packages/core/ui/tabs/tabs-common.ts b/packages/core/ui/tabs/tabs-common.ts deleted file mode 100644 index f4a4b9933f..0000000000 --- a/packages/core/ui/tabs/tabs-common.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Types -import { Tabs as TabsDefinition } from '.'; - -// Requires -import { TabNavigationBase } from '../tab-navigation-base/tab-navigation-base'; -import { CSSType } from '../core/view'; -import { booleanConverter } from '../core/view-base'; -import { Property } from '../core/properties'; - -export * from '../tab-navigation-base/tab-content-item'; -export * from '../tab-navigation-base/tab-navigation-base'; -export * from '../tab-navigation-base/tab-strip'; -export * from '../tab-navigation-base/tab-strip-item'; - -export const traceCategory = 'TabView'; - -@CSSType('Tabs') -export class TabsBase extends TabNavigationBase implements TabsDefinition { - public swipeEnabled: boolean; - public offscreenTabLimit: number; - public tabsPosition: 'top' | 'bottom'; - public iOSTabBarItemsAlignment: IOSTabBarItemsAlignment; -} - -// TODO: Add Unit tests -export const swipeEnabledProperty = new Property({ - name: 'swipeEnabled', - defaultValue: true, - valueConverter: booleanConverter, -}); -swipeEnabledProperty.register(TabsBase); - -// TODO: Add Unit tests -// TODO: Coerce to max number of items? -export const offscreenTabLimitProperty = new Property({ - name: 'offscreenTabLimit', - defaultValue: 1, - valueConverter: (v) => parseInt(v), -}); -offscreenTabLimitProperty.register(TabsBase); - -export const tabsPositionProperty = new Property({ - name: 'tabsPosition', - defaultValue: 'top', -}); -tabsPositionProperty.register(TabsBase); - -export type IOSTabBarItemsAlignment = 'leading' | 'justified' | 'center' | 'centerSelected'; -export const iOSTabBarItemsAlignmentProperty = new Property({ name: 'iOSTabBarItemsAlignment', defaultValue: 'justified' }); -iOSTabBarItemsAlignmentProperty.register(TabsBase); - -export const animationEnabledProperty = new Property({ name: 'animationEnabled', defaultValue: true, valueConverter: booleanConverter }); -animationEnabledProperty.register(TabsBase); From 5a3b9d5e16c801c4eb005c81c3c30d16d4e17499 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Sat, 12 Sep 2020 15:18:08 +0200 Subject: [PATCH 031/363] finish removal of Tabs component --- apps/automated/src/test-runner.ts | 9 - .../src/ui/tabs/tabs-navigation-tests.ts | 284 -------------- apps/automated/src/ui/tabs/tabs-root-tests.ts | 194 --------- .../src/ui/tabs/tabs-tests-native.android.ts | 40 -- .../src/ui/tabs/tabs-tests-native.d.ts | 8 - .../src/ui/tabs/tabs-tests-native.ios.ts | 44 --- apps/automated/src/ui/tabs/tabs-tests-new.ts | 33 -- apps/automated/src/ui/tabs/tabs-tests.ts | 350 ----------------- .../tabs/tabs-tests.e2e-spec.ts | 370 ------------------ .../tabs/tabs-view-base-page.ts | 39 -- apps/ui/src/bottom-navigation/events-page.ts | 8 +- apps/ui/src/main-page.ts | 1 - apps/ui/src/tabs/background-color-page.css | 19 - apps/ui/src/tabs/background-color-page.xml | 24 -- apps/ui/src/tabs/color-page.css | 27 -- apps/ui/src/tabs/color-page.xml | 33 -- apps/ui/src/tabs/custom-tabstrip-page.css | 31 -- apps/ui/src/tabs/custom-tabstrip-page.ts | 22 -- apps/ui/src/tabs/custom-tabstrip-page.xml | 41 -- apps/ui/src/tabs/default-page.ts | 15 - apps/ui/src/tabs/default-page.xml | 89 ----- .../ui/src/tabs/dynamic-color-change-page.css | 28 -- apps/ui/src/tabs/dynamic-color-change-page.ts | 37 -- .../ui/src/tabs/dynamic-color-change-page.xml | 44 --- apps/ui/src/tabs/events-page.ts | 40 -- apps/ui/src/tabs/events-page.xml | 36 -- apps/ui/src/tabs/first-page.ts | 13 - apps/ui/src/tabs/first-page.xml | 7 - apps/ui/src/tabs/font-icons-page.css | 39 -- apps/ui/src/tabs/font-icons-page.xml | 63 --- apps/ui/src/tabs/font-page.css | 27 -- apps/ui/src/tabs/font-page.xml | 33 -- .../src/tabs/frame-in-tabs-inner-page-1.xml | 3 - .../src/tabs/frame-in-tabs-inner-page-2.xml | 3 - .../src/tabs/frame-in-tabs-inner-page-3.xml | 3 - .../src/tabs/frame-in-tabs-inner-page-4.xml | 3 - apps/ui/src/tabs/frame-in-tabs.ts | 3 - apps/ui/src/tabs/frame-in-tabs.xml | 24 -- apps/ui/src/tabs/highlight-color-page.css | 3 - apps/ui/src/tabs/highlight-color-page.xml | 24 -- apps/ui/src/tabs/icon-change-page.ts | 17 - apps/ui/src/tabs/icon-change-page.xml | 23 -- .../ui/src/tabs/icon-title-placement-page.xml | 30 -- apps/ui/src/tabs/issue-5470-page.xml | 27 -- apps/ui/src/tabs/item-color-page.css | 20 - apps/ui/src/tabs/item-color-page.xml | 40 -- apps/ui/src/tabs/main-page.ts | 38 -- apps/ui/src/tabs/main-page.xml | 6 - .../tabs/nested-bottom-navigation-page.xml | 39 -- apps/ui/src/tabs/nested-layout-page.xml | 26 -- apps/ui/src/tabs/reselect-page.ts | 68 ---- apps/ui/src/tabs/reselect-page.xml | 37 -- apps/ui/src/tabs/second-page.ts | 13 - apps/ui/src/tabs/second-page.xml | 7 - apps/ui/src/tabs/swipe-disabled-page.xml | 40 -- apps/ui/src/tabs/tab-strip-item-page.xml | 16 - apps/ui/src/tabs/tab-strip-items-page.xml | 88 ----- apps/ui/src/tabs/tabs-binding-page.ts | 6 - apps/ui/src/tabs/tabs-binding-page.xml | 17 - apps/ui/src/tabs/tabs-binding-view-model.ts | 59 --- apps/ui/src/tabs/tabs-page.ts | 15 - apps/ui/src/tabs/tabs-page.xml | 36 -- apps/ui/src/tabs/tabs-position-page.xml | 40 -- apps/ui/src/tabs/text-transform-page.css | 27 -- apps/ui/src/tabs/text-transform-page.xml | 33 -- packages/core/ui/index.ts | 1 - .../tab-strip-item/index.ts | 2 - 67 files changed, 4 insertions(+), 2881 deletions(-) delete mode 100644 apps/automated/src/ui/tabs/tabs-navigation-tests.ts delete mode 100644 apps/automated/src/ui/tabs/tabs-root-tests.ts delete mode 100644 apps/automated/src/ui/tabs/tabs-tests-native.android.ts delete mode 100644 apps/automated/src/ui/tabs/tabs-tests-native.d.ts delete mode 100644 apps/automated/src/ui/tabs/tabs-tests-native.ios.ts delete mode 100644 apps/automated/src/ui/tabs/tabs-tests-new.ts delete mode 100644 apps/automated/src/ui/tabs/tabs-tests.ts delete mode 100644 apps/ui/e2e/suites/tab-navigation/tabs/tabs-tests.e2e-spec.ts delete mode 100644 apps/ui/e2e/suites/tab-navigation/tabs/tabs-view-base-page.ts delete mode 100644 apps/ui/src/tabs/background-color-page.css delete mode 100644 apps/ui/src/tabs/background-color-page.xml delete mode 100644 apps/ui/src/tabs/color-page.css delete mode 100644 apps/ui/src/tabs/color-page.xml delete mode 100644 apps/ui/src/tabs/custom-tabstrip-page.css delete mode 100644 apps/ui/src/tabs/custom-tabstrip-page.ts delete mode 100644 apps/ui/src/tabs/custom-tabstrip-page.xml delete mode 100644 apps/ui/src/tabs/default-page.ts delete mode 100644 apps/ui/src/tabs/default-page.xml delete mode 100644 apps/ui/src/tabs/dynamic-color-change-page.css delete mode 100644 apps/ui/src/tabs/dynamic-color-change-page.ts delete mode 100644 apps/ui/src/tabs/dynamic-color-change-page.xml delete mode 100644 apps/ui/src/tabs/events-page.ts delete mode 100644 apps/ui/src/tabs/events-page.xml delete mode 100644 apps/ui/src/tabs/first-page.ts delete mode 100644 apps/ui/src/tabs/first-page.xml delete mode 100644 apps/ui/src/tabs/font-icons-page.css delete mode 100644 apps/ui/src/tabs/font-icons-page.xml delete mode 100644 apps/ui/src/tabs/font-page.css delete mode 100644 apps/ui/src/tabs/font-page.xml delete mode 100644 apps/ui/src/tabs/frame-in-tabs-inner-page-1.xml delete mode 100644 apps/ui/src/tabs/frame-in-tabs-inner-page-2.xml delete mode 100644 apps/ui/src/tabs/frame-in-tabs-inner-page-3.xml delete mode 100644 apps/ui/src/tabs/frame-in-tabs-inner-page-4.xml delete mode 100644 apps/ui/src/tabs/frame-in-tabs.ts delete mode 100644 apps/ui/src/tabs/frame-in-tabs.xml delete mode 100644 apps/ui/src/tabs/highlight-color-page.css delete mode 100644 apps/ui/src/tabs/highlight-color-page.xml delete mode 100644 apps/ui/src/tabs/icon-change-page.ts delete mode 100644 apps/ui/src/tabs/icon-change-page.xml delete mode 100644 apps/ui/src/tabs/icon-title-placement-page.xml delete mode 100644 apps/ui/src/tabs/issue-5470-page.xml delete mode 100644 apps/ui/src/tabs/item-color-page.css delete mode 100644 apps/ui/src/tabs/item-color-page.xml delete mode 100644 apps/ui/src/tabs/main-page.ts delete mode 100644 apps/ui/src/tabs/main-page.xml delete mode 100644 apps/ui/src/tabs/nested-bottom-navigation-page.xml delete mode 100644 apps/ui/src/tabs/nested-layout-page.xml delete mode 100644 apps/ui/src/tabs/reselect-page.ts delete mode 100644 apps/ui/src/tabs/reselect-page.xml delete mode 100644 apps/ui/src/tabs/second-page.ts delete mode 100644 apps/ui/src/tabs/second-page.xml delete mode 100644 apps/ui/src/tabs/swipe-disabled-page.xml delete mode 100644 apps/ui/src/tabs/tab-strip-item-page.xml delete mode 100644 apps/ui/src/tabs/tab-strip-items-page.xml delete mode 100644 apps/ui/src/tabs/tabs-binding-page.ts delete mode 100644 apps/ui/src/tabs/tabs-binding-page.xml delete mode 100644 apps/ui/src/tabs/tabs-binding-view-model.ts delete mode 100644 apps/ui/src/tabs/tabs-page.ts delete mode 100644 apps/ui/src/tabs/tabs-page.xml delete mode 100644 apps/ui/src/tabs/tabs-position-page.xml delete mode 100644 apps/ui/src/tabs/text-transform-page.css delete mode 100644 apps/ui/src/tabs/text-transform-page.xml diff --git a/apps/automated/src/test-runner.ts b/apps/automated/src/test-runner.ts index 015b824777..06d0464759 100644 --- a/apps/automated/src/test-runner.ts +++ b/apps/automated/src/test-runner.ts @@ -200,15 +200,6 @@ export function isRunningOnEmulator(): boolean { // TODO: uncomment this // allTests["BOTTOM-NAVIGATION-NAVIGATION"] = bottomNavigationNavigationTests; - import * as tabsTests from './ui/tabs/tabs-tests'; - allTests['TABS'] = tabsTests; - - import * as tabsTestsNew from './ui/tabs/tabs-tests-new'; - allTests['TABS-NEW'] = tabsTestsNew; - - import * as tabsNavigationTests from './ui/tabs/tabs-navigation-tests'; - allTests['TABS-NAVIGATION'] = tabsNavigationTests; - import * as tabViewTests from './ui/tab-view/tab-view-tests'; allTests['TAB-VIEW'] = tabViewTests; diff --git a/apps/automated/src/ui/tabs/tabs-navigation-tests.ts b/apps/automated/src/ui/tabs/tabs-navigation-tests.ts deleted file mode 100644 index 44023ca28b..0000000000 --- a/apps/automated/src/ui/tabs/tabs-navigation-tests.ts +++ /dev/null @@ -1,284 +0,0 @@ -import * as TKUnit from '../../tk-unit'; -import * as helper from '../../ui-helper'; -import { Label } from '@nativescript/core/ui/label'; -import { StackLayout } from '@nativescript/core/ui/layouts/stack-layout'; -import { Frame } from '@nativescript/core/ui/frame'; -import { Page } from '@nativescript/core/ui/page'; -import { ListView, ItemEventData } from '@nativescript/core/ui/list-view'; -import { Tabs, TabContentItem, TabStrip, TabStripItem } from '@nativescript/core/ui/tabs'; -import { Button } from '@nativescript/core/ui/button'; - -var ASYNC = 2; - -function _createTabsNavigation(): Tabs { - var tabView = new Tabs(); - tabView.id = 'BottomNavigation'; - - return tabView; -} - -function _createContentItems(count: number): Array { - const items = new Array(); - for (let i = 0; i < count; i++) { - const label = new Label(); - label.text = 'Tab ' + i; - const tabEntry = new TabContentItem(); - tabEntry.content = label; - items.push(tabEntry); - } - - return items; -} - -function _createTabStrip(count: number): TabStrip { - const items = new Array(); - for (let i = 0; i < count; i++) { - let tabStripEntry = new TabStripItem(); - tabStripEntry.title = 'Tab ' + i; - items.push(tabStripEntry); - } - - const tabStrip = new TabStrip(); - tabStrip.items = items; - - return tabStrip; -} - -function _createListView(): ListView { - var listView = new ListView(); - listView.id = 'ListView'; - var items = Array.apply(null, Array(10)).map(function (_, i) { - return i; - }); - - listView.on(ListView.itemLoadingEvent, function (args: ItemEventData) { - var button =