diff --git a/android/android.js b/android/android.js index acf848f2..f9675c40 100644 --- a/android/android.js +++ b/android/android.js @@ -19,18 +19,32 @@ window.DEFAULTS = { EXPIRE_SECONDS: 3600 }; -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(); +import choo from 'choo'; +import html from 'choo/html'; +import Raven from 'raven-js'; + +import assets from '../common/assets'; +import header from '../app/ui/header'; +import locale from '../common/locales'; +import storage from '../app/storage'; +import controller from '../app/controller'; +import User from './user'; +import intents from './stores/intents'; +import home from './pages/home'; +import upload from './pages/upload'; +import share from './pages/share'; +import preferences from './pages/preferences'; +import error from './pages/error'; if (navigator.userAgent === 'Send Android') { assets.setPrefix('/android_asset'); } +const app = choo(); +//app.use(state); +app.use(controller); +app.use(intents); + function body(main) { return function(state, emit) { return html` @@ -56,12 +70,14 @@ function body(main) { }; } -app.use(require('./stores/state').default); app.use((state, emitter) => { state.translate = locale.getTranslator(); state.capabilities = { account: true }; //TODO + state.storage = storage; + state.user = new User(storage); + state.raven = Raven; window.finishLogin = async function(accountInfo) { await state.user.finishLogin(accountInfo); @@ -72,14 +88,11 @@ app.use((state, emitter) => { window.appState = state; window.appEmit = emitter.emit.bind(emitter); }); -app.use(require('../app/controller').default); -app.use(require('./stores/intents').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); -app.route('/preferences', require('./pages/preferences').default); -app.route('/error', require('./pages/error').default); +app.route('/upload', upload); +app.route('/share/:id', share); +app.route('/preferences', preferences); +app.route('/error', error); //app.route('/debugging', require('./pages/debugging').default); // add /api/filelist app.mount('body'); diff --git a/android/app/app.iml b/android/app/app.iml index 1fc6f7ac..72864524 100644 --- a/android/app/app.iml +++ b/android/app/app.iml @@ -131,9 +131,7 @@ - - @@ -146,7 +144,6 @@ - diff --git a/android/app/src/main/java/com/mozilla/send/sendandroid/MainActivity.kt b/android/app/src/main/java/com/mozilla/send/sendandroid/MainActivity.kt index d48ccf26..368bfbe7 100644 --- a/android/app/src/main/java/com/mozilla/send/sendandroid/MainActivity.kt +++ b/android/app/src/main/java/com/mozilla/send/sendandroid/MainActivity.kt @@ -47,6 +47,9 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + // https://developers.google.com/web/tools/chrome-devtools/remote-debugging/webviews + WebView.setWebContentsDebuggingEnabled(true); // TODO only dev builds + mWebView = findViewById(R.id.webview) as AdvancedWebView mWebView!!.setListener(this, this) mWebView!!.setWebChromeClient(LoggingWebChromeClient()) @@ -149,7 +152,7 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener { mToCall = "finishLogin(${toPass})" this@MainActivity.runOnUiThread({ // But then we also reload this here because we need to make sure onPageFinished runs after mToCall has been set. - // We can't guarantee that onPageFinished has already been called at this point. + // We can't guarantee that onPageFinished wasn't already called at this point. mWebView!!.loadUrl("file:///android_asset/android.html") }) @@ -181,11 +184,9 @@ class MainActivity : AppCompatActivity(), AdvancedWebView.Listener { if (mToCall != null) { this@MainActivity.runOnUiThread({ mWebView?.evaluateJavascript(mToCall, fun (value: String) { - // noop + mToCall = null }) }) - - mToCall = null } } diff --git a/android/pages/home.js b/android/pages/home.js index f6c83e61..74ec8ed3 100644 --- a/android/pages/home.js +++ b/android/pages/home.js @@ -1,42 +1,60 @@ const html = require('choo/html'); +const { list } = require('../../app/utils'); +const archiveTile = require('../../app/ui/archiveTile'); +const modal = require('../../app/ui/modal'); +const intro = require('../../app/ui/intro'); +const assets = require('../../common/assets'); -export default function mainPage(state, emit) { - function clickPreferences(event) { +module.exports = function(state, emit) { + function onchange(event) { event.preventDefault(); - emit('pushState', '/preferences'); + const newFiles = Array.from(event.target.files); + + emit('addFiles', { files: newFiles }); } - function uploadFile(event) { - event.preventDefault(); - const target = event.target; - const file = target.files[0]; - if (file.size === 0) { - return; - } - - emit('pushState', '/options'); - emit('addFiles', { files: [file] }); + function onclick() { + document.getElementById('file-upload').click(); } - return html` -
-
- - - - - -

Private, Encrypted File Sharing

-
- Send files through a safe, private, and encrypted link that automatically expires to ensure your stuff does not remain online forever. + const archives = state.storage.files + .map(archive => archiveTile(state, emit, archive)) + .reverse(); + + let content = ''; + let button = html` + + `; + if (state.uploading) { + content = archiveTile.uploading(state, emit); + } else if (state.archive) { + content = archiveTile.wip(state, emit); + button = ''; + } else { + content = + archives.length < 1 + ? intro(state) + : list(archives, 'list-reset h-full overflow-y-scroll', 'mb-3'); + } + + return html` +
+ ${state.modal && modal(state, emit)} ${content} +
+ ${button} +
-
-
- - -
-
-`; -} + + `; +}; diff --git a/android/pages/options.js b/android/pages/options.js deleted file mode 100644 index 8491305b..00000000 --- a/android/pages/options.js +++ /dev/null @@ -1,92 +0,0 @@ -/* globals DEFAULTS */ -const html = require('choo/html'); - -export default function options(state, emit) { - function clickCancel(event) { - event.preventDefault(); - emit('pushState', '/'); - } - - async function submitForm(event) { - event.preventDefault(); - if (this.addPassword.checked) { - if (this.password.value !== this.confirmPassword.value) { - state.passwordDoesNotMatchError = true; - emit('render'); - return; - } else { - state.passwordDoesNotMatchError = false; - } - } - state.timeLimit = parseInt(event.target.maxTime); - emit('upload', { - type: 'click', - dlimit: parseInt(event.target.numDownloads.value), - password: event.target.password.value - }); - emit('pushState', '/upload'); - } - - function addPasswordChange(event) { - const pw = document.getElementById('password-section'); - if (event.target.checked) { - pw.style.display = 'block'; - } else { - pw.style.display = 'none'; - } - } - - const passwordDoesNotMatchDisplayStyle = state.passwordDoesNotMatchError - ? 'display: block' - : 'display: none'; - const passwordChecked = state.passwordDoesNotMatchError ? true : false; - - return html` -
-
- - cancel - -
Selected files
-
    -
  • file
  • -
-
-
-
-
Expires after
- - or - -
-
- - -
-
- Passwords must match. -
-
Password:
- -
Confirm password:
- -
-
- -
-
-
-
-`; -} diff --git a/app/ui/archiveTile.js b/app/ui/archiveTile.js index ecbce233..77f92a0b 100644 --- a/app/ui/archiveTile.js +++ b/app/ui/archiveTile.js @@ -189,13 +189,13 @@ module.exports = function(state, emit, archive) { module.exports.wip = function(state, emit) { return html` -
+
${ list( Array.from(state.archive.files) .reverse() .map(f => fileInfo(f, remove(f))), - 'list-reset h-full overflow-y-scroll px-4 bg-blue-lightest md:max-h-half-screen', + 'list-reset overflow-y-scroll px-4 bg-blue-lightest md:h-full md:max-h-half-screen', 'bg-white px-2 mt-3 border border-grey-light rounded' ) } @@ -209,7 +209,7 @@ module.exports.wip = function(state, emit) { />