wip on using shared ui in android
3
.gitignore
vendored
@ -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/*
|
||||
|
@ -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`<body class="flex flex-col items-center font-sans bg-blue-lightest md:h-screen md:bg-grey-lightest">
|
||||
${header(state, emit)}
|
||||
<a id="hamburger" class="absolute pin-t pin-r z-50" href="#" onclick=${clickPreferences}>
|
||||
<img src=${assets.get('preferences.png')} />
|
||||
</a>
|
||||
${main(state, emit)}
|
||||
</body>`;
|
||||
|
||||
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);
|
||||
|
Before Width: | Height: | Size: 305 KiB |
Before Width: | Height: | Size: 115 KiB |
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 17 KiB |
@ -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;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>Firefox Send</title>
|
||||
<link href="index.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<script src="vendor.js"></script>
|
||||
<script src="android.js"></script>
|
||||
</body>
|
||||
</html>
|
Before Width: | Height: | Size: 5.4 KiB |
@ -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'
|
||||
)}`
|
||||
);
|
||||
|
@ -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);
|
||||
|
@ -174,7 +174,7 @@ module.exports = function(state, emit, archive) {
|
||||
|
||||
module.exports.wip = function(state, emit) {
|
||||
return html`
|
||||
<article class="h-full flex flex-col bg-white z-20">
|
||||
<article class="flex flex-col bg-white z-20 md:h-full">
|
||||
${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`
|
||||
<article class="flex flex-col items-center justify-center border border-dashed border-blue-light px-6 py-16 h-full">
|
||||
<article class="flex flex-col items-center justify-center border border-dashed border-blue-light px-6 py-16 md:h-full">
|
||||
<img src="${assets.get('addfiles.svg')}" width="48" height="48"/>
|
||||
<div class="pt-6 pb-2 text-center text-lg font-bold uppercase tracking-wide">${state.translate(
|
||||
'uploadDropDragMessage'
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
57
build/android_index_plugin.js
Normal file
@ -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`
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>Firefox Send</title>
|
||||
<link href="${files['app.css']}" rel="stylesheet">
|
||||
<script src="${files['vendor.js']}"></script>
|
||||
<script src="${assets['public/locales/en-US/send.ftl']}"></script>
|
||||
<script src="${files['android.js']}"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
.toString()
|
||||
.replace(/\n\s{6}/g, '\n');
|
||||
compilation.assets['index.html'] = {
|
||||
source() {
|
||||
return page;
|
||||
},
|
||||
size() {
|
||||
return page.length;
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AndroidIndexPlugin;
|
@ -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);
|
||||
|
@ -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',
|
||||
|