From 37009b1fcf51589aab7ac175503a7b8a18ac9f8c Mon Sep 17 00:00:00 2001
From: Dan Abramov <dan.abramov@gmail.com>
Date: Thu, 21 Jul 2016 21:22:31 +0100
Subject: [PATCH] Attempt to reuse Chrome tab on OS X (#62)

Fixes #38
---
 scripts/eject.js               | 13 +++++++---
 scripts/openChrome.applescript | 45 ++++++++++++++++++++++++++++++++++
 scripts/start.js               | 24 +++++++++++++++++-
 3 files changed, 77 insertions(+), 5 deletions(-)
 create mode 100644 scripts/openChrome.applescript

diff --git a/scripts/eject.js b/scripts/eject.js
index 174f222f7..34bf88186 100644
--- a/scripts/eject.js
+++ b/scripts/eject.js
@@ -46,7 +46,8 @@ prompt('Are you sure you want to eject? This action is permanent. [y/N]', functi
     path.join('config', 'webpack.config.dev.js'),
     path.join('config', 'webpack.config.prod.js'),
     path.join('scripts', 'build.js'),
-    path.join('scripts', 'start.js')
+    path.join('scripts', 'start.js'),
+    path.join('scripts', 'openChrome.applescript')
   ];
 
   // Ensure that the host folder is clean and we won't override any files
@@ -68,9 +69,13 @@ prompt('Are you sure you want to eject? This action is permanent. [y/N]', functi
 
   files.forEach(function(file) {
     console.log('Copying ' + file + ' to ' + hostPath);
-    var content = fs.readFileSync(path.join(selfPath, file), 'utf8');
-    // Remove license header
-    content = content.replace(/^\/\*\*(\*(?!\/)|[^*])*\*\//, '').trim() + '\n';
+    content = fs
+      .readFileSync(path.join(selfPath, file), 'utf8')
+      // Remove license header from JS
+      .replace(/^\/\*\*(\*(?!\/)|[^*])*\*\//, '')
+      // Remove license header from AppleScript
+      .replace(/^--.*\n/gm, '')
+      .trim() + '\n';
     fs.writeFileSync(path.join(hostPath, file), content);
   });
   console.log();
diff --git a/scripts/openChrome.applescript b/scripts/openChrome.applescript
new file mode 100644
index 000000000..0035dcad5
--- /dev/null
+++ b/scripts/openChrome.applescript
@@ -0,0 +1,45 @@
+-- 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.
+on run argv
+  set theURL to item 1 of argv
+
+  tell application "Chrome"
+
+    if (count every window) = 0 then
+      make new window
+    end if
+
+    -- Find a tab currently running the debugger
+    set found to false
+    set theTabIndex to -1
+    repeat with theWindow in every window
+      set theTabIndex to 0
+      repeat with theTab in every tab of theWindow
+        set theTabIndex to theTabIndex + 1
+        if theTab's URL is theURL then
+          set found to true
+          exit repeat
+        end if
+      end repeat
+
+      if found then
+        exit repeat
+      end if
+    end repeat
+
+    if found then
+      tell theTab to reload
+      set index of theWindow to 1
+      set theWindow's active tab index to theTabIndex
+    else
+      tell window 1
+        activate
+        make new tab with properties {URL:theURL}
+      end tell
+    end if
+  end tell
+end run
diff --git a/scripts/start.js b/scripts/start.js
index a7e39caf2..b80dfc031 100644
--- a/scripts/start.js
+++ b/scripts/start.js
@@ -9,6 +9,7 @@
 
 process.env.NODE_ENV = 'development';
 
+var path = require('path');
 var chalk = require('chalk');
 var webpack = require('webpack');
 var WebpackDevServer = require('webpack-dev-server');
@@ -117,6 +118,27 @@ compiler.plugin('done', function (stats) {
   }
 });
 
+function openBrowser() {
+  if (process.platform === 'darwin') {
+    try {
+      // Try our best to reuse existing tab
+      // on OS X Google Chrome with AppleScript
+      execSync('ps cax | grep "Google Chrome"');
+      execSync(
+        'osascript ' +
+        path.resolve(__dirname, './openChrome.applescript') +
+        ' http://localhost:3000/'
+      );
+      return;
+    } catch (err) {
+      // Ignore errors.
+    }
+  }
+  // Fallback to opn
+  // (It will always open new tab)
+  opn('http://localhost:3000/');
+}
+
 new WebpackDevServer(compiler, {
   historyApiFallback: true,
   hot: true, // Note: only CSS is currently hot reloaded
@@ -128,5 +150,5 @@ new WebpackDevServer(compiler, {
   }
 
   console.log('Starting the development server...');
-  opn('http://localhost:3000/');
+  openBrowser();
 });
-- 
GitLab