From 037c79730dc6245ea8058233ba9bda255e6650ce Mon Sep 17 00:00:00 2001 From: Danny Coates Date: Mon, 12 Nov 2018 11:13:31 -0800 Subject: [PATCH] converting some things to choo/component --- .gitignore | 1 + android/android.iml | 11 -- android/android.js | 4 +- android/app/app.iml | 196 ------------------------------- android/app/build.gradle | 3 +- android/app/buildAssets.sh | 7 ++ android/generateAndLinkBundle.js | 10 -- app/main.js | 7 +- app/routes.js | 33 +----- app/ui/account.js | 119 +++++++++++++------ app/ui/body.js | 28 +++++ app/ui/footer.js | 118 +++++++++++-------- app/ui/fxPromo.js | 19 --- app/ui/header.js | 55 +++++---- app/ui/promo.js | 39 ++++++ webpack.config.js | 1 + 16 files changed, 270 insertions(+), 381 deletions(-) delete mode 100644 android/android.iml delete mode 100644 android/app/app.iml create mode 100755 android/app/buildAssets.sh delete mode 100644 android/generateAndLinkBundle.js create mode 100644 app/ui/body.js delete mode 100644 app/ui/fxPromo.js create mode 100644 app/ui/promo.js diff --git a/.gitignore b/.gitignore index 397f0537..00aca6da 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ dist .nyc_output .tox .pytest_cache +*.iml android/app/src/main/assets ios/send-ios/assets/ios.js ios/send-ios/assets/vendor.js diff --git a/android/android.iml b/android/android.iml deleted file mode 100644 index eff6737c..00000000 --- a/android/android.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/android/android.js b/android/android.js index bdefe305..83e21c9c 100644 --- a/android/android.js +++ b/android/android.js @@ -24,7 +24,7 @@ import html from 'choo/html'; import Raven from 'raven-js'; import assets from '../common/assets'; -import header from '../app/ui/header'; +import Header from '../app/ui/header'; import locale from '../common/locales'; import storage from '../app/storage'; import controller from '../app/controller'; @@ -59,7 +59,7 @@ function body(main) { > - ${header(state, emit)} ${main(state, emit)} + ${state.cache(Header, 'header').render()} ${main(state, emit)} `; diff --git a/android/app/app.iml b/android/app/app.iml deleted file mode 100644 index 72864524..00000000 --- a/android/app/app.iml +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index 4f597e68..4b15da97 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -35,8 +35,7 @@ dependencies { } task generateAndLinkBundle(type: Exec, description: 'Generate the android.js bundle and link it into the assets directory') { - commandLine 'node' - args '../generateAndLinkBundle.js' + commandLine './buildAssets.sh' } tasks.withType(JavaCompile) { diff --git a/android/app/buildAssets.sh b/android/app/buildAssets.sh new file mode 100755 index 00000000..07cef6e8 --- /dev/null +++ b/android/app/buildAssets.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +npm run build +rm -rf src/main/assets +mkdir -p src/main/assets +cp -R ../../dist/* src/main/assets +sed -i '' 's/url(/url(\/android_asset/g' src/main/assets/app.*.css \ No newline at end of file diff --git a/android/generateAndLinkBundle.js b/android/generateAndLinkBundle.js deleted file mode 100644 index c646a18b..00000000 --- a/android/generateAndLinkBundle.js +++ /dev/null @@ -1,10 +0,0 @@ -const child_process = require('child_process'); -const path = require('path'); - -child_process.execSync('npm run build'); -child_process.execSync( - `cp -R ${path.resolve(__dirname, '../dist/*')} ${path.resolve( - __dirname, - 'app/src/main/assets' - )}` -); diff --git a/app/main.js b/app/main.js index 37dbd6f5..29966925 100644 --- a/app/main.js +++ b/app/main.js @@ -1,5 +1,7 @@ import 'fast-text-encoding'; // MS Edge support import 'fluent-intl-polyfill'; +import choo from 'choo'; +import nanotiming from 'nanotiming'; import routes from './routes'; import capabilities from './capabilities'; import locale from '../common/locales'; @@ -14,7 +16,10 @@ import './main.css'; import User from './user'; (async function start() { - const app = routes(); + const app = routes(choo()); + if (process.env.NODE_ENV === 'production') { + nanotiming.disabled = true; + } if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) { Raven.config(window.SENTRY_ID, window.RAVEN_CONFIG).install(); } diff --git a/app/routes.js b/app/routes.js index cb616c42..6c64cae8 100644 --- a/app/routes.js +++ b/app/routes.js @@ -1,37 +1,8 @@ const choo = require('choo'); -const html = require('choo/html'); -const nanotiming = require('nanotiming'); const download = require('./ui/download'); -const footer = require('./ui/footer'); -const fxPromo = require('./ui/fxPromo'); -const header = require('./ui/header'); +const body = require('./ui/body'); -nanotiming.disabled = true; - -function banner(state, emit) { - if (state.promo && !state.route.startsWith('/unsupported/')) { - return fxPromo(state, emit); - } -} - -function body(main) { - return function(state, emit) { - const b = html` - ${banner(state, emit)} - ${header(state, emit)} - ${main(state, emit)} - ${footer(state)} - `; - if (state.layout) { - // server side only - return state.layout(state, b); - } - return b; - }; -} - -module.exports = function() { - const app = choo(); +module.exports = function(app = choo()) { app.route('/', body(require('./ui/home'))); app.route('/download/:id', body(download)); app.route('/download/:id/:key', body(download)); diff --git a/app/ui/account.js b/app/ui/account.js index 3e25a0dc..c9f87469 100644 --- a/app/ui/account.js +++ b/app/ui/account.js @@ -1,58 +1,101 @@ const html = require('choo/html'); +const Component = require('choo/component'); -module.exports = function(state, emit) { - if (!state.capabilities.account) { - return null; +class Account extends Component { + constructor(name, state, emit) { + super(name); + this.state = state; + this.emit = emit; + this.enabled = state.capabilities.account; + this.local = state.components[name] = {}; + this.setState(); } - const user = state.user; - if (!user.loggedIn) { - return html``; - } - return html`
- - -
`; - function avatarClick(event) { + avatarClick(event) { event.preventDefault(); const menu = document.getElementById('accountMenu'); menu.classList.toggle('invisible'); menu.focus(); } - function hideMenu(event) { + hideMenu(event) { event.stopPropagation(); const menu = document.getElementById('accountMenu'); menu.classList.add('invisible'); } - function login(event) { + login(event) { event.preventDefault(); - emit('login'); + this.emit('login'); } - function logout(event) { + logout(event) { event.preventDefault(); - emit('logout'); + this.emit('logout'); } -}; + + changed() { + return this.local.loggedIn !== this.state.user.loggedIn; + } + + setState() { + const changed = this.changed(); + if (changed) { + this.local.loggedIn = this.state.user.loggedIn; + } + return changed; + } + + update() { + return this.setState(); + } + + createElement() { + if (!this.enabled) { + return null; + } + const user = this.state.user; + const translate = this.state.translate; + if (!this.local.loggedIn) { + return html` +
+ +
+ `; + } + return html` +
+ + +
+ `; + } +} + +module.exports = Account; diff --git a/app/ui/body.js b/app/ui/body.js new file mode 100644 index 00000000..c208acf9 --- /dev/null +++ b/app/ui/body.js @@ -0,0 +1,28 @@ +const html = require('choo/html'); +const Promo = require('./promo'); +const Header = require('./header'); +const Footer = require('./footer'); + +function banner(state) { + if (state.promo && !state.route.startsWith('/unsupported/')) { + return state.cache(Promo, 'promo').render(); + } +} + +module.exports = function body(main) { + return function(state, emit) { + const b = html` + + ${banner(state, emit)} ${state.cache(Header, 'header').render()} + ${main(state, emit)} ${state.cache(Footer, 'footer').render()} + + `; + if (state.layout) { + // server side only + return state.layout(state, b); + } + return b; + }; +}; diff --git a/app/ui/footer.js b/app/ui/footer.js index 913b88bc..f5933eb1 100644 --- a/app/ui/footer.js +++ b/app/ui/footer.js @@ -1,52 +1,74 @@ const html = require('choo/html'); +const Component = require('choo/component'); const version = require('../../package.json').version; const { browserName } = require('../utils'); -module.exports = function(state) { - const browser = browserName(); - const feedbackUrl = `https://qsurvey.mozilla.com/s3/txp-firefox-send?ver=${version}&browser=${browser}`; - const footer = html``; - // HACK - // We only want to render this once because we - // toggle the targets of the links with utils/openLinksInNewTab - footer.isSameNode = function(target) { - return target && target.nodeName && target.nodeName === 'FOOTER'; - }; - return footer; -}; +class Footer extends Component { + constructor(name, state) { + super(name); + this.state = state; + } + + update() { + return false; + } + + createElement() { + const translate = this.state.translate; + const browser = browserName(); + const feedbackUrl = `https://qsurvey.mozilla.com/s3/txp-firefox-send?ver=${version}&browser=${browser}`; + return html` + + `; + } +} + +module.exports = Footer; diff --git a/app/ui/fxPromo.js b/app/ui/fxPromo.js deleted file mode 100644 index b791f291..00000000 --- a/app/ui/fxPromo.js +++ /dev/null @@ -1,19 +0,0 @@ -const html = require('choo/html'); -const assets = require('../../common/assets'); - -module.exports = function() { - return html` -
-
- Firefox - Send is brought to you by the all-new Firefox. - Download Firefox now ≫ - -
-
`; -}; diff --git a/app/ui/header.js b/app/ui/header.js index 9deac68f..768c5d51 100644 --- a/app/ui/header.js +++ b/app/ui/header.js @@ -1,25 +1,34 @@ const html = require('choo/html'); -const account = require('./account'); +const Component = require('choo/component'); +const Account = require('./account'); -module.exports = function(state, emit) { - const header = html` -
- - ${account(state, emit)} - -
`; - // HACK - // We only want to render this once because we - // toggle the targets of the links with utils/openLinksInNewTab - // header.isSameNode = function(target) { - // return target && target.nodeName && target.nodeName === 'HEADER'; - // }; - return header; -}; +class Header extends Component { + constructor(name, state, emit) { + super(name); + this.state = state; + this.emit = emit; + this.account = state.cache(Account, 'account'); + } + + update() { + this.account.render(); + return false; + } + + createElement() { + return html` +
+ + ${this.account.render()} +
+ `; + } +} + +module.exports = Header; diff --git a/app/ui/promo.js b/app/ui/promo.js new file mode 100644 index 00000000..de9d5fc6 --- /dev/null +++ b/app/ui/promo.js @@ -0,0 +1,39 @@ +const html = require('choo/html'); +const Component = require('choo/component'); +const assets = require('../../common/assets'); + +class Promo extends Component { + constructor(name) { + super(name); + } + + update() { + return false; + } + + createElement() { + return html` +
+
+ Firefox + Send is brought to you by the all-new Firefox. + Download Firefox now ≫ + +
+
+ `; + } +} + +module.exports = Promo; diff --git a/webpack.config.js b/webpack.config.js index 7dd10331..d1cd2011 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -185,6 +185,7 @@ const web = { from: '*.*' } ]), + new webpack.EnvironmentPlugin(['NODE_ENV']), new webpack.IgnorePlugin(/\.\.\/dist/), // used in common/*.js new webpack.IgnorePlugin(/require-from-string/), // used in common/locales.js new webpack.HashedModuleIdsPlugin(),