fix-next(css): className to preserve root views classes (#7725)

This commit is contained in:
Vasil Chimev
2019-08-30 09:09:35 +03:00
committed by GitHub
parent 92c3338dd5
commit d23ffb8dbf
13 changed files with 263 additions and 66 deletions

View File

@@ -40,6 +40,8 @@ import {
LoadAppCSSEventData,
UnhandledErrorEventData
} from "./application";
import { CLASS_PREFIX, pushToRootViewCssClasses, removeFromRootViewCssClasses } from "../css/system-classes";
import { DeviceOrientation } from "../ui/enums/enums";
export { UnhandledErrorEventData, DiscardedErrorEventData, CssChangedEventData, LoadAppCSSEventData };
@@ -54,11 +56,10 @@ export const uncaughtErrorEvent = "uncaughtError";
export const discardedErrorEvent = "discardedError";
export const orientationChangedEvent = "orientationChanged";
export const CSS_CLASS_PREFIX = "ns-";
const ORIENTATION_CSS_CLASSES = [
`${CSS_CLASS_PREFIX}${DeviceOrientation.portrait}`,
`${CSS_CLASS_PREFIX}${DeviceOrientation.landscape}`,
`${CSS_CLASS_PREFIX}${DeviceOrientation.unknown}`
`${CLASS_PREFIX}${DeviceOrientation.portrait}`,
`${CLASS_PREFIX}${DeviceOrientation.landscape}`,
`${CLASS_PREFIX}${DeviceOrientation.unknown}`
];
let cssFile: string = "./app.css";
@@ -126,9 +127,15 @@ export function loadAppCss(): void {
}
export function orientationChanged(rootView: View, newOrientation: "portrait" | "landscape" | "unknown"): void {
const newOrientationCssClass = `${CSS_CLASS_PREFIX}${newOrientation}`;
const newOrientationCssClass = `${CLASS_PREFIX}${newOrientation}`;
if (!rootView.cssClasses.has(newOrientationCssClass)) {
ORIENTATION_CSS_CLASSES.forEach(c => rootView.cssClasses.delete(c));
const removeCssClass = (c: string) => {
removeFromRootViewCssClasses(c);
rootView.cssClasses.delete(c);
};
ORIENTATION_CSS_CLASSES.forEach(c => removeCssClass(c));
pushToRootViewCssClasses(newOrientationCssClass);
rootView.cssClasses.add(newOrientationCssClass);
rootView._onCssStateChange();
}

View File

@@ -53,11 +53,6 @@ export const lowMemoryEvent: string;
*/
export const orientationChangedEvent: string;
/**
* String value "ns-" used for CSS class prefix.
*/
export const CSS_CLASS_PREFIX: string;
/**
* Event data containing information for the application events.
*/

View File

@@ -1,4 +1,3 @@
import {
ApplicationEventData,
CssChangedEventData,
@@ -9,9 +8,8 @@ import {
} from ".";
import {
CSS_CLASS_PREFIX, displayedEvent, exitEvent, getCssFileName, launchEvent, livesync,
lowMemoryEvent, notify, on, orientationChanged, orientationChangedEvent, resumeEvent,
setApplication, suspendEvent
displayedEvent, exitEvent, getCssFileName, launchEvent, livesync, lowMemoryEvent, notify, on,
orientationChanged, orientationChangedEvent, resumeEvent, setApplication, suspendEvent
} from "./application-common";
// First reexport so that app module is initialized.
@@ -19,18 +17,15 @@ export * from "./application-common";
// TODO: Remove this and get it from global to decouple builder for angular
import { createViewFromEntry } from "../ui/builder";
import { CLASS_PREFIX, getRootViewCssClasses, pushToRootViewCssClasses } from "../css/system-classes";
import { ios as iosView, View } from "../ui/core/view";
import { Frame, NavigationEntry } from "../ui/frame";
import { device } from "../platform/platform";
import { profile } from "../profiling";
import { ios } from "../utils/utils";
const ROOT = "root";
const IOS_PLATFORM = "ios";
const ROOT_VIEW_CSS_CLASSES = [
`${CSS_CLASS_PREFIX}${ROOT}`,
`${CSS_CLASS_PREFIX}${IOS_PLATFORM}`
];
const getVisibleViewController = ios.getVisibleViewController;
// NOTE: UIResponder with implementation of window - related to https://github.com/NativeScript/ios-runtime/issues/430
@@ -317,9 +312,12 @@ function createRootView(v?: View) {
}
const deviceType = device.deviceType.toLowerCase();
ROOT_VIEW_CSS_CLASSES.push(`${CSS_CLASS_PREFIX}${deviceType}`);
ROOT_VIEW_CSS_CLASSES.push(`${CSS_CLASS_PREFIX}${iosApp.orientation}`);
ROOT_VIEW_CSS_CLASSES.forEach(c => rootView.cssClasses.add(c));
pushToRootViewCssClasses(`${CLASS_PREFIX}${IOS_PLATFORM}`);
pushToRootViewCssClasses(`${CLASS_PREFIX}${deviceType}`);
pushToRootViewCssClasses(`${CLASS_PREFIX}${iosApp.orientation}`);
const rootViewCssClasses = getRootViewCssClasses();
rootViewCssClasses.forEach(c => rootView.cssClasses.add(c));
return rootView;
}

View File

@@ -0,0 +1,30 @@
/**
* @module "system-classes"
*/ /** */
/**
* String value "ns-" used for CSS system class prefix.
*/
export const CLASS_PREFIX: string;
/**
* Gets CSS system class for modal root view.
*/
export function getModalRootViewCssClass(): string;
/**
* Gets CSS system classes for root view.
*/
export function getRootViewCssClasses(): string[];
/**
* * Appends new CSS class to the system classes and returns the new length of the array.
* @param value New CSS system class.
*/
export function pushToRootViewCssClasses(value: string): number;
/**
* Removes CSS class from the system classes and returns it.
* @param value
*/
export function removeFromRootViewCssClasses(value: string): string;

View File

@@ -0,0 +1,32 @@
const MODAL = "modal";
const ROOT = "root";
export const CLASS_PREFIX = "ns-";
const modalRootViewCssClass = `${CLASS_PREFIX}${MODAL}`;
const rootViewCssClasses = [`${CLASS_PREFIX}${ROOT}`];
export function getModalRootViewCssClass(): string {
return modalRootViewCssClass;
}
export function getRootViewCssClasses(): string[] {
return rootViewCssClasses;
}
export function pushToRootViewCssClasses(value: string): number {
rootViewCssClasses.push(value);
return rootViewCssClasses.length;
}
export function removeFromRootViewCssClasses(value: string): string {
const index = rootViewCssClasses.indexOf(value);
let removedElement;
if (index > -1) {
removedElement = rootViewCssClasses.splice(index, 1);
}
return removedElement;
}

View File

@@ -1,10 +1,13 @@
// Definitions.
import { ViewBase as ViewBaseDefinition } from ".";
import {
AlignSelf, FlexGrow, FlexShrink, FlexWrapBefore, Order
} from "../../layouts/flexbox-layout";
import { Page } from "../../page";
import { Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf } from "../../layouts/flexbox-layout";
// Types.
import { Property, CssProperty, CssAnimationProperty, InheritedProperty, Style, clearInheritedProperties, propagateInheritableProperties, propagateInheritableCssProperties, initNativeView } from "../properties";
import { getModalRootViewCssClass, getRootViewCssClasses } from "../../../css/system-classes";
import { Source } from "../../../utils/debug";
import { Binding, BindingOptions, Observable, WrappedValue, PropertyChangeData, traceEnabled, traceWrite, traceCategories } from "../bindable";
import { isIOS, isAndroid } from "../../../platform";
@@ -22,10 +25,9 @@ export { isIOS, isAndroid, layout, Color };
export * from "../bindable";
export * from "../properties";
import * as dnm from "../../../debugger/dom-node";
import * as ssm from "../../styling/style-scope";
// import { DOMNode } from "../../../debugger/dom-node";
import * as dnm from "../../../debugger/dom-node";
let domNodeModule: typeof dnm;
function ensuredomNodeModule(): void {
@@ -1036,11 +1038,26 @@ bindingContextProperty.register(ViewBase);
export const classNameProperty = new Property<ViewBase, string>({
name: "className",
valueChanged(view: ViewBase, oldValue: string, newValue: string) {
let classes = view.cssClasses;
classes.clear();
if (typeof newValue === "string" && newValue !== "") {
newValue.split(" ").forEach(c => classes.add(c));
const cssClasses = view.cssClasses;
const modalViewCssClass = getModalRootViewCssClass();
const rootViewCssClasses = getRootViewCssClasses();
const shouldAddModalRootViewCssClass = cssClasses.has(modalViewCssClass);
const shouldAddRootViewCssClasses = cssClasses.has(rootViewCssClasses[0]);
cssClasses.clear();
if (shouldAddModalRootViewCssClass) {
cssClasses.add(modalViewCssClass);
} else if (shouldAddRootViewCssClasses) {
rootViewCssClasses.forEach(c => cssClasses.add(c));
}
if (typeof newValue === "string" && newValue !== "") {
newValue.split(" ").forEach(c => cssClasses.add(c));
}
view._onCssStateChange();
}
});
@@ -1058,4 +1075,4 @@ export function booleanConverter(v: string): boolean {
}
throw new Error(`Invalid boolean: ${v}`);
}
}

View File

@@ -5,9 +5,8 @@ import {
} from ".";
import {
ViewBase, Property, booleanConverter, EventData, layout,
getEventOrGestureName, traceEnabled, traceWrite, traceCategories,
InheritedProperty, ShowModalOptions
booleanConverter, EventData, getEventOrGestureName, InheritedProperty, layout,
Property, ShowModalOptions, traceCategories, traceEnabled, traceWrite, ViewBase
} from "../view-base";
import { HorizontalAlignment, VerticalAlignment, Visibility, Length, PercentLength } from "../../styling/style-properties";
@@ -20,6 +19,7 @@ import {
fromString as gestureFromString
} from "../../gestures";
import { getModalRootViewCssClass } from "../../../css/system-classes";
import { createViewFromEntry } from "../../builder";
import { sanitizeModuleName } from "../../builder/module-name-sanitizer";
import { StyleScope } from "../../styling/style-scope";
@@ -31,9 +31,6 @@ export * from "../view-base";
export { LinearGradient };
import * as am from "../../animation";
import { CSS_CLASS_PREFIX } from "../../../application";
const MODAL = "modal";
let animationModule: typeof am;
function ensureAnimationModule() {
@@ -373,7 +370,9 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
protected _showNativeModalView(parent: ViewCommon, options: ShowModalOptions) {
_rootModalViews.push(this);
this.cssClasses.add(`${CSS_CLASS_PREFIX}${MODAL}`);
const modalRootViewCssClass = getModalRootViewCssClass();
this.cssClasses.add(modalRootViewCssClass);
parent._modal = this;
this._modalParent = parent;

View File

@@ -7,9 +7,10 @@ import { Page } from "../page";
// Types.
import * as application from "../../application";
import {
FrameBase, goBack, _stack, NavigationType,
Observable, View, traceCategories, traceEnabled, traceError, traceWrite
_stack, FrameBase, goBack, NavigationType, Observable,
traceCategories, traceEnabled, traceError, traceWrite, View
} from "./frame-common";
import {
@@ -19,6 +20,7 @@ import {
// TODO: Remove this and get it from global to decouple builder for angular
import { createViewFromEntry } from "../builder";
import { CLASS_PREFIX, getRootViewCssClasses, pushToRootViewCssClasses } from "../../css/system-classes";
import { device } from "../../platform/platform";
import { profile } from "../../profiling";
@@ -32,12 +34,7 @@ interface AnimatorState {
transitionName: string;
}
const ROOT = "root";
const ANDROID_PLATFORM = "android";
const ROOT_VIEW_CSS_CLASSES = [
`${application.CSS_CLASS_PREFIX}${ROOT}`,
`${application.CSS_CLASS_PREFIX}${ANDROID_PLATFORM}`
];
const INTENT_EXTRA = "com.tns.activity";
const ROOT_VIEW_ID_EXTRA = "com.tns.activity.rootViewId";
@@ -1289,9 +1286,12 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks {
activityRootViewsMap.set(rootView._domId, new WeakRef(rootView));
const deviceType = device.deviceType.toLowerCase();
ROOT_VIEW_CSS_CLASSES.push(`${application.CSS_CLASS_PREFIX}${deviceType}`);
ROOT_VIEW_CSS_CLASSES.push(`${application.CSS_CLASS_PREFIX}${application.android.orientation}`);
ROOT_VIEW_CSS_CLASSES.forEach(c => this._rootView.cssClasses.add(c));
pushToRootViewCssClasses(`${CLASS_PREFIX}${ANDROID_PLATFORM}`);
pushToRootViewCssClasses(`${CLASS_PREFIX}${deviceType}`);
pushToRootViewCssClasses(`${CLASS_PREFIX}${application.android.orientation}`);
const rootViewCssClasses = getRootViewCssClasses();
rootViewCssClasses.forEach(c => this._rootView.cssClasses.add(c));
}
// Initialize native visual tree;

View File

@@ -10,4 +10,4 @@
export function _layoutRootView(rootView: any, parentBounds: any) {
throw new Error("Not implemented for Android");
}
}
}

View File

@@ -3,6 +3,7 @@
*/
import { View } from "./core/view";
export module ios {
/**
* Gets actual height of a [UIView](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/) widget in device pixels.

View File

@@ -24,4 +24,4 @@ export module ios {
return utils.layout.toDevicePixels(min);
}
}
}