diff --git a/.gitignore b/.gitignore index 67cfd3f8..397f0537 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,7 @@ dist .nyc_output .tox .pytest_cache -android/app/src/main/assets/vendor.js -android/app/src/main/assets/android.js +android/app/src/main/assets ios/send-ios/assets/ios.js ios/send-ios/assets/vendor.js ios/send-ios.xcodeproj/project.xcworkspace/xcuserdata/* diff --git a/android/android.js b/android/android.js index a19dd05e..4fc7c85e 100644 --- a/android/android.js +++ b/android/android.js @@ -20,12 +20,42 @@ window.DEFAULTS = { }; const choo = require('choo'); +const html = require('choo/html'); +const assets = require('../common/assets'); +const header = require('../app/ui/header'); +const locale = require('../common/locales'); +const home = require('../app/ui/home'); const app = choo(); +function body(main) { + return function(state, emit) { + return html` + ${header(state, emit)} + + + + ${main(state, emit)} + `; + + function clickPreferences(event) { + event.preventDefault(); + emit('pushState', '/preferences'); + } + }; +} + +app.use((state, emitter) => { + state.translate = locale.getTranslator(); + state.capabilities = {}; //TODO + + // for debugging + window.appState = state; + window.appEmit = emitter.emit.bind(emitter); +}); app.use(require('./stores/state').default); app.use(require('../app/fileManager').default); app.use(require('./stores/intents').default); -app.route('/', require('./pages/home').default); +app.route('/', body(home)); app.route('/options', require('./pages/options').default); app.route('/upload', require('./pages/upload').default); app.route('/share/:id', require('./pages/share').default); diff --git a/android/app/src/main/assets/background_1.jpg b/android/app/src/main/assets/background_1.jpg deleted file mode 100644 index c92d3fb1..00000000 Binary files a/android/app/src/main/assets/background_1.jpg and /dev/null differ diff --git a/android/app/src/main/assets/cloud-upload.png b/android/app/src/main/assets/cloud-upload.png deleted file mode 100644 index 1667ca78..00000000 Binary files a/android/app/src/main/assets/cloud-upload.png and /dev/null differ diff --git a/android/app/src/main/assets/copy-link.png b/android/app/src/main/assets/copy-link.png deleted file mode 100644 index 31ad553d..00000000 Binary files a/android/app/src/main/assets/copy-link.png and /dev/null differ diff --git a/android/app/src/main/assets/encrypted-envelope.png b/android/app/src/main/assets/encrypted-envelope.png deleted file mode 100644 index 94073533..00000000 Binary files a/android/app/src/main/assets/encrypted-envelope.png and /dev/null differ diff --git a/android/app/src/main/assets/index.css b/android/app/src/main/assets/index.css deleted file mode 100644 index c1e37fad..00000000 --- a/android/app/src/main/assets/index.css +++ /dev/null @@ -1,124 +0,0 @@ -html { - height: 100vh; -} - -body { - box-sizing: border-box; - margin: 0; - min-height: 100vh; - background-image: repeating-linear-gradient( - 45deg, - white, - white 5px, - #ea000e 5px, - #ea000e 25px, - white 25px, - white 30px, - #0083ff 30px, - #0083ff 50px - ); -} - -#white { - display: flex; - flex-direction: column; - min-height: 100vh; - background-color: white; - margin: 0 10px; - padding: 10px; - text-align: center; -} - -#centering { - flex: 1; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - height: 100%; - width: 100%; -} - -#label { - position: fixed; - right: 2em; - bottom: 1em; -} - -#label img { - height: 60px; - width: 60px; -} - -#input { - display: none; -} - -#url { - display: none; -} - -#copy-link { - text-align: right; -} - -#copy-image { - position: relative; - top: 6px; - height: 30px; - width: 30px; -} - -.spacer { - height: 12em; -} - -#send-another { - margin-bottom: 1em; - height: 60px; - width: 60px; - position: fixed; - right: 2em; - bottom: 1em; -} - -.card { - margin: 6px; - padding: 6px; - border: 1px solid white; - border-radius: 5px; - box-shadow: 5px 5px 5px 5px #d5d5d5; - text-align: left; -} - -.progress { - display: inline-block; - height: 4px; - border-radius: 2px; - background-color: #1b96ef; - color: white; -} - -.cancel { - text-align: right; -} - -#preferences { - text-align: left; -} - -#hamburger { - position: fixed; - right: 2em; - top: 1em; -} - -#top-banner { - position: fixed; - top: 1em; - left: 2em; -} - -#options { - text-align: left; -} diff --git a/android/app/src/main/assets/index.html b/android/app/src/main/assets/index.html deleted file mode 100644 index 404ff156..00000000 --- a/android/app/src/main/assets/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - Firefox Send - - - - - - - diff --git a/android/app/src/main/assets/top-banner.png b/android/app/src/main/assets/top-banner.png deleted file mode 100644 index 42ef25df..00000000 Binary files a/android/app/src/main/assets/top-banner.png and /dev/null differ diff --git a/android/generateAndLinkBundle.js b/android/generateAndLinkBundle.js index 4c453e45..8cdde2f1 100644 --- a/android/generateAndLinkBundle.js +++ b/android/generateAndLinkBundle.js @@ -1,21 +1,10 @@ const child_process = require('child_process'); -const fs = require('fs'); const path = require('path'); child_process.execSync('npm run build'); - -const prefix = path.join('..', '..', 'dist'); -const json_string = fs.readFileSync(path.join(prefix, 'manifest.json')); -const manifest = JSON.parse(json_string); - -const android_filename = manifest['android.js']; -fs.writeFileSync( - 'src/main/assets/android.js', - fs.readFileSync(`${prefix}${android_filename}`) -); - -const vendor_filename = manifest['vendor.js']; -fs.writeFileSync( - 'src/main/assets/vendor.js', - fs.readFileSync(`${prefix}${vendor_filename}`) +child_process.execSync( + `cp -R ${path.resolve(__dirname, '../dist')} ${path.resolve( + __dirname, + 'app/src/main/assets' + )}` ); diff --git a/android/stores/state.js b/android/stores/state.js index 469fd6cc..ffb8ae3f 100644 --- a/android/stores/state.js +++ b/android/stores/state.js @@ -12,9 +12,6 @@ export default function initialState(state, emitter) { getAsset(name) { return `${state.prefix}/${name}`; }, - translate: (...toTranslate) => { - return toTranslate.map(o => JSON.stringify(o)).toString(); - }, raven: { captureException: e => { console.error('ERROR ' + e + ' ' + e.stack); diff --git a/app/ui/archiveTile.js b/app/ui/archiveTile.js index 4b401a39..cd63155c 100644 --- a/app/ui/archiveTile.js +++ b/app/ui/archiveTile.js @@ -174,7 +174,7 @@ module.exports = function(state, emit, archive) { module.exports.wip = function(state, emit) { return html` -
+
${list( state.archive.files.map(f => fileInfo(f, remove(f))), 'list-reset h-full overflow-y-scroll p-4 bg-blue-lightest md:max-h-half-screen', @@ -280,7 +280,7 @@ module.exports.uploading = function(state, emit) { module.exports.empty = function(state, emit) { return html` -
+
${state.translate( 'uploadDropDragMessage' diff --git a/android/app/src/main/assets/preferences.png b/assets/preferences.png similarity index 100% rename from android/app/src/main/assets/preferences.png rename to assets/preferences.png diff --git a/build/android_index_plugin.js b/build/android_index_plugin.js new file mode 100644 index 00000000..7250ae6d --- /dev/null +++ b/build/android_index_plugin.js @@ -0,0 +1,57 @@ +const path = require('path'); +const html = require('choo/html'); +const NAME = 'AndroidIndexPlugin'; + +function chunkFileNames(compilation) { + const names = {}; + for (const chunk of compilation.chunks) { + for (const file of chunk.files) { + if (!/\.map$/.test(file)) { + names[`${chunk.name}${path.extname(file)}`] = file; + } + } + } + return names; +} +class AndroidIndexPlugin { + apply(compiler) { + const assets = {}; + compiler.hooks.compilation.tap(NAME, compilation => { + compilation.hooks.moduleAsset.tap(NAME, (mod, file) => { + if (mod.userRequest) { + assets[ + path.join(path.dirname(file), path.basename(mod.userRequest)) + ] = file; + } + }); + }); + compiler.hooks.emit.tap(NAME, compilation => { + const files = chunkFileNames(compilation); + const page = html` + + + Firefox Send + + + + + + + + + ` + .toString() + .replace(/\n\s{6}/g, '\n'); + compilation.assets['index.html'] = { + source() { + return page; + }, + size() { + return page.length; + } + }; + }); + } +} + +module.exports = AndroidIndexPlugin; diff --git a/server/bin/dev.js b/server/bin/dev.js index d13a54b4..b4ea500b 100644 --- a/server/bin/dev.js +++ b/server/bin/dev.js @@ -1,5 +1,3 @@ -const fs = require('fs'); -const path = require('path'); const assets = require('../../common/assets'); const locales = require('../../common/locales'); const routes = require('../routes'); @@ -12,21 +10,6 @@ const config = require('../config'); const ID_REGEX = '([0-9a-fA-F]{10})'; -const androidIndex = fs.readFileSync( - path.resolve(__dirname, '../../android/app/src/main/assets/index.html'), - 'utf8' -); - -function android(req, res) { - res.set('Content-Type', 'text/html'); - res.send( - androidIndex - .replace('index.css', '/android_asset/index.css') - .replace('vendor.js', assets.get('vendor.js')) - .replace('android.js', assets.get('android.js')) - ); -} - module.exports = function(app, devServer) { const wsapp = express(); expressWs(wsapp, null, { perMessageDeflate: false }); @@ -36,6 +19,13 @@ module.exports = function(app, devServer) { assets.setMiddleware(devServer.middleware); locales.setMiddleware(devServer.middleware); app.use(morgan('dev', { stream: process.stderr })); + function android(req, res) { + const index = devServer.middleware.fileSystem.readFileSync( + devServer.middleware.getFilenameFromUrl('/index.html') + ); + res.set('Content-Type', 'text/html'); + res.send(index); + } if (process.env.ANDROID) { // map all html routes to the android index.html app.get('/', android); diff --git a/webpack.config.js b/webpack.config.js index ee40528a..7dd10331 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -3,6 +3,7 @@ const webpack = require('webpack'); const CopyPlugin = require('copy-webpack-plugin'); const ManifestPlugin = require('webpack-manifest-plugin'); const VersionPlugin = require('./build/version_plugin'); +const AndroidIndexPlugin = require('./build/android_index_plugin'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const webJsOptions = { @@ -182,11 +183,6 @@ const web = { { context: 'public', from: '*.*' - }, - { - context: 'android/app/src/main/assets', - from: '*.*', - to: 'android_asset' } ]), new webpack.IgnorePlugin(/\.\.\/dist/), // used in common/*.js @@ -196,6 +192,7 @@ const web = { filename: '[name].[hash:8].css' }), new VersionPlugin(), + new AndroidIndexPlugin(), new ManifestPlugin() // used by server side to resolve hashed assets ], devtool: 'source-map',