Skip to content

Commit

Permalink
feat(auto-dark): Month Picker Auto Dark Mode (iOS) (#18)
Browse files Browse the repository at this point in the history
* feat(auto-dark): Month Picker Auto Dark Mode (iOS)
  • Loading branch information
gusparis authored Jun 24, 2020
1 parent 87fc9a9 commit 13a7dea
Show file tree
Hide file tree
Showing 13 changed files with 660 additions and 496 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ Picker modal cancelation button text style.
<RNMonthPicker cancelButtonStyle={{ color: 'red', letterSpacing: 0.25 }} />
```

#### `enableAutoDarkMode` (`iOS only`)

Enables auto Dark Mode recognition. If set to `false` or iOS lower than v13.0, it will always display Light Mode. Default `true`. ***Android Dark Theme selector currently under construction.***

```js
<RNMonthPicker enableAutoDarkMode={false} />
```

## Running example
1. Install required pods in example/ios by running `npx pod-install`.
2. Run `yarn start` to start Metro Bundler.
Expand Down
6 changes: 3 additions & 3 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ PODS:
- React-cxxreact (= 0.62.2)
- React-jsi (= 0.62.2)
- React-jsinspector (0.62.2)
- react-native-month-year-picker (1.0.4):
- react-native-month-year-picker (1.1.3):
- React
- React-RCTActionSheet (0.62.2):
- React-Core/RCTActionSheetHeaders (= 0.62.2)
Expand Down Expand Up @@ -443,7 +443,7 @@ SPEC CHECKSUMS:
React-jsi: b6dc94a6a12ff98e8877287a0b7620d365201161
React-jsiexecutor: 1540d1c01bb493ae3124ed83351b1b6a155db7da
React-jsinspector: 512e560d0e985d0e8c479a54a4e5c147a9c83493
react-native-month-year-picker: f419759ad21088a3523f06a53e0f77d6a95f5fed
react-native-month-year-picker: ef1d6f26c8416f74d027a56cf648060aae87bc24
React-RCTActionSheet: f41ea8a811aac770e0cc6e0ad6b270c644ea8b7c
React-RCTAnimation: 49ab98b1c1ff4445148b72a3d61554138565bad0
React-RCTBlob: a332773f0ebc413a0ce85942a55b064471587a71
Expand All @@ -459,4 +459,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 56c2537f71f3f02200d6918c542a8e89a0b422fa

COCOAPODS: 1.9.1
COCOAPODS: 1.9.3
11 changes: 11 additions & 0 deletions ios/RNDarkMode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// RNDarkMode.h
// RNMonthPicker
//
// Created by Gustavo Paris on 15/06/2020.
// Copyright © 2020 Facebook. All rights reserved.
//
#import <React/RCTBridgeModule.h>

@interface RNDarkModeManager : NSObject <RCTBridgeModule>
@end
25 changes: 25 additions & 0 deletions ios/RNDarkMode.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// RNDarkMode.m
// RNMonthPicker
//
// Created by Gustavo Paris on 15/06/2020.
// Copyright © 2020 Facebook. All rights reserved.
//
#import "RNDarkMode.h"
#import <React/RCTLog.h>

@implementation RNDarkModeManager

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(isDarkMode:(RCTResponseSenderBlock)callback) {
NSNumber* isDark = [NSNumber numberWithBool:false];
if (@available(iOS 13.0, *)) {
if (UITraitCollection.currentTraitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
isDark = [NSNumber numberWithBool:true];
}
}
callback(@[[NSNull null], isDark]);
}

@end
1 change: 1 addition & 0 deletions ios/RNMonthPicker.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
@property (nonatomic, assign) NSDate* value;
@property (nonatomic, assign) NSDate* minimumDate;
@property (nonatomic, assign) NSDate* maximumDate;
@property (nonatomic, assign) BOOL enableAutoDarkMode;

@end
8 changes: 8 additions & 0 deletions ios/RNMonthPicker.m
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ - (void)initYears:(NSInteger)selectedYear {
}
}

- (void)setEnableAutoDarkMode:(BOOL) enableAutoDarkMode {
if (@available(iOS 13.0, *)) {
if (!enableAutoDarkMode) {
self.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
}
}
}

- (void)setValue:(nonnull NSDate *)value {
if (value != _value) {
NSDateComponents *selectedDateComponents = [gregorian components:(NSCalendarUnitMonth|NSCalendarUnitYear) fromDate:value];
Expand Down
1 change: 1 addition & 0 deletions ios/RNMonthPickerManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ - (UIView *)view
RCT_EXPORT_VIEW_PROPERTY(value, NSDate)
RCT_EXPORT_VIEW_PROPERTY(minimumDate, NSDate)
RCT_EXPORT_VIEW_PROPERTY(maximumDate, NSDate)
RCT_EXPORT_VIEW_PROPERTY(enableAutoDarkMode, BOOL)

@end
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
"licenseFilename": "LICENSE",
"readmeFilename": "README.md",
"peerDependencies": {
"react": "*",
"react-native": "*"
"react": ">= 16.11.0",
"react-native": ">= 0.60.0"
},
"devDependencies": {
"@react-native-community/eslint-config": "^1.1.0",
Expand All @@ -45,4 +45,4 @@
"invariant": "^2.2.4",
"moment": "^2.24.0"
}
}
}
2 changes: 1 addition & 1 deletion src/MonthPicker.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import moment from 'moment';
import invariant from 'invariant';

import RNMonthPickerDialogModule from './RNMonthPickerDialogModule';
import { ACTION_DATE_SET, ACTION_DISMISSED } from '.';
import { ACTION_DATE_SET, ACTION_DISMISSED } from './utils';

const NATIVE_FORMAT = 'YYYY-MM';
const DEFAULT_OUTPUT_FORMAT = 'MM-YYYY';
Expand Down
39 changes: 23 additions & 16 deletions src/MonthPicker.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,22 @@ import {
Animated,
Text,
TouchableOpacity,
Appearance,
NativeModules,
} from 'react-native';
import moment from 'moment';
import invariant from 'invariant';

import RNMonthPickerView from './RNMonthPickerNativeComponent';
import { ACTION_DATE_SET, ACTION_DISMISSED } from '.';
import { ACTION_DATE_SET, ACTION_DISMISSED, useTheme } from './utils';

const { width } = Dimensions.get('screen');
const NATIVE_FORMAT = 'M-YYYY';
const DEFAULT_OUTPUT_FORMAT = 'MM-YYYY';
const { Value, timing } = Animated;

const DARK_MODE_COLOR = '#636366';
const LIGHT_MODE_COLOR = '#f2f2f2';
const LIGHT_MODE_OK_COLOR = '#007aff';
const DARK_MODE_OK_COLOR = '#0a84ff';

const isDarkMode = Appearance.getColorScheme() === 'dark';

const styles = StyleSheet.create({
container: {
width,
backgroundColor: isDarkMode ? DARK_MODE_COLOR : LIGHT_MODE_COLOR,
position: 'absolute',
zIndex: 500,
bottom: 0,
Expand All @@ -45,12 +37,10 @@ const styles = StyleSheet.create({
picker: { flex: 1 },
okStyle: {
fontWeight: '500',
color: isDarkMode ? DARK_MODE_OK_COLOR : LIGHT_MODE_OK_COLOR,
letterSpacing: 1.0,
},
cancelStyle: {
fontWeight: '400',
color: isDarkMode ? LIGHT_MODE_COLOR : DARK_MODE_COLOR,
letterSpacing: 0.25,
},
});
Expand All @@ -59,6 +49,7 @@ class MonthPicker extends React.PureComponent {
state = {
slideAnim: new Value(0),
currentDate: this.props.value,
theme: {},
};

slideIn = () => {
Expand Down Expand Up @@ -106,7 +97,11 @@ class MonthPicker extends React.PureComponent {
};

componentDidMount() {
this.slideIn();
const darkMode = NativeModules.RNDarkModeManager;
darkMode.isDarkMode((error, isDark) => {
const theme = this.props.enableAutoDarkMode ? isDark : !isDark;
this.setState({ theme: useTheme(theme) }, () => this.slideIn());
});
}

render() {
Expand All @@ -118,20 +113,31 @@ class MonthPicker extends React.PureComponent {
cancelButton = 'Cancel',
okButtonStyle,
cancelButtonStyle,
enableAutoDarkMode = true,
} = this.props;
const { theme } = this.state;
invariant(value, 'value prop is required!');

return (
<Animated.View
style={{ ...styles.container, height: this.state.slideAnim }}>
style={{
...styles.container,
...theme.container,
height: this.state.slideAnim,
}}>
<View style={styles.toolbarContainer}>
<TouchableOpacity onPress={this.onCancel}>
<Text style={cancelButtonStyle || styles.cancelStyle}>
<Text
style={
cancelButtonStyle || [styles.cancelStyle, theme.cancelButton]
}>
{cancelButton}
</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.onConfirm}>
<Text style={okButtonStyle || styles.okStyle}>{okButton}</Text>
<Text style={okButtonStyle || [styles.okStyle, theme.okButton]}>
{okButton}
</Text>
</TouchableOpacity>
</View>
<View style={styles.pickerContainer}>
Expand All @@ -141,6 +147,7 @@ class MonthPicker extends React.PureComponent {
value={this.getLongFromDate(value)}
minimumDate={this.getLongFromDate(minimumDate)}
maximumDate={this.getLongFromDate(maximumDate)}
enableAutoDarkMode={enableAutoDarkMode}
/>
</View>
</Animated.View>
Expand Down
4 changes: 1 addition & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import MonthPicker from './MonthPicker';

export const ACTION_DATE_SET = 'dateSetAction';
export const ACTION_DISMISSED = 'dismissedAction';
export { ACTION_DATE_SET, ACTION_DISMISSED } from './utils';

export default MonthPicker;
22 changes: 22 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Platform } from 'react-native';

export const ACTION_DATE_SET = 'dateSetAction';
export const ACTION_DISMISSED = 'dismissedAction';

const theme = {
ios: {
dark: {
container: { backgroundColor: '#636366' },
cancelButton: { color: '#f2f2f2' },
okButton: { color: '#0a84ff' },
},
light: {
container: { backgroundColor: '#f2f2f2' },
cancelButton: { color: '#636366' },
okButton: { color: '#007aff' },
},
},
};

export const useTheme = (isDarkMode) =>
theme[Platform.OS][isDarkMode ? 'dark' : 'light'];
Loading

0 comments on commit 13a7dea

Please # to comment.