Skip to content

Commit

Permalink
Merge pull request #102 from nfcampos/system-item
Browse files Browse the repository at this point in the history
Add iOS-only systemItem prop for buttons in Navigator.Config
  • Loading branch information
benkraus committed Jul 14, 2017
2 parents 7bc0841 + e8b8b77 commit 3f91a95
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 13 deletions.
3 changes: 2 additions & 1 deletion docs/api/navigator-config.md
Expand Up @@ -180,7 +180,8 @@ type Button = {

// ios-only
style: 'plain' | 'default';

systemItem: 'done' | 'cancel' | 'edit' | 'save' | 'add' | 'flexibleSpace' | 'compose' | 'reply' | 'action' | 'organize' | 'bookmarks' | 'search' | 'refresh' | 'stop' | 'camera' | 'trash' | 'play' | 'pause' | 'rewind' | 'fastForward' | 'undo' | 'redo' | 'pageCurl';

// android-only
};

Expand Down
3 changes: 3 additions & 0 deletions example/index.js
Expand Up @@ -8,6 +8,9 @@ Navigator.registerScreen(
'SharedElementFromScreen',
() => require('./screens/SharedElementFromScreen')
);
Navigator.registerScreen('NavigationBar', () =>
require('./screens/NavigationBar')
);
Navigator.registerScreen(
'ScreenOne',
() => require('./screens/NavigationExampleScreen'),
Expand Down
73 changes: 73 additions & 0 deletions example/screens/NavigationBar.js
@@ -0,0 +1,73 @@
import React, { Component, PropTypes } from 'react';
import { Dimensions } from 'react-native';

import Navigator from 'native-navigation';

import LoremImage from '../components/LoremImage';
import Screen from '../components/Screen';
import Row from '../components/Row';

const propTypes = {};
const defaultProps = {};
const contextTypes = {
nativeNavigationInstanceId: PropTypes.string,
};

const { width } = Dimensions.get('window');

export default class NavigationExampleScreen extends Component {
state = {};

render() {
return (
<Screen>
<Navigator.Config {...this.state} />
<LoremImage width={width} height={width / 1.6} />
<Row
title="Title"
onPress={() => this.setState({
title: 'A title',
subtitle: undefined,
rightButtons: undefined,
})}
/>
<Row
title="Title and subtitle"
onPress={() => this.setState({
title: 'A title',
subtitle: 'A subtitle',
rightButtons: undefined,
})}
/>
<Row
title="Right button with title"
onPress={() => this.setState({
title: 'A title',
subtitle: undefined,
rightButtons: [{ title: 'Hello' }],
})}
/>
<Row
title="Right button with system item"
onPress={() => this.setState({
title: 'A title',
subtitle: undefined,
rightButtons: [{ systemItem: 'add' }],
})}
/>
<Row
title="Several right buttons"
onPress={() => this.setState({
title: 'A title',
subtitle: undefined,
rightButtons: [{ systemItem: 'add' }, { systemItem: 'edit' }],
})}
/>
</Screen>
);
}
}

NavigationExampleScreen.defaultProps = defaultProps;
NavigationExampleScreen.propTypes = propTypes;
NavigationExampleScreen.contextTypes = contextTypes;
6 changes: 5 additions & 1 deletion example/screens/NavigationExampleScreen.js
Expand Up @@ -49,9 +49,13 @@ export default class NavigationExampleScreen extends Component {
onPress={() => Navigator.dismiss()}
/>
<Row
title="Title"
title="Shared elements"
onPress={() => Navigator.push('SharedElementFromScreen')}
/>
<Row
title="Navigation bar customisation"
onPress={() => Navigator.push('NavigationBar')}
/>
</Screen>
);
}
Expand Down
64 changes: 53 additions & 11 deletions lib/ios/native-navigation/ReactNavigationImplementation.swift
Expand Up @@ -51,15 +51,23 @@ class BlockBarButtonItem: UIBarButtonItem {
self.target = self
}

convenience init(barButtonSystemItem: UIBarButtonSystemItem) {
self.init(barButtonSystemItem: barButtonSystemItem, target: nil, action: #selector(barButtonItemPressed))
self.target = self
}

convenience init(
title: String?,
image: UIImage?,
barButtonSystemItem: UIBarButtonSystemItem?,
style: UIBarButtonItemStyle,
enabled: Bool?,
tintColor: UIColor?,
titleTextAttributes: [String: Any]?
) {
if let title = title {
if let barButtonSystemItem = barButtonSystemItem {
self.init(barButtonSystemItem: barButtonSystemItem)
} else if let title = title {
self.init(title: title, style: style)
} else {
self.init(image: image, style: style)
Expand Down Expand Up @@ -192,6 +200,36 @@ func barButtonStyleFromString(_ string: String?) -> UIBarButtonItemStyle {
}
}

func barButtonSystemItemFromString(_ string: String?) -> UIBarButtonSystemItem? {
switch string {
case .some("done"): return .done
case .some("cancel"): return .cancel
case .some("edit"): return .edit
case .some("save"): return .save
case .some("add"): return .add
case .some("flexibleSpace"): return .flexibleSpace
// case .some("fixedSpace"): return .fixedSpace
case .some("compose"): return .compose
case .some("reply"): return .reply
case .some("action"): return .action
case .some("organize"): return .organize
case .some("bookmarks"): return .bookmarks
case .some("search"): return .search
case .some("refresh"): return .refresh
case .some("stop"): return .stop
case .some("camera"): return .camera
case .some("trash"): return .trash
case .some("play"): return .play
case .some("pause"): return .pause
case .some("rewind"): return .rewind
case .some("fastForward"): return .fastForward
case .some("undo"): return .undo
case .some("redo"): return .redo
case .some("pageCurl"): return .pageCurl
default: return nil
}
}

func statusBarStyleFromString(_ string: String?) -> UIStatusBarStyle {
switch(string) {
case .some("light"): return .lightContent
Expand Down Expand Up @@ -233,7 +271,7 @@ func lower(_ key: String) -> String {
return key.substring(to: i).lowercased() + key.substring(from: i)
}

func configurebarButtonItemFromPrefix(
func configureBarButtonItemFromPrefix(
_ prefix: String,
_ props: [String: AnyObject],
_ passedItem: UIBarButtonItem?
Expand All @@ -246,6 +284,8 @@ func configurebarButtonItemFromPrefix(

let title = stringForKey(lower("\(prefix)Title"), props)
let image = imageForKey(lower("\(prefix)Image"), props)
let systemItem = stringForKey(lower("\(prefix)SystemItem"), props)
let barButtonSystemItem = barButtonSystemItemFromString(systemItem)
let enabled = boolForKey(lower("\(prefix)Enabled"), props)
let tintColor = colorForKey(lower("\(prefix)TintColor"), props)
let style = stringForKey(lower("\(prefix)Style"), props)
Expand All @@ -262,30 +302,32 @@ func configurebarButtonItemFromPrefix(
let barButton = BlockBarButtonItem(
title: title ?? prev.title,
image: image ?? prev.image,
barButtonSystemItem: barButtonSystemItem,
style: barButtonStyleFromString(style),
enabled: enabled,
tintColor: tintColor,
titleTextAttributes: titleTextAttributes
)

barButton.accessibilityLabel = accessibilityLabel
barButton.accessibilityIdentifier = testID

return barButton
} else {
return nil
}
} else {
if (title != nil || image != nil) {
if (title != nil || image != nil || barButtonSystemItem != nil) {
let barButton = BlockBarButtonItem(
title: title,
image: image,
barButtonSystemItem: barButtonSystemItem,
style: barButtonStyleFromString(style),
enabled: enabled,
tintColor: tintColor,
titleTextAttributes: titleTextAttributes
)

barButton.accessibilityLabel = accessibilityLabel
barButton.accessibilityIdentifier = testID

Expand All @@ -301,7 +343,7 @@ func configureBarButtonArrayForKey(_ key: String, _ props: [String: AnyObject])
var result = [BlockBarButtonItem]()
for item in buttons {
if let buttonProps = item as? [String: AnyObject] {
if let button = configurebarButtonItemFromPrefix("", buttonProps, nil) {
if let button = configureBarButtonItemFromPrefix("", buttonProps, nil) {
result.append(button)
}
}
Expand Down Expand Up @@ -387,7 +429,7 @@ open class DefaultReactNavigationImplementation: ReactNavigationImplementation {
tabBar.isTranslucent = false
}
}

if numberHasChanged("tintColor", prev, next) {
if let tintColor = colorForKey("tintColor", next) {
tabBar.tintColor = tintColor
Expand All @@ -406,7 +448,7 @@ open class DefaultReactNavigationImplementation: ReactNavigationImplementation {

}
}

if mapHasChanged("backgroundImage", prev, next) {
tabBar.backgroundImage = imageForKey("backgroundImage", next)
}
Expand Down Expand Up @@ -487,7 +529,7 @@ open class DefaultReactNavigationImplementation: ReactNavigationImplementation {
}
}
navItem.setRightBarButtonItems(rightBarButtonItems, animated: true)
} else if let rightBarButtonItem = configurebarButtonItemFromPrefix("right", next, navItem.rightBarButtonItem) {
} else if let rightBarButtonItem = configureBarButtonItemFromPrefix("right", next, navItem.rightBarButtonItem) {
rightBarButtonItem.actionHandler = { [weak viewController] in
viewController?.emitEvent("onRightPress", body: nil)
}
Expand All @@ -502,7 +544,7 @@ open class DefaultReactNavigationImplementation: ReactNavigationImplementation {
}
}
navItem.setLeftBarButtonItems(leftBarButtonItems, animated: true)
} else if let leftBarButtonItem = configurebarButtonItemFromPrefix("left", next, navItem.leftBarButtonItem) {
} else if let leftBarButtonItem = configureBarButtonItemFromPrefix("left", next, navItem.leftBarButtonItem) {
leftBarButtonItem.actionHandler = { [weak viewController] in
// TODO(lmr): we want to dismiss here...
viewController?.emitEvent("onLeftPress", body: nil)
Expand Down

0 comments on commit 3f91a95

Please sign in to comment.