From 23537546fec0d8148af1aa1ceda0609e346209c8 Mon Sep 17 00:00:00 2001
From: Scott Nonnenberg <scott@signal.org>
Date: Thu, 5 Apr 2018 15:30:40 -0700
Subject: [PATCH] Big refactor: ts/ directory for all typescript, including
 react

Split out test-specific and general utility react components too.

And moved our test/legacy* files for the Style Guide into a styleguide/
subdirectory of test/.

I think we'll be able to live in this directory structure for a while.
---
 .eslintignore                                 |  2 +-
 .gitignore                                    |  2 +-
 Gruntfile.js                                  |  4 +---
 background.html                               |  6 +++++
 package.json                                  |  6 ++---
 styleguide.config.js                          | 17 +++++++++-----
 test/{ => styleguide}/legacy_bridge.js        |  7 +++---
 test/{ => styleguide}/legacy_templates.js     | 19 +++++++++++-----
 .../components}/conversation/Message.md       |  0
 .../components}/conversation/Message.tsx      |  0
 .../components}/conversation/Reply.md         |  0
 .../components}/conversation/Reply.tsx        |  0
 .../components/utility}/BackboneWrapper.md    |  0
 .../components/utility}/BackboneWrapper.tsx   |  2 +-
 .../util => ts/test}/ConversationContext.md   |  0
 .../util => ts/test}/ConversationContext.tsx  |  2 +-
 .../index.ts => ts/test/StyleGuideUtil.ts     | 22 +++++++++----------
 tsconfig.json                                 |  2 +-
 18 files changed, 54 insertions(+), 37 deletions(-)
 rename test/{ => styleguide}/legacy_bridge.js (88%)
 rename test/{ => styleguide}/legacy_templates.js (68%)
 rename {js/react => ts/components}/conversation/Message.md (100%)
 rename {js/react => ts/components}/conversation/Message.tsx (100%)
 rename {js/react => ts/components}/conversation/Reply.md (100%)
 rename {js/react => ts/components}/conversation/Reply.tsx (100%)
 rename {js/react/util => ts/components/utility}/BackboneWrapper.md (100%)
 rename {js/react/util => ts/components/utility}/BackboneWrapper.tsx (98%)
 rename {js/react/util => ts/test}/ConversationContext.md (100%)
 rename {js/react/util => ts/test}/ConversationContext.tsx (92%)
 rename js/react/util/index.ts => ts/test/StyleGuideUtil.ts (67%)

diff --git a/.eslintignore b/.eslintignore
index c810ffb50..c29c5fbb8 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -14,7 +14,7 @@ test/views/*.js
 /*.js
 
 # typescript-generated files
-js/react/**/*.js
+ts/**/*.js
 
 
 # ES2015+ files
diff --git a/.gitignore b/.gitignore
index ac02d8728..c1f9a6d9a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,4 +24,4 @@ test/test.js
 libtextsecure/test/test.js
 
 # React / TypeScript
-js/react/**/*.js
+ts/**/*.js
diff --git a/Gruntfile.js b/Gruntfile.js
index c5f360d08..46abd1ec2 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -107,7 +107,6 @@ module.exports = function(grunt) {
         '!js/logging.js',
         '!js/modules/**/*.js',
         '!js/Mp3LameEncoder.min.js',
-        '!js/react/**/*.js',
         '!js/signal_protocol_store.js',
         '!js/views/conversation_search_view.js',
         '!js/views/debug_log_view.js',
@@ -162,7 +161,6 @@ module.exports = function(grunt) {
         '!js/libtextsecure.js',
         '!js/modules/**/*.js',
         '!js/Mp3LameEncoder.min.js',
-        '!js/react/**/*.js',
         '!js/WebAudioRecorderMp3.js',
         'test/**/*.js',
         '!test/blanket_mocha.js',
@@ -193,7 +191,7 @@ module.exports = function(grunt) {
         tasks: ['jscs']
       },
       transpile: {
-        files: ['./js/react/**/*.js'],
+        files: ['./ts/**/*.js'],
         tasks: ['exec:transpile']
       }
     },
diff --git a/background.html b/background.html
index 930015b70..ac5db582d 100644
--- a/background.html
+++ b/background.html
@@ -20,6 +20,12 @@
   <title>Signal</title>
   <link href='images/icon_128.png' rel='shortcut icon'>
   <link href="stylesheets/manifest.css" rel="stylesheet" type="text/css" />
+
+  <!-- When making changes to these templates, be sure to update these two places:
+    1) test/styleguide/legacy_templates.js
+    2) test/index.html
+  -->
+
   <script type='text/x-tmpl-mustache' id='app-migration-screen'>
     <div class='content'>
       <img src='images/icon_128.png'>
diff --git a/package.json b/package.json
index bf443bfc5..1d4dedc3c 100644
--- a/package.json
+++ b/package.json
@@ -41,15 +41,14 @@
     "test-server": "mocha --recursive test/server",
     "test-server-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/server",
     "eslint": "eslint .",
-    "tslint": "tslint ./js/react/**/*.{ts,tsx}",
+    "tslint": "tslint ts/**/*.{ts,tsx}",
     "transpile": "tsc",
-    "clean-transpile": "rimraf js/react/**/*.js js/react/*.js",
+    "clean-transpile": "rimraf ts/**/*.js ts/*.js",
     "open-coverage": "open coverage/lcov-report/index.html",
     "styleguide": "styleguidist server"
   },
   "dependencies": {
     "@sindresorhus/is": "^0.8.0",
-    "@types/qs": "^6.5.1",
     "archiver": "^2.1.1",
     "blob-util": "^1.3.0",
     "blueimp-canvas-to-blob": "^3.14.0",
@@ -92,6 +91,7 @@
     "websocket": "^1.0.25"
   },
   "devDependencies": {
+    "@types/qs": "^6.5.1",
     "@types/react": "^16.3.1",
     "@types/react-dom": "^16.0.4",
     "arraybuffer-loader": "^1.0.3",
diff --git a/styleguide.config.js b/styleguide.config.js
index 4825bbd42..1c5e0e724 100644
--- a/styleguide.config.js
+++ b/styleguide.config.js
@@ -10,17 +10,22 @@ module.exports = {
     {
       name: 'Conversation',
       description: 'Everything necessary to render a conversation',
-      components: 'js/react/conversation/*.tsx',
+      components: 'ts/components/conversation/*.tsx',
     },
     {
       name: 'Utility',
-      description: 'Utility components only used for testing',
-      components: 'js/react/util/*.tsx',
+      description: 'Utility components used across the application',
+      components: 'ts/components/utility/*.tsx',
+    },
+    {
+      name: 'Test',
+      description: 'Components only used for testing',
+      components: 'ts/test/**/*.tsx',
     },
   ],
   context: {
     // Exposes necessary utilities in the global scope for all readme code snippets
-    util: 'js/react/util',
+    util: 'ts/test/StyleGuideUtil',
   },
   // We don't want one long, single page
   pagePerSection: true,
@@ -42,7 +47,7 @@ module.exports = {
       // Mirrors the order used in background.js.
       scripts: [
         {
-          src: 'test/legacy_bridge.js',
+          src: 'test/styleguide/legacy_bridge.js',
         },
         {
           src: 'node_modules/moment/min/moment-with-locales.min.js',
@@ -123,7 +128,7 @@ module.exports = {
         },
         // Hacky way of including templates for Backbone components
         {
-          src: 'test/legacy_templates.js',
+          src: 'test/styleguide/legacy_templates.js',
         },
       ],
     },
diff --git a/test/legacy_bridge.js b/test/styleguide/legacy_bridge.js
similarity index 88%
rename from test/legacy_bridge.js
rename to test/styleguide/legacy_bridge.js
index 53961f595..8319fbede 100644
--- a/test/legacy_bridge.js
+++ b/test/styleguide/legacy_bridge.js
@@ -1,5 +1,6 @@
+/* global window: false */
 
-// Because we aren't hosting the styleguide in Electron, we can't rely on preload.js
+// Because we aren't hosting the Style Guide in Electron, we can't rely on preload.js
 //   to set things up for us. This gives us the minimum bar shims for everything it
 //   provdes.
 //
@@ -17,14 +18,14 @@ window.Signal.Migrations = {
   getPlaceholderMigrations: () => {},
 };
 
-window.Signal.React = window.Signal.React = {};
+window.Signal.React = {};
 
 window.EmojiConvertor = function EmojiConvertor() {};
 window.EmojiConvertor.prototype.init_colons = () => {};
 window.EmojiConvertor.prototype.signalReplace = html => html;
 window.EmojiConvertor.prototype.replace_unified = string => string;
 window.EmojiConvertor.prototype.img_sets = {
-  apple: {}
+  apple: {},
 };
 
 window.i18n = () => '';
diff --git a/test/legacy_templates.js b/test/styleguide/legacy_templates.js
similarity index 68%
rename from test/legacy_templates.js
rename to test/styleguide/legacy_templates.js
index 90748ffce..090c2c085 100644
--- a/test/legacy_templates.js
+++ b/test/styleguide/legacy_templates.js
@@ -1,20 +1,27 @@
+/* global window: false */
 
 // Taken from background.html.
-// Templates are here solely to support the Backbone views rendered in the styleguide.
+// Templates are here solely to support the Backbone views rendered in the Style Guide.
+
+// Note: Any change here must be reflected in background.html to be reflected in the app
+//   and test/index.html to be reflected in the unit tests.
 
 window.Whisper.View.Templates = {
   hasRetry: `
-    {{ messageNotSent }}
-    <span href='#' class='retry'>{{ resend }}</span>
+    {{ messageNotSent }} <span href='#' class='retry'>{{ resend }}</span>
   `,
   'some-failed': `
     {{ someFailed }}
   `,
   keychange: `
-    <span class='content' dir='auto'><span class='shield icon'></span> {{ content }}</span>
+    <span class='content' dir='auto'>
+      <span class='shield icon'></span> {{ content }}
+    </span>
   `,
   'verified-change': `
-    <span class='content' dir='auto'><span class='{{ icon }} icon'></span> {{ content }}</span>
+    <span class='content' dir='auto'>
+      <span class='{{ icon }} icon'></span> {{ content }}
+    </span>
   `,
   message: `
     {{> avatar }}
@@ -41,5 +48,5 @@ window.Whisper.View.Templates = {
   `,
   expirationTimerUpdate: `
     <span class='content'><span class='icon clock'></span> {{ content }}</span>
-  `
+  `,
 };
diff --git a/js/react/conversation/Message.md b/ts/components/conversation/Message.md
similarity index 100%
rename from js/react/conversation/Message.md
rename to ts/components/conversation/Message.md
diff --git a/js/react/conversation/Message.tsx b/ts/components/conversation/Message.tsx
similarity index 100%
rename from js/react/conversation/Message.tsx
rename to ts/components/conversation/Message.tsx
diff --git a/js/react/conversation/Reply.md b/ts/components/conversation/Reply.md
similarity index 100%
rename from js/react/conversation/Reply.md
rename to ts/components/conversation/Reply.md
diff --git a/js/react/conversation/Reply.tsx b/ts/components/conversation/Reply.tsx
similarity index 100%
rename from js/react/conversation/Reply.tsx
rename to ts/components/conversation/Reply.tsx
diff --git a/js/react/util/BackboneWrapper.md b/ts/components/utility/BackboneWrapper.md
similarity index 100%
rename from js/react/util/BackboneWrapper.md
rename to ts/components/utility/BackboneWrapper.md
diff --git a/js/react/util/BackboneWrapper.tsx b/ts/components/utility/BackboneWrapper.tsx
similarity index 98%
rename from js/react/util/BackboneWrapper.tsx
rename to ts/components/utility/BackboneWrapper.tsx
index 6194d76e6..b66e22685 100644
--- a/js/react/util/BackboneWrapper.tsx
+++ b/ts/components/utility/BackboneWrapper.tsx
@@ -18,7 +18,7 @@ interface BackboneViewConstructor {
 }
 
 /**
- * Allows Backbone Views to be rendered inside of React (primarily for the styleguide)
+ * Allows Backbone Views to be rendered inside of React (primarily for the Style Guide)
  * while we slowly replace the internals of a given Backbone view with React.
  */
 export class BackboneWrapper extends React.Component<Props, {}> {
diff --git a/js/react/util/ConversationContext.md b/ts/test/ConversationContext.md
similarity index 100%
rename from js/react/util/ConversationContext.md
rename to ts/test/ConversationContext.md
diff --git a/js/react/util/ConversationContext.tsx b/ts/test/ConversationContext.tsx
similarity index 92%
rename from js/react/util/ConversationContext.tsx
rename to ts/test/ConversationContext.tsx
index 9c3651840..d05f32e50 100644
--- a/js/react/util/ConversationContext.tsx
+++ b/ts/test/ConversationContext.tsx
@@ -10,7 +10,7 @@ interface Props {
 
 /**
  * Provides the parent elements necessary to allow the main Signal Desktop stylesheet to
- * apply (with no changes) to messages in this context.
+ * apply (with no changes) to messages in the Style Guide.
  */
 export class ConversationContext extends React.Component<Props, {}> {
   public render() {
diff --git a/js/react/util/index.ts b/ts/test/StyleGuideUtil.ts
similarity index 67%
rename from js/react/util/index.ts
rename to ts/test/StyleGuideUtil.ts
index c1a36aa29..c4affea90 100644
--- a/js/react/util/index.ts
+++ b/ts/test/StyleGuideUtil.ts
@@ -5,16 +5,16 @@ import React from 'react';
 import ReactDOM from 'react-dom';
 
 
-// Helper components used in the styleguide, exposed at 'util' in the global scope via the
-//   context option in react-styleguidist.
+// Helper components used in the Style Guide, exposed at 'util' in the global scope via
+//   the 'context' option in react-styleguidist.
 
 export { ConversationContext } from './ConversationContext';
-export { BackboneWrapper } from './BackboneWrapper';
+export { BackboneWrapper } from '../components/utility/BackboneWrapper';
 
 // Here we can make things inside Webpack available to Backbone views like preload.js.
 
-import { Message } from '../conversation/Message';
-import { Reply } from '../conversation/Reply';
+import { Message } from '../components/conversation/Message';
+import { Reply } from '../components/conversation/Reply';
 
 
 // TypeScript wants two things when you import:
@@ -23,13 +23,13 @@ import { Reply } from '../conversation/Reply';
 // Anything else will raise an error, that it can't find the module. And so, we ignore...
 
 // @ts-ignore
-import gif from '../../../fixtures/giphy-GVNvOUpeYmI7e.gif';
+import gif from '../../fixtures/giphy-GVNvOUpeYmI7e.gif';
 // @ts-ignore
-import mp3 from '../../../fixtures/incompetech-com-Agnus-Dei-X.mp3';
+import mp3 from '../../fixtures/incompetech-com-Agnus-Dei-X.mp3';
 // @ts-ignore
-import txt from '../../../fixtures/lorem-ipsum.txt';
+import txt from '../../fixtures/lorem-ipsum.txt';
 // @ts-ignore
-import mp4 from '../../../fixtures/pixabay-Soap-Bubble-7141.mp4';
+import mp4 from '../../fixtures/pixabay-Soap-Bubble-7141.mp4';
 
 export {
   mp3,
@@ -48,10 +48,10 @@ const theme = urlOptions.theme || 'android';
 const locale = urlOptions.locale || 'en';
 
 // @ts-ignore
-import localeMessages from '../../../_locales/en/messages.json';
+import localeMessages from '../../_locales/en/messages.json';
 
 // @ts-ignore
-import { setup } from '../../modules/i18n';
+import { setup } from '../../js/modules/i18n';
 
 const i18n = setup(locale, localeMessages);
 
diff --git a/tsconfig.json b/tsconfig.json
index 8d7c1fe73..37eb7b9c0 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -11,7 +11,7 @@
     // "sourceMap": true,                     /* Generates corresponding '.map' file. */
     // "outFile": "./",                       /* Concatenate and emit output to single file. */
     // "outDir": "./",                        /* Redirect output structure to the directory. */
-    "rootDir": "./js/react",                  /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
+    "rootDir": "./ts",                        /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
     // "removeComments": true,                /* Do not emit comments to output. */
     // "noEmit": true,                        /* Do not emit outputs. */
     // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */