mirror of
https://gitlab.com/timvisee/send.git
synced 2025-12-08 15:10:54 +03:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2807b1cad5 | ||
|
|
157e832c95 | ||
|
|
d78fcd3721 | ||
|
|
ac7ab79aef | ||
|
|
00fb353465 | ||
|
|
f0ec5a9496 | ||
|
|
7a31082da1 | ||
|
|
b54f4575ee | ||
|
|
490a1e88eb | ||
|
|
2f8a3c9904 | ||
|
|
e7fdf76120 | ||
|
|
d0d41b743a | ||
|
|
a2995411d6 | ||
|
|
3246c4a621 | ||
|
|
48faf929a4 | ||
|
|
b7f922a999 | ||
|
|
bfcdf9340d | ||
|
|
4ed515f5a3 | ||
|
|
84b2737ffb | ||
|
|
deabca5a94 | ||
|
|
e9a49e23e8 |
@@ -1,6 +1,28 @@
|
|||||||
import hash from 'string-hash';
|
import hash from 'string-hash';
|
||||||
|
|
||||||
const experiments = {};
|
const experiments = {
|
||||||
|
'SyI-hI7gT9agiH-f3f0BYg': {
|
||||||
|
id: 'SyI-hI7gT9agiH-f3f0BYg',
|
||||||
|
run: function(variant, state, emitter) {
|
||||||
|
state.promo = variant === 1 ? 'body' : 'header';
|
||||||
|
emitter.emit('render');
|
||||||
|
},
|
||||||
|
eligible: function() {
|
||||||
|
return (
|
||||||
|
!/firefox/i.test(navigator.userAgent) &&
|
||||||
|
document.querySelector('html').lang === 'en-US'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
variant: function(state) {
|
||||||
|
return this.luckyNumber(state) > 0.5 ? 1 : 0;
|
||||||
|
},
|
||||||
|
luckyNumber: function(state) {
|
||||||
|
return luckyNumber(
|
||||||
|
`${this.id}:${state.storage.get('testpilot_ga__cid')}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//Returns a number between 0 and 1
|
//Returns a number between 0 and 1
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
@@ -32,12 +54,12 @@ export default function initialize(state, emitter) {
|
|||||||
checkExperiments(state, emitter);
|
checkExperiments(state, emitter);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const enrolled = state.storage.enrolled;
|
const enrolled = state.storage.enrolled.filter(([id, variant]) => {
|
||||||
enrolled.forEach(([id, variant]) => {
|
|
||||||
const xp = experiments[id];
|
const xp = experiments[id];
|
||||||
if (xp) {
|
if (xp) {
|
||||||
xp.run(variant, state, emitter);
|
xp.run(variant, state, emitter);
|
||||||
}
|
}
|
||||||
|
return !!xp;
|
||||||
});
|
});
|
||||||
// single experiment per session for now
|
// single experiment per session for now
|
||||||
if (enrolled.length === 0) {
|
if (enrolled.length === 0) {
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ export default class FileReceiver extends Nanobus {
|
|||||||
});
|
});
|
||||||
if (file.pwd) {
|
if (file.pwd) {
|
||||||
const encoder = new TextEncoder();
|
const encoder = new TextEncoder();
|
||||||
console.log(file.password + file.url);
|
|
||||||
this.authKeyPromise = window.crypto.subtle
|
this.authKeyPromise = window.crypto.subtle
|
||||||
.importKey(
|
.importKey(
|
||||||
'raw',
|
'raw',
|
||||||
|
|||||||
@@ -47,4 +47,4 @@ app.use(fileManager);
|
|||||||
app.use(dragManager);
|
app.use(dragManager);
|
||||||
app.use(experiments);
|
app.use(experiments);
|
||||||
|
|
||||||
app.mount('#page-one');
|
app.mount('body');
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ let experiment = null;
|
|||||||
export default function initialize(state, emitter) {
|
export default function initialize(state, emitter) {
|
||||||
appState = state;
|
appState = state;
|
||||||
emitter.on('DOMContentLoaded', () => {
|
emitter.on('DOMContentLoaded', () => {
|
||||||
addExitHandlers();
|
// addExitHandlers();
|
||||||
experiment = storage.enrolled[0];
|
experiment = storage.enrolled[0];
|
||||||
sendEvent(category(), 'visit', {
|
sendEvent(category(), 'visit', {
|
||||||
cm5: storage.totalUploads,
|
cm5: storage.totalUploads,
|
||||||
@@ -29,6 +29,9 @@ export default function initialize(state, emitter) {
|
|||||||
});
|
});
|
||||||
//TODO restart handlers... somewhere
|
//TODO restart handlers... somewhere
|
||||||
});
|
});
|
||||||
|
emitter.on('exit', evt => {
|
||||||
|
exitEvent(evt);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function category() {
|
function category() {
|
||||||
@@ -81,6 +84,8 @@ function urlToMetric(url) {
|
|||||||
case 'https://testpilot.firefox.com/':
|
case 'https://testpilot.firefox.com/':
|
||||||
case 'https://testpilot.firefox.com/experiments/send':
|
case 'https://testpilot.firefox.com/experiments/send':
|
||||||
return 'testpilot';
|
return 'testpilot';
|
||||||
|
case 'https://www.mozilla.org/firefox/new/?utm_campaign=send-acquisition&utm_medium=referral&utm_source=send.firefox.com':
|
||||||
|
return 'promo';
|
||||||
default:
|
default:
|
||||||
return 'other';
|
return 'other';
|
||||||
}
|
}
|
||||||
@@ -244,6 +249,7 @@ function exitEvent(target) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
function addExitHandlers() {
|
function addExitHandlers() {
|
||||||
const links = Array.from(document.querySelectorAll('a'));
|
const links = Array.from(document.querySelectorAll('a'));
|
||||||
links.forEach(l => {
|
links.forEach(l => {
|
||||||
|
|||||||
@@ -1,17 +1,43 @@
|
|||||||
const choo = require('choo');
|
const choo = require('choo');
|
||||||
|
const html = require('choo/html');
|
||||||
const download = require('./download');
|
const download = require('./download');
|
||||||
|
const header = require('../templates/header');
|
||||||
|
const footer = require('../templates/footer');
|
||||||
|
const fxPromo = require('../templates/fxPromo');
|
||||||
|
|
||||||
const app = choo();
|
const app = choo();
|
||||||
|
|
||||||
app.route('/', require('./home'));
|
function body(template) {
|
||||||
app.route('/share/:id', require('../templates/share'));
|
return function(state, emit) {
|
||||||
app.route('/download/:id', download);
|
const b = html`<body>
|
||||||
app.route('/download/:id/:key', download);
|
${state.promo === 'header' ? fxPromo(state, emit) : ''}
|
||||||
app.route('/completed', require('../templates/completed'));
|
${header(state)}
|
||||||
app.route('/unsupported/:reason', require('../templates/unsupported'));
|
<div class="all">
|
||||||
app.route('/legal', require('../templates/legal'));
|
<noscript>
|
||||||
app.route('/error', require('../templates/error'));
|
<h2>Firefox Send requires JavaScript</h2>
|
||||||
app.route('/blank', require('../templates/blank'));
|
<p><a href="https://github.com/mozilla/send/blob/master/docs/faq.md#why-does-firefox-send-require-javascript">Why does Firefox Send require JavaScript?</a></p>
|
||||||
app.route('*', require('../templates/notFound'));
|
<p>Please enable JavaScript and try again.</p>
|
||||||
|
</noscript>
|
||||||
|
${template(state, emit)}
|
||||||
|
</div>
|
||||||
|
${footer(state)}
|
||||||
|
</body>`;
|
||||||
|
if (state.layout) {
|
||||||
|
return state.layout(state, b);
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
app.route('/', body(require('./home')));
|
||||||
|
app.route('/share/:id', body(require('../templates/share')));
|
||||||
|
app.route('/download/:id', body(download));
|
||||||
|
app.route('/download/:id/:key', body(download));
|
||||||
|
app.route('/completed', body(require('../templates/completed')));
|
||||||
|
app.route('/unsupported/:reason', body(require('../templates/unsupported')));
|
||||||
|
app.route('/legal', body(require('../templates/legal')));
|
||||||
|
app.route('/error', body(require('../templates/error')));
|
||||||
|
app.route('/blank', body(require('../templates/blank')));
|
||||||
|
app.route('*', body(require('../templates/notFound')));
|
||||||
|
|
||||||
module.exports = app;
|
module.exports = app;
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
|
|
||||||
module.exports = function(state) {
|
module.exports = function() {
|
||||||
const div = html`<div id="page-one"></div>`;
|
const div = html`<div id="page-one"></div>`;
|
||||||
if (state.layout) {
|
|
||||||
return state.layout(state, div);
|
|
||||||
}
|
|
||||||
return div;
|
return div;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
const progress = require('./progress');
|
const progress = require('./progress');
|
||||||
const { fadeOut } = require('../utils');
|
const { fadeOut } = require('../utils');
|
||||||
|
const fxPromo = require('./fxPromo');
|
||||||
|
|
||||||
module.exports = function(state, emit) {
|
module.exports = function(state, emit) {
|
||||||
const div = html`
|
const div = html`
|
||||||
|
<div id="page-one">
|
||||||
<div id="download" class="fadeIn">
|
<div id="download" class="fadeIn">
|
||||||
<div id="download-progress">
|
<div id="download-progress">
|
||||||
<div id="dl-title" class="title">${state.translate(
|
<div id="dl-title" class="title">${state.translate(
|
||||||
@@ -15,9 +17,11 @@ module.exports = function(state, emit) {
|
|||||||
<div class="progress-text"></div>
|
<div class="progress-text"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a class="send-new" data-state="completed" href="/" onclick=${sendNew}>${state.translate(
|
<a class="send-new" data-state="completed" href="/" onclick=${
|
||||||
'sendYourFilesLink'
|
sendNew
|
||||||
)}</a>
|
}>${state.translate('sendYourFilesLink')}</a>
|
||||||
|
</div>
|
||||||
|
${state.promo === 'body' ? fxPromo(state, emit) : ''}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
const progress = require('./progress');
|
const progress = require('./progress');
|
||||||
const { bytes } = require('../utils');
|
const { bytes } = require('../utils');
|
||||||
|
const fxPromo = require('./fxPromo');
|
||||||
|
|
||||||
module.exports = function(state) {
|
module.exports = function(state, emit) {
|
||||||
const transfer = state.transfer;
|
const transfer = state.transfer;
|
||||||
const div = html`
|
const div = html`
|
||||||
|
<div id="page-one">
|
||||||
<div id="download-progress" class="fadeIn">
|
<div id="download-progress" class="fadeIn">
|
||||||
<div id="dl-title" class="title">${state.translate(
|
<div id="dl-title" class="title">${state.translate(
|
||||||
'downloadingPageProgress',
|
'downloadingPageProgress',
|
||||||
@@ -22,6 +24,8 @@ module.exports = function(state) {
|
|||||||
)}</div>
|
)}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
${state.promo === 'body' ? fxPromo(state, emit) : ''}
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return div;
|
return div;
|
||||||
|
|||||||
31
app/templates/footer.js
Normal file
31
app/templates/footer.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
const html = require('choo/html');
|
||||||
|
const assets = require('../../common/assets');
|
||||||
|
|
||||||
|
module.exports = function(state) {
|
||||||
|
return html`<div class="footer">
|
||||||
|
<div class="legal-links">
|
||||||
|
<a href="https://www.mozilla.org" role="presentation"><img class="mozilla-logo" src="${assets.get(
|
||||||
|
'mozilla-logo.svg'
|
||||||
|
)}" alt="mozilla"/></a>
|
||||||
|
<a href="https://www.mozilla.org/about/legal">${state.translate(
|
||||||
|
'footerLinkLegal'
|
||||||
|
)}</a>
|
||||||
|
<a href="https://testpilot.firefox.com/about">${state.translate(
|
||||||
|
'footerLinkAbout'
|
||||||
|
)}</a>
|
||||||
|
<a href="/legal">${state.translate('footerLinkPrivacy')}</a>
|
||||||
|
<a href="/legal">${state.translate('footerLinkTerms')}</a>
|
||||||
|
<a href="https://www.mozilla.org/privacy/websites/#cookies">${state.translate(
|
||||||
|
'footerLinkCookies'
|
||||||
|
)}</a>
|
||||||
|
</div>
|
||||||
|
<div class="social-links">
|
||||||
|
<a href="https://github.com/mozilla/send" role="presentation"><img class="github" src="${assets.get(
|
||||||
|
'github-icon.svg'
|
||||||
|
)}" alt="github"/></a>
|
||||||
|
<a href="https://twitter.com/FxTestPilot" role="presentation"><img class="twitter" src="${assets.get(
|
||||||
|
'twitter-icon.svg'
|
||||||
|
)}" alt="twitter"/></a>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
};
|
||||||
44
app/templates/fxPromo.js
Normal file
44
app/templates/fxPromo.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
const html = require('choo/html');
|
||||||
|
const assets = require('../../common/assets');
|
||||||
|
|
||||||
|
// function replaceLinks(str, urls) {
|
||||||
|
// let i = -1;
|
||||||
|
// const s = str.replace(/<a>([^<]+)<\/a>/g, (m, v) => {
|
||||||
|
// i++;
|
||||||
|
// return `<a class="link" href="${urls[i]}">${v}</a>`;
|
||||||
|
// });
|
||||||
|
// return [`<span>${s}</span>`];
|
||||||
|
// }
|
||||||
|
|
||||||
|
module.exports = function(state, emit) {
|
||||||
|
// function close() {
|
||||||
|
// document.querySelector('.banner').remove();
|
||||||
|
// }
|
||||||
|
|
||||||
|
function clicked(evt) {
|
||||||
|
emit('exit', evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="banner">
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
src="${assets.get('firefox_logo-only.svg')}"
|
||||||
|
class="firefox-logo-small"
|
||||||
|
alt="Firefox"/>
|
||||||
|
<span>Send is brought to you by the all-new Firefox.
|
||||||
|
<a
|
||||||
|
class="link"
|
||||||
|
href="https://www.mozilla.org/firefox/new/?utm_campaign=send-acquisition&utm_medium=referral&utm_source=send.firefox.com"
|
||||||
|
onclick=${clicked}
|
||||||
|
>Download Firefox now ≫</a></span>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
<img
|
||||||
|
src="${assets.get('close-16.svg')}"
|
||||||
|
class="icon-delete"
|
||||||
|
onclick=${close}>
|
||||||
|
*/
|
||||||
21
app/templates/header.js
Normal file
21
app/templates/header.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
const html = require('choo/html');
|
||||||
|
const assets = require('../../common/assets');
|
||||||
|
|
||||||
|
module.exports = function(state) {
|
||||||
|
return html`<header class="header">
|
||||||
|
<div class="send-logo">
|
||||||
|
<a href="/">
|
||||||
|
<img src="${assets.get(
|
||||||
|
'send_logo.svg'
|
||||||
|
)}" alt="Send"/><h1 class="site-title">Send</h1>
|
||||||
|
</a>
|
||||||
|
<div class="site-subtitle">
|
||||||
|
<a href="https://testpilot.firefox.com">Firefox Test Pilot</a>
|
||||||
|
<div>${state.translate('siteSubtitle')}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="https://qsurvey.mozilla.com/s3/txp-firefox-send" rel="noreferrer noopener" class="feedback" target="_blank">${state.translate(
|
||||||
|
'siteFeedback'
|
||||||
|
)}</a>
|
||||||
|
</header>`;
|
||||||
|
};
|
||||||
@@ -30,9 +30,5 @@ module.exports = function(state) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
if (state.layout) {
|
|
||||||
return state.layout(state, div);
|
|
||||||
}
|
|
||||||
return div;
|
return div;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,9 +17,5 @@ module.exports = function(state) {
|
|||||||
)}</a>
|
)}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
if (state.layout) {
|
|
||||||
return state.layout(state, div);
|
|
||||||
}
|
|
||||||
return div;
|
return div;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const assets = require('../../common/assets');
|
|||||||
const notFound = require('./notFound');
|
const notFound = require('./notFound');
|
||||||
const downloadPassword = require('./downloadPassword');
|
const downloadPassword = require('./downloadPassword');
|
||||||
const { bytes } = require('../utils');
|
const { bytes } = require('../utils');
|
||||||
|
const fxPromo = require('./fxPromo');
|
||||||
|
|
||||||
function getFileFromDOM() {
|
function getFileFromDOM() {
|
||||||
const el = document.getElementById('dl-file');
|
const el = document.getElementById('dl-file');
|
||||||
@@ -61,6 +62,7 @@ module.exports = function(state, emit) {
|
|||||||
</div>
|
</div>
|
||||||
<a class="send-new" href="/">${state.translate('sendYourFilesLink')}</a>
|
<a class="send-new" href="/">${state.translate('sendYourFilesLink')}</a>
|
||||||
</div>
|
</div>
|
||||||
|
${state.promo === 'body' ? fxPromo(state, emit) : ''}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -68,9 +70,5 @@ module.exports = function(state, emit) {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
emit('download', fileInfo);
|
emit('download', fileInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.layout) {
|
|
||||||
return state.layout(state, div);
|
|
||||||
}
|
|
||||||
return div;
|
return div;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,10 +10,18 @@ module.exports = function(progressRatio) {
|
|||||||
const percent = Math.floor(progressRatio * 100);
|
const percent = Math.floor(progressRatio * 100);
|
||||||
const div = html`
|
const div = html`
|
||||||
<div class="progress-bar">
|
<div class="progress-bar">
|
||||||
<svg id="progress" width="${oDiameter}" height="${oDiameter}" viewPort="0 0 ${oDiameter} ${oDiameter}" version="1.1">
|
<svg id="progress" width="${oDiameter}" height="${
|
||||||
|
oDiameter
|
||||||
|
}" viewPort="0 0 ${oDiameter} ${oDiameter}" version="1.1">
|
||||||
<circle r="${radius}" cx="${oRadius}" cy="${oRadius}" fill="transparent"/>
|
<circle r="${radius}" cx="${oRadius}" cy="${oRadius}" fill="transparent"/>
|
||||||
<circle id="bar" r="${radius}" cx="${oRadius}" cy="${oRadius}" fill="transparent" transform="rotate(-90 ${oRadius} ${oRadius})" stroke-dasharray="${circumference}" stroke-dashoffset="${dashOffset}"/>
|
<circle id="bar" r="${radius}" cx="${oRadius}" cy="${
|
||||||
<text class="percentage" text-anchor="middle" x="50%" y="98"><tspan class="percent-number">${percent}</tspan><tspan class="percent-sign">%</tspan></text>
|
oRadius
|
||||||
|
}" fill="transparent" transform="rotate(-90 ${oRadius} ${
|
||||||
|
oRadius
|
||||||
|
})" stroke-dasharray="${circumference}" stroke-dashoffset="${dashOffset}"/>
|
||||||
|
<text class="percentage" text-anchor="middle" x="50%" y="98"><tspan class="percent-number">${
|
||||||
|
percent
|
||||||
|
}</tspan><tspan class="percent-sign">%</tspan></text>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -42,9 +42,5 @@ module.exports = function(state) {
|
|||||||
)}</div>
|
)}</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
const div = html`<div id="page-one">${msg}</div>`;
|
const div = html`<div id="page-one">${msg}</div>`;
|
||||||
|
|
||||||
if (state.layout) {
|
|
||||||
return state.layout(state, div);
|
|
||||||
}
|
|
||||||
return div;
|
return div;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ module.exports = function(state, emit) {
|
|||||||
const div = html`
|
const div = html`
|
||||||
<div class="selectPassword">
|
<div class="selectPassword">
|
||||||
<div id="addPasswordWrapper">
|
<div id="addPasswordWrapper">
|
||||||
<input id="addPassword" type="checkbox" autocomplete="off" onchange=${togglePasswordInput}/>
|
<input id="addPassword" type="checkbox" autocomplete="off" onchange=${
|
||||||
|
togglePasswordInput
|
||||||
|
}/>
|
||||||
<label for="addPassword">
|
<label for="addPassword">
|
||||||
${state.translate('requirePasswordCheckbox')}</label>
|
${state.translate('requirePasswordCheckbox')}</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,10 +43,6 @@ module.exports = function(state, emit) {
|
|||||||
document
|
document
|
||||||
.querySelector('.setPassword')
|
.querySelector('.setPassword')
|
||||||
.classList.toggle('hidden', !boxChecked);
|
.classList.toggle('hidden', !boxChecked);
|
||||||
document
|
|
||||||
.getElementById('copy')
|
|
||||||
.classList.toggle('wait-password', boxChecked);
|
|
||||||
document.getElementById('copy-btn').disabled = boxChecked;
|
|
||||||
if (boxChecked) {
|
if (boxChecked) {
|
||||||
unlockInput.focus();
|
unlockInput.focus();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
const assets = require('../../common/assets');
|
const assets = require('../../common/assets');
|
||||||
const fileList = require('./fileList');
|
const fileList = require('./fileList');
|
||||||
|
const fxPromo = require('./fxPromo');
|
||||||
const { fadeOut } = require('../utils');
|
const { fadeOut } = require('../utils');
|
||||||
|
|
||||||
module.exports = function(state, emit) {
|
module.exports = function(state, emit) {
|
||||||
@@ -35,6 +36,7 @@ module.exports = function(state, emit) {
|
|||||||
title="${state.translate('uploadPageBrowseButton1')}">
|
title="${state.translate('uploadPageBrowseButton1')}">
|
||||||
${state.translate('uploadPageBrowseButton1')}</label>
|
${state.translate('uploadPageBrowseButton1')}</label>
|
||||||
</div>
|
</div>
|
||||||
|
${state.promo === 'body' ? fxPromo(state, emit) : ''}
|
||||||
${fileList(state, emit)}
|
${fileList(state, emit)}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -67,9 +69,5 @@ module.exports = function(state, emit) {
|
|||||||
await fadeOut('page-one');
|
await fadeOut('page-one');
|
||||||
emit('upload', { file, type: 'click' });
|
emit('upload', { file, type: 'click' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.layout) {
|
|
||||||
return state.layout(state, div);
|
|
||||||
}
|
|
||||||
return div;
|
return div;
|
||||||
};
|
};
|
||||||
|
|||||||
26
app/utils.js
26
app/utils.js
@@ -105,19 +105,31 @@ function bytes(num) {
|
|||||||
}
|
}
|
||||||
const exponent = Math.min(Math.floor(Math.log10(num) / 3), UNITS.length - 1);
|
const exponent = Math.min(Math.floor(Math.log10(num) / 3), UNITS.length - 1);
|
||||||
const n = Number(num / Math.pow(1000, exponent));
|
const n = Number(num / Math.pow(1000, exponent));
|
||||||
const nStr = LOCALIZE_NUMBERS
|
let nStr = n.toFixed(1);
|
||||||
? n.toLocaleString(navigator.languages, {
|
if (LOCALIZE_NUMBERS) {
|
||||||
|
try {
|
||||||
|
const locale = document.querySelector('html').lang;
|
||||||
|
nStr = n.toLocaleString(locale, {
|
||||||
minimumFractionDigits: 1,
|
minimumFractionDigits: 1,
|
||||||
maximumFractionDigits: 1
|
maximumFractionDigits: 1
|
||||||
})
|
});
|
||||||
: n.toFixed(1);
|
} catch (e) {
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
}
|
||||||
return `${nStr}${UNITS[exponent]}`;
|
return `${nStr}${UNITS[exponent]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function percent(ratio) {
|
function percent(ratio) {
|
||||||
return LOCALIZE_NUMBERS
|
if (LOCALIZE_NUMBERS) {
|
||||||
? ratio.toLocaleString(navigator.languages, { style: 'percent' })
|
try {
|
||||||
: `${Math.floor(ratio * 100)}%`;
|
const locale = document.querySelector('html').lang;
|
||||||
|
return ratio.toLocaleString(locale, { style: 'percent' });
|
||||||
|
} catch (e) {
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `${Math.floor(ratio * 100)}%`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function allowedCopy() {
|
function allowedCopy() {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 239 KiB After Width: | Height: | Size: 16 KiB |
@@ -8,7 +8,6 @@ html {
|
|||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center top;
|
background-position: center top;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
max-width: 1440px;
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +129,7 @@ body {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
max-width: 630px;
|
max-width: 650px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -213,7 +212,7 @@ a {
|
|||||||
|
|
||||||
.upload-window {
|
.upload-window {
|
||||||
border: 3px dashed rgba(0, 148, 251, 0.5);
|
border: 3px dashed rgba(0, 148, 251, 0.5);
|
||||||
margin: 0 auto;
|
margin: 0 auto 10px;
|
||||||
height: 255px;
|
height: 255px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -227,7 +226,6 @@ a {
|
|||||||
|
|
||||||
.upload-window.ondrag {
|
.upload-window.ondrag {
|
||||||
border: 5px dashed rgba(0, 148, 251, 0.5);
|
border: 5px dashed rgba(0, 148, 251, 0.5);
|
||||||
margin: 0 auto;
|
|
||||||
height: 251px;
|
height: 251px;
|
||||||
transform: scale(1.04);
|
transform: scale(1.04);
|
||||||
border-radius: 4.2px;
|
border-radius: 4.2px;
|
||||||
@@ -709,6 +707,10 @@ tbody {
|
|||||||
width: 70px;
|
width: 70px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.firefox-logo-small {
|
||||||
|
width: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
#dl-firefox,
|
#dl-firefox,
|
||||||
#update-firefox {
|
#update-firefox {
|
||||||
margin-bottom: 181px;
|
margin-bottom: 181px;
|
||||||
@@ -766,7 +768,7 @@ tbody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#download {
|
#download {
|
||||||
margin: 0 auto;
|
margin: 0 auto 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -955,6 +957,29 @@ tbody {
|
|||||||
background-position: 2px 1px;
|
background-position: 2px 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.banner {
|
||||||
|
padding: 0 15px;
|
||||||
|
height: 48px;
|
||||||
|
background-color: #efeff1;
|
||||||
|
color: #4a4a4f;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-content: center;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner > div {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner > div > span {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-device-width: 992px), (max-width: 992px) {
|
@media (max-device-width: 992px), (max-width: 992px) {
|
||||||
.popup .popuptext {
|
.popup .popuptext {
|
||||||
left: auto;
|
left: auto;
|
||||||
|
|||||||
2200
package-lock.json
generated
2200
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
45
package.json
45
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "firefox-send",
|
"name": "firefox-send",
|
||||||
"description": "File Sharing Experiment",
|
"description": "File Sharing Experiment",
|
||||||
"version": "2.0.0",
|
"version": "2.1.2",
|
||||||
"author": "Mozilla (https://mozilla.org)",
|
"author": "Mozilla (https://mozilla.org)",
|
||||||
"repository": "mozilla/send",
|
"repository": "mozilla/send",
|
||||||
"homepage": "https://github.com/mozilla/send/",
|
"homepage": "https://github.com/mozilla/send/",
|
||||||
@@ -43,66 +43,66 @@
|
|||||||
"node": ">=8.2.0"
|
"node": ">=8.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "^7.1.5",
|
"autoprefixer": "^7.1.6",
|
||||||
"babel-core": "^6.26.0",
|
"babel-core": "^6.26.0",
|
||||||
"babel-loader": "^7.1.2",
|
"babel-loader": "^7.1.2",
|
||||||
"babel-plugin-yo-yoify": "^1.0.1",
|
"babel-plugin-yo-yoify": "^1.0.1",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"babel-preset-env": "^1.6.0",
|
"babel-preset-env": "^1.6.1",
|
||||||
"babel-preset-es2015": "^6.24.1",
|
"babel-preset-es2015": "^6.24.1",
|
||||||
"babel-preset-stage-2": "^6.24.1",
|
"babel-preset-stage-2": "^6.24.1",
|
||||||
"base64-js": "^1.2.1",
|
"base64-js": "^1.2.1",
|
||||||
"copy-webpack-plugin": "^4.1.1",
|
"copy-webpack-plugin": "^4.2.0",
|
||||||
"cross-env": "^5.0.5",
|
"cross-env": "^5.1.1",
|
||||||
"css-loader": "^0.28.7",
|
"css-loader": "^0.28.7",
|
||||||
"css-mqpacker": "^6.0.1",
|
"css-mqpacker": "^6.0.1",
|
||||||
"cssnano": "^3.10.0",
|
"cssnano": "^3.10.0",
|
||||||
"eslint": "^4.8.0",
|
"eslint": "^4.10.0",
|
||||||
"eslint-plugin-mocha": "^4.11.0",
|
"eslint-plugin-mocha": "^4.11.0",
|
||||||
"eslint-plugin-node": "^5.2.0",
|
"eslint-plugin-node": "^5.2.1",
|
||||||
"eslint-plugin-security": "^1.4.0",
|
"eslint-plugin-security": "^1.4.0",
|
||||||
"expose-loader": "^0.7.3",
|
"expose-loader": "^0.7.3",
|
||||||
"extract-loader": "^1.0.1",
|
"extract-loader": "^1.0.1",
|
||||||
"file-loader": "^1.1.5",
|
"file-loader": "^1.1.5",
|
||||||
"git-rev-sync": "^1.9.1",
|
"git-rev-sync": "^1.9.1",
|
||||||
"github-changes": "^1.1.0",
|
"github-changes": "^1.1.1",
|
||||||
"html-loader": "^0.5.1",
|
"html-loader": "^0.5.1",
|
||||||
"husky": "^0.14.3",
|
"husky": "^0.14.3",
|
||||||
"lint-staged": "^4.2.3",
|
"lint-staged": "^4.3.0",
|
||||||
"mocha": "^3.5.3",
|
"mocha": "^3.5.3",
|
||||||
"nanobus": "^4.2.0",
|
"nanobus": "^4.3.0",
|
||||||
"npm-run-all": "^4.1.1",
|
"npm-run-all": "^4.1.2",
|
||||||
"postcss-loader": "^2.0.6",
|
"postcss-loader": "^2.0.8",
|
||||||
"prettier": "^1.7.4",
|
"prettier": "^1.8.2",
|
||||||
"proxyquire": "^1.8.0",
|
"proxyquire": "^1.8.0",
|
||||||
"raven-js": "^3.18.1",
|
"raven-js": "^3.19.1",
|
||||||
"redis-mock": "^0.20.0",
|
"redis-mock": "^0.20.0",
|
||||||
"require-from-string": "^2.0.1",
|
"require-from-string": "^2.0.1",
|
||||||
"rimraf": "^2.6.2",
|
"rimraf": "^2.6.2",
|
||||||
"selenium-webdriver": "^3.6.0",
|
"selenium-webdriver": "^3.6.0",
|
||||||
"sinon": "^4.0.1",
|
"sinon": "^4.1.2",
|
||||||
"string-hash": "^1.1.3",
|
"string-hash": "^1.1.3",
|
||||||
"stylelint-config-standard": "^17.0.0",
|
"stylelint-config-standard": "^17.0.0",
|
||||||
"stylelint-no-unsupported-browser-features": "^1.0.1",
|
"stylelint-no-unsupported-browser-features": "^1.0.1",
|
||||||
"supertest": "^3.0.0",
|
"supertest": "^3.0.0",
|
||||||
"testpilot-ga": "^0.3.0",
|
"testpilot-ga": "^0.3.0",
|
||||||
"val-loader": "^1.0.2",
|
"val-loader": "^1.0.2",
|
||||||
"webpack": "^3.6.0",
|
"webpack": "^3.8.1",
|
||||||
"webpack-dev-server": "^2.9.1",
|
"webpack-dev-server": "2.9.1",
|
||||||
"webpack-manifest-plugin": "^1.3.2",
|
"webpack-manifest-plugin": "^1.3.2",
|
||||||
"webpack-unassert-loader": "^1.2.0"
|
"webpack-unassert-loader": "^1.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aws-sdk": "^2.130.0",
|
"aws-sdk": "^2.149.0",
|
||||||
"body-parser": "^1.18.2",
|
"body-parser": "^1.18.2",
|
||||||
"choo": "^6.4.2",
|
"choo": "^6.5.1",
|
||||||
|
"cldr-core": "^32.0.0",
|
||||||
"connect-busboy": "0.0.2",
|
"connect-busboy": "0.0.2",
|
||||||
"convict": "^4.0.1",
|
"convict": "^4.0.1",
|
||||||
"express": "^4.16.2",
|
"express": "^4.16.2",
|
||||||
"express-request-language": "^1.1.12",
|
|
||||||
"fluent": "^0.4.1",
|
"fluent": "^0.4.1",
|
||||||
"fluent-langneg": "^0.1.0",
|
"fluent-langneg": "^0.1.0",
|
||||||
"helmet": "^3.8.2",
|
"helmet": "^3.9.0",
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
"mozlog": "^2.1.1",
|
"mozlog": "^2.1.1",
|
||||||
"raven": "^2.2.1",
|
"raven": "^2.2.1",
|
||||||
@@ -112,6 +112,7 @@
|
|||||||
"en-US",
|
"en-US",
|
||||||
"ast",
|
"ast",
|
||||||
"az",
|
"az",
|
||||||
|
"bs",
|
||||||
"ca",
|
"ca",
|
||||||
"cak",
|
"cak",
|
||||||
"cs",
|
"cs",
|
||||||
@@ -132,6 +133,7 @@
|
|||||||
"id",
|
"id",
|
||||||
"it",
|
"it",
|
||||||
"ja",
|
"ja",
|
||||||
|
"ka",
|
||||||
"kab",
|
"kab",
|
||||||
"ko",
|
"ko",
|
||||||
"ms",
|
"ms",
|
||||||
@@ -145,6 +147,7 @@
|
|||||||
"sl",
|
"sl",
|
||||||
"sr",
|
"sr",
|
||||||
"sv-SE",
|
"sv-SE",
|
||||||
|
"tl",
|
||||||
"tr",
|
"tr",
|
||||||
"uk",
|
"uk",
|
||||||
"vi",
|
"vi",
|
||||||
|
|||||||
@@ -76,3 +76,5 @@ footerLinkTerms = الشروط
|
|||||||
footerLinkCookies = الكعكات
|
footerLinkCookies = الكعكات
|
||||||
requirePasswordCheckbox = اطلب كلمة سر لتنزيل هذا الملف
|
requirePasswordCheckbox = اطلب كلمة سر لتنزيل هذا الملف
|
||||||
addPasswordButton = أضِف كلمة سر
|
addPasswordButton = أضِف كلمة سر
|
||||||
|
// This label is followed by the password needed to download a file
|
||||||
|
passwordResult = كلمة السر: { $password }
|
||||||
|
|||||||
@@ -87,3 +87,5 @@ footerLinkCookies = Cookies
|
|||||||
requirePasswordCheckbox = Riquir una contraseña pa baxar esti ficheru
|
requirePasswordCheckbox = Riquir una contraseña pa baxar esti ficheru
|
||||||
addPasswordButton = Amestar contraseña
|
addPasswordButton = Amestar contraseña
|
||||||
passwordTryAgain = Contraseña incorreuta. Volvi tentalo.
|
passwordTryAgain = Contraseña incorreuta. Volvi tentalo.
|
||||||
|
// This label is followed by the password needed to download a file
|
||||||
|
passwordResult = Contraseña: { $password }
|
||||||
|
|||||||
@@ -87,3 +87,5 @@ footerLinkCookies = Küpsistest
|
|||||||
requirePasswordCheckbox = Selle faili allalaadimiseks nõutakse parooli
|
requirePasswordCheckbox = Selle faili allalaadimiseks nõutakse parooli
|
||||||
addPasswordButton = Lisa parool
|
addPasswordButton = Lisa parool
|
||||||
passwordTryAgain = Vale parool. Palun proovi uuesti.
|
passwordTryAgain = Vale parool. Palun proovi uuesti.
|
||||||
|
// This label is followed by the password needed to download a file
|
||||||
|
passwordResult = Parool: { $password }
|
||||||
|
|||||||
@@ -87,4 +87,6 @@ footerLinkTerms = 이용 약관
|
|||||||
footerLinkCookies = 쿠키
|
footerLinkCookies = 쿠키
|
||||||
requirePasswordCheckbox = 이 파일을 다운로드하려면 비밀번호가 필요함
|
requirePasswordCheckbox = 이 파일을 다운로드하려면 비밀번호가 필요함
|
||||||
addPasswordButton = 비밀번호 추가
|
addPasswordButton = 비밀번호 추가
|
||||||
incorrectPassword = 비밀번호가 일치하지 않습니다. 다시 시도해주세요.
|
passwordTryAgain = 비밀번호가 맞지 않습니다. 다시 시도해 주세요.
|
||||||
|
// This label is followed by the password needed to download a file
|
||||||
|
passwordResult = 비밀번호: { $password }
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ siteSubtitle = un experiment web
|
|||||||
siteFeedback = Feedback
|
siteFeedback = Feedback
|
||||||
uploadPageHeader = Partajare de fișiere privată și criptată
|
uploadPageHeader = Partajare de fișiere privată și criptată
|
||||||
uploadPageLearnMore = Află mai multe
|
uploadPageLearnMore = Află mai multe
|
||||||
|
uploadPageDropMessage = Aruncă fișierul aici pentru a începe încărcarea.
|
||||||
|
uploadPageBrowseButton = Alege un fișier din calculator.
|
||||||
uploadPageBrowseButton1 = Selectează un fișier pentru încărcare
|
uploadPageBrowseButton1 = Selectează un fișier pentru încărcare
|
||||||
|
uploadPageMultipleFilesAlert = Încărcarea mai multor fișiere deodată sau a dosarelor nu este suportată.
|
||||||
uploadPageBrowseButtonTitle = Încarcă fișier
|
uploadPageBrowseButtonTitle = Încarcă fișier
|
||||||
uploadingPageProgress = Se încarcă { $filename } ({ $size })
|
uploadingPageProgress = Se încarcă { $filename } ({ $size })
|
||||||
importingFile = Se importă…
|
importingFile = Se importă…
|
||||||
@@ -15,6 +18,7 @@ notifyUploadDone = Încărcarea s-a finalizat.
|
|||||||
uploadingPageMessage =
|
uploadingPageMessage =
|
||||||
uploadingPageCancel = Anulează încărcarea
|
uploadingPageCancel = Anulează încărcarea
|
||||||
uploadCancelNotification = Încărcarea a fost anulată.
|
uploadCancelNotification = Încărcarea a fost anulată.
|
||||||
|
uploadingPageLargeFileMessage = Stai calm! Acest fișier este mare. S-ar putea să dureze un timp încărcarea.
|
||||||
uploadingFileNotification = Notifică-mă când încărcarea este încheiată.
|
uploadingFileNotification = Notifică-mă când încărcarea este încheiată.
|
||||||
uploadSuccessConfirmHeader = Pregătit pentru trimitere
|
uploadSuccessConfirmHeader = Pregătit pentru trimitere
|
||||||
uploadSvgAlt = Încarcă
|
uploadSvgAlt = Încarcă
|
||||||
@@ -27,8 +31,10 @@ sendAnotherFileLink = Trimite un alt fișier
|
|||||||
downloadAltText = Descarcă
|
downloadAltText = Descarcă
|
||||||
downloadFileName = Descarcă { $filename }
|
downloadFileName = Descarcă { $filename }
|
||||||
downloadFileSize = ({ $size })
|
downloadFileSize = ({ $size })
|
||||||
|
unlockInputLabel = Introdu parola
|
||||||
unlockInputPlaceholder = Parolă
|
unlockInputPlaceholder = Parolă
|
||||||
unlockButtonLabel = Deblochează
|
unlockButtonLabel = Deblochează
|
||||||
|
downloadFileTitle = Descarcă fișierul criptat
|
||||||
// Text and title used on the download link/button (indicates an action).
|
// Text and title used on the download link/button (indicates an action).
|
||||||
downloadButtonLabel = Descarcă
|
downloadButtonLabel = Descarcă
|
||||||
downloadNotification = Descărcarea s-a încheiat.
|
downloadNotification = Descărcarea s-a încheiat.
|
||||||
@@ -40,7 +46,9 @@ sendYourFilesLink = Încearcă Firefox Send
|
|||||||
downloadingPageProgress = Se descarcă { $filename } ({ $size })
|
downloadingPageProgress = Se descarcă { $filename } ({ $size })
|
||||||
errorAltText = Eroare la încărcare
|
errorAltText = Eroare la încărcare
|
||||||
errorPageHeader = Ceva a mers prost!
|
errorPageHeader = Ceva a mers prost!
|
||||||
|
errorPageMessage = A apărut o eroare la încărcarea fișierului.
|
||||||
errorPageLink = Trimite un alt fișier
|
errorPageLink = Trimite un alt fișier
|
||||||
|
fileTooBig = Acest fișier este prea mare. Trebuie să fie sub { $size }.
|
||||||
linkExpiredAlt = Link expirat
|
linkExpiredAlt = Link expirat
|
||||||
expiredPageHeader = Acest link a expirat sau nu a existat de la bun început!
|
expiredPageHeader = Acest link a expirat sau nu a existat de la bun început!
|
||||||
notSupportedHeader = Browserul tău nu este suportat.
|
notSupportedHeader = Browserul tău nu este suportat.
|
||||||
@@ -52,6 +60,7 @@ copyFileList = Copiază URL-ul
|
|||||||
// expiryFileList is used as a column header
|
// expiryFileList is used as a column header
|
||||||
expiryFileList = Expiră în
|
expiryFileList = Expiră în
|
||||||
deleteFileList = Șterge
|
deleteFileList = Șterge
|
||||||
|
nevermindButton = Uită
|
||||||
legalHeader = Termeni de utilizare și politica de confidențialitate
|
legalHeader = Termeni de utilizare și politica de confidențialitate
|
||||||
deletePopupText = Ștergi aceast fișier?
|
deletePopupText = Ștergi aceast fișier?
|
||||||
deletePopupYes = Da
|
deletePopupYes = Da
|
||||||
|
|||||||
@@ -87,3 +87,5 @@ footerLinkCookies = Cookies
|
|||||||
requirePasswordCheckbox = Pri preberaní súboru vyžadovať heslo
|
requirePasswordCheckbox = Pri preberaní súboru vyžadovať heslo
|
||||||
addPasswordButton = Pridať heslo
|
addPasswordButton = Pridať heslo
|
||||||
passwordTryAgain = Nesprávne heslo. Skúste to znova.
|
passwordTryAgain = Nesprávne heslo. Skúste to znova.
|
||||||
|
// This label is followed by the password needed to download a file
|
||||||
|
passwordResult = Heslo: { $password }
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ sendAnotherFileLink = మరో ఫైలును పంపండి
|
|||||||
downloadAltText = దిగుమతి
|
downloadAltText = దిగుమతి
|
||||||
downloadFileName = దిగుమతి { $filename }
|
downloadFileName = దిగుమతి { $filename }
|
||||||
downloadFileSize = ({ $size })
|
downloadFileSize = ({ $size })
|
||||||
|
unlockInputLabel = సంకేతపదాన్ని తెలపండి
|
||||||
|
unlockInputPlaceholder = సంకేతపదం
|
||||||
|
unlockButtonLabel = తాళం తీయి
|
||||||
// Text and title used on the download link/button (indicates an action).
|
// Text and title used on the download link/button (indicates an action).
|
||||||
downloadButtonLabel = దిగుమతి
|
downloadButtonLabel = దిగుమతి
|
||||||
downloadNotification = మీ దిగుమతి పూర్తయ్యింది.
|
downloadNotification = మీ దిగుమతి పూర్తయ్యింది.
|
||||||
@@ -69,3 +72,8 @@ footerLinkAbout = టెస్ట్ పైలట్ గురించి
|
|||||||
footerLinkPrivacy = గోప్యత
|
footerLinkPrivacy = గోప్యత
|
||||||
footerLinkTerms = నియమాలు
|
footerLinkTerms = నియమాలు
|
||||||
footerLinkCookies = కుకీలు
|
footerLinkCookies = కుకీలు
|
||||||
|
requirePasswordCheckbox = ఈ ఫైల్ను దింపుకోటానికి సంకేతపదం అవసరం
|
||||||
|
addPasswordButton = సంకేతపదం జోడించండి
|
||||||
|
passwordTryAgain = సరికాని సంకేతపదం. మళ్ళీ ప్రయత్నించండి.
|
||||||
|
// This label is followed by the password needed to download a file
|
||||||
|
passwordResult = సంకేతపదం: { $password }
|
||||||
|
|||||||
@@ -4,11 +4,9 @@ const fs = require('fs');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
function allLangs() {
|
function allLangs() {
|
||||||
const langs = fs.readdirSync(
|
return fs.readdirSync(
|
||||||
path.join(__dirname, '..', 'dist', 'public', 'locales')
|
path.join(__dirname, '..', 'dist', 'public', 'locales')
|
||||||
);
|
);
|
||||||
langs.unshift('en-US'); // default first, TODO change for fluent-langneg
|
|
||||||
return langs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.l10n_dev) {
|
if (config.l10n_dev) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ module.exports = function(state, body = '') {
|
|||||||
: '';
|
: '';
|
||||||
return html`
|
return html`
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="${state.locale}">
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
@@ -71,58 +71,7 @@ module.exports = function(state, body = '') {
|
|||||||
<script defer src="${locales.get(state.locale)}"></script>
|
<script defer src="${locales.get(state.locale)}"></script>
|
||||||
<script defer src="${assets.get('app.js')}"></script>
|
<script defer src="${assets.get('app.js')}"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
|
||||||
<header class="header">
|
|
||||||
<div class="send-logo">
|
|
||||||
<a href="/">
|
|
||||||
<img src="${assets.get(
|
|
||||||
'send_logo.svg'
|
|
||||||
)}" alt="Send"/><h1 class="site-title">Send</h1>
|
|
||||||
</a>
|
|
||||||
<div class="site-subtitle">
|
|
||||||
<a href="https://testpilot.firefox.com">Firefox Test Pilot</a>
|
|
||||||
<div>${state.translate('siteSubtitle')}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a href="https://qsurvey.mozilla.com/s3/txp-firefox-send" rel="noreferrer noopener" class="feedback" target="_blank">${state.translate(
|
|
||||||
'siteFeedback'
|
|
||||||
)}</a>
|
|
||||||
</header>
|
|
||||||
<div class="all">
|
|
||||||
<noscript>
|
|
||||||
<h2>Firefox Send requires JavaScript</h2>
|
|
||||||
<p><a href="https://github.com/mozilla/send/blob/master/docs/faq.md#why-does-firefox-send-require-javascript">Why does Firefox Send require JavaScript?</a></p>
|
|
||||||
<p>Please enable JavaScript and try again.</p>
|
|
||||||
</noscript>
|
|
||||||
${body}
|
${body}
|
||||||
</div>
|
|
||||||
<div class="footer">
|
|
||||||
<div class="legal-links">
|
|
||||||
<a href="https://www.mozilla.org" role="presentation"><img class="mozilla-logo" src="${assets.get(
|
|
||||||
'mozilla-logo.svg'
|
|
||||||
)}" alt="mozilla"/></a>
|
|
||||||
<a href="https://www.mozilla.org/about/legal">${state.translate(
|
|
||||||
'footerLinkLegal'
|
|
||||||
)}</a>
|
|
||||||
<a href="https://testpilot.firefox.com/about">${state.translate(
|
|
||||||
'footerLinkAbout'
|
|
||||||
)}</a>
|
|
||||||
<a href="/legal">${state.translate('footerLinkPrivacy')}</a>
|
|
||||||
<a href="/legal">${state.translate('footerLinkTerms')}</a>
|
|
||||||
<a href="https://www.mozilla.org/privacy/websites/#cookies">${state.translate(
|
|
||||||
'footerLinkCookies'
|
|
||||||
)}</a>
|
|
||||||
</div>
|
|
||||||
<div class="social-links">
|
|
||||||
<a href="https://github.com/mozilla/send" role="presentation"><img class="github" src="${assets.get(
|
|
||||||
'github-icon.svg'
|
|
||||||
)}" alt="github"/></a>
|
|
||||||
<a href="https://twitter.com/FxTestPilot" role="presentation"><img class="twitter" src="${assets.get(
|
|
||||||
'twitter-icon.svg'
|
|
||||||
)}" alt="twitter"/></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,20 +1,40 @@
|
|||||||
const busboy = require('connect-busboy');
|
const busboy = require('connect-busboy');
|
||||||
const helmet = require('helmet');
|
const helmet = require('helmet');
|
||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
const requestLanguage = require('express-request-language');
|
|
||||||
const languages = require('../languages');
|
const languages = require('../languages');
|
||||||
const storage = require('../storage');
|
const storage = require('../storage');
|
||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
const pages = require('./pages');
|
const pages = require('./pages');
|
||||||
// const lang = require('fluent-langneg')
|
const { negotiateLanguages } = require('fluent-langneg');
|
||||||
const IS_DEV = config.env === 'development';
|
const IS_DEV = config.env === 'development';
|
||||||
|
const acceptLanguages = /(([a-zA-Z]+(-[a-zA-Z0-9]+){0,2})|\*)(;q=[0-1](\.[0-9]+)?)?/g;
|
||||||
|
const langData = require('cldr-core/supplemental/likelySubtags.json');
|
||||||
|
|
||||||
module.exports = function(app) {
|
module.exports = function(app) {
|
||||||
app.use(
|
app.use(function(req, res, next) {
|
||||||
requestLanguage({
|
const header = req.headers['accept-language'] || 'en-US';
|
||||||
languages
|
if (header.length > 255) {
|
||||||
|
req.language = 'en-US';
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
const langs = header.replace(/\s/g, '').match(acceptLanguages);
|
||||||
|
const preferred = langs
|
||||||
|
.map(l => {
|
||||||
|
const parts = l.split(';');
|
||||||
|
return {
|
||||||
|
locale: parts[0],
|
||||||
|
q: parts[1] ? parseFloat(parts[1].split('=')[1]) : 1
|
||||||
|
};
|
||||||
})
|
})
|
||||||
);
|
.sort((a, b) => b.q - a.q)
|
||||||
|
.map(x => x.locale);
|
||||||
|
req.language = negotiateLanguages(preferred, languages, {
|
||||||
|
strategy: 'lookup',
|
||||||
|
likelySubtags: langData.supplemental.likelySubtags,
|
||||||
|
defaultLocale: 'en-US'
|
||||||
|
})[0];
|
||||||
|
next();
|
||||||
|
});
|
||||||
app.use(helmet());
|
app.use(helmet());
|
||||||
app.use(
|
app.use(
|
||||||
helmet.hsts({
|
helmet.hsts({
|
||||||
@@ -22,7 +42,6 @@ module.exports = function(app) {
|
|||||||
force: !IS_DEV
|
force: !IS_DEV
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
if (!IS_DEV) {
|
|
||||||
app.use(
|
app.use(
|
||||||
helmet.contentSecurityPolicy({
|
helmet.contentSecurityPolicy({
|
||||||
directives: {
|
directives: {
|
||||||
@@ -34,7 +53,7 @@ module.exports = function(app) {
|
|||||||
],
|
],
|
||||||
imgSrc: ["'self'", 'https://www.google-analytics.com'],
|
imgSrc: ["'self'", 'https://www.google-analytics.com'],
|
||||||
scriptSrc: ["'self'"],
|
scriptSrc: ["'self'"],
|
||||||
styleSrc: ["'self'", 'https://code.cdn.mozilla.net'],
|
styleSrc: ["'self'", "'unsafe-inline'", 'https://code.cdn.mozilla.net'],
|
||||||
fontSrc: ["'self'", 'https://code.cdn.mozilla.net'],
|
fontSrc: ["'self'", 'https://code.cdn.mozilla.net'],
|
||||||
formAction: ["'none'"],
|
formAction: ["'none'"],
|
||||||
frameAncestors: ["'none'"],
|
frameAncestors: ["'none'"],
|
||||||
@@ -43,7 +62,6 @@ module.exports = function(app) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
|
||||||
app.use(
|
app.use(
|
||||||
busboy({
|
busboy({
|
||||||
limits: {
|
limits: {
|
||||||
|
|||||||
Reference in New Issue
Block a user