Skip to content

Commit ccf59ba

Browse files
committed
[close ptmt#52] Rewrite UIExplorer's skin, add external bundle loader
1 parent 3e193ed commit ccf59ba

File tree

5 files changed

+163
-119
lines changed

5 files changed

+163
-119
lines changed

Examples/UIExplorer/UIExplorer/AppDelegate.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616

1717
@class RCTBridge;
1818

19-
@interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate>
19+
@interface AppDelegate : NSObject <NSApplicationDelegate, NSToolbarDelegate, NSWindowDelegate>
2020

2121
@property (strong, nonatomic) NSWindow *window;
22-
@property (strong) NSArray<NSString *> *argv;
23-
@property(assign) Class<NSWindowRestoration> restorationClass;
22+
@property (strong, nonatomic) NSArray<NSString *> *argv;
23+
@property (assign, nonatomic) Class<NSWindowRestoration> restorationClass;
2424
@property (nonatomic, readonly) RCTBridge *bridge;
25+
@property (strong, nonatomic) NSURL *sourceURL;
2526

2627
@end

Examples/UIExplorer/UIExplorer/AppDelegate.m

Lines changed: 131 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,51 @@
1313
*/
1414

1515
#import "AppDelegate.h"
16+
#import <Cocoa/Cocoa.h>
1617

1718
#import "RCTBridge.h"
1819
#import "RCTJavaScriptLoader.h"
1920
#import "RCTRootView.h"
20-
#import <Cocoa/Cocoa.h>
21+
#import "RCTEventDispatcher.h"
2122

22-
@interface AppDelegate() <RCTBridgeDelegate>
23+
@interface AppDelegate() <RCTBridgeDelegate, NSSearchFieldDelegate>
2324

2425
@end
2526

27+
2628
@implementation AppDelegate
2729

2830
-(id)init
2931
{
3032
if(self = [super init]) {
33+
34+
// -- Init Window
3135
NSRect contentSize = NSMakeRect(200, 500, 1000, 500); // TODO: should not be hardcoded
3236

3337
self.window = [[NSWindow alloc] initWithContentRect:contentSize
34-
styleMask:NSTitledWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask
38+
styleMask:NSTitledWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask | NSFullSizeContentViewWindowMask
3539
backing:NSBackingStoreBuffered
3640
defer:NO];
3741
NSWindowController *windowController = [[NSWindowController alloc] initWithWindow:self.window];
3842

3943
[[self window] setTitle:@"UIExplorerApp"];
44+
[[self window] setTitleVisibility:NSWindowTitleHidden];
45+
[[self window] setAppearance:[NSAppearance appearanceNamed:NSAppearanceNameVibrantLight ]];
46+
[windowController showWindow:self.window];
4047

4148
[windowController setShouldCascadeWindows:NO];
4249
[windowController setWindowFrameAutosaveName:@"UIExplorer"];
50+
[self setDefaultURL];
4351

44-
[windowController showWindow:self.window];
52+
// -- Init Toolbar
53+
NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"mainToolbar"];
54+
[toolbar setDelegate:self];
55+
[toolbar setSizeMode:NSToolbarSizeModeRegular];
56+
57+
[self.window setToolbar:toolbar];
4558

46-
NSMenu *mainMenu = [[NSMenu alloc] initWithTitle:@"" ];
47-
NSMenuItem *containerItem = [[NSMenuItem alloc] init];
48-
NSMenu *rootMenu = [[NSMenu alloc] initWithTitle:@"" ];
49-
[containerItem setSubmenu:rootMenu];
50-
[mainMenu addItem:containerItem];
51-
[rootMenu addItemWithTitle:@"Quit UIExplorer" action:@selector(terminate:) keyEquivalent:@"q"];
52-
[NSApp setMainMenu:mainMenu];
59+
// -- Init Menu
60+
[self setUpMainMenu];
5361
}
5462
return self;
5563
}
@@ -69,50 +77,24 @@ - (void)applicationDidFinishLaunching:(NSNotification * __unused)aNotification
6977
[self.window setContentView:rootView];
7078
}
7179

72-
73-
/**
74-
* Indicates whether Hot Loading is supported or not.
75-
* Note: this method will be removed soon, once Hot Loading is supported on OSS.
76-
*/
77-
- (BOOL)bridgeSupportsHotLoading:(__unused RCTBridge *)bridge
80+
- (void)setDefaultURL
7881
{
79-
return YES;
82+
#if DEBUG
83+
_sourceURL = [NSURL URLWithString:@"http://localhost:8081/Examples/UIExplorer/UIExplorerApp.osx.bundle?platform=osx&dev=true"];
84+
#else
85+
_sourceURL = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
86+
#endif
8087
}
8188

89+
- (void)resetBridgeToDefault
90+
{
91+
[self setDefaultURL];
92+
[_bridge reload];
93+
}
8294

8395
- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge
8496
{
85-
NSURL *sourceURL;
86-
87-
/**
88-
* Loading JavaScript code - uncomment the one you want.
89-
*
90-
* OPTION 1
91-
* Load from development server. Start the server from the repository root:
92-
*
93-
* $ npm start
94-
*
95-
* To run on device, change `localhost` to the IP address of your computer
96-
* (you can get this by typing `ifconfig` into the terminal and selecting the
97-
* `inet` value under `en0:`) and make sure your computer and iOS device are
98-
* on the same Wi-Fi network.
99-
*/
100-
101-
sourceURL = [NSURL URLWithString:@"http://localhost:8081/Examples/UIExplorer/UIExplorerApp.osx.bundle?platform=osx&dev=true"];
102-
103-
/**
104-
* OPTION 2
105-
* Load from pre-bundled file on disk. To re-generate the static bundle, `cd`
106-
* to your Xcode project folder and run
107-
*
108-
* $ curl 'http://localhost:8081/Examples/UIExplorer/UIExplorerApp.osx.bundle?platform=osx&dev=false' -o main.jsbundle
109-
*
110-
* then add the `main.jsbundle` file to your project and uncomment this line:
111-
*/
112-
113-
//sourceURL = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
114-
115-
return sourceURL;
97+
return _sourceURL;
11698
}
11799

118100
- (void)loadSourceForBridge:(RCTBridge *)bridge
@@ -122,4 +104,104 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge
122104
onComplete:loadCallback];
123105
}
124106

107+
- (NSArray *)toolbarAllowedItemIdentifiers:(__unused NSToolbar *)toolbar
108+
{
109+
return @[NSToolbarFlexibleSpaceItemIdentifier, @"searchBar", NSToolbarFlexibleSpaceItemIdentifier, @"resetButton"];
110+
}
111+
112+
- (NSArray *)toolbarDefaultItemIdentifiers:(__unused NSToolbar *)toolbar
113+
{
114+
return @[NSToolbarFlexibleSpaceItemIdentifier, @"searchBar", NSToolbarFlexibleSpaceItemIdentifier, @"resetButton"];
115+
}
116+
117+
- (NSToolbarItem *)toolbar:(NSToolbar * __unused)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL __unused)flag {
118+
119+
if ([itemIdentifier isEqualToString:@"searchBar"]) {
120+
NSSearchField *searchField = [[NSSearchField alloc] init];
121+
[searchField setFrameSize:NSMakeSize(400, searchField.intrinsicContentSize.height)];
122+
[searchField setDelegate:self];
123+
[searchField setAction:@selector(searchURLorQuery:)];
124+
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
125+
[item setView:searchField];
126+
return item;
127+
}
128+
129+
if ([itemIdentifier isEqualToString:@"resetButton"]) {
130+
NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 50, 33)];
131+
[button setBezelStyle:NSRoundedBezelStyle];
132+
[button setImage:[NSImage imageNamed:NSImageNameRefreshTemplate]];
133+
[button setTarget:self];
134+
[button setAction:@selector(resetBridgeToDefault)];
135+
NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
136+
[item setView:button];
137+
[item setAction:@selector(resetBridgeToDefault)];
138+
139+
return item;
140+
}
141+
return nil;
142+
143+
}
144+
145+
- (IBAction)searchURLorQuery:(id)sender {
146+
if ([[sender stringValue] containsString:@"http"]) {
147+
_sourceURL =[NSURL URLWithString:[sender stringValue]];
148+
_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];
149+
NSString * moduleName = [_sourceURL.lastPathComponent stringByReplacingOccurrencesOfString:@".osx.bundle" withString:@""];
150+
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:_bridge
151+
moduleName:moduleName
152+
initialProperties:nil];
153+
NSLog(@"moduleName: %@", moduleName);
154+
[self.window setContentView:rootView];
155+
} else {
156+
[_bridge.eventDispatcher sendDeviceEventWithName:@"onSearchExample"
157+
body:@{@"query": [sender stringValue]}
158+
];
159+
}
160+
}
161+
162+
- (void) setUpMainMenu
163+
{
164+
NSMenu *mainMenu = [[NSMenu alloc] initWithTitle:@"" ];
165+
NSMenuItem *containerItem = [[NSMenuItem alloc] init];
166+
NSMenu *rootMenu = [[NSMenu alloc] initWithTitle:@"" ];
167+
[containerItem setSubmenu:rootMenu];
168+
[mainMenu addItem:containerItem];
169+
[rootMenu addItemWithTitle:@"Quit UIExplorer" action:@selector(terminate:) keyEquivalent:@"q"];
170+
[NSApp setMainMenu:mainMenu];
171+
172+
NSMenuItem *editItemContainer = [[NSMenuItem alloc] init];
173+
NSMenu *editMenu = [[NSMenu alloc] initWithTitle:@"Edit"];
174+
[editItemContainer setSubmenu:editMenu];
175+
[editMenu setAutoenablesItems:NO];
176+
[editMenu addItem:[self addEditMenuItem:@"Undo" action:@selector(undo) key:@"z" ]];
177+
[editMenu addItem:[self addEditMenuItem:@"Redo" action:@selector(redo) key:@"Z" ]];
178+
[editMenu addItem:[self addEditMenuItem:@"Cut" action:@selector(cut:) key:@"x" ]];
179+
[editMenu addItem:[self addEditMenuItem:@"Copy" action:@selector(copy:) key:@"c" ]];
180+
[editMenu addItem:[self addEditMenuItem:@"Paste" action:@selector(paste:) key:@"v" ]];
181+
[editMenu addItem:[self addEditMenuItem:@"SelectAll" action:@selector(selectAll:) key:@"a" ]];
182+
[[NSApp mainMenu] addItem:editItemContainer];
183+
}
184+
185+
- (NSMenuItem *)addEditMenuItem:(NSString *)title
186+
action:(SEL _Nullable)action
187+
key:(NSString *)key
188+
{
189+
NSMenuItem * menuItem = [[NSMenuItem alloc] init];
190+
[menuItem setTitle:title];
191+
[menuItem setEnabled:YES];
192+
[menuItem setAction:action];
193+
[menuItem setKeyEquivalent:key];
194+
return menuItem;
195+
}
196+
197+
- (void)undo
198+
{
199+
[[[self window] undoManager] undo];
200+
}
201+
202+
- (void)redo
203+
{
204+
[[[self window] undoManager] redo];
205+
}
206+
125207
@end

Examples/UIExplorer/UIExplorerApp.osx.js

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,10 @@ class UIExplorerApp extends React.Component {
5656
}
5757

5858
class Welcome extends React.Component {
59-
constructor() {
60-
super();
61-
this.state = {
62-
onHover: false
63-
};
64-
}
6559
render() {
66-
var backgroundStyles = this.state.onHover ? { backgroundColor: 'black'} : {};
6760
return (
6861
<View style={styles.welcomeWrapper}>
69-
<TouchableHighlight style={backgroundStyles}
70-
onMouseEnter={() => this.setState({onHover: true})}
71-
onMouseLeave={() => this.setState({onHover: false})}>
72-
<Text style={styles.welcomeText}>Choose an example on the left side</Text>
73-
</TouchableHighlight>
62+
<Text style={styles.welcomeText}>Choose an example on the left side</Text>
7463
</View>
7564
);
7665
}
@@ -79,18 +68,17 @@ class Welcome extends React.Component {
7968
var styles = StyleSheet.create({
8069
container: {
8170
flex: 1,
82-
backgroundColor: '#ddd',
8371
flexDirection: 'row'
8472
},
8573
itemWrapper: {
8674
backgroundColor: '#eaeaea',
8775
},
8876
leftPanel: {
8977
width: 300,
90-
backgroundColor: '#333'
9178
},
9279
rightPanel: {
9380
flex: 1,
81+
backgroundColor: '#fff'
9482
},
9583
welcomeWrapper: {
9684
flex: 1,

0 commit comments

Comments
 (0)