diff --git a/re-natal.coffee b/re-natal.coffee index ad63628..7810585 100644 --- a/re-natal.coffee +++ b/re-natal.coffee @@ -192,8 +192,8 @@ init = (projName) -> handlersPath = "src/#{projNameUs}/handlers.cljs" subsPath = "src/#{projNameUs}/subs.cljs" - exec "cp #{resources}handlers.cljs #{handlersPath}" - exec "cp #{resources}subs.cljs #{subsPath}" + exec "cp #{resources}cljs/handlers.cljs #{handlersPath}" + exec "cp #{resources}cljs/subs.cljs #{subsPath}" edit handlersPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName]] edit subsPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName]] @@ -207,30 +207,42 @@ init = (projName) -> coreAndroidPath = "src/#{projNameUs}/android/core.cljs" coreIosPath = "src/#{projNameUs}/ios/core.cljs" - exec "cp #{resources}core.cljs #{coreAndroidPath}" + exec "cp #{resources}cljs/core.cljs #{coreAndroidPath}" edit coreAndroidPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName], [platformRx, "android"]] - exec "cp #{resources}core.cljs #{coreIosPath}" + exec "cp #{resources}cljs/core.cljs #{coreIosPath}" edit coreIosPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName], [platformRx, "ios"]] - fs.mkdirSync "src/env" - fs.mkdirSync "src/env/ios" - fs.mkdirSync "src/env/android" + fs.mkdirSync "env" + fs.mkdirSync "env/dev" + fs.mkdirSync "env/dev/env" + fs.mkdirSync "env/dev/env/ios" + fs.mkdirSync "env/dev/env/android" + fs.mkdirSync "env/prod" + fs.mkdirSync "env/prod/env" + fs.mkdirSync "env/prod/env/ios" + fs.mkdirSync "env/prod/env/android" - envIosDevPath = "src/env/ios/dev.cljs" - envIosProdPath = "src/env/ios/prod.cljs" - envAndroidDevPath = "src/env/android/dev.cljs" - envAndroidProdPath = "src/env/android/prod.cljs" + mainIosDevPath = "env/dev/env/ios/main.cljs" + mainIosProdPath = "env/prod/env/ios/main.cljs" + mainAndroidDevPath = "env/dev/env/android/main.cljs" + mainAndroidProdPath = "env/prod/env/android/main.cljs" - exec "cp #{resources}dev.cljs #{envIosDevPath}" - edit envIosDevPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName], [platformRx, "ios"]] - exec "cp #{resources}prod.cljs #{envIosProdPath}" - edit envIosProdPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName], [platformRx, "ios"]] - exec "cp #{resources}dev.cljs #{envAndroidDevPath}" - edit envAndroidDevPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName], [platformRx, "android"]] - exec "cp #{resources}prod.cljs #{envAndroidProdPath}" - edit envAndroidProdPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName], [platformRx, "android"]] + exec "cp #{resources}cljs/main_dev.cljs #{mainIosDevPath}" + edit mainIosDevPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName], [platformRx, "ios"]] + exec "cp #{resources}cljs/main_prod.cljs #{mainIosProdPath}" + edit mainIosProdPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName], [platformRx, "ios"]] + exec "cp #{resources}cljs/main_dev.cljs #{mainAndroidDevPath}" + edit mainAndroidDevPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName], [platformRx, "android"]] + exec "cp #{resources}cljs/main_prod.cljs #{mainAndroidProdPath}" + edit mainAndroidProdPath, [[projNameHyphRx, projNameHyph], [projNameRx, projName], [platformRx, "android"]] + requestImgMacroDevPath = "env/dev/env/require_img.clj" + requestImgMacroProdPath = "env/prod/env/require_img.clj" + exec "cp #{resources}require_img_dev.clj #{requestImgMacroDevPath}" + exec "cp #{resources}require_img_prod.clj #{requestImgMacroProdPath}" + + exec "cp -r #{resources}images ." log 'Creating React Native skeleton. Relax, this takes a while...' @@ -360,12 +372,9 @@ getDeviceUuids = -> generateDevScripts = (method) -> try fs.statSync '.re-natal' - fs.unlinkSync 'index.android.js' - fs.unlinkSync 'index.ios.js' - - fs.writeFileSync 'index.ios.js', "require('react-native');require('figwheel-bridge')."+method+"('ios');", null, 2 + fs.writeFileSync 'index.ios.js', "require('react-native');require('figwheel-bridge')."+method+"('ios');" log 'index.ios.js was regenerated' - fs.writeFileSync 'index.android.js', "require('react-native');require('figwheel-bridge')."+method+"('android');", null, 2 + fs.writeFileSync 'index.android.js', "require('react-native');require('figwheel-bridge')."+method+"('android');" log 'index.android.js was regenerated' catch {message} logErr \ diff --git a/resources/AppDelegate.h b/resources/AppDelegate.h deleted file mode 100644 index f75750f..0000000 --- a/resources/AppDelegate.h +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import - -@interface AppDelegate : UIResponder - -@property (nonatomic, strong) UIWindow *window; - -@end diff --git a/resources/AppDelegate.m b/resources/AppDelegate.m deleted file mode 100644 index f37f422..0000000 --- a/resources/AppDelegate.m +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import "AppDelegate.h" - -#import "RCTRootView.h" -#import "RCTEventDispatcher.h" -#import "ABYServer.h" -#import "ABYContextManager.h" -#import "RCTContextExecutor.h" - -/** - This class exists so that a client-created `JSGlobalContextRef` - instance and optional JavaScript thread can be injected - into an `RCTContextExecutor`. - */ -@interface ABYContextExecutor : RCTContextExecutor - -/** - Sets the JavaScript thread that will be used when `init`ing - an instance of this class. If not set, `[NSThread mainThread]` - will be used. - - @param thread the thread - */ -+(void) setJavaScriptThread:(NSThread*)thread; - -/** - Sets the context that will be used when `init`ing an instance - of this class. - @param context the context - */ -+(void) setContext:(JSGlobalContextRef)context; - -@end - -static NSThread* staticJavaScriptThread = nil; -static JSGlobalContextRef staticContext; - -@implementation ABYContextExecutor - -RCT_EXPORT_MODULE() - -- (instancetype)init -{ - id me = [self initWithJavaScriptThread:(staticJavaScriptThread ? staticJavaScriptThread : [NSThread mainThread]) - globalContextRef:staticContext]; - staticJavaScriptThread = nil; - JSGlobalContextRelease(staticContext); - return me; -} - -+(void) setJavaScriptThread:(NSThread*)thread -{ - staticJavaScriptThread = thread; -} - -+(void) setContext:(JSGlobalContextRef)context -{ - staticContext = JSGlobalContextRetain(context); -} - -@end - - -@interface AppDelegate() - -@property (strong, nonatomic) ABYServer* replServer; -@property (strong, nonatomic) ABYContextManager* contextManager; -@property (strong, nonatomic) NSURL* compilerOutputDirectory; - -@end - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - NSURL *jsCodeLocation; - - /** - * Loading JavaScript code - uncomment the one you want. - * - * OPTION 1 - * Load from development server. Start the server from the repository root: - * - * $ npm start - * - * To run on device, change `localhost` to the IP address of your computer - * (you can get this by typing `ifconfig` into the terminal and selecting the - * `inet` value under `en0:`) and make sure your computer and iOS device are - * on the same Wi-Fi network. - */ - - jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"]; - - /** - * OPTION 2 - * Load from pre-bundled file on disk. To re-generate the static bundle - * from the root of your project directory, run - * - * $ react-native bundle --minify - * - * see http://facebook.github.io/react-native/docs/runningondevice.html - */ - -// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; - - // Set up the ClojureScript compiler output directory - self.compilerOutputDirectory = [[self privateDocumentsDirectory] URLByAppendingPathComponent:@"cljs-out"]; - - // Set up our context manager - self.contextManager = [[ABYContextManager alloc] initWithContext:JSGlobalContextCreate(NULL) - compilerOutputDirectory:self.compilerOutputDirectory]; - - // Inject our context using ABYContextExecutor - [ABYContextExecutor setContext:self.contextManager.context]; - - // Set React Native to intstantiate our ABYContextExecutor, doing this by slipping the executorClass - // assignement between alloc and initWithBundleURL:moduleProvider:launchOptions: - RCTBridge *bridge = [RCTBridge alloc]; - bridge.executorClass = [ABYContextExecutor class]; - bridge = [bridge initWithBundleURL:jsCodeLocation - moduleProvider:nil - launchOptions:launchOptions]; - - // Set up a root view using the bridge defined above - RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge - moduleName:@"$PROJECT_NAME$" - initialProperties:nil]; - - // Set up to be notified when the React Native UI is up - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(contentDidAppear) - name:RCTContentDidAppearNotification - object:rootView]; - - self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - UIViewController *rootViewController = [[UIViewController alloc] init]; - rootViewController.view = rootView; - self.window.rootViewController = rootViewController; - [self.window makeKeyAndVisible]; - return YES; -} - -- (NSURL *)privateDocumentsDirectory -{ - NSURL *libraryDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject]; - - return [libraryDirectory URLByAppendingPathComponent:@"Private Documents"]; -} - -- (void)createDirectoriesUpTo:(NSURL*)directory -{ - if (![[NSFileManager defaultManager] fileExistsAtPath:[directory path]]) { - NSError *error = nil; - - if (![[NSFileManager defaultManager] createDirectoryAtPath:[directory path] - withIntermediateDirectories:YES - attributes:nil - error:&error]) { - NSLog(@"Can't create directory %@ [%@]", [directory path], error); - abort(); - } - } -} - --(void)requireAppNamespaces:(JSContext*)context -{ - [context evaluateScript:[NSString stringWithFormat:@"goog.require('%@');", [self munge:@"$PROJECT_NAME_HYPHENATED$.ios.core"]]]; -} - -- (JSValue*)getValue:(NSString*)name inNamespace:(NSString*)namespace fromContext:(JSContext*)context -{ - JSValue* namespaceValue = nil; - for (NSString* namespaceElement in [namespace componentsSeparatedByString: @"."]) { - if (namespaceValue) { - namespaceValue = namespaceValue[[self munge:namespaceElement]]; - } else { - namespaceValue = context[[self munge:namespaceElement]]; - } - } - - return namespaceValue[[self munge:name]]; -} - -- (NSString*)munge:(NSString*)s -{ - return [[[s stringByReplacingOccurrencesOfString:@"-" withString:@"_"] - stringByReplacingOccurrencesOfString:@"!" withString:@"_BANG_"] - stringByReplacingOccurrencesOfString:@"?" withString:@"_QMARK_"]; -} - -- (void)contentDidAppear -{ - // Ensure private documents directory exists - [self createDirectoriesUpTo:[self privateDocumentsDirectory]]; - - // Copy resources from bundle "out" to compilerOutputDirectory - - NSFileManager* fileManager = [NSFileManager defaultManager]; - fileManager.delegate = self; - - // First blow away old compiler output directory - [fileManager removeItemAtPath:self.compilerOutputDirectory.path error:nil]; - - // Copy files from bundle to compiler output driectory - NSString *outPath = [[NSBundle mainBundle] pathForResource:@"out" ofType:nil]; - [fileManager copyItemAtPath:outPath toPath:self.compilerOutputDirectory.path error:nil]; - - [self.contextManager setUpAmblyImportScript]; - - NSString* mainJsFilePath = [[self.compilerOutputDirectory URLByAppendingPathComponent:@"main" isDirectory:NO] URLByAppendingPathExtension:@"js"].path; - - NSURL* googDirectory = [self.compilerOutputDirectory URLByAppendingPathComponent:@"goog"]; - - [self.contextManager bootstrapWithDepsFilePath:mainJsFilePath - googBasePath:[[googDirectory URLByAppendingPathComponent:@"base" isDirectory:NO] URLByAppendingPathExtension:@"js"].path]; - - JSContext* context = [JSContext contextWithJSGlobalContextRef:self.contextManager.context]; - [self requireAppNamespaces:context]; - - JSValue* initFn = [self getValue:@"init" inNamespace:@"$PROJECT_NAME_HYPHENATED$.ios.core" fromContext:context]; - NSAssert(!initFn.isUndefined, @"Could not find the app init function"); - [initFn callWithArguments:@[]]; - - // Send a nonsense UI event to cause React Native to load our Reagent UI - RCTRootView* rootView = (RCTRootView*)self.window.rootViewController.view; - [rootView.bridge.modules[@"RCTEventDispatcher"] sendInputEventWithName:@"dummy" body:@{@"target": @1}]; - - // Now that React Native has been initialized, fire up our REPL server - self.replServer = [[ABYServer alloc] initWithContext:self.contextManager.context - compilerOutputDirectory:self.compilerOutputDirectory]; - [self.replServer startListening]; -} - -@end diff --git a/resources/core.cljs b/resources/cljs/core.cljs similarity index 90% rename from resources/core.cljs rename to resources/cljs/core.cljs index cef2431..7900e20 100644 --- a/resources/core.cljs +++ b/resources/cljs/core.cljs @@ -1,4 +1,5 @@ (ns ^:figwheel-always $PROJECT_NAME_HYPHENATED$.$PLATFORM$.core + (:require-macros [env.require-img :refer [require-img]]) (:require [reagent.core :as r :refer [atom]] [re-frame.core :refer [subscribe dispatch dispatch-sync]] [$PROJECT_NAME_HYPHENATED$.handlers] @@ -12,12 +13,14 @@ (def image (r/adapt-react-class (.-Image js/React))) (def touchable-highlight (r/adapt-react-class (.-TouchableHighlight js/React))) +(def logo-img (require-img "./images/cljs.png")) + (defn widget [] (let [greeting (subscribe [:get-greeting])] (fn [] [view {:style {:flexDirection "column" :margin 40 :alignItems "center"}} [text {:style {:fontSize 30 :fontWeight "100" :marginBottom 20 :textAlign "center"}} @greeting] - [image {:source {:uri "https://raw.githubusercontent.com/cljsinfo/logo.cljs/master/cljs.png"} + [image {:source logo-img :style {:width 80 :height 80 :marginBottom 30}}] [touchable-highlight {:style {:backgroundColor "#999" :padding 10 :borderRadius 5}} [text {:style {:color "white" :textAlign "center" :fontWeight "bold"}} "press me"]]]))) diff --git a/resources/handlers.cljs b/resources/cljs/handlers.cljs similarity index 100% rename from resources/handlers.cljs rename to resources/cljs/handlers.cljs diff --git a/resources/dev.cljs b/resources/cljs/main_dev.cljs similarity index 81% rename from resources/dev.cljs rename to resources/cljs/main_dev.cljs index 85a3800..4e487e0 100644 --- a/resources/dev.cljs +++ b/resources/cljs/main_dev.cljs @@ -1,4 +1,4 @@ - (ns env.$PLATFORM$.dev + (ns env.$PLATFORM$.main (:require [$PROJECT_NAME_HYPHENATED$.$PLATFORM$.core :as core])) (enable-console-print!) diff --git a/resources/prod.cljs b/resources/cljs/main_prod.cljs similarity index 76% rename from resources/prod.cljs rename to resources/cljs/main_prod.cljs index 2b7df63..89b4fb9 100644 --- a/resources/prod.cljs +++ b/resources/cljs/main_prod.cljs @@ -1,4 +1,4 @@ - (ns env.$PLATFORM$.prod + (ns env.$PLATFORM$.main (:require [$PROJECT_NAME_HYPHENATED$.$PLATFORM$.core :as core])) (core/init) diff --git a/resources/subs.cljs b/resources/cljs/subs.cljs similarity index 100% rename from resources/subs.cljs rename to resources/cljs/subs.cljs diff --git a/resources/images/cljs.png b/resources/images/cljs.png new file mode 100644 index 0000000..7468cab Binary files /dev/null and b/resources/images/cljs.png differ diff --git a/resources/project.clj b/resources/project.clj index 04daae7..20688d5 100644 --- a/resources/project.clj +++ b/resources/project.clj @@ -14,31 +14,31 @@ ["do" "clean" ["with-profile" "prod" "cljsbuild" "once" "ios"] ["with-profile" "prod" "cljsbuild" "once" "android"]]} - :profiles {:dev {:cljsbuild {:builds {:ios {:source-paths ["src"] + :profiles {:dev {:cljsbuild {:builds {:ios {:source-paths ["src" "env/dev"] :figwheel {:on-jsload $PROJECT_NAME_HYPHENATED$.ios.core/mount-root :heads-up-display false :debug false} :compiler {:output-to "target/ios/not-used.js" - :main "env.ios.dev" + :main "env.ios.main" :output-dir "target/ios" :optimizations :none}} - :android {:source-paths ["src"] + :android {:source-paths ["src" "env/dev"] :figwheel {:on-jsload $PROJECT_NAME_HYPHENATED$.android.core/mount-root :heads-up-display false :debug true} :compiler {:output-to "target/android/not-used.js" - :main "env.android.dev" + :main "env.android.main" :output-dir "target/android" :optimizations :none}}}} } - :prod {:cljsbuild {:builds {:ios {:source-paths ["src"] + :prod {:cljsbuild {:builds {:ios {:source-paths ["src" "env/prod"] :compiler {:output-to "index.ios.js" - :main "env.ios.prod" + :main "env.ios.main" :output-dir "target/ios" :optimizations :simple}} - :android {:source-paths ["src"] + :android {:source-paths ["src" "env/prod"] :compiler {:output-to "index.android.js" - :main "env.android.prod" + :main "env.android.main" :output-dir "target/android" :optimizations :simple}}}} }}) \ No newline at end of file diff --git a/resources/require_img_dev.clj b/resources/require_img_dev.clj new file mode 100644 index 0000000..8f06dbd --- /dev/null +++ b/resources/require_img_dev.clj @@ -0,0 +1,6 @@ +(ns env.require-img) + +(defmacro require-img + "Load image from local packager service" + [src] + {:uri (str "http://localhost:8081/" src)}) diff --git a/resources/require_img_prod.clj b/resources/require_img_prod.clj new file mode 100644 index 0000000..ceedc8a --- /dev/null +++ b/resources/require_img_prod.clj @@ -0,0 +1,6 @@ +(ns env.require-img) + +(defmacro require-img + "Creates 'require' statements for images" + [src] + (list 'js/require src))