From 6b9764e6c69aaa63eb15974d474efa9e19d2d134 Mon Sep 17 00:00:00 2001
From: Mikunj <mikunj@live.com.au>
Date: Wed, 5 Dec 2018 13:35:53 +1100
Subject: [PATCH] Added launcher view.

---
 app/user_config.js        |   2 +-
 js/launcher_start.js      |   7 +++
 js/views/launcher_view.js |  26 ++++++++++
 launcher.html             |  43 ++++++++++++++++
 launcher_preload.js       |  31 +++++++++++
 main.js                   | 105 +++++++++++++++++++++++++++++++++++++-
 package.json              |   1 +
 7 files changed, 212 insertions(+), 3 deletions(-)
 create mode 100644 js/launcher_start.js
 create mode 100644 js/views/launcher_view.js
 create mode 100644 launcher.html
 create mode 100644 launcher_preload.js

diff --git a/app/user_config.js b/app/user_config.js
index 4da1f62a0..44a0b1171 100644
--- a/app/user_config.js
+++ b/app/user_config.js
@@ -1,6 +1,6 @@
 const path = require('path');
 
-const { app } = require('electron');
+const app = require('electron').app || require('electron').remote.app;
 
 const { start } = require('./base_config');
 const config = require('./config');
diff --git a/js/launcher_start.js b/js/launcher_start.js
new file mode 100644
index 000000000..38ec1e9e5
--- /dev/null
+++ b/js/launcher_start.js
@@ -0,0 +1,7 @@
+/* global $, Whisper, storage */
+const $body = $(document.body);
+
+// eslint-disable-next-line strict
+window.view = new Whisper.LauncherView();
+$body.html('');
+window.view.$el.prependTo($body);
diff --git a/js/views/launcher_view.js b/js/views/launcher_view.js
new file mode 100644
index 000000000..4c7c8282b
--- /dev/null
+++ b/js/views/launcher_view.js
@@ -0,0 +1,26 @@
+/* global i18n: false */
+/* global Whisper: false */
+/* global $: false */
+
+/* eslint-disable no-new */
+
+// eslint-disable-next-line func-names
+(function() {
+  'use strict';
+
+  window.Whisper = window.Whisper || {};
+
+  Whisper.LauncherView = Whisper.View.extend({
+    className: 'launcher',
+    templateName: 'launcher',
+    initialize() {
+      this.render();
+    },
+    render_attributes() {
+      return {
+        title: 'WOOOWEEE',
+      };
+    },
+  });
+
+})();
diff --git a/launcher.html b/launcher.html
new file mode 100644
index 000000000..448dfe36b
--- /dev/null
+++ b/launcher.html
@@ -0,0 +1,43 @@
+<html>
+<head>
+  <meta http-equiv="Content-Security-Policy"
+    content="default-src 'none';
+            child-src 'self';
+            connect-src 'self' https: wss:;
+            font-src 'self';
+            form-action 'self';
+            frame-src 'none';
+            img-src 'self' blob: data:;
+            media-src 'self' blob:;
+            object-src 'none';
+            script-src 'self';
+            style-src 'self' 'unsafe-inline';"
+  >
+  <link href="stylesheets/manifest.css" rel="stylesheet" type="text/css" />
+  <style>
+  </style>
+  <script type='text/x-tmpl-mustache' id='launcher'>
+    <div class='content'>
+      <h4>{{ title }}</h4>
+    </div>
+  </script>
+
+  <script type='text/javascript' src='js/components.js'></script>
+  <script type='text/javascript' src='js/views/whisper_view.js'></script>
+  <script type='text/javascript' src='js/views/launcher_view.js'></script>
+</head>
+<body>
+  <div class='app-loading-screen'>
+      <div class='content'>
+        <img src='images/loki/loki_icon_128.png'>
+        <div class='container'>
+          <span class='dot'></span>
+          <span class='dot'></span>
+          <span class='dot'></span>
+        </div>
+        <div class='message'></div>
+      </div>
+    </div>
+    <script type='text/javascript' src='js/launcher_start.js'></script>
+</body>
+</html>
diff --git a/launcher_preload.js b/launcher_preload.js
new file mode 100644
index 000000000..fdd5041da
--- /dev/null
+++ b/launcher_preload.js
@@ -0,0 +1,31 @@
+/* global window */
+
+const { ipcRenderer } = require('electron');
+const url = require('url');
+const i18n = require('./js/modules/i18n');
+
+const userConfig = require('./app/user_config');
+
+const config = url.parse(window.location.toString(), true).query;
+const { locale } = config;
+const localeMessages = ipcRenderer.sendSync('locale-data');
+
+window.theme = config.theme;
+window.i18n = i18n.setup(locale, localeMessages);
+
+// So far we're only using this for Signal.Types
+const Signal = require('./js/modules/signal');
+
+window.Signal = Signal.setup({
+  Attachments: null,
+  userDataPath: null,
+  getRegionCode: () => null,
+});
+
+window.userConfig = userConfig;
+window.getEnvironment = () => config.environment;
+window.getVersion = () => config.version;
+window.getAppInstance = () => config.appInstance;
+
+window.onLogin = (passPhrase) => ipcRenderer.send('launcher_login', passPhrase);
+require('./js/logging');
diff --git a/main.js b/main.js
index 1e794c6da..94a02b58f 100644
--- a/main.js
+++ b/main.js
@@ -420,6 +420,93 @@ function setupAsStandalone() {
   }
 }
 
+let launcherWindow;
+function showLauncher() {
+  if (launcherWindow) {
+    launcherWindow.show();
+    return;
+  }
+
+  const windowOptions = Object.assign(
+    {
+      show: !startInTray, // allow to start minimised in tray
+      width: DEFAULT_WIDTH,
+      height: DEFAULT_HEIGHT,
+      minWidth: MIN_WIDTH,
+      minHeight: MIN_HEIGHT,
+      autoHideMenuBar: false,
+      webPreferences: {
+        nodeIntegration: false,
+        nodeIntegrationInWorker: false,
+        // sandbox: true,
+        preload: path.join(__dirname, 'launcher_preload.js'),
+        nativeWindowOpen: true,
+      },
+      icon: path.join(__dirname, 'images', 'icon_256.png'),
+    },
+    _.pick(windowConfig, [
+      'maximized',
+      'autoHideMenuBar',
+      'width',
+      'height',
+      'x',
+      'y',
+    ])
+  );
+
+  launcherWindow = new BrowserWindow(windowOptions);
+
+  launcherWindow.loadURL(prepareURL([__dirname, 'launcher.html']));
+
+  captureClicks(launcherWindow);
+
+  // Ingested in preload.js via a sendSync call
+  ipc.on('locale-data', event => {
+    // eslint-disable-next-line no-param-reassign
+    event.returnValue = locale.messages;
+  });
+
+  launcherWindow.on('close', e => {
+     // If the application is terminating, just do the default
+     if (
+      config.environment === 'test' ||
+      config.environment === 'test-lib' ||
+      (windowState.shouldQuit())
+    ) {
+      return;
+    }
+
+    // Prevent the shutdown
+    e.preventDefault();
+    launcherWindow.hide();
+
+    // On Mac, or on other platforms when the tray icon is in use, the window
+    // should be only hidden, not closed, when the user clicks the close button
+    if (
+      !windowState.shouldQuit() &&
+      (usingTrayIcon || process.platform === 'darwin')
+    ) {
+      // toggle the visibility of the show/hide tray icon menu entries
+      if (tray) {
+        tray.updateContextMenu();
+      }
+
+      return;
+    }
+
+    launcherWindow.readyForShutdown = true;
+    app.quit();
+  });
+
+  launcherWindow.on('closed', () => {
+    launcherWindow = null;
+  });
+
+  launcherWindow.once('ready-to-show', () => {
+    launcherWindow.show();
+  });
+}
+
 let aboutWindow;
 function showAbout() {
   if (aboutWindow) {
@@ -654,7 +741,21 @@ app.on('ready', async () => {
     key = crypto.randomBytes(32).toString('hex');
     userConfig.set('key', key);
   }
-  await sql.initialize({ configDir: userDataPath, key });
+
+  // If we have a password set then show the launcher
+  // Otherwise show the main window
+  const passHash = userConfig.get('passHash');
+  if (!passHash) {
+    showLauncher();
+  } else {
+    await showMainWindow(key);
+  }
+});
+
+async function showMainWindow(sqlKey) {
+  const userDataPath = await getRealPath(app.getPath('userData'));
+
+  await sql.initialize({ configDir: userDataPath, key: sqlKey });
   await sqlChannels.initialize();
 
   try {
@@ -698,7 +799,7 @@ app.on('ready', async () => {
   }
 
   setupMenu();
-});
+}
 
 function setupMenu(options) {
   const { platform } = process;
diff --git a/package.json b/package.json
index ef51ba443..b37c2b068 100644
--- a/package.json
+++ b/package.json
@@ -224,6 +224,7 @@
       "background.html",
       "about.html",
       "settings.html",
+      "launcher.html",
       "permissions_popup.html",
       "debug_log.html",
       "_locales/**",