wip on using shared ui in android
|
@ -6,8 +6,7 @@ dist
|
||||||
.nyc_output
|
.nyc_output
|
||||||
.tox
|
.tox
|
||||||
.pytest_cache
|
.pytest_cache
|
||||||
android/app/src/main/assets/vendor.js
|
android/app/src/main/assets
|
||||||
android/app/src/main/assets/android.js
|
|
||||||
ios/send-ios/assets/ios.js
|
ios/send-ios/assets/ios.js
|
||||||
ios/send-ios/assets/vendor.js
|
ios/send-ios/assets/vendor.js
|
||||||
ios/send-ios.xcodeproj/project.xcworkspace/xcuserdata/*
|
ios/send-ios.xcodeproj/project.xcworkspace/xcuserdata/*
|
||||||
|
|
|
@ -20,12 +20,42 @@ window.DEFAULTS = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const choo = require('choo');
|
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();
|
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('./stores/state').default);
|
||||||
app.use(require('../app/fileManager').default);
|
app.use(require('../app/fileManager').default);
|
||||||
app.use(require('./stores/intents').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('/options', require('./pages/options').default);
|
||||||
app.route('/upload', require('./pages/upload').default);
|
app.route('/upload', require('./pages/upload').default);
|
||||||
app.route('/share/:id', require('./pages/share').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 child_process = require('child_process');
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
child_process.execSync('npm run build');
|
child_process.execSync('npm run build');
|
||||||
|
child_process.execSync(
|
||||||
const prefix = path.join('..', '..', 'dist');
|
`cp -R ${path.resolve(__dirname, '../dist')} ${path.resolve(
|
||||||
const json_string = fs.readFileSync(path.join(prefix, 'manifest.json'));
|
__dirname,
|
||||||
const manifest = JSON.parse(json_string);
|
'app/src/main/assets'
|
||||||
|
)}`
|
||||||
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}`)
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,9 +12,6 @@ export default function initialState(state, emitter) {
|
||||||
getAsset(name) {
|
getAsset(name) {
|
||||||
return `${state.prefix}/${name}`;
|
return `${state.prefix}/${name}`;
|
||||||
},
|
},
|
||||||
translate: (...toTranslate) => {
|
|
||||||
return toTranslate.map(o => JSON.stringify(o)).toString();
|
|
||||||
},
|
|
||||||
raven: {
|
raven: {
|
||||||
captureException: e => {
|
captureException: e => {
|
||||||
console.error('ERROR ' + e + ' ' + e.stack);
|
console.error('ERROR ' + e + ' ' + e.stack);
|
||||||
|
|
|
@ -174,7 +174,7 @@ module.exports = function(state, emit, archive) {
|
||||||
|
|
||||||
module.exports.wip = function(state, emit) {
|
module.exports.wip = function(state, emit) {
|
||||||
return html`
|
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(
|
${list(
|
||||||
state.archive.files.map(f => fileInfo(f, remove(f))),
|
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',
|
'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) {
|
module.exports.empty = function(state, emit) {
|
||||||
return html`
|
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"/>
|
<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(
|
<div class="pt-6 pb-2 text-center text-lg font-bold uppercase tracking-wide">${state.translate(
|
||||||
'uploadDropDragMessage'
|
'uploadDropDragMessage'
|
||||||
|
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
@ -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 assets = require('../../common/assets');
|
||||||
const locales = require('../../common/locales');
|
const locales = require('../../common/locales');
|
||||||
const routes = require('../routes');
|
const routes = require('../routes');
|
||||||
|
@ -12,21 +10,6 @@ const config = require('../config');
|
||||||
|
|
||||||
const ID_REGEX = '([0-9a-fA-F]{10})';
|
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) {
|
module.exports = function(app, devServer) {
|
||||||
const wsapp = express();
|
const wsapp = express();
|
||||||
expressWs(wsapp, null, { perMessageDeflate: false });
|
expressWs(wsapp, null, { perMessageDeflate: false });
|
||||||
|
@ -36,6 +19,13 @@ module.exports = function(app, devServer) {
|
||||||
assets.setMiddleware(devServer.middleware);
|
assets.setMiddleware(devServer.middleware);
|
||||||
locales.setMiddleware(devServer.middleware);
|
locales.setMiddleware(devServer.middleware);
|
||||||
app.use(morgan('dev', { stream: process.stderr }));
|
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) {
|
if (process.env.ANDROID) {
|
||||||
// map all html routes to the android index.html
|
// map all html routes to the android index.html
|
||||||
app.get('/', android);
|
app.get('/', android);
|
||||||
|
|
|
@ -3,6 +3,7 @@ const webpack = require('webpack');
|
||||||
const CopyPlugin = require('copy-webpack-plugin');
|
const CopyPlugin = require('copy-webpack-plugin');
|
||||||
const ManifestPlugin = require('webpack-manifest-plugin');
|
const ManifestPlugin = require('webpack-manifest-plugin');
|
||||||
const VersionPlugin = require('./build/version_plugin');
|
const VersionPlugin = require('./build/version_plugin');
|
||||||
|
const AndroidIndexPlugin = require('./build/android_index_plugin');
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
|
||||||
const webJsOptions = {
|
const webJsOptions = {
|
||||||
|
@ -182,11 +183,6 @@ const web = {
|
||||||
{
|
{
|
||||||
context: 'public',
|
context: 'public',
|
||||||
from: '*.*'
|
from: '*.*'
|
||||||
},
|
|
||||||
{
|
|
||||||
context: 'android/app/src/main/assets',
|
|
||||||
from: '*.*',
|
|
||||||
to: 'android_asset'
|
|
||||||
}
|
}
|
||||||
]),
|
]),
|
||||||
new webpack.IgnorePlugin(/\.\.\/dist/), // used in common/*.js
|
new webpack.IgnorePlugin(/\.\.\/dist/), // used in common/*.js
|
||||||
|
@ -196,6 +192,7 @@ const web = {
|
||||||
filename: '[name].[hash:8].css'
|
filename: '[name].[hash:8].css'
|
||||||
}),
|
}),
|
||||||
new VersionPlugin(),
|
new VersionPlugin(),
|
||||||
|
new AndroidIndexPlugin(),
|
||||||
new ManifestPlugin() // used by server side to resolve hashed assets
|
new ManifestPlugin() // used by server side to resolve hashed assets
|
||||||
],
|
],
|
||||||
devtool: 'source-map',
|
devtool: 'source-map',
|
||||||
|
|