Add `react-native-macos-init` for adding macOS apps to existing `react-native init` projects. (#291)

* Got npx command line working.

* Generating project folder.

* Added macOS template files.

* Lint fixes

* Remove temp workarounds.

* Make react-native.config.js mac and windows compatible.

* Restore parity of macOS components with iOS because the `react-native init` sample app depends on them: e.g. StatusBar.

* Updated NewAppScreen language for macOS.

* Added `--prerelease` switch to allow installing pre-rerelease versions without prompting as this will be needed in CI.
Made tweaks to templates and fixed template schemes to rename to project name.
This commit is contained in:
Tom Underhill 2020-04-01 17:22:01 -07:00 коммит произвёл GitHub
Родитель feed0ac06b
Коммит ef31e51828
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
49 изменённых файлов: 6275 добавлений и 71 удалений

Просмотреть файл

@ -5,6 +5,8 @@
Libraries/vendor/**/* Libraries/vendor/**/*
Libraries/Renderer/* Libraries/Renderer/*
packages/*/node_modules packages/*/node_modules
packages/*/lib
packages/*/lib-commonjs
pr-inactivity-bookmarklet.js pr-inactivity-bookmarklet.js
question-bookmarklet.js question-bookmarklet.js
flow/ flow/

3
.gitignore поставляемый
Просмотреть файл

@ -68,7 +68,8 @@ package-lock.json
/coverage /coverage
/third-party /third-party
/packages/ /packages/*
!/packages/react-native-macos-init/
# Root dir shouldn't have Xcode project # Root dir shouldn't have Xcode project
/*.xcodeproj /*.xcodeproj

Просмотреть файл

@ -24,7 +24,7 @@ import type {SyntheticEvent} from '../../Types/CoreEventTypes';
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes'; import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
import type {ViewProps} from '../View/ViewPropTypes'; import type {ViewProps} from '../View/ViewPropTypes';
import type {TextStyleProp} from '../../StyleSheet/StyleSheet'; import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
import type {NativeOrDynamicColorType} from '../../Color/NativeOrDynamicColorType'; // ]TODO(macOS ISS#2323203) import type {NativeOrDynamicColorType} from '../../Color/NativeOrDynamicColorType'; // TODO(macOS ISS#2323203)
type PickerIOSChangeEvent = SyntheticEvent< type PickerIOSChangeEvent = SyntheticEvent<
$ReadOnly<{| $ReadOnly<{|

Просмотреть файл

@ -12,4 +12,156 @@
// TODO(macOS ISS#2323203) // TODO(macOS ISS#2323203)
module.exports = require('../UnimplementedViews/UnimplementedView'); 'use strict';
const React = require('react');
const ReactNative = require('../../Renderer/shims/ReactNative');
const StyleSheet = require('../../StyleSheet/StyleSheet');
const View = require('../View/View');
const processColor = require('../../StyleSheet/processColor');
const RCTPickerNativeComponent = require('./RCTPickerNativeComponent');
import type {SyntheticEvent} from '../../Types/CoreEventTypes';
import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
import type {ViewProps} from '../View/ViewPropTypes';
import type {TextStyleProp} from '../../StyleSheet/StyleSheet';
import type {NativeOrDynamicColorType} from '../../Color/NativeOrDynamicColorType'; // TODO(macOS ISS#2323203)
type PickerIOSChangeEvent = SyntheticEvent<
$ReadOnly<{|
newValue: number | string,
newIndex: number,
|}>,
>;
type RCTPickerIOSItemType = $ReadOnly<{|
label: ?Label,
value: ?(number | string),
textColor: ?(number | NativeOrDynamicColorType), // TODO(macOS ISS#2323203)
|}>;
type RCTPickerIOSType = Class<
ReactNative.NativeComponent<
$ReadOnly<{|
items: $ReadOnlyArray<RCTPickerIOSItemType>,
onChange: (event: PickerIOSChangeEvent) => void,
onResponderTerminationRequest: () => boolean,
onStartShouldSetResponder: () => boolean,
selectedIndex: number,
style?: ?TextStyleProp,
testID?: ?string,
|}>,
>,
>;
type Label = Stringish | number;
type Props = $ReadOnly<{|
...ViewProps,
children: React.ChildrenArray<React.Element<typeof PickerIOSItem>>,
itemStyle?: ?TextStyleProp,
onChange?: ?(event: PickerIOSChangeEvent) => mixed,
onValueChange?: ?(itemValue: string | number, itemIndex: number) => mixed,
selectedValue: ?(number | string),
|}>;
type State = {|
selectedIndex: number,
items: $ReadOnlyArray<RCTPickerIOSItemType>,
|};
type ItemProps = $ReadOnly<{|
label: ?Label,
value?: ?(number | string),
color?: ?ColorValue,
|}>;
const PickerIOSItem = (props: ItemProps) => {
return null;
};
class PickerIOS extends React.Component<Props, State> {
_picker: ?React.ElementRef<RCTPickerIOSType> = null;
state = {
selectedIndex: 0,
items: [],
};
static Item = PickerIOSItem;
static getDerivedStateFromProps(props: Props): State {
let selectedIndex = 0;
const items = [];
React.Children.toArray(props.children)
.filter(child => child !== null)
.forEach(function(child, index) {
if (child.props.value === props.selectedValue) {
selectedIndex = index;
}
items.push({
value: child.props.value,
label: child.props.label,
textColor: processColor(child.props.color),
});
});
return {selectedIndex, items};
}
render() {
return (
<View style={this.props.style}>
<RCTPickerNativeComponent
ref={picker => {
this._picker = picker;
}}
testID={this.props.testID}
style={[styles.pickerIOS, this.props.itemStyle]}
items={this.state.items}
selectedIndex={this.state.selectedIndex}
onChange={this._onChange}
onStartShouldSetResponder={() => true}
onResponderTerminationRequest={() => false}
/>
</View>
);
}
_onChange = event => {
if (this.props.onChange) {
this.props.onChange(event);
}
if (this.props.onValueChange) {
this.props.onValueChange(
event.nativeEvent.newValue,
event.nativeEvent.newIndex,
);
}
// The picker is a controlled component. This means we expect the
// on*Change handlers to be in charge of updating our
// `selectedValue` prop. That way they can also
// disallow/undo/mutate the selection of certain values. In other
// words, the embedder of this component should be the source of
// truth, not the native component.
if (
this._picker &&
this.state.selectedIndex !== event.nativeEvent.newIndex
) {
this._picker.setNativeProps({
selectedIndex: this.state.selectedIndex,
});
}
};
}
const styles = StyleSheet.create({
pickerIOS: {
// The picker will conform to whatever width is given, but we do
// have to set the component's height explicitly on the
// surrounding view to ensure it gets rendered.
height: 216,
},
});
module.exports = PickerIOS;

Просмотреть файл

@ -12,15 +12,14 @@
'use strict'; 'use strict';
var React = require('React'); const React = require('react');
var StyleSheet = require('StyleSheet'); const StyleSheet = require('../../StyleSheet/StyleSheet');
var requireNativeComponent = require('requireNativeComponent'); const RCTProgressViewNativeComponent = require('./RCTProgressViewNativeComponent');
import type {NativeComponent} from 'ReactNative'; import type {ImageSource} from '../../Image/ImageSource';
import type {ImageSource} from 'ImageSource'; import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
import type {ColorValue} from 'StyleSheetTypes'; import type {ViewProps} from '../View/ViewPropTypes';
import type {ViewProps} from 'ViewPropTypes';
type Props = $ReadOnly<{| type Props = $ReadOnly<{|
...ViewProps, ...ViewProps,
@ -56,20 +55,14 @@ type Props = $ReadOnly<{|
trackImage?: ?ImageSource, trackImage?: ?ImageSource,
|}>; |}>;
type NativeProgressViewIOS = Class<NativeComponent<Props>>;
const RCTProgressView = ((requireNativeComponent(
'RCTProgressView',
): any): NativeProgressViewIOS);
/** /**
* Use `ProgressViewIOS` to render a UIProgressView on iOS. * Use `ProgressViewIOS` to render a UIProgressView on iOS.
*/ */
const ProgressViewIOS = ( const ProgressViewIOS = (
props: Props, props: Props,
forwardedRef?: ?React.Ref<typeof RCTProgressView>, forwardedRef?: ?React.Ref<typeof RCTProgressViewNativeComponent>,
) => ( ) => (
<RCTProgressView <RCTProgressViewNativeComponent
{...props} {...props}
style={[styles.progressView, props.style]} style={[styles.progressView, props.style]}
ref={forwardedRef} ref={forwardedRef}
@ -82,11 +75,9 @@ const styles = StyleSheet.create({
}, },
}); });
// $FlowFixMe - TODO T29156721 `React.forwardRef` is not defined in Flow, yet.
const ProgressViewIOSWithRef = React.forwardRef(ProgressViewIOS); const ProgressViewIOSWithRef = React.forwardRef(ProgressViewIOS);
/* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an /* $FlowFixMe(>=0.89.0 site=react_native_ios_fb) This comment suppresses an
* error found when Flow v0.89 was deployed. To see the error, delete this * error found when Flow v0.89 was deployed. To see the error, delete this
* comment and run Flow. */ * comment and run Flow. */
// $FlowFixMe module.exports = (ProgressViewIOSWithRef: typeof RCTProgressViewNativeComponent);
module.exports = (ProgressViewIOSWithRef: NativeProgressViewIOS);

Просмотреть файл

@ -25,6 +25,13 @@ const DebugInstructions = Platform.select({
Native debug menu. Native debug menu.
</Text> </Text>
), ),
// [TODO(macOS ISS#2323203)
macos: () => (
<Text>
Secondary click in this window to open the React Native debug menu.
</Text>
),
// ]TODO(macOS ISS#2323203)
default: () => ( default: () => (
<Text> <Text>
Press <Text style={styles.highlight}>menu button</Text> or{' '} Press <Text style={styles.highlight}>menu button</Text> or{' '}

Просмотреть файл

@ -24,6 +24,14 @@ const ReloadInstructions = Platform.select({
reload your app's code. reload your app's code.
</Text> </Text>
), ),
// [TODO(macOS ISS#2323203)
macos: () => (
<Text>
Secondary click in this window and choose{' '}
<Text style={styles.highlight}>Reload</Text> to reload your app's code.
</Text>
),
// ]TODO(macOS ISS#2323203)
default: () => ( default: () => (
<Text> <Text>
Double tap <Text style={styles.highlight}>R</Text> on your keyboard to Double tap <Text style={styles.highlight}>R</Text> on your keyboard to

Просмотреть файл

@ -16,10 +16,9 @@ const warnOnce = require('warnOnce');
// Export React, plus some native additions. // Export React, plus some native additions.
module.exports = { module.exports = {
// Components // Components
/*
get AccessibilityInfo() { get AccessibilityInfo() {
return require('AccessibilityInfo'); return require('AccessibilityInfo');
},*/ },
get ActivityIndicator() { get ActivityIndicator() {
return require('ActivityIndicator'); return require('ActivityIndicator');
}, },
@ -57,8 +56,7 @@ module.exports = {
/* /*
get ImageEditor() { get ImageEditor() {
return require('ImageEditor'); return require('ImageEditor');
}, },*/
*/
get ImageStore() { get ImageStore() {
warnOnce( warnOnce(
'imagestore-deprecation', 'imagestore-deprecation',
@ -76,15 +74,14 @@ module.exports = {
get KeyboardAvoidingView() { get KeyboardAvoidingView() {
return require('KeyboardAvoidingView'); return require('KeyboardAvoidingView');
}, },
get ListView() { get ListView() {
warnOnce( warnOnce(
'listview-deprecation', 'listview-deprecation',
'ListView is deprecated and will be removed in a future release. ' + 'ListView is deprecated and will be removed in a future release. ' +
'See https://fb.me/nolistview for more information', 'See https://fb.me/nolistview for more information',
); );
return require('ListView'); return require('ListView');
}, },*/
/*
get MaskedViewIOS() { get MaskedViewIOS() {
warnOnce( warnOnce(
'maskedviewios-moved', 'maskedviewios-moved',
@ -94,6 +91,7 @@ module.exports = {
); );
return require('MaskedViewIOS'); return require('MaskedViewIOS');
}, },
/*
get Modal() { get Modal() {
return require('Modal'); return require('Modal');
},*/ },*/
@ -103,13 +101,12 @@ module.exports = {
get PickerIOS() { get PickerIOS() {
return require('../Components/Picker/PickerIOS'); return require('../Components/Picker/PickerIOS');
}, },
/*
get ProgressBarAndroid() { get ProgressBarAndroid() {
return require('ProgressBarAndroid'); return require('ProgressBarAndroid');
}, },
get ProgressViewIOS() { get ProgressViewIOS() {
return require('ProgressViewIOS'); return require('ProgressViewIOS');
},*/ },
get SafeAreaView() { get SafeAreaView() {
return require('SafeAreaView'); return require('SafeAreaView');
}, },
@ -119,11 +116,9 @@ module.exports = {
get SectionList() { get SectionList() {
return require('SectionList'); return require('SectionList');
}, },
/*
get SegmentedControlIOS() { get SegmentedControlIOS() {
return require('SegmentedControlIOS'); return require('SegmentedControlIOS');
}, },
*/
get Slider() { get Slider() {
warnOnce( warnOnce(
'slider-moved', 'slider-moved',
@ -139,10 +134,11 @@ module.exports = {
/* /*
get RefreshControl() { get RefreshControl() {
return require('RefreshControl'); return require('RefreshControl');
}, },*/
get StatusBar() { get StatusBar() {
return require('StatusBar'); return require('StatusBar');
}, },
/*
get SwipeableFlatList() { get SwipeableFlatList() {
return require('SwipeableFlatList'); return require('SwipeableFlatList');
},*/ },*/

Просмотреть файл

@ -135,6 +135,8 @@
2DE7E8061FB2A4F3009E225D /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D51DA2DD8B000FE1B8 /* libRCTWebSocket-tvOS.a */; }; 2DE7E8061FB2A4F3009E225D /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D51DA2DD8B000FE1B8 /* libRCTWebSocket-tvOS.a */; };
2DE7E8071FB2A4F3009E225D /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D91DA2DD8B000FE1B8 /* libReact.a */; }; 2DE7E8071FB2A4F3009E225D /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DD323D91DA2DD8B000FE1B8 /* libReact.a */; };
3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; }; 3578590A1B28D2CF00341EDB /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 357859011B28D2C500341EDB /* libRCTLinking.a */; };
383C517F243447EC00CCBC30 /* UpdatePropertiesExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 272E6B3C1BEA849E001FCF37 /* UpdatePropertiesExampleView.m */; };
383C51A624344A4600CCBC30 /* FlexibleSizeExampleView.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F441E81BEBE5030039B79C /* FlexibleSizeExampleView.m */; };
38C500E222D3CF2E00BCD999 /* RCTConvert_UIColorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 38C500E122D3CF2E00BCD999 /* RCTConvert_UIColorTests.m */; }; 38C500E222D3CF2E00BCD999 /* RCTConvert_UIColorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 38C500E122D3CF2E00BCD999 /* RCTConvert_UIColorTests.m */; };
39AA31A41DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 39AA31A31DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m */; }; 39AA31A41DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 39AA31A31DC1DFDC000F7EBB /* RCTUnicodeDecodeTests.m */; };
3D05746D1DE6008900184BB4 /* libRCTPushNotification-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D05746C1DE6008900184BB4 /* libRCTPushNotification-tvOS.a */; }; 3D05746D1DE6008900184BB4 /* libRCTPushNotification-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D05746C1DE6008900184BB4 /* libRCTPushNotification-tvOS.a */; };
@ -3130,6 +3132,8 @@
18FC77901EF4770B002B3F17 /* ViewController.m in Sources */, 18FC77901EF4770B002B3F17 /* ViewController.m in Sources */,
18FC778D1EF4770B002B3F17 /* main.m in Sources */, 18FC778D1EF4770B002B3F17 /* main.m in Sources */,
18FC778A1EF4770B002B3F17 /* AppDelegate.m in Sources */, 18FC778A1EF4770B002B3F17 /* AppDelegate.m in Sources */,
383C51A624344A4600CCBC30 /* FlexibleSizeExampleView.m in Sources */,
383C517F243447EC00CCBC30 /* UpdatePropertiesExampleView.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

Просмотреть файл

@ -6,7 +6,7 @@
* *
*/ */
#import <UIKit/UIKit.h> #import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
#import <React/RCTView.h> #import <React/RCTView.h>

Просмотреть файл

@ -13,7 +13,12 @@
#import <React/RCTRootViewDelegate.h> #import <React/RCTRootViewDelegate.h>
#import <React/RCTViewManager.h> #import <React/RCTViewManager.h>
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
#import "AppDelegate.h" #import "AppDelegate.h"
#else // [TODO(macOS ISS#2323203)
#import "../../RNTester-macOS/AppDelegate.h"
#define UITextView NSTextView
#endif // ]TODO(macOS ISS#2323203)
@interface FlexibleSizeExampleViewManager : RCTViewManager @interface FlexibleSizeExampleViewManager : RCTViewManager
@ -23,7 +28,7 @@
RCT_EXPORT_MODULE(); RCT_EXPORT_MODULE();
- (UIView *)view - (RCTUIView *)view // TODO(macOS ISS#2323203)
{ {
return [FlexibleSizeExampleView new]; return [FlexibleSizeExampleView new];
} }
@ -60,9 +65,13 @@ RCT_EXPORT_MODULE();
#ifndef TARGET_OS_TV #ifndef TARGET_OS_TV
_currentSizeTextView.editable = NO; _currentSizeTextView.editable = NO;
#endif #endif
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
_currentSizeTextView.text = @"Resizable view has not been resized yet"; _currentSizeTextView.text = @"Resizable view has not been resized yet";
_currentSizeTextView.textColor = [UIColor blackColor]; #else // [TODO(macOS ISS#2323203)
_currentSizeTextView.backgroundColor = [UIColor whiteColor]; _currentSizeTextView.string = @"Resizable view has not been resized yet";
#endif // ]TODO(macOS ISS#2323203)
_currentSizeTextView.textColor = [RCTUIColor blackColor]; // TODO(macOS ISS#2323203)
_currentSizeTextView.backgroundColor = [RCTUIColor whiteColor]; // TODO(macOS ISS#2323203)
_currentSizeTextView.font = [UIFont boldSystemFontOfSize:10]; _currentSizeTextView.font = [UIFont boldSystemFontOfSize:10];
_resizableRootView.delegate = self; _resizableRootView.delegate = self;
@ -82,7 +91,8 @@ RCT_EXPORT_MODULE();
} }
- (NSArray<UIView<RCTComponent> *> *)reactSubviews - (NSArray<RCTUIView<RCTComponent> *> *)reactSubviews // TODO(macOS ISS#2323203)
{ {
// this is to avoid unregistering our RCTRootView when the component is removed from RN hierarchy // this is to avoid unregistering our RCTRootView when the component is removed from RN hierarchy
(void)[super reactSubviews]; (void)[super reactSubviews];
@ -99,10 +109,20 @@ RCT_EXPORT_MODULE();
if (!_sizeUpdated) { if (!_sizeUpdated) {
_sizeUpdated = TRUE; _sizeUpdated = TRUE;
_currentSizeTextView.text = [NSString stringWithFormat:@"RCTRootViewDelegate: content with initially unknown size has appeared, updating root view's size so the content fits."]; #if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
_currentSizeTextView.text =
#else // [TODO(macOS ISS#2323203)
_currentSizeTextView.string =
#endif // ]TODO(macOS ISS#2323203)
[NSString stringWithFormat:@"RCTRootViewDelegate: content with initially unknown size has appeared, updating root view's size so the content fits."];
} else { } else {
_currentSizeTextView.text = [NSString stringWithFormat:@"RCTRootViewDelegate: content size has been changed to (%ld, %ld), updating root view's size.", #if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
_currentSizeTextView.text =
#else // [TODO(macOS ISS#2323203)
_currentSizeTextView.string =
#endif // ]TODO(macOS ISS#2323203)
[NSString stringWithFormat:@"RCTRootViewDelegate: content size has been changed to (%ld, %ld), updating root view's size.",
(long)newFrame.size.width, (long)newFrame.size.width,
(long)newFrame.size.height]; (long)newFrame.size.height];

Просмотреть файл

@ -6,7 +6,7 @@
* *
*/ */
#import <UIKit/UIKit.h> #import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
#import <React/RCTView.h> #import <React/RCTView.h>

Просмотреть файл

@ -11,7 +11,11 @@
#import <React/RCTRootView.h> #import <React/RCTRootView.h>
#import <React/RCTViewManager.h> #import <React/RCTViewManager.h>
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
#import "AppDelegate.h" #import "AppDelegate.h"
#else // [TODO(macOS ISS#2323203)
#import "../../RNTester-macOS/AppDelegate.h"
#endif // ]TODO(macOS ISS#2323203)
@interface UpdatePropertiesExampleViewManager : RCTViewManager @interface UpdatePropertiesExampleViewManager : RCTViewManager
@ -21,7 +25,7 @@
RCT_EXPORT_MODULE(); RCT_EXPORT_MODULE();
- (UIView *)view - (RCTUIView *)view // TODO(macOS ISS#2323203)
{ {
return [UpdatePropertiesExampleView new]; return [UpdatePropertiesExampleView new];
} }
@ -31,7 +35,11 @@ RCT_EXPORT_MODULE();
@implementation UpdatePropertiesExampleView @implementation UpdatePropertiesExampleView
{ {
RCTRootView *_rootView; RCTRootView *_rootView;
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
UIButton *_button; UIButton *_button;
#else // [TODO(macOS ISS#2323203)
NSButton *_button;
#endif // ]TODO(macOS ISS#2323203)
BOOL _beige; BOOL _beige;
} }
@ -47,6 +55,7 @@ RCT_EXPORT_MODULE();
moduleName:@"SetPropertiesExampleApp" moduleName:@"SetPropertiesExampleApp"
initialProperties:@{@"color":@"beige"}]; initialProperties:@{@"color":@"beige"}];
#if !TARGET_OS_OSX // TODO(macOS ISS#2323203)
_button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; _button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_button setTitle:@"Native Button" forState:UIControlStateNormal]; [_button setTitle:@"Native Button" forState:UIControlStateNormal];
[_button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [_button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
@ -55,6 +64,12 @@ RCT_EXPORT_MODULE();
[_button addTarget:self [_button addTarget:self
action:@selector(changeColor) action:@selector(changeColor)
forControlEvents:UIControlEventTouchUpInside]; forControlEvents:UIControlEventTouchUpInside];
#else // [TODO(macOS ISS#2323203)
_button = [[NSButton alloc] init];
[_button setTitle:@"Native Button"];
[_button setTarget:self];
[_button setAction:@selector(changeColor)];
#endif // ]TODO(macOS ISS#2323203)
[self addSubview:_button]; [self addSubview:_button];
[self addSubview:_rootView]; [self addSubview:_rootView];
@ -79,7 +94,7 @@ RCT_EXPORT_MODULE();
[_rootView setAppProperties:@{@"color":_beige ? @"beige" : @"purple"}]; [_rootView setAppProperties:@{@"color":_beige ? @"beige" : @"purple"}];
} }
- (NSArray<UIView<RCTComponent> *> *)reactSubviews - (NSArray<RCTUIView<RCTComponent> *> *)reactSubviews // TODO(macOS ISS#2323203)
{ {
// this is to avoid unregistering our RCTRootView when the component is removed from RN hierarchy // this is to avoid unregistering our RCTRootView when the component is removed from RN hierarchy
(void)[super reactSubviews]; (void)[super reactSubviews];

Просмотреть файл

@ -1,5 +1,5 @@
/** /**
* Copyright (c) 2015-present, Facebook, Inc. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
@ -16,17 +16,17 @@ const ComponentExamples: Array<RNTesterExample> = [
{ {
key: 'ActivityIndicatorExample', key: 'ActivityIndicatorExample',
module: require('./ActivityIndicatorExample'), module: require('./ActivityIndicatorExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'ARTExample', key: 'ARTExample',
module: require('./ARTExample'), module: require('./ARTExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'ButtonExample', key: 'ButtonExample',
module: require('./ButtonExample'), module: require('./ButtonExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'DarkModeExample', key: 'DarkModeExample',
@ -41,26 +41,52 @@ const ComponentExamples: Array<RNTesterExample> = [
{ {
key: 'FlatListExample', key: 'FlatListExample',
module: require('./FlatListExample'), module: require('./FlatListExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
// [TODO(OSS Candidate ISS#2710739)
{ {
key: 'FocusEvents', key: 'FocusEvents',
module: require('./FocusEventsExample'), module: require('./FocusEventsExample'),
supportsTVOS: true, supportsTVOS: true,
}, }, // ]TODO(OSS Candidate ISS#2710739)
{ {
key: 'ImageExample', key: 'ImageExample',
module: require('./ImageExample'), module: require('./ImageExample'),
supportsTVOS: true,
},
{
key: 'InputAccessoryViewExample',
module: require('./InputAccessoryViewExample'),
supportsTVOS: true,
},
{
key: 'KeyboardAvoidingViewExample',
module: require('./KeyboardAvoidingViewExample'),
supportsTVOS: false, supportsTVOS: false,
}, },
{ {
key: 'LayoutEventsExample', key: 'LayoutEventsExample',
module: require('./LayoutEventsExample'), module: require('./LayoutEventsExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{
key: 'MaskedViewExample',
module: require('./MaskedViewExample'),
supportsTVOS: true,
},
/* {
key: 'ModalExample',
module: require('./ModalExample'),
supportsTVOS: true,
}, */
{ {
key: 'MultiColumnExample', key: 'MultiColumnExample',
module: require('./MultiColumnExample'), module: require('./MultiColumnExample'),
supportsTVOS: true,
},
{
key: 'NewAppScreenExample',
module: require('./NewAppScreenExample'),
supportsTVOS: false, supportsTVOS: false,
}, },
{ {
@ -68,14 +94,44 @@ const ComponentExamples: Array<RNTesterExample> = [
module: require('./PickerExample'), module: require('./PickerExample'),
supportsTVOS: false, supportsTVOS: false,
}, },
/* {
key: 'PickerIOSExample',
module: require('./PickerIOSExample'),
supportsTVOS: false,
}, */
{
key: 'ProgressViewIOSExample',
module: require('./ProgressViewIOSExample'),
supportsTVOS: true,
},
{
key: 'RefreshControlExample',
module: require('./RefreshControlExample'),
supportsTVOS: false,
},
{
key: 'ScrollViewSimpleExample',
module: require('./ScrollViewSimpleExample'),
supportsTVOS: true,
},
{
key: 'SafeAreaViewExample',
module: require('./SafeAreaViewExample'),
supportsTVOS: true,
},
{ {
key: 'ScrollViewExample', key: 'ScrollViewExample',
module: require('./ScrollViewExample'), module: require('./ScrollViewExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'SectionListExample', key: 'SectionListExample',
module: require('./SectionListExample'), module: require('./SectionListExample'),
supportsTVOS: true,
},
{
key: 'SegmentedControlIOSExample',
module: require('./SegmentedControlIOSExample'),
supportsTVOS: false, supportsTVOS: false,
}, },
{ {
@ -83,6 +139,11 @@ const ComponentExamples: Array<RNTesterExample> = [
module: require('./SliderExample'), module: require('./SliderExample'),
supportsTVOS: false, supportsTVOS: false,
}, },
/* { Depends on Modal which is not implemented for macOS
key: 'StatusBarExample',
module: require('./StatusBarExample'),
supportsTVOS: false,
}, */
{ {
key: 'SwitchExample', key: 'SwitchExample',
module: require('./SwitchExample'), module: require('./SwitchExample'),
@ -91,17 +152,17 @@ const ComponentExamples: Array<RNTesterExample> = [
{ {
key: 'TextExample', key: 'TextExample',
module: require('./TextExample.macos'), module: require('./TextExample.macos'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'TextInputExample', key: 'TextInputExample',
module: require('./TextInputExample.macos'), module: require('./TextInputExample.macos'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'TouchableExample', key: 'TouchableExample',
module: require('./TouchableExample'), module: require('./TouchableExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'TransparentHitTestExample', key: 'TransparentHitTestExample',
@ -111,44 +172,64 @@ const ComponentExamples: Array<RNTesterExample> = [
{ {
key: 'ViewExample', key: 'ViewExample',
module: require('./ViewExample'), module: require('./ViewExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
]; ];
const APIExamples: Array<RNTesterExample> = [ const APIExamples: Array<RNTesterExample> = [
{
key: 'AccessibilityExample',
module: require('./AccessibilityExample'),
supportsTVOS: false,
},
{
key: 'AccessibilityIOSExample',
module: require('./AccessibilityIOSExample'),
supportsTVOS: false,
},
{ {
key: 'ActionSheetIOSExample', key: 'ActionSheetIOSExample',
module: require('./ActionSheetMacOSExample'), module: require('./ActionSheetMacOSExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'AnimatedExampleMacOS', key: 'AnimatedExampleMacOS',
module: require('./AnimatedExampleMacOS'), module: require('./AnimatedExampleMacOS'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'AlertExample', key: 'AlertExample',
module: require('./AlertExample').AlertExample, module: require('./AlertExample').AlertExample,
supportsTVOS: false, supportsTVOS: true,
},
{
key: 'AnExApp',
module: require('./AnimatedGratuitousApp/AnExApp'),
supportsTVOS: true,
}, },
{ {
key: 'AlertMacOSExample', key: 'AlertMacOSExample',
module: require('./AlertMacOSExample'), module: require('./AlertMacOSExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'AsyncStorageExample', key: 'AsyncStorageExample',
module: require('./AsyncStorageExample'), module: require('./AsyncStorageExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'BorderExample', key: 'BorderExample',
module: require('./BorderExample'), module: require('./BorderExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'BoxShadowExample', key: 'BoxShadowExample',
module: require('./BoxShadowExample'), module: require('./BoxShadowExample'),
supportsTVOS: true,
},
{
key: 'CameraRollExample',
module: require('./CameraRollExample'),
supportsTVOS: false, supportsTVOS: false,
}, },
{ {
@ -156,24 +237,44 @@ const APIExamples: Array<RNTesterExample> = [
module: require('./ClipboardExample'), module: require('./ClipboardExample'),
supportsTVOS: false, supportsTVOS: false,
}, },
{
key: 'CrashExample',
module: require('./CrashExample'),
supportsTVOS: false,
},
{
key: 'Dimensions',
module: require('./DimensionsExample'),
supportsTVOS: true,
},
{
key: 'ImageEditingExample',
module: require('./ImageEditingExample'),
supportsTVOS: false,
},
{ {
key: 'LayoutAnimationExample', key: 'LayoutAnimationExample',
module: require('./LayoutAnimationExample'), module: require('./LayoutAnimationExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'LayoutExample', key: 'LayoutExample',
module: require('./LayoutExample'), module: require('./LayoutExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'LinkingExample', key: 'LinkingExample',
module: require('./LinkingExample'), module: require('./LinkingExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'NativeAnimationsExample', key: 'NativeAnimationsExample',
module: require('./NativeAnimationsExample'), module: require('./NativeAnimationsExample'),
supportsTVOS: true,
},
{
key: 'OrientationChangeExample',
module: require('./OrientationChangeExample'),
supportsTVOS: false, supportsTVOS: false,
}, },
{ {
@ -191,26 +292,61 @@ const APIExamples: Array<RNTesterExample> = [
module: require('./PushNotificationIOSExample'), module: require('./PushNotificationIOSExample'),
supportsTVOS: false, supportsTVOS: false,
}, },
{
key: 'RCTRootViewIOSExample',
module: require('./RCTRootViewIOSExample'),
supportsTVOS: true,
},
{ {
key: 'RTLExample', key: 'RTLExample',
module: require('./RTLExample'), module: require('./RTLExample'),
supportsTVOS: false, supportsTVOS: true,
},
{
key: 'ShareExample',
module: require('./ShareExample'),
supportsTVOS: true,
},
{
key: 'SnapshotExample',
module: require('./SnapshotExample'),
supportsTVOS: true,
}, },
{ {
key: 'TimerExample', key: 'TimerExample',
module: require('./TimerExample'), module: require('./TimerExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
{ {
key: 'TransformExample', key: 'TransformExample',
module: require('./TransformExample'), module: require('./TransformExample'),
supportsTVOS: true,
},
/* {
key: 'TurboModuleExample',
module: require('./TurboModuleExample'),
supportsTVOS: false, supportsTVOS: false,
}, },
{
key: 'TVEventHandlerExample',
module: require('./TVEventHandlerExample'),
supportsTVOS: true,
},
{
key: 'VibrationExample',
module: require('./VibrationExample'),
supportsTVOS: false,
}, */
{ {
key: 'WebSocketExample', key: 'WebSocketExample',
module: require('./WebSocketExample'), module: require('./WebSocketExample'),
supportsTVOS: false, supportsTVOS: true,
}, },
/* {
key: 'XHRExample',
module: require('./XHRExample'),
supportsTVOS: true,
}, */
]; ];
const Modules = {}; const Modules = {};

Просмотреть файл

@ -5,14 +5,14 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#import <UIKit/UIKit.h> #import <React/RCTUIKit.h> // TODO(macOS ISS#2323203)
#import <React/RCTConvert.h> #import <React/RCTConvert.h>
#import <React/RCTEventEmitter.h> #import <React/RCTEventEmitter.h>
@interface RCTConvert (UIStatusBar) @interface RCTConvert (UIStatusBar)
#if !TARGET_OS_TV #if !TARGET_OS_TV && !TARGET_OS_OSX // TODO(macOS ISS#2323203)
+ (UIStatusBarStyle)UIStatusBarStyle:(id)json; + (UIStatusBarStyle)UIStatusBarStyle:(id)json;
+ (UIStatusBarAnimation)UIStatusBarAnimation:(id)json; + (UIStatusBarAnimation)UIStatusBarAnimation:(id)json;
#endif #endif

Просмотреть файл

@ -11,7 +11,7 @@
#import "RCTLog.h" #import "RCTLog.h"
#import "RCTUtils.h" #import "RCTUtils.h"
#if !TARGET_OS_TV #if !TARGET_OS_TV && !TARGET_OS_OSX // TODO(macOS ISS#2323203)
@implementation RCTConvert (UIStatusBar) @implementation RCTConvert (UIStatusBar)
RCT_ENUM_CONVERTER(UIStatusBarStyle, (@{ RCT_ENUM_CONVERTER(UIStatusBarStyle, (@{
@ -51,7 +51,7 @@ RCT_EXPORT_MODULE()
@"statusBarFrameWillChange"]; @"statusBarFrameWillChange"];
} }
#if !TARGET_OS_TV #if !TARGET_OS_TV && !TARGET_OS_OSX // TODO(macOS ISS#2323203)
- (void)startObserving - (void)startObserving
{ {

Просмотреть файл

@ -817,6 +817,8 @@
2D74EAFA1DAE9590003B751B /* RCTMultipartDataTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 006FC4131D9B20820057AAAD /* RCTMultipartDataTask.m */; }; 2D74EAFA1DAE9590003B751B /* RCTMultipartDataTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 006FC4131D9B20820057AAAD /* RCTMultipartDataTask.m */; };
2D8C2E331DA40441000EE098 /* RCTMultipartStreamReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 001BFCCF1D8381DE008E587E /* RCTMultipartStreamReader.m */; }; 2D8C2E331DA40441000EE098 /* RCTMultipartStreamReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 001BFCCF1D8381DE008E587E /* RCTMultipartStreamReader.m */; };
352DCFF01D19F4C20056D623 /* RCTI18nUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 352DCFEF1D19F4C20056D623 /* RCTI18nUtil.m */; }; 352DCFF01D19F4C20056D623 /* RCTI18nUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 352DCFEF1D19F4C20056D623 /* RCTI18nUtil.m */; };
383C517D2434412900CCBC30 /* RCTProgressViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13513F3B1B1F43F400FCE529 /* RCTProgressViewManager.m */; };
383C517E243446D900CCBC30 /* RCTStatusBarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 13723B4F1A82FD3C00F88898 /* RCTStatusBarManager.m */; };
385362722283369800B0989C /* RCTSRWebSocket.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFD2C1EA8E3FA008DFB7A /* RCTSRWebSocket.h */; }; 385362722283369800B0989C /* RCTSRWebSocket.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 3D7BFD2C1EA8E3FA008DFB7A /* RCTSRWebSocket.h */; };
38B6D1FF228C879400AC0F0E /* (null) in Sources */ = {isa = PBXBuildFile; }; 38B6D1FF228C879400AC0F0E /* (null) in Sources */ = {isa = PBXBuildFile; };
38BF7CDF22AF1B9900240972 /* JSCExecutorFactory.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8507BBBC21EDACC200AEAFCA /* JSCExecutorFactory.mm */; }; 38BF7CDF22AF1B9900240972 /* JSCExecutorFactory.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8507BBBC21EDACC200AEAFCA /* JSCExecutorFactory.mm */; };
@ -5685,6 +5687,7 @@
657734931EE8356100A0E9EA /* RCTInspector.mm in Sources */, 657734931EE8356100A0E9EA /* RCTInspector.mm in Sources */,
59EB6DBE1EBD6FC90072A5E7 /* RCTUIManagerObserverCoordinator.mm in Sources */, 59EB6DBE1EBD6FC90072A5E7 /* RCTUIManagerObserverCoordinator.mm in Sources */,
18B8F97E21431D6900CE911A /* RCTPlatform.m in Sources */, 18B8F97E21431D6900CE911A /* RCTPlatform.m in Sources */,
383C517E243446D900CCBC30 /* RCTStatusBarManager.m in Sources */,
2D3B5E971D9B089000451313 /* RCTBridge.m in Sources */, 2D3B5E971D9B089000451313 /* RCTBridge.m in Sources */,
2D3B5E9B1D9B08A000451313 /* RCTFrameUpdate.m in Sources */, 2D3B5E9B1D9B08A000451313 /* RCTFrameUpdate.m in Sources */,
2D3B5EE41D9B09BB00451313 /* RCTSegmentedControlManager.m in Sources */, 2D3B5EE41D9B09BB00451313 /* RCTSegmentedControlManager.m in Sources */,
@ -5694,6 +5697,7 @@
1968A2621F67275300EB3D1D /* RCTComponentEvent.m in Sources */, 1968A2621F67275300EB3D1D /* RCTComponentEvent.m in Sources */,
2D3B5EE31D9B09B700451313 /* RCTSegmentedControl.m in Sources */, 2D3B5EE31D9B09B700451313 /* RCTSegmentedControl.m in Sources */,
189727D42141CE7E002A4E2A /* RCTSwitchManager.m in Sources */, 189727D42141CE7E002A4E2A /* RCTSwitchManager.m in Sources */,
383C517D2434412900CCBC30 /* RCTProgressViewManager.m in Sources */,
130443A41E3FEAC600D93A67 /* RCTFollyConvert.mm in Sources */, 130443A41E3FEAC600D93A67 /* RCTFollyConvert.mm in Sources */,
3D7BFD201EA8E351008DFB7A /* RCTPackagerConnection.mm in Sources */, 3D7BFD201EA8E351008DFB7A /* RCTPackagerConnection.mm in Sources */,
59E604A51FE9CCE300BD90C5 /* RCTScrollContentShadowView.m in Sources */, 59E604A51FE9CCE300BD90C5 /* RCTScrollContentShadowView.m in Sources */,

0
android-patches/scripts/patch.sh Normal file → Executable file
Просмотреть файл

Просмотреть файл

@ -0,0 +1,32 @@
'use strict';
const fs = require('fs');
const path = require('path');
const {
copyProjectTemplateAndReplace,
installDependencies,
} = require('./generator-macos');
/**
* Simple utility for running the macOS generator.
*
* @param {String} projectDir root project directory (i.e. contains index.js)
* @param {String} name name of the root JS module for this app
* @param {Object} options command line options container
*/
function generateWindows (projectDir, name, options) {
if (!fs.existsSync(projectDir)) {
fs.mkdirSync(projectDir);
}
installDependencies(options);
copyProjectTemplateAndReplace(
path.join(__dirname, 'generator-macos', 'templates'),
projectDir,
name,
{ overwrite: options.overwrite }
);
}
module.exports = generateWindows;

Просмотреть файл

@ -0,0 +1,103 @@
const fs = require('fs');
const chalk = require('chalk');
const path = require('path');
const copyAndReplace = require('@react-native-community/cli/build/tools/copyAndReplace').default;
const walk = require('@react-native-community/cli/build/tools/walk').default;
const prompt = require('@react-native-community/cli/build/tools/generator/promptSync').default();
function createDir(destPath) {
if (!fs.existsSync(destPath)) {
fs.mkdirSync(destPath);
}
}
function copyAndReplaceWithChangedCallback(srcPath, destRoot, relativeDestPath, replacements, alwaysOverwrite) {
if (!replacements) {
replacements = {};
}
const contentChangedCallback = alwaysOverwrite ? (_, contentChanged) =>
alwaysOverwriteContentChangedCallback(
srcPath,
relativeDestPath,
contentChanged
) : (_, contentChanged) =>
upgradeFileContentChangedCallback(
srcPath,
relativeDestPath,
contentChanged
);
copyAndReplace(
srcPath,
path.join(destRoot, relativeDestPath),
replacements,
contentChangedCallback
);
}
function copyAndReplaceAll(srcPath, destPath, relativeDestDir, replacements, alwaysOverwrite) {
walk(srcPath).forEach(absoluteSrcFilePath => {
const filename = path.relative(srcPath, absoluteSrcFilePath);
const relativeDestPath = path.join(relativeDestDir, filename);
copyAndReplaceWithChangedCallback(absoluteSrcFilePath, destPath, relativeDestPath, replacements, alwaysOverwrite);
});
}
function alwaysOverwriteContentChangedCallback( absoluteSrcFilePath,
relativeDestPath,
contentChanged
) {
if (contentChanged === 'new') {
console.log(`${chalk.bold('new')} ${relativeDestPath}`);
return 'overwrite';
}
if (contentChanged === 'changed') {
console.log(`${chalk.bold('changed')} ${relativeDestPath} ${chalk.yellow('[overwriting]')}`);
return 'overwrite';
}
if (contentChanged === 'identical') {
return 'keep';
}
throw new Error(
`Unknown file changed state: ${relativeDestPath}, ${contentChanged}`
);
}
function upgradeFileContentChangedCallback(
absoluteSrcFilePath,
relativeDestPath,
contentChanged
) {
if (contentChanged === 'new') {
console.log(`${chalk.bold('new')} ${relativeDestPath}`);
return 'overwrite';
}
if (contentChanged === 'changed') {
console.log(
`${chalk.bold(relativeDestPath)} ` +
`has changed in the new version.\nDo you want to keep your ${relativeDestPath} or replace it with the ` +
'latest version?\nIf you ever made any changes ' +
'to this file, you\'ll probably want to keep it.\n' +
`You can see the new version here: ${absoluteSrcFilePath}\n` +
`Do you want to replace ${relativeDestPath}? ` +
'Answer y to replace, n to keep your version: '
);
const answer = prompt();
if (answer === 'y') {
console.log(`Replacing ${relativeDestPath}`);
return 'overwrite';
}
console.log(`Keeping your ${relativeDestPath}`);
return 'keep';
}
if (contentChanged === 'identical') {
return 'keep';
}
throw new Error(
`Unknown file changed state: ${relativeDestPath}, ${contentChanged}`
);
}
module.exports = {
createDir, copyAndReplaceWithChangedCallback, copyAndReplaceAll,
};

Просмотреть файл

@ -0,0 +1,86 @@
'use strict';
const chalk = require('chalk');
const path = require('path');
const childProcess = require('child_process');
const fs = require('fs');
const {
createDir,
copyAndReplaceAll,
copyAndReplaceWithChangedCallback,
} = require('../generator-common');
const macOSDir = 'macos';
function copyProjectTemplateAndReplace(
srcRootPath,
destPath,
newProjectName,
options = {}
) {
if (!srcRootPath) {
throw new Error('Need a path to copy from');
}
if (!destPath) {
throw new Error('Need a path to copy to');
}
if (!newProjectName) {
throw new Error('Need a project name');
}
const projectNameMacOS = newProjectName + '-macOS';
const projectNameIOS = newProjectName;
const xcodeProjName = newProjectName + '.xcodeproj';
const schemeNameMacOS = newProjectName + '-macOS.xcscheme';
const schemeNameIOS = newProjectName + '.xcscheme';
createDir(path.join(destPath, macOSDir));
createDir(path.join(destPath, macOSDir, projectNameIOS));
createDir(path.join(destPath, macOSDir, projectNameMacOS));
createDir(path.join(destPath, macOSDir, xcodeProjName));
createDir(path.join(destPath, macOSDir, xcodeProjName, 'xcshareddata'));
createDir(path.join(destPath, macOSDir, xcodeProjName, 'xcshareddata/xcschemes'));
const templateVars = {
'HelloWorld': newProjectName,
};
[
{ from: path.join(srcRootPath, 'macos/HelloWorld'), to: path.join(macOSDir, projectNameIOS) },
{ from: path.join(srcRootPath, 'macos/HelloWorld-macOS'), to: path.join(macOSDir, projectNameMacOS) },
{ from: path.join(srcRootPath, 'macos/HelloWorld.xcodeproj'), to: path.join(macOSDir, xcodeProjName) },
{ from: path.join(srcRootPath, 'macos/xcschemes/HelloWorld-macOS.xcscheme'), to: path.join(macOSDir, xcodeProjName, 'xcshareddata/xcschemes', schemeNameMacOS) },
{ from: path.join(srcRootPath, 'macos/xcschemes/HelloWorld.xcscheme'), to: path.join(macOSDir, xcodeProjName, 'xcshareddata/xcschemes', schemeNameIOS) },
].forEach((mapping) => copyAndReplaceAll(mapping.from, destPath, mapping.to, templateVars, options.overwrite));
[
{ from: path.join(srcRootPath, 'react-native.config.js'), to: 'react-native.config.js' },
{ from: path.join(srcRootPath, 'metro.config.macos.js'), to: 'metro.config.macos.js' },
].forEach((mapping) => copyAndReplaceWithChangedCallback(mapping.from, destPath, mapping.to, templateVars, options.overwrite));
console.log(chalk.white.bold('To run your app on macOS:'));
console.log(chalk.white(` open ${macOSDir}/${xcodeProjName}`));
console.log(chalk.white(' yarn start:macos'));
console.log(chalk.white.bold(`In Xcode switch to the ${projectNameMacOS} scheme then click Run.`));
}
function installDependencies(options) {
const cwd = process.cwd();
// Patch package.json to have start:macos
const projectPackageJsonPath = path.join(cwd, 'package.json');
const projectPackageJson = JSON.parse(fs.readFileSync(projectPackageJsonPath, { encoding: 'UTF8' }));
projectPackageJson.scripts['start:macos'] = 'node node_modules/react-native-macos/local-cli/cli.js start --use-react-native-macos';
fs.writeFileSync(projectPackageJsonPath, JSON.stringify(projectPackageJson, null, 2));
// Install dependencies using correct package manager
const isYarn = fs.existsSync(path.join(cwd, 'yarn.lock'));
const execOptions = options && options.verbose ? { stdio: 'inherit' } : {};
childProcess.execSync(isYarn ? 'yarn' : 'npm i', execOptions);
}
module.exports = {
copyProjectTemplateAndReplace,
installDependencies,
};

Просмотреть файл

@ -0,0 +1,16 @@
/**
* 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.
*/
#import <Cocoa/Cocoa.h>
@class RCTBridge;
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (nonatomic, readonly) RCTBridge *bridge;
@end

Просмотреть файл

@ -0,0 +1,39 @@
/**
* 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.
*/
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
@interface AppDelegate () <RCTBridgeDelegate>
@end
@implementation AppDelegate
- (void)awakeFromNib {
[super awakeFromNib];
_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
#pragma mark - RCTBridgeDelegate Methods
- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge {
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:@"main"]; // .jsbundle;
}
@end

Просмотреть файл

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,713 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Application-->
<scene sceneID="JPo-4y-FX3">
<objects>
<application id="hnw-xV-0zn" sceneMemberID="viewController">
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="HelloWorld" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="HelloWorld" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About HelloWorld" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
<menuItem title="Services" id="NMo-om-nkz">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
<menuItem title="Hide HelloWorld" keyEquivalent="h" id="Olw-nP-bQN">
<connections>
<action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit HelloWorld" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="dMs-cI-mzQ">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="File" id="bib-Uj-vzu">
<items>
<menuItem title="New" keyEquivalent="n" id="Was-JA-tGl">
<connections>
<action selector="newDocument:" target="Ady-hI-5gd" id="4Si-XN-c54"/>
</connections>
</menuItem>
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
<connections>
<action selector="openDocument:" target="Ady-hI-5gd" id="bVn-NM-KNZ"/>
</connections>
</menuItem>
<menuItem title="Open Recent" id="tXI-mr-wws">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
<items>
<menuItem title="Clear Menu" id="vNY-rz-j42">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="clearRecentDocuments:" target="Ady-hI-5gd" id="Daa-9d-B3U"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
<connections>
<action selector="performClose:" target="Ady-hI-5gd" id="HmO-Ls-i7Q"/>
</connections>
</menuItem>
<menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV">
<connections>
<action selector="saveDocument:" target="Ady-hI-5gd" id="teZ-XB-qJY"/>
</connections>
</menuItem>
<menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A">
<connections>
<action selector="saveDocumentAs:" target="Ady-hI-5gd" id="mDf-zr-I0C"/>
</connections>
</menuItem>
<menuItem title="Revert to Saved" keyEquivalent="r" id="KaW-ft-85H">
<connections>
<action selector="revertDocumentToSaved:" target="Ady-hI-5gd" id="iJ3-Pv-kwq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="aJh-i4-bef"/>
<menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="runPageLayout:" target="Ady-hI-5gd" id="Din-rz-gC5"/>
</connections>
</menuItem>
<menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS">
<connections>
<action selector="print:" target="Ady-hI-5gd" id="qaZ-4w-aoO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Edit" id="5QF-Oa-p0T">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Edit" id="W48-6f-4Dl">
<items>
<menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
<connections>
<action selector="undo:" target="Ady-hI-5gd" id="M6e-cu-g7V"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
<connections>
<action selector="redo:" target="Ady-hI-5gd" id="oIA-Rs-6OD"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
<menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
<connections>
<action selector="cut:" target="Ady-hI-5gd" id="YJe-68-I9s"/>
</connections>
</menuItem>
<menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
<connections>
<action selector="copy:" target="Ady-hI-5gd" id="G1f-GL-Joy"/>
</connections>
</menuItem>
<menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
<connections>
<action selector="paste:" target="Ady-hI-5gd" id="UvS-8e-Qdg"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteAsPlainText:" target="Ady-hI-5gd" id="cEh-KX-wJQ"/>
</connections>
</menuItem>
<menuItem title="Delete" id="pa3-QI-u2k">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="delete:" target="Ady-hI-5gd" id="0Mk-Ml-PaM"/>
</connections>
</menuItem>
<menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
<connections>
<action selector="selectAll:" target="Ady-hI-5gd" id="VNm-Mi-diN"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
<menuItem title="Find" id="4EN-yA-p0u">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Find" id="1b7-l0-nxx">
<items>
<menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
<connections>
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="cD7-Qs-BN4"/>
</connections>
</menuItem>
<menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="WD3-Gg-5AJ"/>
</connections>
</menuItem>
<menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
<connections>
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="NDo-RZ-v9R"/>
</connections>
</menuItem>
<menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
<connections>
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="HOh-sY-3ay"/>
</connections>
</menuItem>
<menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
<connections>
<action selector="performFindPanelAction:" target="Ady-hI-5gd" id="U76-nv-p5D"/>
</connections>
</menuItem>
<menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
<connections>
<action selector="centerSelectionInVisibleArea:" target="Ady-hI-5gd" id="IOG-6D-g5B"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
<items>
<menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
<connections>
<action selector="showGuessPanel:" target="Ady-hI-5gd" id="vFj-Ks-hy3"/>
</connections>
</menuItem>
<menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
<connections>
<action selector="checkSpelling:" target="Ady-hI-5gd" id="fz7-VC-reM"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
<menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleContinuousSpellChecking:" target="Ady-hI-5gd" id="7w6-Qz-0kB"/>
</connections>
</menuItem>
<menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleGrammarChecking:" target="Ady-hI-5gd" id="muD-Qn-j4w"/>
</connections>
</menuItem>
<menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticSpellingCorrection:" target="Ady-hI-5gd" id="2lM-Qi-WAP"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Substitutions" id="9ic-FL-obx">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
<items>
<menuItem title="Show Substitutions" id="z6F-FW-3nz">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontSubstitutionsPanel:" target="Ady-hI-5gd" id="oku-mr-iSq"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
<menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleSmartInsertDelete:" target="Ady-hI-5gd" id="3IJ-Se-DZD"/>
</connections>
</menuItem>
<menuItem title="Smart Quotes" id="hQb-2v-fYv">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticQuoteSubstitution:" target="Ady-hI-5gd" id="ptq-xd-QOA"/>
</connections>
</menuItem>
<menuItem title="Smart Dashes" id="rgM-f4-ycn">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDashSubstitution:" target="Ady-hI-5gd" id="oCt-pO-9gS"/>
</connections>
</menuItem>
<menuItem title="Smart Links" id="cwL-P1-jid">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticLinkDetection:" target="Ady-hI-5gd" id="Gip-E3-Fov"/>
</connections>
</menuItem>
<menuItem title="Data Detectors" id="tRr-pd-1PS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticDataDetection:" target="Ady-hI-5gd" id="R1I-Nq-Kbl"/>
</connections>
</menuItem>
<menuItem title="Text Replacement" id="HFQ-gK-NFA">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleAutomaticTextReplacement:" target="Ady-hI-5gd" id="DvP-Fe-Py6"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Transformations" id="2oI-Rn-ZJC">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Transformations" id="c8a-y6-VQd">
<items>
<menuItem title="Make Upper Case" id="vmV-6d-7jI">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="uppercaseWord:" target="Ady-hI-5gd" id="sPh-Tk-edu"/>
</connections>
</menuItem>
<menuItem title="Make Lower Case" id="d9M-CD-aMd">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowercaseWord:" target="Ady-hI-5gd" id="iUZ-b5-hil"/>
</connections>
</menuItem>
<menuItem title="Capitalize" id="UEZ-Bs-lqG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="capitalizeWord:" target="Ady-hI-5gd" id="26H-TL-nsh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Speech" id="xrE-MZ-jX0">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Speech" id="3rS-ZA-NoH">
<items>
<menuItem title="Start Speaking" id="Ynk-f8-cLZ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="startSpeaking:" target="Ady-hI-5gd" id="654-Ng-kyl"/>
</connections>
</menuItem>
<menuItem title="Stop Speaking" id="Oyz-dy-DGm">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="stopSpeaking:" target="Ady-hI-5gd" id="dX8-6p-jy9"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Format" id="jxT-CU-nIS">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Format" id="GEO-Iw-cKr">
<items>
<menuItem title="Font" id="Gi5-1S-RQB">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq">
<items>
<menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq">
<connections>
<action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/>
</connections>
</menuItem>
<menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/>
</connections>
</menuItem>
<menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq">
<connections>
<action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/>
</connections>
</menuItem>
<menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S">
<connections>
<action selector="underline:" target="Ady-hI-5gd" id="FYS-2b-JAY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/>
<menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/>
</connections>
</menuItem>
<menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST">
<connections>
<action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/>
<menuItem title="Kern" id="jBQ-r6-VK2">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Kern" id="tlD-Oa-oAM">
<items>
<menuItem title="Use Default" id="GUa-eO-cwY">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardKerning:" target="Ady-hI-5gd" id="6dk-9l-Ckg"/>
</connections>
</menuItem>
<menuItem title="Use None" id="cDB-IK-hbR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffKerning:" target="Ady-hI-5gd" id="U8a-gz-Maa"/>
</connections>
</menuItem>
<menuItem title="Tighten" id="46P-cB-AYj">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="tightenKerning:" target="Ady-hI-5gd" id="hr7-Nz-8ro"/>
</connections>
</menuItem>
<menuItem title="Loosen" id="ogc-rX-tC1">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="loosenKerning:" target="Ady-hI-5gd" id="8i4-f9-FKE"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Ligatures" id="o6e-r0-MWq">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Ligatures" id="w0m-vy-SC9">
<items>
<menuItem title="Use Default" id="agt-UL-0e3">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useStandardLigatures:" target="Ady-hI-5gd" id="7uR-wd-Dx6"/>
</connections>
</menuItem>
<menuItem title="Use None" id="J7y-lM-qPV">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="turnOffLigatures:" target="Ady-hI-5gd" id="iX2-gA-Ilz"/>
</connections>
</menuItem>
<menuItem title="Use All" id="xQD-1f-W4t">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="useAllLigatures:" target="Ady-hI-5gd" id="KcB-kA-TuK"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Baseline" id="OaQ-X3-Vso">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Baseline" id="ijk-EB-dga">
<items>
<menuItem title="Use Default" id="3Om-Ey-2VK">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unscript:" target="Ady-hI-5gd" id="0vZ-95-Ywn"/>
</connections>
</menuItem>
<menuItem title="Superscript" id="Rqc-34-cIF">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="superscript:" target="Ady-hI-5gd" id="3qV-fo-wpU"/>
</connections>
</menuItem>
<menuItem title="Subscript" id="I0S-gh-46l">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="subscript:" target="Ady-hI-5gd" id="Q6W-4W-IGz"/>
</connections>
</menuItem>
<menuItem title="Raise" id="2h7-ER-AoG">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="raiseBaseline:" target="Ady-hI-5gd" id="4sk-31-7Q9"/>
</connections>
</menuItem>
<menuItem title="Lower" id="1tx-W0-xDw">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="lowerBaseline:" target="Ady-hI-5gd" id="OF1-bc-KW4"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/>
<menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk">
<connections>
<action selector="orderFrontColorPanel:" target="Ady-hI-5gd" id="mSX-Xz-DV3"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/>
<menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="copyFont:" target="Ady-hI-5gd" id="GJO-xA-L4q"/>
</connections>
</menuItem>
<menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="pasteFont:" target="Ady-hI-5gd" id="JfD-CL-leO"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Text" id="Fal-I4-PZk">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Text" id="d9c-me-L2H">
<items>
<menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1">
<connections>
<action selector="alignLeft:" target="Ady-hI-5gd" id="zUv-R1-uAa"/>
</connections>
</menuItem>
<menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb">
<connections>
<action selector="alignCenter:" target="Ady-hI-5gd" id="spX-mk-kcS"/>
</connections>
</menuItem>
<menuItem title="Justify" id="J5U-5w-g23">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="alignJustified:" target="Ady-hI-5gd" id="ljL-7U-jND"/>
</connections>
</menuItem>
<menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4">
<connections>
<action selector="alignRight:" target="Ady-hI-5gd" id="r48-bG-YeY"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/>
<menuItem title="Writing Direction" id="H1b-Si-o9J">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd">
<items>
<menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title=" Default" id="YGs-j5-SAR">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionNatural:" target="Ady-hI-5gd" id="qtV-5e-UBP"/>
</connections>
</menuItem>
<menuItem title=" Left to Right" id="Lbh-J2-qVU">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionLeftToRight:" target="Ady-hI-5gd" id="S0X-9S-QSf"/>
</connections>
</menuItem>
<menuItem title=" Right to Left" id="jFq-tB-4Kx">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeBaseWritingDirectionRightToLeft:" target="Ady-hI-5gd" id="5fk-qB-AqJ"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="swp-gr-a21"/>
<menuItem title="Selection" enabled="NO" id="cqv-fj-IhA">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title=" Default" id="Nop-cj-93Q">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionNatural:" target="Ady-hI-5gd" id="lPI-Se-ZHp"/>
</connections>
</menuItem>
<menuItem title=" Left to Right" id="BgM-ve-c93">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionLeftToRight:" target="Ady-hI-5gd" id="caW-Bv-w94"/>
</connections>
</menuItem>
<menuItem title=" Right to Left" id="RB4-Sm-HuC">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="makeTextWritingDirectionRightToLeft:" target="Ady-hI-5gd" id="EXD-6r-ZUu"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/>
<menuItem title="Show Ruler" id="vLm-3I-IUL">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="toggleRuler:" target="Ady-hI-5gd" id="FOx-HJ-KwY"/>
</connections>
</menuItem>
<menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="copyRuler:" target="Ady-hI-5gd" id="71i-fW-3W2"/>
</connections>
</menuItem>
<menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="pasteRuler:" target="Ady-hI-5gd" id="cSh-wd-qM2"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="View" id="HyV-fh-RgO">
<items>
<menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="toggleToolbarShown:" target="Ady-hI-5gd" id="BXY-wc-z0C"/>
</connections>
</menuItem>
<menuItem title="Customize Toolbar…" id="1UK-8n-QPP">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="runToolbarCustomizationPalette:" target="Ady-hI-5gd" id="pQI-g3-MTW"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/>
<menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="toggleSidebar:" target="Ady-hI-5gd" id="iwa-gc-5KM"/>
</connections>
</menuItem>
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="toggleFullScreen:" target="Ady-hI-5gd" id="dU3-MA-1Rq"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
<connections>
<action selector="performMiniaturize:" target="Ady-hI-5gd" id="VwT-WD-YPe"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="R4o-n2-Eq4">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="performZoom:" target="Ady-hI-5gd" id="DIl-cC-cCs"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="arrangeInFront:" target="Ady-hI-5gd" id="DRN-fu-gQh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
<items>
<menuItem title="HelloWorld Help" keyEquivalent="?" id="FKE-Sm-Kum">
<connections>
<action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
</connections>
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="0.0"/>
</scene>
<!--Window Controller-->
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
<window key="window" title="HelloWorld" allowsToolTipsWhenApplicationIsInactive="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="720"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<connections>
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
</connections>
</window>
<connections>
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
</connections>
</windowController>
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="467"/>
</scene>
<!--View Controller-->
<scene sceneID="hIz-AP-VOD">
<objects>
<viewController id="XfG-lQ-9wD" customClass="ViewController" sceneMemberID="viewController">
<view key="view" wantsLayer="YES" id="m2S-Jp-Qdl">
<rect key="frame" x="0.0" y="0.0" width="480" height="720"/>
<autoresizingMask key="autoresizingMask"/>
</view>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="640" y="467"/>
</scene>
</scenes>
</document>

Просмотреть файл

@ -0,0 +1,12 @@
/**
* 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.
*/
#import <Cocoa/Cocoa.h>
@interface ViewController : NSViewController
@end

Просмотреть файл

@ -0,0 +1,29 @@
/**
* 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.
*/
#import "ViewController.h"
#import "AppDelegate.h"
#import <React/RCTRootView.h>
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
RCTBridge *bridge = [((AppDelegate *)[NSApp delegate])bridge];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"HelloWorld" initialProperties:nil];
NSView *view = [self view];
[view addSubview:rootView];
[rootView setBackgroundColor:[NSColor windowBackgroundColor]];
[rootView setFrame:[view bounds]];
[rootView setAutoresizingMask:(NSViewMinXMargin | NSViewMinXMargin | NSViewMinYMargin | NSViewMaxYMargin | NSViewWidthSizable | NSViewHeightSizable)];
}
@end

Просмотреть файл

@ -0,0 +1,12 @@
/**
* 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.
*/
#import <Cocoa/Cocoa.h>
int main(int argc, const char *argv[]) {
return NSApplicationMain(argc, argv);
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,15 @@
/**
* 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.
*/
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
@property (nonatomic, strong) UIWindow *window;
@end

Просмотреть файл

@ -0,0 +1,42 @@
/**
* 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.
*/
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"HelloWorld"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
}
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
@end

Просмотреть файл

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="HelloWorld" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>

Просмотреть файл

@ -0,0 +1,53 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Просмотреть файл

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Просмотреть файл

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>HelloWorld</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,16 @@
/**
* 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.
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

Просмотреть файл

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1120"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "6B857DA21EC51FC600A9D063"
BuildableName = "libReact.a"
BlueprintName = "React-macOS"
ReferencedContainer = "container:../node_modules/react-native-macos/React/React.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "38C1415723BBE33000902604"
BuildableName = "HelloWorld-macOS.app"
BlueprintName = "HelloWorld-macOS"
ReferencedContainer = "container:HelloWorld.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "38C1415723BBE33000902604"
BuildableName = "HelloWorld-macOS.app"
BlueprintName = "HelloWorld-macOS"
ReferencedContainer = "container:HelloWorld.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "38C1415723BBE33000902604"
BuildableName = "HelloWorld-macOS.app"
BlueprintName = "HelloWorld-macOS"
ReferencedContainer = "container:HelloWorld.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

Просмотреть файл

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1120"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
BuildableName = "libReact.a"
BlueprintName = "React"
ReferencedContainer = "container:../node_modules/react-native-macos/React/React.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "HelloWorld.app"
BlueprintName = "HelloWorld"
ReferencedContainer = "container:HelloWorld.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "HelloWorld.app"
BlueprintName = "HelloWorld"
ReferencedContainer = "container:HelloWorld.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "HelloWorld.app"
BlueprintName = "HelloWorld"
ReferencedContainer = "container:HelloWorld.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

Просмотреть файл

@ -0,0 +1,19 @@
/**
* This cli config is needed for development purposes, e.g. for running
* integration tests during local development or on CI services.
*/
const path = require('path');
const blacklist = require('metro-config/src/defaults/blacklist');
const rnmPath = path.resolve(__dirname, 'node_modules/react-native-macos');
module.exports = {
resolver: {
extraNodeModules: {
'react-native': rnmPath,
},
platforms: ['macos', 'ios', 'android'],
blacklistRE: blacklist([/node_modules\/react-native\/.*/]),
},
};

Просмотреть файл

@ -0,0 +1,33 @@
/**
* This cli config is needed for the coexistance of react-native and other
* out-of-tree implementations such react-native-macos.
* The following issue is tracked by
* https://github.com/react-native-community/discussions-and-proposals/issues/182
*
* The work-around involves having a metro.config.js for each out-of-tree
* platform, i.e. metro.config.js for react-native and
* metro.config.macos.js for react-native-macos.
* This react-native.config.js looks for a --use-react-native-macos
* switch and when present pushes --config=metro.config.macos.js
* and specifies reactNativePath: 'node_modules/react-native-macos'.
* The metro.config.js has to blacklist 'node_modules/react-native-macos',
* and conversely metro.config.macos.js has to blacklist 'node_modules/react-native'.
*/
'use strict';
const macSwitch = '--use-react-native-macos';
const windowsSwitch = '--use-react-native-windows';
if (process.argv.includes(macSwitch)) {
process.argv = process.argv.filter(arg => arg !== macSwitch);
process.argv.push('--config=metro.config.macos.js');
module.exports = {
reactNativePath: 'node_modules/react-native-macos',
};
} else if (process.argv.includes(windowsSwitch)) {
process.argv = process.argv.filter(arg => arg !== windowsSwitch);
process.argv.push('--config=metro.config.windows.js');
module.exports = {
reactNativePath: 'node_modules/react-native-windows',
};
}

2
packages/react-native-macos-init/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
lib/
lib-commonjs/

Просмотреть файл

@ -0,0 +1,24 @@
# react-native-macos-init
CLI to bootstrap the addition of the macOS platform to `react-native` projects.
## Usage
Run this from an existing `react-native` project to install `react-native-macos` and generate initial project files for macOS.
Example usage
```
$ npx react-native init AwesomeProject
$ cd AwesomeProject
$ npx react-native-macos-init
```
Options:
| option | description | type |
|--------------|------------------------------------------------|-----------|
| --help | Show help | [boolean] |
| --version | The version of react-native-macos to use | [string] |
| --verbose | Enables logging | [boolean] |
| --overwrite | Overwrite any existing files without prompting | [boolean] |
| --prerelease | Install prerelease version without prompting | [boolean] |

12
packages/react-native-macos-init/bin.js поставляемый Executable file
Просмотреть файл

@ -0,0 +1,12 @@
#!/usr/bin/env node
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*
* @format
*/
// Yarn will fail to link workspace binaries if they haven't been built yet. Add
// a simple JS file to forward to the CLI which is built after install.
require('./lib-commonjs/cli');

20
packages/react-native-macos-init/just-task.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,20 @@
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*
* @format
* @ts-check
*/
const {eslintTask, series, task, taskPresets} = require('just-scripts');
taskPresets.lib();
task('eslint', () => {
return eslintTask();
});
task('eslint:fix', () => {
return eslintTask({fix: true});
});
task('lint', series('eslint'));
task('lint:fix', series('eslint:fix'));

Просмотреть файл

@ -0,0 +1,41 @@
{
"name": "react-native-macos-init",
"version": "0.0.9",
"description": "CLI to add react-native-macos to an existing react-native project",
"main": "index.js",
"repository": "https://github.com/microsoft/react-native-macos",
"license": "MIT",
"private": false,
"scripts": {
"build": "just-scripts build",
"clean": "just-scripts clean",
"lint": "just-scripts lint",
"lint:fix": "just-scripts lint:fix"
},
"bin": {
"react-native-macos-init": "./bin.js"
},
"dependencies": {
"chalk": "^3",
"npm-registry": "^0.1.13",
"prompts": "^2.3.0",
"find-up": "^4.1.0",
"semver": "^7.1.3",
"valid-url": "^1.0.9",
"yargs": "^15.1.0"
},
"devDependencies": {
"@types/chalk": "^2.2.0",
"@types/prompts": "^2.0.3",
"@types/semver": "^7.1.0",
"@types/valid-url": "^1.0.2",
"@types/yargs": "^15.0.3",
"just-scripts": "^0.36.1",
"typescript": "3.5.3"
},
"files": [
"bin.js",
"lib-commonjs",
"README.md"
]
}

Просмотреть файл

@ -0,0 +1,303 @@
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*
* @format
*/
import * as yargs from 'yargs';
import * as fs from 'fs';
import * as semver from 'semver';
import {execSync} from 'child_process';
import * as validUrl from 'valid-url';
import * as prompts from 'prompts';
import * as findUp from 'find-up';
import * as chalk from 'chalk';
// @ts-ignore
import * as Registry from 'npm-registry';
const npmConfReg = execSync('npm config get registry')
.toString()
.trim();
const NPM_REGISTRY_URL = validUrl.isUri(npmConfReg)
? npmConfReg
: 'http://registry.npmjs.org';
const npm = new Registry({registry: NPM_REGISTRY_URL});
const argv = yargs.version(false).options({
version: {
type: 'string',
describe: 'The version of react-native-macos to use',
},
verbose: {type: 'boolean', describe: 'Enables logging'},
overwrite: {
type: 'boolean',
describe: 'Overwrite any existing files without prompting',
},
prerelease: {
type: 'boolean',
describe: 'Install prerelease version without prompting',
},
}).argv;
const EXITCODE_NO_MATCHING_RNMACOS = 2;
const EXITCODE_UNSUPPORTED_VERION_RN = 3;
const EXITCODE_USER_CANCEL = 4;
const EXITCODE_NO_REACTNATIVE_FOUND = 5;
const EXITCODE_UNKNOWN_ERROR = 6;
const EXITCODE_NO_PACKAGE_JSON = 7;
function reactNativeMacOSGeneratePath() {
return require.resolve('react-native-macos/local-cli/generate-macos.js', {
paths: [process.cwd()],
});
}
function getReactNativeAppName() {
console.log('Reading application name from package.json...');
const cwd = process.cwd();
const pkgJsonPath = findUp.sync('package.json', {cwd});
if (!pkgJsonPath) {
console.error(
'Unable to find package.json. This should be run from within an existing react-native app.',
);
process.exit(EXITCODE_NO_PACKAGE_JSON);
}
let name = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8')).name;
if (!name) {
const appJsonPath = findUp.sync('app.json', {cwd});
if (appJsonPath) {
console.log('Reading application name from app.json...');
name = JSON.parse(fs.readFileSync(appJsonPath, 'utf8')).name;
}
}
if (!name) {
console.error('Please specify name in package.json or app.json');
}
return name;
}
function getReactNativeVersion() {
console.log('Reading react-native version from node_modules...');
const rnPkgJsonPath = require.resolve('react-native/package.json', {
paths: [process.cwd()],
});
if (fs.existsSync(rnPkgJsonPath)) {
return require(rnPkgJsonPath).version;
}
console.error(
'Error: Must be run from a project that already depends on react-native, and has react-native installed.',
);
process.exit(EXITCODE_NO_REACTNATIVE_FOUND);
}
function errorOutOnUnsupportedVersionOfReactNative(rnVersion: string) {
console.error(`Error: Unsupported version of react-native: ${chalk.cyan(
rnVersion,
)}
react-native-macos supports react-native versions ${chalk.cyan('>=0.60')}`);
process.exit(EXITCODE_UNSUPPORTED_VERION_RN);
}
function getDefaultReactNativeMacOSSemVerForReactNativeVersion(
rnVersion: string,
reactNativeMacOSLatestVersion: string
) {
const validVersion = semver.valid(rnVersion);
if (validVersion) {
const majorRN = semver.major(validVersion);
const minorRN = semver.minor(validVersion);
if (majorRN === 0 && minorRN >= 60) {
const majorRNMac = semver.major(reactNativeMacOSLatestVersion);
const minorRNMac = semver.minor(reactNativeMacOSLatestVersion);
const major = Math.min(majorRN, majorRNMac);
const minor = Math.min(minorRN, minorRNMac);
return `^${major}.${minor}.0-0`;
}
}
errorOutOnUnsupportedVersionOfReactNative(rnVersion);
}
function getMatchingReactNativeSemVerForReactNativeMacOSVersion(
rnmacVersion: string,
) {
const validVersion = semver.valid(rnmacVersion);
if (validVersion) {
const major = semver.major(validVersion);
const minor = semver.minor(validVersion);
if (major === 0 && minor >= 60) {
return `^${major}.${minor}`;
}
}
return 'unknown';
}
function getLatestMatchingVersion(
pkg: string,
versionSemVer: string,
): Promise<string> {
return new Promise((resolve, reject) => {
if (semver.validRange(versionSemVer)) {
// Ideally we'd be able to just use npm.packages.range(pkg, versionSemVer) here,
// but alas it fails to give us the right result for react-native-macos@^0.60.0-microsoft.57
// as it fails to return pre-release versions
npm.packages.releases(
pkg,
(err: any, details: {[key: string]: object}) => {
if (err) {
reject(err);
} else if (details) {
const versions = Object.keys(details);
if (versions.length > 0) {
const candidates = versions
.filter(v => semver.satisfies(v, versionSemVer))
.sort(semver.rcompare);
if (candidates && candidates.length > 0) {
resolve(candidates[0]);
return;
}
}
}
reject(
new Error(`No matching version of ${pkg}@${versionSemVer} found`),
);
},
);
} else {
// Assume that versionSemVer is actually a tag
npm.packages.release(
pkg,
versionSemVer,
(err: any, details: {version: string}[]) => {
if (err) {
reject(err);
} else if (details && details.length > 0) {
resolve(details[0].version);
return;
}
reject(
new Error(`No matching version of ${pkg}@${versionSemVer} found`),
);
},
);
}
});
}
async function getLatestMatchingReactNativeMacOSVersion(
versionSemVer: string,
): Promise<string> {
try {
const version = await getLatestMatchingVersion(
'react-native-macos',
versionSemVer,
);
return version;
} catch (err) {
console.error(
`Error: No version of react-native-macos@${versionSemVer} found`,
);
process.exit(EXITCODE_NO_MATCHING_RNMACOS);
return "";
}
}
/**
* Check if project is using Yarn (has `yarn.lock` in the tree)
*/
function isProjectUsingYarn(cwd: string) {
return findUp.sync('yarn.lock', {cwd});
}
(async () => {
try {
const name = getReactNativeAppName();
let version = argv.version;
const reactNativeMacOSLatestVersion = await getLatestMatchingReactNativeMacOSVersion('latest');
if (!version) {
const rnVersion = getReactNativeVersion();
version = getDefaultReactNativeMacOSSemVerForReactNativeVersion(
rnVersion,
reactNativeMacOSLatestVersion
);
}
const reactNativeMacOSResolvedVersion = await getLatestMatchingReactNativeMacOSVersion(version);
if (!argv.version) {
console.log(
`Latest matching version of ${chalk.bold(
'react-native-macos',
)} for ${chalk.green('react-native')}@${chalk.cyan(
getReactNativeVersion(),
)} is ${chalk.green('react-native-macos')}@${chalk.cyan(
reactNativeMacOSResolvedVersion,
)}`,
);
if (semver.prerelease(reactNativeMacOSResolvedVersion)) {
console.warn(
`
${chalk.green('react-native-macos')}@${chalk.cyan(
reactNativeMacOSResolvedVersion,
)} is a ${chalk.yellow('pre-release')} version.
The latest supported version is ${chalk.green(
'react-native-macos',
)}@${chalk.cyan(reactNativeMacOSLatestVersion)}.
You can either downgrade your version of ${chalk.green(
'react-native',
)} to ${chalk.cyan(
getMatchingReactNativeSemVerForReactNativeMacOSVersion(
reactNativeMacOSLatestVersion,
),
)}, or continue with a ${chalk.yellow(
'pre-release',
)} version of ${chalk.bold('react-native-macos')}.
`,
);
if (!argv.prerelease) {
const confirm = (await prompts({
type: 'confirm',
name: 'confirm',
message: `Do you wish to continue with ${chalk.green(
'react-native-macos',
)}@${chalk.cyan(reactNativeMacOSResolvedVersion)}?`,
})).confirm;
if (!confirm) {
process.exit(EXITCODE_USER_CANCEL);
}
}
}
}
const pkgmgr = isProjectUsingYarn(process.cwd())
? 'yarn add'
: 'npm install --save';
const execOptions = argv.verbose ? {stdio: 'inherit' as 'inherit'} : {};
console.log(
`Installing ${chalk.green('react-native-macos')}@${chalk.cyan(
version,
)}...`,
);
execSync(`${pkgmgr} "react-native-macos@${version}"`, execOptions);
console.log(
chalk.green(`react-native-macos@${version} successfully installed.`),
);
const generateMacOS = require(reactNativeMacOSGeneratePath());
generateMacOS(process.cwd(), name, {
overwrite: argv.overwrite,
verbose: argv.verbose,
});
} catch (error) {
console.error(chalk.red(error.message));
console.error(error);
process.exit(EXITCODE_UNKNOWN_ERROR);
}
})();

Просмотреть файл

@ -0,0 +1,15 @@
{
"compilerOptions": {
"baseUrl": ".",
"target": "es6",
"sourceMap": true,
"noImplicitAny": true,
"preserveConstEnums": true,
"moduleResolution": "node",
"noUnusedLocals": true,
"skipLibCheck": true,
"rootDirs": ["src"],
},
"include": ["src"],
"exclude": ["node_modules"]
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу