Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PlatformColor implementations for iOS and Android #27908

Closed
wants to merge 64 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
befcb09
Added NativeColorValue type and PlatformColor function
tom-un Dec 16, 2019
fac49d5
RNTester and React building and running.
tom-un Dec 16, 2019
02d0d2f
Added Unit Tests
tom-un Dec 16, 2019
b204748
type cleanup
tom-un Dec 16, 2019
00370a6
Fix lint error
tom-un Dec 16, 2019
b16ebd5
Experimental android NativeColorValue defined to test Flow validation.
tom-un Dec 17, 2019
1ac6e49
Changed NativeColorValue to an opaque type.
tom-un Dec 18, 2019
bbc0205
Added IOSDynamicColor and AndroidHypotheticalColor factory methods.
tom-un Dec 19, 2019
e896a94
Implemented fallback color support.
tom-un Dec 20, 2019
488f2c3
Added fallback example
tom-un Dec 20, 2019
424e17c
Cleanup of PlatformColorExample
tom-un Dec 20, 2019
d3eeb85
Got custom android colors stubbed and running.
tom-un Jan 13, 2020
6251d77
Got Android named colors working.
tom-un Jan 14, 2020
2b71a4e
Parse android color resource string path.
tom-un Jan 14, 2020
ffbcea1
Adds support for resolving colors from arbitrary packages
arazabishov Jan 27, 2020
243e6fe
Adds more colors for testing
arazabishov Jan 27, 2020
8d1312f
Adds support for fallback colors on android.
arazabishov Jan 28, 2020
d9ec0ca
Merge pull request #1 from ArazAbishov/fb-platformcolor-android
tom-un Jan 28, 2020
a047ef5
Merge remote-tracking branch 'fb/master' into fb-platformcolor
tom-un Jan 28, 2020
985e489
Restore file to original
tom-un Jan 28, 2020
92a430d
Removed diffs
tom-un Jan 28, 2020
f4aa631
Removed diffs
tom-un Jan 28, 2020
730879e
Cleaned up Flow errors
tom-un Jan 28, 2020
354cf10
Adds a missing dependency
arazabishov Jan 28, 2020
3c57efa
Merge pull request #2 from ArazAbishov/araz/add-missing-dependency
tom-un Jan 28, 2020
6a4f6b0
Added runtime exception errors for invalid Android ColorValues.
tom-un Jan 29, 2020
f0dd0af
Removed old experimental code.
tom-un Jan 29, 2020
fd68267
Added PlatformColor tests to processColor-test.js
tom-un Feb 2, 2020
67961a4
Added PlatformColor tests in processColorArray-test.js
tom-un Feb 2, 2020
b436ced
Fixed android test
tom-un Feb 2, 2020
426bc97
Added PlatformColor normalizeColor-test.js
tom-un Feb 2, 2020
11dceef
Teach Codegen about 'PlatformColorValue'
tom-un Feb 3, 2020
d9102ff
Got Android tests to build again.
tom-un Feb 4, 2020
ed8b3c9
Changes per TheSavior's PR feedback.
tom-un Feb 5, 2020
7a4629b
Changes per nscoding's feedback.
tom-un Feb 5, 2020
888fe53
Created NativeColorValueTypesIOS.<platform>.js for the IOSDynamicColo…
tom-un Feb 5, 2020
ec4261c
Fix analysis-bot Flow errors
tom-un Feb 5, 2020
36b9cae
Renamed NativeColorValueTypesIOS.android.js to Libraries/StyleSheet/N…
tom-un Feb 5, 2020
3a29ea2
Added Android specific color method to test Flow and bundling
tom-un Feb 6, 2020
3af3fb4
Added VariantColorsExample to PlatformColorExample.js
tom-un Feb 9, 2020
00ae701
Changes per mdvacca's PR feedback
tom-un Feb 9, 2020
cbf9114
Reverting changes to unit test code. Will make a future PR to restor…
tom-un Feb 9, 2020
fd0f767
Changes per mdvacca's PR feedback.
tom-un Feb 9, 2020
d58fa62
Changed example to use statically analyzable values only.
tom-un Feb 9, 2020
c0732f6
Changed example to use hooks
tom-un Feb 9, 2020
3d07791
Fixed '!==' v '!=' issues.
tom-un Feb 10, 2020
013eb08
Switched `!= undefined` back to `!== undefined` per analysis-bot.
tom-un Feb 10, 2020
ce961f9
`!== undefined` to `!= null`
tom-un Feb 10, 2020
b8897ee
Rename IOSDynamicColor to DynamicColorIOS and AndroidColor to ColorAn…
tom-un Feb 11, 2020
71d0dfd
Fixed jest tests renaming IOSDynamicColor to DynamicColorIOS
tom-un Feb 11, 2020
5fe7e8a
Fixed some color types.
tom-un Feb 11, 2020
e54379a
Changed NativeActionSHeetManager.js back to number tintColor
tom-un Feb 11, 2020
8dbf43f
Lint fixes
tom-un Feb 11, 2020
4f04c62
Updated invariant message.
tom-un Feb 11, 2020
d84fb32
Got rid of redundant call to processColor()
tom-un Feb 12, 2020
1562d0c
Fixed lint error
tom-un Feb 12, 2020
87b93d5
Renamed NativeColorValueTypes*.* to PlatformColorValueTypes*.*
tom-un Feb 12, 2020
f722153
Merge remote-tracking branch 'fb/master' into fb-platformcolor
tom-un Feb 20, 2020
8ced1e6
Removed ProcessColorValue type from NativeStatusBarManagerAndroid.js.
tom-un Feb 21, 2020
a8da7f3
Merge remote-tracking branch 'fb/master' into fb-platformcolor
tom-un Feb 21, 2020
7adb25f
Refactored so that ColorValue is defined and exported from StyleSheet…
tom-un Feb 21, 2020
ab1cdad
Refactored so that the ColorProp conversion logic is moved out of the…
tom-un Feb 27, 2020
978e14f
Removed changes to *ManagerDelegate.java files as they are codegen ge…
tom-un Feb 28, 2020
8d29ae1
Merge remote-tracking branch 'fb/master' into fb-platformcolor
tom-un Feb 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Libraries/ART/ARTSurfaceView.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ - (void)invalidate

- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
tom-un marked this conversation as resolved.
Show resolved Hide resolved
CGContextRef context = UIGraphicsGetCurrentContext();
for (ARTNode *node in self.subviews) {
[node renderTo:context];
Expand Down
4 changes: 3 additions & 1 deletion Libraries/ActionSheetIOS/ActionSheetIOS.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import RCTActionSheetManager from './NativeActionSheetManager';

const invariant = require('invariant');
const processColor = require('../StyleSheet/processColor');
import type {ColorValue} from '../StyleSheet/StyleSheetTypes';
import type {ProcessedColorValue} from '../StyleSheet/processColor';

/**
* Display action sheets and share sheets on iOS.
Expand Down Expand Up @@ -45,7 +47,7 @@ const ActionSheetIOS = {
+destructiveButtonIndex?: ?number | ?Array<number>,
+cancelButtonIndex?: ?number,
+anchor?: ?number,
+tintColor?: number | string,
+tintColor?: ColorValue | ProcessedColorValue,
+userInterfaceStyle?: string,
|},
callback: (buttonIndex: number) => void,
Expand Down
14 changes: 7 additions & 7 deletions Libraries/Animated/src/nodes/AnimatedInterpolation.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,17 +164,17 @@ function interpolate(
}

function colorToRgba(input: string): string {
let int32Color = normalizeColor(input);
if (int32Color === null) {
let normalizedColor = normalizeColor(input);
if (normalizedColor === null || typeof normalizedColor !== 'number') {
return input;
}

int32Color = int32Color || 0;
normalizedColor = normalizedColor || 0;

const r = (int32Color & 0xff000000) >>> 24;
const g = (int32Color & 0x00ff0000) >>> 16;
const b = (int32Color & 0x0000ff00) >>> 8;
const a = (int32Color & 0x000000ff) / 255;
const r = (normalizedColor & 0xff000000) >>> 24;
const g = (normalizedColor & 0x00ff0000) >>> 16;
const b = (normalizedColor & 0x0000ff00) >>> 8;
const a = (normalizedColor & 0x000000ff) / 255;

return `rgba(${r}, ${g}, ${b}, ${a})`;
}
Expand Down
3 changes: 2 additions & 1 deletion Libraries/Components/ActivityIndicator/ActivityIndicator.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const StyleSheet = require('../../StyleSheet/StyleSheet');
const View = require('../View/View');
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
import type {ViewProps} from '../View/ViewPropTypes';
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';

const PlatformActivityIndicator =
Platform.OS === 'android'
Expand Down Expand Up @@ -50,7 +51,7 @@ type Props = $ReadOnly<{|
*
* See https://reactnative.dev/docs/activityindicator.html#color
*/
color?: ?string,
color?: ?ColorValue,
tom-un marked this conversation as resolved.
Show resolved Hide resolved

/**
* Size of the indicator (default is 'small').
Expand Down
3 changes: 2 additions & 1 deletion Libraries/Components/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const View = require('./View/View');
const invariant = require('invariant');

import type {PressEvent} from '../Types/CoreEventTypes';
import type {ColorValue} from '../StyleSheet/StyleSheetTypes';

type ButtonProps = $ReadOnly<{|
/**
Expand All @@ -41,7 +42,7 @@ type ButtonProps = $ReadOnly<{|
/**
* Color of the text (iOS), or background color of the button (Android)
*/
color?: ?string,
color?: ?ColorValue,

/**
* TV preferred focus (see documentation for the View component).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const requireNativeComponent = require('../../ReactNative/requireNativeComponent
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
import type {ViewProps} from '../View/ViewPropTypes';
import type {SyntheticEvent} from '../../Types/CoreEventTypes';
import type {ProcessedColorValue} from '../../StyleSheet/processColor';

type CheckBoxEvent = SyntheticEvent<
$ReadOnly<{|
Expand Down Expand Up @@ -47,7 +48,12 @@ type NativeProps = $ReadOnly<{|

on?: ?boolean,
enabled?: boolean,
tintColors: {|true: ?number, false: ?number|} | typeof undefined,
tintColors:
tom-un marked this conversation as resolved.
Show resolved Hide resolved
| {|
true: ?ProcessedColorValue,
false: ?ProcessedColorValue,
|}
| typeof undefined,
|}>;

type NativeType = HostComponent<NativeProps>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ class DrawerLayoutAndroid extends React.Component<Props, State> {
...props
} = this.props;
const drawStatusBar =
Platform.Version >= 21 && this.props.statusBarBackgroundColor;
Platform.Version >= 21 && this.props.statusBarBackgroundColor != null;
const drawerViewWrapper = (
<View
style={[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ import type {
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
import type {ProcessedColorValue} from '../../StyleSheet/processColor';
import type {ViewProps} from '../../Components/View/ViewPropTypes';

type PickerItem = $ReadOnly<{|
label: string,
color?: ?Int32,
color?: ?ProcessedColorValue,
tom-un marked this conversation as resolved.
Show resolved Hide resolved
|}>;

type PickerItemSelectEvent = $ReadOnly<{|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ import type {
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
import type {ProcessedColorValue} from '../../StyleSheet/processColor';
import type {ViewProps} from '../../Components/View/ViewPropTypes';

type PickerItem = $ReadOnly<{|
label: string,
color?: ?Int32,
color?: ?ProcessedColorValue,
|}>;

type PickerItemSelectEvent = $ReadOnly<{|
Expand Down
3 changes: 2 additions & 1 deletion Libraries/Components/Picker/PickerIOS.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import RCTPickerNativeComponent, {
} from './RCTPickerNativeComponent';
import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
import type {ProcessedColorValue} from '../../StyleSheet/processColor';
import type {SyntheticEvent} from '../../Types/CoreEventTypes';
import type {ViewProps} from '../View/ViewPropTypes';

Expand All @@ -37,7 +38,7 @@ type PickerIOSChangeEvent = SyntheticEvent<
type RCTPickerIOSItemType = $ReadOnly<{|
label: ?Label,
value: ?(number | string),
textColor: ?number,
textColor: ?ProcessedColorValue,
|}>;

type Label = Stringish | number;
Expand Down
3 changes: 2 additions & 1 deletion Libraries/Components/Picker/RCTPickerNativeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const requireNativeComponent = require('../../ReactNative/requireNativeComponent
import type {HostComponent} from '../../Renderer/shims/ReactNativeTypes';
import type {SyntheticEvent} from '../../Types/CoreEventTypes';
import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
import type {ProcessedColorValue} from '../../StyleSheet/processColor';
import codegenNativeCommands from '../../Utilities/codegenNativeCommands';
import * as React from 'react';

Expand All @@ -28,7 +29,7 @@ type PickerIOSChangeEvent = SyntheticEvent<
type RCTPickerIOSItemType = $ReadOnly<{|
label: ?Label,
value: ?(number | string),
textColor: ?number,
textColor: ?ProcessedColorValue,
|}>;

type Label = Stringish | number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const React = require('react');
import ProgressBarAndroidNativeComponent from './ProgressBarAndroidNativeComponent';

import type {ViewProps} from '../View/ViewPropTypes';
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';

export type ProgressBarAndroidProps = $ReadOnly<{|
...ViewProps,
Expand Down Expand Up @@ -49,7 +50,7 @@ export type ProgressBarAndroidProps = $ReadOnly<{|
/**
* Color of the progress bar.
*/
color?: ?string,
color?: ?ColorValue,
/**
* Used to locate this view in end-to-end tests.
*/
Expand Down
3 changes: 2 additions & 1 deletion Libraries/Components/StatusBar/StatusBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const React = require('react');

const invariant = require('invariant');
const processColor = require('../../StyleSheet/processColor');
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';

import NativeStatusBarManagerAndroid from './NativeStatusBarManagerAndroid';
import NativeStatusBarManagerIOS from './NativeStatusBarManagerIOS';
Expand Down Expand Up @@ -62,7 +63,7 @@ type AndroidProps = $ReadOnly<{|
* The background color of the status bar.
* @platform android
*/
backgroundColor?: ?string,
backgroundColor?: ?ColorValue,
/**
* If the status bar is translucent.
* When translucent is set to true, the app will draw under the status bar.
Expand Down
10 changes: 8 additions & 2 deletions Libraries/Pressability/PressabilityDebug.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
'use strict';

import normalizeColor from '../StyleSheet/normalizeColor.js';
import type {ColorValue} from '../StyleSheet/StyleSheetTypes';

import Touchable from '../Components/Touchable/Touchable';
import View from '../Components/View/View';
import * as React from 'react';

type Props = $ReadOnly<{|
color: string,
color: ColorValue,
hitSlop: ?$ReadOnly<{|
bottom?: ?number,
left?: ?number,
Expand All @@ -43,8 +45,12 @@ type Props = $ReadOnly<{|
export function PressabilityDebugView({color, hitSlop}: Props): React.Node {
if (__DEV__) {
if (isEnabled()) {
const normalizedColor = normalizeColor(color);
tom-un marked this conversation as resolved.
Show resolved Hide resolved
if (typeof normalizedColor !== 'number') {
return null;
}
const baseColor =
'#' + (normalizeColor(color) ?? 0).toString(16).padStart(8, '0');
'#' + (normalizedColor ?? 0).toString(16).padStart(8, '0');

return (
<View
Expand Down
2 changes: 1 addition & 1 deletion Libraries/Share/Share.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class Share {
typeof content.message === 'string' ? content.message : undefined,
url: typeof content.url === 'string' ? content.url : undefined,
subject: options.subject,
tintColor: tintColor != null ? tintColor : undefined,
tintColor: typeof tintColor === 'number' ? tintColor : undefined,
excludedActivityTypes: options.excludedActivityTypes,
},
error => reject(error),
Expand Down
41 changes: 41 additions & 0 deletions Libraries/StyleSheet/PlatformColorValueTypes.android.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/

'use strict';

import type {ColorValue} from './StyleSheetTypes';
import type {ProcessedColorValue} from './processColor';

export opaque type NativeColorValue = {
resource_paths?: Array<string>,
};

export const PlatformColor = (...names: Array<string>): ColorValue => {
return {resource_paths: names};
};

export const ColorAndroidPrivate = (color: string): ColorValue => {
return {resource_paths: [color]};
};

export const normalizeColorObject = (
color: NativeColorValue,
): ?ProcessedColorValue => {
if ('resource_paths' in color) {
return color;
}
return null;
};

export const processColorObject = (
color: NativeColorValue,
): ?NativeColorValue => {
return color;
};
77 changes: 77 additions & 0 deletions Libraries/StyleSheet/PlatformColorValueTypes.ios.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/

'use strict';

import type {ColorValue} from './StyleSheetTypes';
import type {ProcessedColorValue} from './processColor';

export opaque type NativeColorValue = {
semantic?: Array<string>,
dynamic?: {
light: ?(ColorValue | ProcessedColorValue),
dark: ?(ColorValue | ProcessedColorValue),
},
};

export const PlatformColor = (...names: Array<string>): ColorValue => {
return {semantic: names};
};

export type DynamicColorIOSTuplePrivate = {
light: ColorValue,
dark: ColorValue,
};

export const DynamicColorIOSPrivate = (
tuple: DynamicColorIOSTuplePrivate,
): ColorValue => {
return {dynamic: {light: tuple.light, dark: tuple.dark}};
};

export const normalizeColorObject = (
color: NativeColorValue,
): ?ProcessedColorValue => {
if ('semantic' in color) {
// an ios semantic color
return color;
} else if ('dynamic' in color && color.dynamic !== undefined) {
const normalizeColor = require('./normalizeColor');

// a dynamic, appearance aware color
const dynamic = color.dynamic;
const dynamicColor: NativeColorValue = {
dynamic: {
light: normalizeColor(dynamic.light),
dark: normalizeColor(dynamic.dark),
},
};
return dynamicColor;
}

return null;
};

export const processColorObject = (
color: NativeColorValue,
): ?NativeColorValue => {
if ('dynamic' in color && color.dynamic != null) {
const processColor = require('./processColor');
const dynamic = color.dynamic;
const dynamicColor: NativeColorValue = {
dynamic: {
light: processColor(dynamic.light),
dark: processColor(dynamic.dark),
},
};
return dynamicColor;
}
return color;
};
18 changes: 18 additions & 0 deletions Libraries/StyleSheet/PlatformColorValueTypesAndroid.android.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/

'use strict';

import type {ColorValue} from './StyleSheetTypes';
import {ColorAndroidPrivate} from './PlatformColorValueTypes';

export const ColorAndroid = (color: string): ColorValue => {
return ColorAndroidPrivate(color);
};
Loading