Compare commits

...

51 Commits

Author SHA1 Message Date
Danny Coates
18216ce430 v3.0.20 2019-10-21 11:33:54 -07:00
Danny Coates
1711a2d1d7 added "te" to production languages 2019-10-21 10:36:34 -07:00
Danny Coates
8b2080a2f0 updated deps 2019-10-21 10:24:07 -07:00
Danny Coates
006ee1d2e6 Merge pull request #1408 from drakkein/master
Strip tracking URL params
2019-10-21 10:13:56 -07:00
Danny Coates
0a7c473965 Merge pull request #1405 from mozilla/dark-mode
Dark theme
2019-10-21 10:07:42 -07:00
Hampus
4e124d174c Pontoon: Update Swedish (sv-SE) localization of Firefox Send
Localization authors:
- Hampus <hampus.bengtsson@gmail.com>
2019-10-19 00:33:34 +00:00
Artem Polivanchuk
524b2a5668 Pontoon: Update Ukrainian (uk) localization of Firefox Send
Localization authors:
- Artem Polivanchuk <artem@mozilla.org.ua>
2019-10-17 08:52:12 +00:00
Marcelo Ghelman
844f036a27 Pontoon: Update Portuguese (Brazil) (pt-BR) localization of Firefox Send
Localization authors:
- Marcelo Ghelman <marcelo.ghelman@gmail.com>
2019-10-16 14:33:03 +00:00
Marcelo Ghelman
7d6c781ea5 Pontoon: Update Portuguese (Brazil) (pt-BR) localization of Firefox Send
Localization authors:
- Marcelo Ghelman <marcelo.ghelman@gmail.com>
2019-10-16 14:12:33 +00:00
Wiktor Furman
ad9577daaf Update package-lock 2019-10-15 15:50:09 +02:00
Wiktor Furman
114068c531 Strip tracking url parameters 2019-10-15 15:29:48 +02:00
Niksend Mizuhara
0daa03e04c Pontoon: Update Chinese (China) (zh-CN) localization of Firefox Send
Localization authors:
- Niksend Mizuhara <i@rhinecho.com>
2019-10-07 01:53:05 +00:00
Danny Coates
63348fd36a updated deps 2019-10-03 23:32:49 -07:00
Danny Coates
c71c246959 Dark theme 2019-10-03 23:10:11 -07:00
Sander Lepik
2b7504e969 Pontoon: Update Estonian (et) localization of Firefox Send
Localization authors:
- Sander Lepik <sander.lepik@eesti.ee>
2019-10-01 05:14:31 +00:00
Selyan Sliman Amiri
b942554c80 Pontoon: Update Kabyle (kab) localization of Firefox Send
Localization authors:
- Selyan Sliman Amiri <selyan.kab@gmail.com>
2019-09-30 09:32:51 +00:00
Juan Sián
1ae227fddd Pontoon: Update Kaqchikel (cak) localization of Firefox Send
Localization authors:
- Juan Sián <ajtzibsyan@yahoo.com>
2019-09-26 23:32:48 +00:00
Jordi Serratosa
a63fe18d15 Pontoon: Update Catalan (ca) localization of Firefox Send
Localization authors:
- Jordi Serratosa <jordis@softcatala.cat>
2019-09-25 09:56:59 +00:00
Danny Coates
ea1ea2aa68 v3.0.19 2019-09-23 09:24:10 -07:00
Danny Coates
90d06d71d3 updated deps 2019-09-23 09:22:22 -07:00
Kim Younggeon
11f2deb7a6 Pontoon: Update Korean (ko) localization of Firefox Send
Localization authors:
- Kim Younggeon <mail@kyg.kr>
2019-09-23 03:52:14 +00:00
Danny Coates
0f5edf023a Merge pull request #1400 from mozilla/task/update-engines
task: update engines in package.json and README to clarify that node 10x is expected.
2019-09-19 11:02:42 -07:00
Rachel Tublitz
3be0621647 task: update engines in package.json and README to clarify that node 10.x is expected 2019-09-19 13:37:05 -04:00
Marcelo Ghelman
fc07bfdb85 Pontoon: Update Portuguese (Brazil) (pt-BR) localization of Firefox Send
Localization authors:
- Marcelo Ghelman <marcelo.ghelman@gmail.com>
2019-09-15 05:17:20 +00:00
صفا الفليج
581a989304 Pontoon: Update Arabic (ar) localization of Firefox Send
Localization authors:
- صفا الفليج <safa1996alfulaij@gmail.com>
2019-09-11 18:34:38 +00:00
ItielMaN
047d6a85ab Pontoon: Update Hebrew (he) localization of Firefox Send
Localization authors:
- ItielMaN <itiel_yn8@walla.com>
2019-09-08 21:12:53 +00:00
Luiz Felipe F M Costa
90f6a07d4a refactored Dockerfile 2019-09-06 20:04:45 -07:00
Arash Mousavi
8f4a53db64 Pontoon: Update Persian (fa) localization of Firefox Send
Localization authors:
- Arash Mousavi <mousavi.arash@gmail.com>
2019-09-06 21:53:28 +00:00
Danny Coates
c2dd51c638 v3.0.18 2019-09-06 10:40:36 -07:00
Danny Coates
cdd98af86a updated deps 2019-09-06 10:39:42 -07:00
Danny Coates
883f2bc0f9 wait until serviceWorker activate to precache 2019-09-05 19:04:03 -07:00
Danny Coates
94f1eabbc7 v3.0.17 2019-09-05 15:59:42 -07:00
Danny Coates
902bc6628e cache fonts 2019-09-05 15:57:07 -07:00
Danny Coates
460b741f17 clean service worker cache after activate instead of on install 2019-09-05 15:24:26 -07:00
Danny Coates
d5c488196d no-cache harder 2019-09-05 13:33:12 -07:00
Danny Coates
9ad9c9feb2 fixed git hooks 2019-09-05 13:16:32 -07:00
Danny Coates
6576e4a74c added sync-npm-dependencies script and hooks 2019-09-05 08:14:14 -07:00
Danny Coates
950872109e updated deps 2019-09-05 08:11:20 -07:00
Martijn Dekker
87051d27ed Pontoon: Update Interlingua (ia) localization of Firefox Send
Localization authors:
- Martijn Dekker <martijn@inlv.org>
2019-09-03 22:52:26 +00:00
Marcelo Ghelman
3451803b37 Pontoon: Update Portuguese (Brazil) (pt-BR) localization of Firefox Send
Localization authors:
- Marcelo Ghelman <marcelo.ghelman@gmail.com>
2019-08-29 10:32:02 +00:00
dskmori
ac15153e8f Pontoon: Update Japanese (ja) localization of Firefox Send
Localization authors:
- dskmori <ghoti.fish.dsk@gmail.com>
2019-08-28 13:12:29 +00:00
Danny Coates
924f5dc682 disable streaming download on mobile firefox 2019-08-26 10:49:19 -07:00
Danny Coates
ff9be6a213 updated deps 2019-08-26 08:58:34 -07:00
Roberto Alvarado
883728570e Pontoon: Update Spanish (Mexico) (es-MX) localization of Firefox Send
Localization authors:
- Roberto Alvarado <ralv888@gmail.com>
- Adolfo Jayme Barrientos <fitoschido@gmail.com>
2019-08-25 05:52:41 +00:00
Adolfo Jayme Barrientos
0435f17f9a Pontoon: Update Spanish (Mexico) (es-MX) localization of Firefox Send
Localization authors:
- Roberto Alvarado <ralv888@gmail.com>
- Adolfo Jayme Barrientos <fitoschido@gmail.com>
2019-08-20 16:34:33 +00:00
Danny Coates
1e1268fff0 fixed hebrew fluent variable name 2019-08-19 10:59:35 -07:00
Quế Tùng
252d7817e3 Pontoon: Update Vietnamese (vi) localization of Firefox Send
Localization authors:
- Quế Tùng <best.cloney.1301@gmail.com>
2019-08-17 15:53:31 +00:00
Danny Coates
ce28c38ebe v3.0.16 2019-08-12 10:10:07 -07:00
Danny Coates
f0407f9beb use custom configstore that doesn't use the fs 2019-08-12 10:00:57 -07:00
Sahithi
c6f222eb57 Pontoon: Update Telugu (te) localization of Firefox Send
Localization authors:
- Sahithi <sahithi@swecha.net>
2019-08-11 08:54:01 +00:00
leo.toneff
6dd6135185 Pontoon: Update Norwegian Bokmål (nb-NO) localization of Firefox Send
Localization authors:
- leo.toneff <leo.toneff@gmail.com>
- Håvar Henriksen <havar@firefox.no>
2019-08-10 16:33:36 +00:00
75 changed files with 2435 additions and 1528 deletions

View File

@@ -1,10 +1,8 @@
node_modules .circleci
.git
.tox
.DS_Store
firefox
assets
docs
test
coverage
.nyc_output .nyc_output
.vscode
.DS_Store
coverage
docs
firefox
node_modules

View File

@@ -19,6 +19,7 @@ rules:
node/no-unsupported-features/es-syntax: off node/no-unsupported-features/es-syntax: off
node/no-unsupported-features/node-builtins: off node/no-unsupported-features/node-builtins: off
node/no-unpublished-require: off node/no-unpublished-require: off
node/no-unpublished-import: off
security/detect-non-literal-fs-filename: off security/detect-non-literal-fs-filename: off
security/detect-object-injection: off security/detect-object-injection: off

View File

@@ -1,6 +1,7 @@
Abdalrahman Hwoij Abdalrahman Hwoij
Abhinav Adduri Abhinav Adduri
Adnan Kičin Adnan Kičin
Adolfo Jayme Barrientos
Alberto Castro Alberto Castro
Alexander Slovesnik Alexander Slovesnik
Alfredos-Panagiotis Damkalis Alfredos-Panagiotis Damkalis
@@ -63,6 +64,7 @@ George Raptis
Georgianizator Georgianizator
Gonçalo Matos Gonçalo Matos
Gwenn Gwenn
Hampus
Hugo Hugo
Hugo Abreu Hugo Abreu
Hyeonseok Shin Hyeonseok Shin
@@ -93,6 +95,7 @@ Juraj Cigáň
Kerim Kalamujić Kerim Kalamujić
Khaled Hosny Khaled Hosny
Kim Ludvigsen Kim Ludvigsen
Kim Younggeon
Kohei Yoshino Kohei Yoshino
Lan Glad Lan Glad
Lasse Liehu Lasse Liehu
@@ -101,6 +104,7 @@ Lobodzets
LuFlo LuFlo
Luis A. Sánchez Luis A. Sánchez
Luiz Carlos de Morais Luiz Carlos de Morais
Luiz Felipe F M Costa
Luna Jernberg Luna Jernberg
Mahay Alam Khan Mahay Alam Khan
Marcelo Ghelman Marcelo Ghelman
@@ -110,6 +114,7 @@ Mark Heijl
Mark Liang Mark Liang
Mark Liang (You-Wen) Mark Liang (You-Wen)
Marko Andrejić Marko Andrejić
Martijn Dekker
Marwan Mohamad Marwan Mohamad
Matjaž Horvat Matjaž Horvat
Maykon Chagas Maykon Chagas
@@ -131,6 +136,7 @@ Myungjae Won
Nicholas Skinsacos Nicholas Skinsacos
Nihad Nihad
Nihad Suljić Nihad Suljić
Niksend Mizuhara
Oscar Oscar
Paulius Paulius
Pedro Burlamaqui Bendahan Pedro Burlamaqui Bendahan
@@ -138,7 +144,9 @@ Peter deHaan
Pierre Neter Pierre Neter
Pin-guang Chen Pin-guang Chen
Piotr Drąg Piotr Drąg
Quentí
Quế Tùng Quế Tùng
Rachel Tublitz
Radu Popescu Radu Popescu
Rhoslyn Prys Rhoslyn Prys
RickieES RickieES
@@ -161,6 +169,7 @@ Sara Todaro
Sav22999 Sav22999
Schieck :) Schieck :)
Selim Şumlu Selim Şumlu
Selyan Sliman Amiri
Sidak Singh Aulakh Sidak Singh Aulakh
Slimane Amiri Slimane Amiri
Slimane Selyan AMIRI Slimane Selyan AMIRI
@@ -183,6 +192,7 @@ Victor Bychek
Vimal Raghubir Vimal Raghubir
Vitaliy Krutko Vitaliy Krutko
Weihang Lo Weihang Lo
Wiktor Furman
Wil Clouser Wil Clouser
YFdyh000 YFdyh000
Yassine Aït-El-Mouden Yassine Aït-El-Mouden
@@ -213,9 +223,11 @@ jesferman1993
jlG jlG
josotrix josotrix
jspam jspam
julen
julenx julenx
kenrick95 kenrick95
kumincir kumincir
leo.toneff
m4hdi.pdroid m4hdi.pdroid
mail mail
manxmensch manxmensch

View File

@@ -1,19 +1,59 @@
FROM node:10 AS builder ##
RUN addgroup --gid 10001 app && adduser --disabled-password --gecos '' --gid 10001 --home /app --uid 10001 app # Firefox Send - Mozilla
COPY package*.json /app/ #
WORKDIR /app # License https://github.com/mozilla/send/blob/master/LICENSE
RUN npm install --production ##
FROM node:10-slim
RUN addgroup --gid 10001 app && adduser --disabled-password --gecos '' --gid 10001 --home /app --uid 10001 app # Build project
FROM node:10 AS builder
RUN set -x \
# Add user
&& addgroup --gid 10001 app \
&& adduser --disabled-password \
--gecos '' \
--gid 10001 \
--home /app \
--uid 10001 \
app
COPY --chown=app:app . /app
USER app USER app
WORKDIR /app WORKDIR /app
COPY --chown=app:app --from=builder /app . RUN ls -la
COPY --chown=app:app . . RUN set -x \
# Build
&& npm ci \
&& npm run build
# Main image
FROM node:10-slim
RUN set -x \
# Add user
&& addgroup --gid 10001 app \
&& adduser --disabled-password \
--gecos '' \
--gid 10001 \
--home /app \
--uid 10001 \
app
RUN apt-get update && apt-get -y install git-core
USER app
WORKDIR /app
COPY --chown=app:app package*.json ./
COPY --chown=app:app app app
COPY --chown=app:app common common
COPY --chown=app:app public/locales public/locales
COPY --chown=app:app server server
COPY --chown=app:app --from=builder /app/dist dist
RUN ls -la
RUN npm ci --production && npm cache clean --force
RUN mkdir -p /app/.config/configstore RUN mkdir -p /app/.config/configstore
RUN ln -s dist/version.json version.json RUN ln -s dist/version.json version.json
ENV PORT=1443 ENV PORT=1443
EXPOSE $PORT
EXPOSE ${PORT}
CMD ["node", "server/bin/prod.js"] CMD ["node", "server/bin/prod.js"]

View File

@@ -1,4 +1,4 @@
# [![Firefox Send](./assets/logo.svg)](https://send.firefox.com/) # [![Firefox Send](./assets/icon.svg)](https://send.firefox.com/) Firefox Send
[![CircleCI](https://img.shields.io/circleci/project/github/mozilla/send.svg)](https://circleci.com/gh/mozilla/send) [![CircleCI](https://img.shields.io/circleci/project/github/mozilla/send.svg)](https://circleci.com/gh/mozilla/send)
@@ -30,7 +30,7 @@ A file sharing experiment which allows you to send encrypted files to other user
## Requirements ## Requirements
- [Node.js 10.0+](https://nodejs.org/) - [Node.js 10.x](https://nodejs.org/)
- [Redis server](https://redis.io/) (optional for development) - [Redis server](https://redis.io/) (optional for development)
- [AWS S3](https://aws.amazon.com/s3/) or compatible service. (optional) - [AWS S3](https://aws.amazon.com/s3/) or compatible service. (optional)

View File

@@ -60,9 +60,7 @@ function body(main) {
</a>`; </a>`;
*/ */
return html` return html`
<body <body class="flex flex-col items-center font-sans bg-grey-10 h-screen">
class="flex flex-col items-center font-sans bg-grey-lightest h-screen"
>
${state.cache(Header, 'header').render()} ${main(state, emit)} ${state.cache(Header, 'header').render()} ${main(state, emit)}
</body> </body>
`; `;

View File

@@ -25,7 +25,7 @@ module.exports = function(state, emit) {
let content = ''; let content = '';
let button = html` let button = html`
<div <div
class="bg-blue rounded-full m-4 flex items-center justify-center shadow-lg" class="bg-blue-50 rounded-full m-4 flex items-center justify-center shadow-lg"
style="width: 56px; height: 56px" style="width: 56px; height: 56px"
onclick="${onclick}" onclick="${onclick}"
> >

View File

@@ -76,8 +76,8 @@ async function polyfillStreams() {
} }
export default async function getCapabilities() { export default async function getCapabilities() {
const serviceWorker = const browser = browserName();
'serviceWorker' in navigator && browserName() !== 'edge'; const serviceWorker = 'serviceWorker' in navigator && browser !== 'edge';
let crypto = await checkCrypto(); let crypto = await checkCrypto();
const nativeStreams = checkStreams(); const nativeStreams = checkStreams();
let polyStreams = false; let polyStreams = false;
@@ -97,13 +97,16 @@ export default async function getCapabilities() {
window.matchMedia('(display-mode: standalone)').matches || window.matchMedia('(display-mode: standalone)').matches ||
navigator.standalone; navigator.standalone;
const mobileFirefox =
browser === 'firefox' && /mobile/i.test(navigator.userAgent);
return { return {
account, account,
crypto, crypto,
serviceWorker, serviceWorker,
streamUpload: nativeStreams || polyStreams, streamUpload: nativeStreams || polyStreams,
streamDownload: streamDownload:
nativeStreams && serviceWorker && browserName() !== 'safari', nativeStreams && serviceWorker && browser !== 'safari' && !mobileFirefox,
multifile: nativeStreams || polyStreams, multifile: nativeStreams || polyStreams,
share, share,
standalone standalone

View File

@@ -39,7 +39,7 @@ body {
} }
.btn { .btn {
@apply bg-blue-dark; @apply bg-blue-60;
@apply text-white; @apply text-white;
@apply cursor-pointer; @apply cursor-pointer;
@apply py-4; @apply py-4;
@@ -48,11 +48,11 @@ body {
} }
.btn:hover { .btn:hover {
@apply bg-blue-darker; @apply bg-blue-70;
} }
.btn:focus { .btn:focus {
@apply bg-blue-darker; @apply bg-blue-70;
} }
.checkbox { .checkbox {
@@ -70,7 +70,7 @@ body {
} }
.checkbox > label::before { .checkbox > label::before {
/* @apply bg-grey-lightest; */ /* @apply bg-grey-10; */
@apply border; @apply border;
@apply rounded-sm; @apply rounded-sm;
@@ -82,16 +82,16 @@ body {
} }
.checkbox > label:hover::before { .checkbox > label:hover::before {
@apply border-blue-dark; @apply border-blue-50;
} }
.checkbox > input:focus + label::before { .checkbox > input:focus + label::before {
@apply border-blue-dark; @apply border-blue-50;
} }
.checkbox > input:checked + label::before { .checkbox > input:checked + label::before {
@apply bg-blue-dark; @apply bg-blue-50;
@apply border-blue-dark; @apply border-blue-50;
background-image: url('../assets/lock.svg'); background-image: url('../assets/lock.svg');
background-position: center; background-position: center;
@@ -104,8 +104,8 @@ body {
} }
.checkbox > input:disabled + label::before { .checkbox > input:disabled + label::before {
@apply bg-blue-dark; @apply bg-blue-50;
@apply border-blue-dark; @apply border-blue-50;
background-image: url('../assets/lock.svg'); background-image: url('../assets/lock.svg');
background-position: center; background-position: center;
@@ -153,9 +153,21 @@ footer li:hover {
white-space: nowrap; white-space: nowrap;
} }
.link-blue {
@apply text-blue-60;
}
.link-blue:hover {
@apply text-blue-70;
}
.link-blue:focus {
@apply text-blue-70;
}
.main-header img { .main-header img {
height: 32px; height: 32px;
width: 170px; width: auto;
} }
.intro { .intro {
@@ -193,14 +205,14 @@ footer li:hover {
} }
progress { progress {
@apply bg-grey-light; @apply bg-grey-30;
@apply rounded-sm; @apply rounded-sm;
@apply w-full; @apply w-full;
@apply h-1; @apply h-1;
} }
progress::-webkit-progress-bar { progress::-webkit-progress-bar {
@apply bg-grey-light; @apply bg-grey-30;
@apply rounded-sm; @apply rounded-sm;
@apply w-full; @apply w-full;
@apply h-1; @apply h-1;
@@ -290,6 +302,55 @@ select {
} }
} }
@screen dark {
body {
@apply text-grey-10;
background-image: unset;
}
.btn {
@apply bg-blue-40;
@apply text-white;
}
.btn:hover {
@apply bg-blue-50;
}
.btn:focus {
@apply bg-blue-50;
}
.link-blue {
@apply text-blue-40;
}
.link-blue:hover {
@apply text-blue-50;
}
.link-blue:focus {
@apply text-blue-50;
}
.main > section {
@apply bg-grey-90;
}
.mozilla-logo {
background-color: white;
border: 1px solid white;
}
@screen md {
.main > section {
@apply border;
@apply border-grey-80;
}
}
}
@tailwind utilities; @tailwind utilities;
@responsive { @responsive {
@@ -325,8 +386,6 @@ select {
.signin:hover, .signin:hover,
.signin:focus { .signin:focus {
@apply shadow-btn;
transform: scale(1.0625); transform: scale(1.0625);
} }
@@ -337,19 +396,19 @@ select {
/* begin signin button color experiment */ /* begin signin button color experiment */
.white-blue { .white-blue {
@apply border-blue-dark; @apply border-blue-60;
@apply border-2; @apply border-2;
@apply text-blue-dark; @apply text-blue-60;
} }
.white-blue:hover, .white-blue:hover,
.white-blue:focus { .white-blue:focus {
@apply bg-blue-dark; @apply bg-blue-60;
@apply text-white; @apply text-white;
} }
.blue { .blue {
@apply bg-blue-dark; @apply bg-blue-60;
@apply text-white; @apply text-white;
} }

View File

@@ -62,7 +62,7 @@ if (process.env.NODE_ENV === 'production') {
fileInfo: null fileInfo: null
}; };
const app = routes(choo()); const app = routes(choo({ hash: true }));
// eslint-disable-next-line require-atomic-updates // eslint-disable-next-line require-atomic-updates
window.app = app; window.app = app;
app.use(experiments); app.use(experiments);

View File

@@ -2,7 +2,7 @@ const choo = require('choo');
const download = require('./ui/download'); const download = require('./ui/download');
const body = require('./ui/body'); const body = require('./ui/body');
module.exports = function(app = choo()) { module.exports = function(app = choo({ hash: true })) {
app.route('/', body(require('./ui/home'))); app.route('/', body(require('./ui/home')));
app.route('/download/:id', body(download)); app.route('/download/:id', body(download));
app.route('/download/:id/:key', body(download)); app.route('/download/:id/:key', body(download));

View File

@@ -11,13 +11,14 @@ const map = new Map();
const IMAGES = /.*\.(png|svg|jpg)$/; const IMAGES = /.*\.(png|svg|jpg)$/;
const VERSIONED_ASSET = /\.[A-Fa-f0-9]{8}\.(js|css|png|svg|jpg)$/; const VERSIONED_ASSET = /\.[A-Fa-f0-9]{8}\.(js|css|png|svg|jpg)$/;
const DOWNLOAD_URL = /\/api\/download\/([A-Fa-f0-9]{4,})/; const DOWNLOAD_URL = /\/api\/download\/([A-Fa-f0-9]{4,})/;
const FONT = /\.woff2?$/;
self.addEventListener('install', event => { self.addEventListener('install', () => {
event.waitUntil(precache()); self.skipWaiting();
}); });
self.addEventListener('activate', event => { self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim()); event.waitUntil(self.clients.claim().then(precache));
}); });
async function decryptStream(id) { async function decryptStream(id) {
@@ -83,16 +84,28 @@ async function decryptStream(id) {
} }
async function precache() { async function precache() {
try {
await cleanCache();
const cache = await caches.open(version);
const images = assets.match(IMAGES);
await cache.addAll(images);
} catch (e) {
console.error(e);
// cache will get populated on demand
}
}
async function cleanCache() {
const oldCaches = await caches.keys(); const oldCaches = await caches.keys();
for (const c of oldCaches) { for (const c of oldCaches) {
if (c !== version) { if (c !== version) {
await caches.delete(c); await caches.delete(c);
} }
} }
const cache = await caches.open(version); }
const images = assets.match(IMAGES);
await cache.addAll(images); function cacheable(url) {
return self.skipWaiting(); return VERSIONED_ASSET.test(url) || FONT.test(url);
} }
async function cachedOrFetched(req) { async function cachedOrFetched(req) {
@@ -102,7 +115,7 @@ async function cachedOrFetched(req) {
return cached; return cached;
} }
const fetched = await fetch(req); const fetched = await fetch(req);
if (fetched.ok && VERSIONED_ASSET.test(req.url)) { if (fetched.ok && cacheable(req.url)) {
cache.put(req, fetched.clone()); cache.put(req, fetched.clone());
} }
return fetched; return fetched;
@@ -115,7 +128,7 @@ self.onfetch = event => {
const dlmatch = DOWNLOAD_URL.exec(url.pathname); const dlmatch = DOWNLOAD_URL.exec(url.pathname);
if (dlmatch) { if (dlmatch) {
event.respondWith(decryptStream(dlmatch[1])); event.respondWith(decryptStream(dlmatch[1]));
} else if (VERSIONED_ASSET.test(url.pathname)) { } else if (cacheable(url.pathname)) {
event.respondWith(cachedOrFetched(req)); event.respondWith(cachedOrFetched(req));
} }
}; };

View File

@@ -64,8 +64,7 @@ class Account extends Component {
return html` return html`
<send-account> <send-account>
<button <button
class="px-4 py-2 md:px-8 md:py-4 focus:outline signin ${this class="px-4 py-2 md:px-8 md:py-4 focus:outline signin border-2 link-blue border-blue-60 hover:border-blue-70 dark:border-blue-40 dark:hover:border-blue-50"
.buttonClass}"
onclick="${e => this.login(e)}" onclick="${e => this.login(e)}"
title="${translate('signInOnlyButton')}" title="${translate('signInOnlyButton')}"
> >
@@ -79,19 +78,19 @@ class Account extends Component {
<input <input
type="image" type="image"
alt="${user.email}" alt="${user.email}"
class="w-8 h-8 rounded-full border text-blue md:text-white focus:outline" class="w-8 h-8 rounded-full border text-blue-50 md:text-white focus:outline"
src="${user.avatar}" src="${user.avatar}"
onclick="${e => this.avatarClick(e)}" onclick="${e => this.avatarClick(e)}"
/> />
<ul <ul
id="accountMenu" id="accountMenu"
class="invisible absolute top-0 right-0 mt-10 pt-2 pb-2 bg-white shadow-md whitespace-no-wrap outline-none z-50" class="invisible absolute top-0 right-0 mt-10 pt-2 pb-2 bg-white shadow-md whitespace-no-wrap outline-none z-50 dark:bg-grey-80"
onblur="${e => this.hideMenu(e)}" onblur="${e => this.hideMenu(e)}"
> >
<li class="p-2 text-grey-dark">${user.email}</li> <li class="p-2 text-grey-60 dark:text-grey-50">${user.email}</li>
<li> <li>
<button <button
class="block w-full text-left px-4 py-2 text-grey-darkest hover:bg-blue hover:text-white cursor-pointer focus:outline" class="block w-full text-left px-4 py-2 text-grey-80 dark:text-grey-30 hover:bg-blue-50 hover:text-white cursor-pointer focus:outline"
onclick="${e => this.logout(e)}" onclick="${e => this.logout(e)}"
title="${translate('signOut')}" title="${translate('signOut')}"
> >

View File

@@ -46,7 +46,7 @@ function password(state) {
id="password-input" id="password-input"
class="${state.archive.password class="${state.archive.password
? '' ? ''
: 'invisible'} border rounded focus:border-blue-dark leading-normal my-1 py-1 px-2 h-8" : 'invisible'} border rounded focus:border-blue-60 leading-normal my-1 py-1 px-2 h-8 dark:bg-grey-80"
autocomplete="off" autocomplete="off"
maxlength="${MAX_LENGTH}" maxlength="${MAX_LENGTH}"
type="password" type="password"
@@ -58,7 +58,7 @@ function password(state) {
<label <label
id="password-msg" id="password-msg"
for="password-input" for="password-input"
class="block text-xs text-grey-darker" class="block text-xs text-grey-70"
></label> ></label>
</div> </div>
`; `;
@@ -106,7 +106,9 @@ function password(state) {
function fileInfo(file, action) { function fileInfo(file, action) {
return html` return html`
<send-file class="flex flex-row items-center p-3 w-full"> <send-file class="flex flex-row items-center p-3 w-full">
<img class="h-8" src="${assets.get('blue_file.svg')}"/> <svg class="h-8 w-8 text-white dark:text-grey-90">
<use xlink:href="${assets.get('blue_file.svg')}#icon"/>
</svg>
<p class="ml-4 w-full"> <p class="ml-4 w-full">
<h1 class="text-base font-medium word-break-all">${file.name}</h1> <h1 class="text-base font-medium word-break-all">${file.name}</h1>
<div class="text-sm font-normal opacity-75 pt-1">${bytes( <div class="text-sm font-normal opacity-75 pt-1">${bytes(
@@ -120,7 +122,9 @@ function fileInfo(file, action) {
function archiveInfo(archive, action) { function archiveInfo(archive, action) {
return html` return html`
<p class="w-full flex items-center"> <p class="w-full flex items-center">
<img class="mr-3 flex-shrink-0" src="${assets.get('blue_file.svg')}"/> <svg class="h-8 w-6 mr-3 flex-shrink-0 text-white dark:text-grey-90">
<use xlink:href="${assets.get('blue_file.svg')}#icon"/>
</svg>
<p class="flex-grow"> <p class="flex-grow">
<h1 class="text-base font-medium word-break-all">${archive.name}</h1> <h1 class="text-base font-medium word-break-all">${archive.name}</h1>
<div class="text-sm font-normal opacity-75 pt-1">${bytes( <div class="text-sm font-normal opacity-75 pt-1">${bytes(
@@ -140,7 +144,7 @@ function archiveDetails(translate, archive) {
ontoggle="${toggled}" ontoggle="${toggled}"
> >
<summary <summary
class="flex items-center text-blue-dark text-sm cursor-pointer outline-none" class="flex items-center link-blue text-sm cursor-pointer outline-none"
> >
<svg <svg
class="fill-current w-4 h-4 mr-1" class="fill-current w-4 h-4 mr-1"
@@ -170,20 +174,25 @@ module.exports = function(state, emit, archive) {
state.capabilities.share || platform() === 'android' state.capabilities.share || platform() === 'android'
? html` ? html`
<button <button
class="text-blue-dark hover:text-blue-darker focus:text-blue-darker self-end flex items-end" class="link-blue self-end flex items-start"
onclick=${share} onclick=${share}
title="Share link" title="Share link"
> >
<img src="${assets.get('share-24.svg')}" class="mr-2" />Share link <svg class="h-4 w-4 mr-2">
<use xlink:href="${assets.get('share-24.svg')}#icon" />
</svg>
Share link
</button> </button>
` `
: html` : html`
<button <button
class="text-blue-dark hover:text-blue-darker focus:text-blue-darker focus:outline self-end flex items-center" class="link-blue focus:outline self-end flex items-center"
onclick=${copy} onclick=${copy}
title="${state.translate('copyLinkButton')}" title="${state.translate('copyLinkButton')}"
> >
<img src="${assets.get('copy-16.svg')}" class="mr-2" /> <svg class="h-4 w-4 mr-2">
<use xlink:href="${assets.get('copy-16.svg')}#icon" />
</svg>
${state.translate('copyLinkButton')} ${state.translate('copyLinkButton')}
</button> </button>
`; `;
@@ -191,12 +200,14 @@ module.exports = function(state, emit, archive) {
platform() === 'web' platform() === 'web'
? html` ? html`
<a <a
class="flex items-baseline text-blue-dark hover:text-blue-darker focus:text-blue-darker" class="flex items-baseline link-blue"
href="${archive.url}" href="${archive.url}"
title="${state.translate('downloadButtonLabel')}" title="${state.translate('downloadButtonLabel')}"
tabindex="0" tabindex="0"
> >
<img src="${assets.get('dl.svg')}" class="mr-2" /> <svg class="h-4 w-3 mr-2">
<use xlink:href="${assets.get('dl.svg')}#icon" />
</svg>
${state.translate('downloadButtonLabel')} ${state.translate('downloadButtonLabel')}
</a> </a>
` `
@@ -206,7 +217,7 @@ module.exports = function(state, emit, archive) {
return html` return html`
<send-archive <send-archive
id="archive-${archive.id}" id="archive-${archive.id}"
class="flex flex-col items-start rounded shadow-light bg-white p-4 w-full" class="flex flex-col items-start rounded shadow-light bg-white p-4 w-full dark:bg-grey-90 dark:border dark:border-grey-70"
> >
${archiveInfo( ${archiveInfo(
archive, archive,
@@ -225,7 +236,7 @@ module.exports = function(state, emit, archive) {
${expiryInfo(state.translate, archive)} ${expiryInfo(state.translate, archive)}
</div> </div>
${archiveDetails(state.translate, archive)} ${archiveDetails(state.translate, archive)}
<hr class="w-full border-t my-4" /> <hr class="w-full border-t my-4 dark:border-grey-70" />
<div class="flex justify-between w-full"> <div class="flex justify-between w-full">
${dl} ${copyOrShare} ${dl} ${copyOrShare}
</div> </div>
@@ -269,18 +280,21 @@ module.exports = function(state, emit, archive) {
module.exports.wip = function(state, emit) { module.exports.wip = function(state, emit) {
return html` return html`
<send-upload-area class="flex flex-col bg-white h-full w-full" id="wip"> <send-upload-area
class="flex flex-col bg-white h-full w-full dark:bg-grey-90"
id="wip"
>
${list( ${list(
Array.from(state.archive.files) Array.from(state.archive.files)
.reverse() .reverse()
.map(f => .map(f =>
fileInfo(f, remove(f, state.translate('deleteButtonHover'))) fileInfo(f, remove(f, state.translate('deleteButtonHover')))
), ),
'flex-shrink bg-grey-lightest rounded-t overflow-y-auto px-6 py-4 md:h-full md:max-h-half-screen', 'flex-shrink bg-grey-10 rounded-t overflow-y-auto px-6 py-4 md:h-full md:max-h-half-screen dark:bg-black',
'bg-white px-2 my-2 shadow-light rounded' 'bg-white px-2 my-2 shadow-light rounded dark:bg-grey-90 dark:border dark:border-grey-80'
)} )}
<div <div
class="flex-shrink-0 flex-grow flex items-end p-4 bg-grey-lightest rounded-b mb-1 font-medium" class="flex-shrink-0 flex-grow flex items-end p-4 bg-grey-10 rounded-b mb-1 font-medium dark:bg-grey-90"
> >
<input <input
id="file-upload" id="file-upload"
@@ -300,10 +314,12 @@ module.exports.wip = function(state, emit) {
class="flex items-center cursor-pointer" class="flex items-center cursor-pointer"
title="${state.translate('addFilesButton')}" title="${state.translate('addFilesButton')}"
> >
<img src="${assets.get('addfiles.svg')}" class="w-6 h-6 mr-2" /> <svg class="w-6 h-6 mr-2 link-blue">
<use xlink:href="${assets.get('addfiles.svg')}#plus" />
</svg>
${state.translate('addFilesButton')} ${state.translate('addFilesButton')}
</label> </label>
<div class="font-normal text-sm text-grey-darker"> <div class="font-normal text-sm text-grey-70 dark:text-grey-40">
${state.translate('totalSize', { ${state.translate('totalSize', {
size: bytes(state.archive.size) size: bytes(state.archive.size)
})} })}
@@ -378,22 +394,22 @@ module.exports.uploading = function(state, emit) {
return html` return html`
<send-upload-area <send-upload-area
id="${archive.id}" id="${archive.id}"
class="flex flex-col items-start rounded shadow-light bg-white p-4 w-full" class="flex flex-col items-start rounded shadow-light bg-white p-4 w-full dark:bg-grey-90"
> >
${archiveInfo(archive)} ${archiveInfo(archive)}
<div class="text-xs text-grey-dark w-full mt-2 mb-2"> <div class="text-xs opacity-75 w-full mt-2 mb-2">
${expiryInfo(state.translate, { ${expiryInfo(state.translate, {
dlimit: state.archive.dlimit, dlimit: state.archive.dlimit,
dtotal: 0, dtotal: 0,
expiresAt: Date.now() + 500 + state.archive.timeLimit * 1000 expiresAt: Date.now() + 500 + state.archive.timeLimit * 1000
})} })}
</div> </div>
<div class="text-blue-dark text-sm font-medium mt-2"> <div class="link-blue text-sm font-medium mt-2">
${progressPercent} ${progressPercent}
</div> </div>
<progress class="my-3" value="${progress}">${progressPercent}</progress> <progress class="my-3" value="${progress}">${progressPercent}</progress>
<button <button
class="text-blue-dark hover:text-blue-darker focus:text-blue-darker self-end font-medium" class="link-blue self-end font-medium"
onclick=${cancel} onclick=${cancel}
title="${state.translate('deletePopupCancel')}" title="${state.translate('deletePopupCancel')}"
> >
@@ -415,7 +431,7 @@ module.exports.empty = function(state, emit) {
? '' ? ''
: html` : html`
<button <button
class="center font-medium text-sm text-blue-dark hover:text-blue-darker focus:text-blue-darker mt-4 mb-2" class="center font-medium text-sm link-blue mt-4 mb-2"
onclick="${event => { onclick="${event => {
event.stopPropagation(); event.stopPropagation();
emit('signup-cta', 'drop'); emit('signup-cta', 'drop');
@@ -428,14 +444,16 @@ module.exports.empty = function(state, emit) {
`; `;
return html` return html`
<send-upload-area <send-upload-area
class="flex flex-col items-center justify-center border-2 border-dashed border-grey-transparent rounded px-6 py-16 h-full w-full" class="flex flex-col items-center justify-center border-2 border-dashed border-grey-transparent rounded px-6 py-16 h-full w-full dark:border-grey-60"
onclick="${e => { onclick="${e => {
if (e.target.tagName !== 'LABEL') { if (e.target.tagName !== 'LABEL') {
document.getElementById('file-upload').click(); document.getElementById('file-upload').click();
} }
}}" }}"
> >
<img src="${assets.get('addfiles.svg')}" width="48" height="48" /> <svg class="w-10 h-10 link-blue">
<use xlink:href="/${assets.get('addfiles.svg')}#plus" />
</svg>
<div class="pt-6 pb-2 text-center text-lg font-bold tracking-wide"> <div class="pt-6 pb-2 text-center text-lg font-bold tracking-wide">
${state.translate('dragAndDropFiles')} ${state.translate('dragAndDropFiles')}
</div> </div>
@@ -469,14 +487,11 @@ module.exports.empty = function(state, emit) {
`; `;
function focus(event) { function focus(event) {
event.target.nextElementSibling.classList.add('bg-blue-darker', 'outline'); event.target.nextElementSibling.classList.add('bg-blue-70', 'outline');
} }
function blur(event) { function blur(event) {
event.target.nextElementSibling.classList.remove( event.target.nextElementSibling.classList.remove('bg-blue-70', 'outline');
'bg-blue-darker',
'outline'
);
} }
function add(event) { function add(event) {
@@ -501,8 +516,10 @@ module.exports.preview = function(state, emit) {
</div> </div>
`; `;
return html` return html`
<send-archive class="flex flex-col max-h-full bg-white p-4 w-full md:w-128"> <send-archive
<div class="border rounded py-3 px-6"> class="flex flex-col max-h-full bg-white p-4 w-full md:w-128 dark:bg-grey-90"
>
<div class="border rounded py-3 px-6 dark:border-grey-70">
${archiveInfo(archive)} ${details} ${archiveInfo(archive)} ${details}
</div> </div>
<button <button
@@ -529,10 +546,10 @@ module.exports.downloading = function(state) {
const progressPercent = percent(progress); const progressPercent = percent(progress);
return html` return html`
<send-archive <send-archive
class="flex flex-col bg-white rounded shadow-light p-4 w-full max-w-sm md:w-128" class="flex flex-col bg-white rounded shadow-light p-4 w-full max-w-sm md:w-128 dark:bg-grey-90"
> >
${archiveInfo(archive)} ${archiveInfo(archive)}
<div class="text-blue-dark text-sm font-medium mt-2"> <div class="link-blue text-sm font-medium mt-2">
${progressPercent} ${progressPercent}
</div> </div>
<progress class="my-3" value="${progress}">${progressPercent}</progress> <progress class="my-3" value="${progress}">${progressPercent}</progress>

View File

@@ -18,7 +18,7 @@ module.exports = function body(main) {
return function(state, emit) { return function(state, emit) {
const b = html` const b = html`
<body <body
class="flex flex-col items-center font-sans md:h-screen md:bg-grey-lightest" class="flex flex-col items-center font-sans md:h-screen md:bg-grey-10 dark:bg-black"
> >
${banner(state, emit)} ${state.cache(Header, 'header').render()} ${banner(state, emit)} ${state.cache(Header, 'header').render()}
${main(state, emit)} ${state.cache(Footer, 'footer').render()} ${main(state, emit)} ${state.cache(Footer, 'footer').render()}

View File

@@ -10,14 +10,16 @@ module.exports = function(name, url) {
<h1 class="text-3xl font-bold my-4"> <h1 class="text-3xl font-bold my-4">
${state.translate('notifyUploadEncryptDone')} ${state.translate('notifyUploadEncryptDone')}
</h1> </h1>
<p class="font-normal leading-normal text-grey-darkest word-break-all"> <p
class="font-normal leading-normal text-grey-80 word-break-all dark:text-grey-40"
>
${state.translate('copyLinkDescription')} <br /> ${state.translate('copyLinkDescription')} <br />
${name} ${name}
</p> </p>
<input <input
type="text" type="text"
id="share-url" id="share-url"
class="w-full my-4 border rounded-lg leading-loose h-12 px-2 py-1" class="w-full my-4 border rounded-lg leading-loose h-12 px-2 py-1 dark:bg-grey-80"
value="${url}" value="${url}"
readonly="true" readonly="true"
/> />
@@ -29,7 +31,7 @@ module.exports = function(name, url) {
${state.translate('copyLinkButton')} ${state.translate('copyLinkButton')}
</button> </button>
<button <button
class="text-blue-dark hover:text-blue-darker focus:text-blue-darker my-4 font-medium cursor-pointer focus:outline" class="link-blue my-4 font-medium cursor-pointer focus:outline"
onclick="${close}" onclick="${close}"
title="${state.translate('okButton')}" title="${state.translate('okButton')}"
> >

View File

@@ -41,7 +41,9 @@ function preview(state, emit) {
<h1 class="text-3xl font-bold mb-4"> <h1 class="text-3xl font-bold mb-4">
${state.translate('downloadTitle')} ${state.translate('downloadTitle')}
</h1> </h1>
<p class="w-full text-grey-darkest text-center leading-normal"> <p
class="w-full text-grey-80 text-center leading-normal dark:text-grey-40"
>
${state.translate('downloadDescription')} ${state.translate('downloadDescription')}
</p> </p>
${archiveTile.preview(state, emit)} ${archiveTile.preview(state, emit)}

View File

@@ -5,13 +5,13 @@ module.exports = function(state) {
return html` return html`
<div <div
id="download-complete" id="download-complete"
class="flex flex-col items-center justify-center h-full w-full bg-white p-2" class="flex flex-col items-center justify-center h-full w-full bg-white p-2 dark:bg-grey-90"
> >
<h1 class="text-center text-3xl font-bold my-2"> <h1 class="text-center text-3xl font-bold my-2">
${state.translate('downloadFinish')} ${state.translate('downloadFinish')}
</h1> </h1>
<img src="${assets.get('completed.svg')}" class="my-12 h-48" /> <img src="${assets.get('completed.svg')}" class="my-12 h-48" />
<p class="text-grey-darkest leading-normal"> <p class="text-grey-80 leading-normal dark:text-grey-40">
${state.translate('trySendDescription')} ${state.translate('trySendDescription')}
</p> </p>
<p class="my-5"> <p class="my-5">

View File

@@ -6,12 +6,14 @@ module.exports = function(state, emit) {
const div = html` const div = html`
<div <div
class="h-full w-full flex flex-col items-center justify-center bg-white py-8 max-w-md mx-auto" class="h-full w-full flex flex-col items-center justify-center bg-white py-8 max-w-md mx-auto dark:bg-grey-90"
> >
<h1 class="text-3xl font-bold mb-4"> <h1 class="text-3xl font-bold mb-4">
${state.translate('downloadTitle')} ${state.translate('downloadTitle')}
</h1> </h1>
<p class="w-full mb-4 text-center text-grey-darkest leading-normal"> <p
class="w-full mb-4 text-center text-grey-80 dark:text-grey-40 leading-normal"
>
${state.translate('downloadDescription')} ${state.translate('downloadDescription')}
</p> </p>
<form <form
@@ -22,8 +24,8 @@ module.exports = function(state, emit) {
<input <input
id="password-input" id="password-input"
class="w-full border-l border-t border-b rounded-l-lg rounded-r-none ${invalid class="w-full border-l border-t border-b rounded-l-lg rounded-r-none ${invalid
? 'border-red' ? 'border-red dark:border-red-40'
: 'border-grey'} leading-loose px-2 py-1" : 'border-grey'} leading-loose px-2 py-1 dark:bg-grey-80"
maxlength="32" maxlength="32"
autocomplete="off" autocomplete="off"
placeholder="${state.translate('unlockInputPlaceholder')}" placeholder="${state.translate('unlockInputPlaceholder')}"
@@ -34,7 +36,7 @@ module.exports = function(state, emit) {
type="submit" type="submit"
id="password-btn" id="password-btn"
class="btn rounded-r-lg rounded-l-none ${invalid class="btn rounded-r-lg rounded-l-none ${invalid
? 'bg-red hover:bg-red focus:bg-red' ? 'bg-red hover:bg-red focus:bg-red dark:bg-red-40'
: ''}" : ''}"
value="${state.translate('unlockButtonLabel')}" value="${state.translate('unlockButtonLabel')}"
title="${state.translate('unlockButtonLabel')}" title="${state.translate('unlockButtonLabel')}"
@@ -42,7 +44,7 @@ module.exports = function(state, emit) {
</form> </form>
<label <label
id="password-error" id="password-error"
class="${invalid ? '' : 'invisible'} text-red my-4" class="${invalid ? '' : 'invisible'} text-red dark:text-red-40 my-4"
for="password-input" for="password-input"
> >
${state.translate('passwordTryAgain')} ${state.translate('passwordTryAgain')}
@@ -72,7 +74,9 @@ module.exports = function(state, emit) {
const password = el.value; const password = el.value;
if (password.length > 0) { if (password.length > 0) {
document.getElementById('password-btn').disabled = true; document.getElementById('password-btn').disabled = true;
state.fileInfo.url = window.location.href; // Strip any url parameters between fileId and secretKey
const fileInfoUrl = window.location.href.replace(/\?.+#/, '#');
state.fileInfo.url = fileInfoUrl;
state.fileInfo.password = password; state.fileInfo.password = password;
emit('getMetadata'); emit('getMetadata');
} }

View File

@@ -13,7 +13,7 @@ module.exports = function(state, emit) {
${state.translate('errorPageHeader')} ${state.translate('errorPageHeader')}
</h1> </h1>
<img class="my-12 h-48" src="${assets.get('error.svg')}" /> <img class="my-12 h-48" src="${assets.get('error.svg')}" />
<p class="max-w-md text-center text-grey-darkest leading-normal"> <p class="max-w-md text-center text-grey-80 leading-normal">
${state.translate('trySendDescription')} ${state.translate('trySendDescription')}
</p> </p>
<p class="my-5"> <p class="my-5">

View File

@@ -19,12 +19,9 @@ class Footer extends Component {
const feedbackUrl = `https://qsurvey.mozilla.com/s3/Firefox-Send-Product-Feedback?ver=${version}&browser=${browser}`; const feedbackUrl = `https://qsurvey.mozilla.com/s3/Firefox-Send-Product-Feedback?ver=${version}&browser=${browser}`;
return html` return html`
<footer <footer
class="flex flex-col md:flex-row items-start w-full flex-none self-start p-6 md:p-8 font-medium text-xs text-grey-dark md:items-center justify-between" class="flex flex-col md:flex-row items-start w-full flex-none self-start p-6 md:p-8 font-medium text-xs text-grey-60 dark:text-grey-40 md:items-center justify-between"
> >
<a <a class="mozilla-logo m-2" href="https://www.mozilla.org/">
class="mozilla-logo pb-10 md:pb-0 m-2"
href="https://www.mozilla.org/"
>
Mozilla Mozilla
</a> </a>
<ul <ul

View File

@@ -16,15 +16,27 @@ class Header extends Component {
this.account.render(); this.account.render();
return false; return false;
} }
createElement() { createElement() {
const title = const title =
platform() === 'android' platform() === 'android'
? html` ? html`
<a class=""><img src="${assets.get('logo.svg')}"/></a> <a class="flex flex-row items-center">
<img src="${assets.get('icon.svg')}" />
<svg class="w-48">
<use xlink:href="${assets.get('wordmark.svg')}#logo" />
</svg>
</a>
` `
: html` : html`
<a class="" href="/"><img src="${assets.get('logo.svg')}"/></a> <a class="flex flex-row items-center" href="/">
<img
alt="${this.state.translate('title')}"
src="${assets.get('icon.svg')}"
/>
<svg class="w-48 md:w-64">
<use xlink:href="${assets.get('wordmark.svg')}#logo" />
</svg>
</a>
`; `;
return html` return html`
<header <header

View File

@@ -4,7 +4,7 @@ const assets = require('../../common/assets');
module.exports = function intro(state) { module.exports = function intro(state) {
return html` return html`
<send-intro <send-intro
class="flex flex-col items-center justify-center bg-white px-6 md:py-0 py-6 mb-0 h-full w-full" class="flex flex-col items-center justify-center bg-white px-6 md:py-0 py-6 mb-0 h-full w-full dark:bg-grey-90"
> >
<div class="mt-12 flex flex-col h-full"> <div class="mt-12 flex flex-col h-full">
<h1 class="text-3xl font-bold md:pb-2"> <h1 class="text-3xl font-bold md:pb-2">

View File

@@ -6,7 +6,7 @@ module.exports = function(state, emit) {
<main class="main"> <main class="main">
${state.modal && modal(state, emit)} ${state.modal && modal(state, emit)}
<div <div
class="flex flex-col items-center bg-white m-4 px-6 py-8 border border-grey-light md:border-none md:px-12 md:py-16 shadow w-full md:h-full" class="flex flex-col items-center bg-white m-4 px-6 py-8 border border-grey-30 md:border-none md:px-12 md:py-16 shadow w-full md:h-full dark:bg-grey-90"
> >
<h1 class="text-center text-3xl font-bold"> <h1 class="text-center text-3xl font-bold">
${state.translate('legalTitle')} ${state.translate('legalTitle')}
@@ -19,7 +19,7 @@ module.exports = function(state, emit) {
href="https://www.mozilla.org/privacy/" href="https://www.mozilla.org/privacy/"
target="__blank" target="__blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="text-blue-dark hover:underline" class="link-blue hover:underline"
>Mozilla Privacy Policy</a >Mozilla Privacy Policy</a
> >
<span <span
@@ -31,7 +31,7 @@ module.exports = function(state, emit) {
href="https://github.com/mozilla/send/blob/master/docs/metrics.md" href="https://github.com/mozilla/send/blob/master/docs/metrics.md"
target="__blank" target="__blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="text-blue-dark hover:underline" class="link-blue hover:underline"
>here</a >here</a
>. >.
</p> </p>

View File

@@ -3,13 +3,12 @@ const html = require('choo/html');
module.exports = function(state, emit) { module.exports = function(state, emit) {
return html` return html`
<send-modal <send-modal
class="absolute inset-0 flex items-center justify-center overflow-hidden z-40 bg-white md:rounded-xl md:my-8" class="absolute inset-0 flex items-center justify-center overflow-hidden z-40 bg-white md:rounded-xl md:my-8 dark:bg-grey-90"
onclick="${close}"
> >
<div <div
class="h-full w-full max-h-screen absolute top-0 flex items-center justify-center" class="h-full w-full max-h-screen absolute top-0 flex items-center justify-center"
> >
<div class="w-full" onclick="${e => e.stopPropagation()}"> <div class="w-full">
${state.modal(state, emit, close)} ${state.modal(state, emit, close)}
</div> </div>
</div> </div>

View File

@@ -12,7 +12,7 @@ module.exports = function(state, emit) {
'downloadTitle' 'downloadTitle'
)}</h1> )}</h1>
<p <p
class="w-full p-2 border border-yellow-light rounded md:w-4/5 text-orange-dark bg-yellow-lighter text-center leading-normal" class="w-full p-2 border border-yellow-50 rounded md:w-4/5 text-orange-60 bg-yellow-40 text-center leading-normal"
> >
⚠️ ${state.translate('noStreamsWarning')} ⚠️ ⚠️ ${state.translate('noStreamsWarning')} ⚠️
</p> </p>

View File

@@ -13,7 +13,7 @@ module.exports = function(state, emit) {
${state.translate('expiredTitle')} ${state.translate('expiredTitle')}
</h1> </h1>
<img src="${assets.get('notFound.svg')}" class="my-12" /> <img src="${assets.get('notFound.svg')}" class="my-12" />
<p class="max-w-md text-center text-grey-darkest leading-normal"> <p class="max-w-md text-center text-grey-80 leading-normal">
${state.translate('trySendDescription')} ${state.translate('trySendDescription')}
</p> </p>
<p class="my-5"> <p class="my-5">

View File

@@ -15,7 +15,7 @@ class Promo extends Component {
createElement() { createElement() {
return html` return html`
<send-promo <send-promo
class="w-full flex-row items-center content-center justify-center bg-white text-grey-darkest px-4 py-3 flex border-b border-grey-banner leading-normal" class="w-full flex-row items-center content-center justify-center bg-white text-grey-80 px-4 py-3 flex border-b border-grey-banner leading-normal dark:bg-grey-90 dark:text-grey-20 dark:border-grey-80"
> >
<div class="flex items-center mx-auto"> <div class="flex items-center mx-auto">
<img <img
@@ -26,7 +26,7 @@ class Promo extends Component {
<span class="ml-2 sm:ml-4 text-xs sm:text-base"> <span class="ml-2 sm:ml-4 text-xs sm:text-base">
${this.state.translate('trailheadPromo')}${' '} ${this.state.translate('trailheadPromo')}${' '}
<a <a
class="underline text-blue-dark" class="underline link-blue"
href="http://www.mozilla.org/firefox/accounts/?utm_source=send.firefox.com&utm_medium=banner&utm_campaign=trailhead&utm_content=protect-your-privacy" href="http://www.mozilla.org/firefox/accounts/?utm_source=send.firefox.com&utm_medium=banner&utm_campaign=trailhead&utm_content=protect-your-privacy"
>${this.state.translate('learnMore')}</a >${this.state.translate('learnMore')}</a
> >

View File

@@ -6,7 +6,7 @@ module.exports = function(selected, options, translate, changed, htmlId) {
return html` return html`
<select <select
id="${htmlId}" id="${htmlId}"
class="appearance-none cursor-pointer border rounded bg-grey-lightest hover:border-blue-dark focus:border-blue-dark pl-1 pr-8 py-1 my-1 h-8" class="appearance-none cursor-pointer border rounded bg-grey-10 hover:border-blue-50 focus:border-blue-50 pl-1 pr-8 py-1 my-1 h-8 dark:bg-grey-80"
onchange="${choose}" onchange="${choose}"
> >
${options.map( ${options.map(

View File

@@ -9,14 +9,16 @@ module.exports = function(name, url) {
<h1 class="text-3xl font-bold my-4"> <h1 class="text-3xl font-bold my-4">
${state.translate('notifyUploadEncryptDone')} ${state.translate('notifyUploadEncryptDone')}
</h1> </h1>
<p class="font-normal leading-normal text-grey-darkest word-break-all"> <p
class="font-normal leading-normal text-grey-80 word-break-all dark:text-grey-40"
>
${state.translate('shareLinkDescription')}<br /> ${state.translate('shareLinkDescription')}<br />
${name} ${name}
</p> </p>
<input <input
type="text" type="text"
id="share-url" id="share-url"
class="w-full my-4 border rounded-lg leading-loose h-12 px-2 py-1" class="w-full my-4 border rounded-lg leading-loose h-12 px-2 py-1 dark:bg-grey-80"
value="${url}" value="${url}"
readonly="true" readonly="true"
/> />
@@ -28,7 +30,7 @@ module.exports = function(name, url) {
${state.translate('shareLinkButton')} ${state.translate('shareLinkButton')}
</button> </button>
<button <button
class="text-blue-dark hover:text-blue-darker focus:text-blue-darker my-4 font-medium cursor-pointer focus:outline" class="link-blue my-4 font-medium cursor-pointer focus:outline"
onclick="${close}" onclick="${close}"
title="${state.translate('okButton')}" title="${state.translate('okButton')}"
> >

View File

@@ -20,7 +20,7 @@ module.exports = function(trigger) {
${state.translate('accountBenefitTitle')} ${state.translate('accountBenefitTitle')}
</h1> </h1>
<ul <ul
class="leading-normal text-grey-darkest my-2 mt-4 pl-4 md:self-center" class="leading-normal list-disc text-grey-80 my-2 mt-4 pl-4 md:self-center dark:text-grey-40"
> >
<li> <li>
${state.translate('accountBenefitLargeFiles', { ${state.translate('accountBenefitLargeFiles', {
@@ -42,7 +42,7 @@ module.exports = function(trigger) {
<input <input
id="email-input" id="email-input"
type="email" type="email"
class="${hidden} border rounded-lg w-full px-2 py-1 h-12 mb-3 text-lg text-grey-darker leading-loose" class="${hidden} border rounded-lg w-full px-2 py-1 h-12 mb-3 text-lg text-grey-70 leading-loose dark:bg-grey-80 dark:text-white"
placeholder=${state.translate('emailPlaceholder')} placeholder=${state.translate('emailPlaceholder')}
/> />
<input <input
@@ -54,7 +54,7 @@ module.exports = function(trigger) {
/> />
</form> </form>
<button <button
class="my-3 text-blue-dark hover:text-blue-darker focus:text-blue-darker font-medium" class="my-3 link-blue font-medium"
title="${state.translate('deletePopupCancel')}" title="${state.translate('deletePopupCancel')}"
onclick=${cancel} onclick=${cancel}
> >

View File

@@ -16,7 +16,7 @@ module.exports = function() {
<h1 class="text-3xl font-bold my-4"> <h1 class="text-3xl font-bold my-4">
Tell us what you think. Tell us what you think.
</h1> </h1>
<p class="font-normal leading-normal text-grey-darkest px-4"> <p class="font-normal leading-normal text-grey-80 px-4">
Love Firefox Send? Take a quick survey to let us know how we can make Love Firefox Send? Take a quick survey to let us know how we can make
it better. it better.
</p> </p>
@@ -30,7 +30,7 @@ module.exports = function() {
Give feedback Give feedback
</a> </a>
<button <button
class="text-blue-dark hover:text-blue-darker focus:text-blue-darker font-medium cursor-pointer focus:outline" class="link-blue font-medium cursor-pointer focus:outline"
onclick="${close}" onclick="${close}"
title="Skip" title="Skip"
> >

View File

@@ -27,7 +27,7 @@ module.exports = function(state, emit) {
<main class="main"> <main class="main">
${state.modal && modal(state, emit)} ${state.modal && modal(state, emit)}
<section <section
class="flex flex-col items-center justify-center text-center bg-white m-6 px-6 py-8 border border-grey-light md:border-none md:px-12 md:py-16 shadow w-full md:h-full" class="flex flex-col items-center justify-center text-center bg-white m-6 px-6 py-8 border border-grey-30 md:border-none md:px-12 md:py-16 shadow w-full md:h-full dark:bg-grey-90"
> >
<h1 class="text-3xl font-bold">${strings.header}</h1> <h1 class="text-3xl font-bold">${strings.header}</h1>
<p class="mt-4 mb-8 max-w-md leading-normal">${strings.description}</p> <p class="mt-4 mb-8 max-w-md leading-normal">${strings.description}</p>

View File

@@ -1,9 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs> <symbol id="plus" viewBox="0 0 24 24">
<polygon id="addfiles-a" points="11.143 6 11.143 11.143 6 11.143 6 12.857 11.143 12.857 11.143 18 12.857 18 12.857 12.857 18 12.857 18 11.143 12.857 11.143 12.857 6"/>
</defs>
<g fill="none" fill-rule="evenodd"> <g fill="none" fill-rule="evenodd">
<path fill="#0060df" fill-rule="nonzero" d="M12,22.6666667 C17.8910373,22.6666667 22.6666667,17.8910373 22.6666667,12 C22.6666667,6.10896267 17.8910373,1.33333333 12,1.33333333 C6.10896267,1.33333333 1.33333333,6.10896267 1.33333333,12 C1.33333333,17.8910373 6.10896267,22.6666667 12,22.6666667 Z M12,24 C5.372583,24 0,18.627417 0,12 C0,5.372583 5.372583,0 12,0 C18.627417,0 24,5.372583 24,12 C24,18.627417 18.627417,24 12,24 Z"/> <path fill="currentColor" fill-rule="nonzero" d="M12,22.6666667 C17.8910373,22.6666667 22.6666667,17.8910373 22.6666667,12 C22.6666667,6.10896267 17.8910373,1.33333333 12,1.33333333 C6.10896267,1.33333333 1.33333333,6.10896267 1.33333333,12 C1.33333333,17.8910373 6.10896267,22.6666667 12,22.6666667 Z M12,24 C5.372583,24 0,18.627417 0,12 C0,5.372583 5.372583,0 12,0 C18.627417,0 24,5.372583 24,12 C24,18.627417 18.627417,24 12,24 Z"/>
<use fill="#0060df" xlink:href="#addfiles-a"/> <polygon fill="currentColor" points="11.143 6 11.143 11.143 6 11.143 6 12.857 11.143 12.857 11.143 18 12.857 18 12.857 12.857 18 12.857 18 11.143 12.857 11.143 12.857 6"/>
</g> </g>
</symbol>
<use xlink:href="#plus"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 856 B

After

Width:  |  Height:  |  Size: 831 B

View File

@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg width="26px" height="32px" viewBox="0 0 26 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: sketchtool 53 (72520) - https://sketchapp.com --> <symbol id="icon" viewBox="0 0 26 32">
<title>6AF7DAB4-6456-44F2-AABE-F001D910B641</title>
<desc>Created with sketchtool.</desc>
<defs> <defs>
<path d="M21.848475,31.6653183 L2.89005487,31.6653183 C1.32717435,31.6653183 0.104050469,30.3742431 0.104050469,28.8793139 L0.104050469,2.7860044 C0.104050469,1.22312388 1.39512568,0 2.89005487,0 L14.7135857,0 C15.4610503,0 16.2085149,0.271805307 16.6841742,0.815415921 L23.8190635,7.95030523 C24.3626741,8.49391584 24.6344794,9.17342911 24.6344794,9.9208937 L24.6344794,28.8793139 C24.6344794,30.3742431 23.4113555,31.6653183 21.848475,31.6653183 Z" id="path-1"></path> <path d="M21.848475,31.6653183 L2.89005487,31.6653183 C1.32717435,31.6653183 0.104050469,30.3742431 0.104050469,28.8793139 L0.104050469,2.7860044 C0.104050469,1.22312388 1.39512568,0 2.89005487,0 L14.7135857,0 C15.4610503,0 16.2085149,0.271805307 16.6841742,0.815415921 L23.8190635,7.95030523 C24.3626741,8.49391584 24.6344794,9.17342911 24.6344794,9.9208937 L24.6344794,28.8793139 C24.6344794,30.3742431 23.4113555,31.6653183 21.848475,31.6653183 Z" id="path-1"></path>
</defs> </defs>
@@ -14,14 +12,15 @@
<mask id="mask-2" fill="white"> <mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use> <use xlink:href="#path-1"></use>
</mask> </mask>
<use id="Mask" fill="#45A1FF" opacity="0.6" xlink:href="#path-1"></use> <use id="Mask" fill="#45a1ff" xlink:href="#path-1"></use>
<path d="M24.3031318,10.6474633 L16.7826187,10.6474633 C15.2742552,10.6474633 14.051485,9.42469306 14.051485,7.91632957 L14.051485,0.395816478" id="Path" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" mask="url(#mask-2)"></path> <path d="M24.3031318,10.6474633 L16.7826187,10.6474633 C15.2742552,10.6474633 14.051485,9.42469306 14.051485,7.91632957 L14.051485,0.395816478" id="Path" stroke="currentColor" stroke-width="2" stroke-linecap="round" mask="url(#mask-2)"></path>
<path d="M7.2830232,8.93885547 L8.91906464,8.93885547" id="Path" stroke="#0060DF" stroke-width="2" stroke-linecap="round" mask="url(#mask-2)"></path> <path d="M7.2830232,8.93885547 L8.91906464,8.93885547" id="Path" stroke="currentColor" stroke-width="2" stroke-linecap="round" mask="url(#mask-2)"></path>
<path d="M7.2830232,15.7798836 L17.5412669,15.7798836" id="Path" stroke="#0060DF" stroke-width="2" stroke-linecap="round" mask="url(#mask-2)"></path> <path d="M7.2830232,15.7798836 L17.5412669,15.7798836" id="Path" stroke="currentColor" stroke-width="2" stroke-linecap="round" mask="url(#mask-2)"></path>
<path d="M7.2830232,22.6209117 L17.5412669,22.6209117" id="Path" stroke="#0060DF" stroke-width="2" stroke-linecap="round" mask="url(#mask-2)"></path> <path d="M7.2830232,22.6209117 L17.5412669,22.6209117" id="Path" stroke="currentColor" stroke-width="2" stroke-linecap="round" mask="url(#mask-2)"></path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</symbol>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 16 16"><path fill="#4A4A4A" d="M9.414 8l5.293-5.293a1 1 0 0 0-1.414-1.414L8 6.586 2.707 1.293a1 1 0 0 0-1.414 1.414L6.586 8l-5.293 5.293a1 1 0 1 0 1.414 1.414L8 9.414l5.293 5.293a1 1 0 0 0 1.414-1.414z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 16 16"><path fill="#737373" d="M9.414 8l5.293-5.293a1 1 0 0 0-1.414-1.414L8 6.586 2.707 1.293a1 1 0 0 0-1.414 1.414L6.586 8l-5.293 5.293a1 1 0 1 0 1.414 1.414L8 9.414l5.293 5.293a1 1 0 0 0 1.414-1.414z"/></svg>

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 287 B

View File

@@ -1 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill="#0060df" d="M14.707 8.293l-3-3A1 1 0 0 0 11 5h-1V4a1 1 0 0 0-.293-.707l-3-3A1 1 0 0 0 6 0H3a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h3v3a2 2 0 0 0 2 2h5a2 2 0 0 0 2-2V9a1 1 0 0 0-.293-.707zM12.586 9H11V7.414zm-5-5H6V2.414zM6 7v2H3V2h2v2.5a.5.5 0 0 0 .5.5H8a2 2 0 0 0-2 2zm2 7V7h2v2.5a.5.5 0 0 0 .5.5H13v4z"/></svg> <svg xmlns="http://www.w3.org/2000/svg">
<symbol id="icon" viewBox="0 0 16 16">
<path fill="currentColor" d="M14.707 8.293l-3-3A1 1 0 0 0 11 5h-1V4a1 1 0 0 0-.293-.707l-3-3A1 1 0 0 0 6 0H3a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h3v3a2 2 0 0 0 2 2h5a2 2 0 0 0 2-2V9a1 1 0 0 0-.293-.707zM12.586 9H11V7.414zm-5-5H6V2.414zM6 7v2H3V2h2v2.5a.5.5 0 0 0 .5.5H8a2 2 0 0 0-2 2zm2 7V7h2v2.5a.5.5 0 0 0 .5.5H13v4z"/>
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 398 B

After

Width:  |  Height:  |  Size: 411 B

View File

@@ -1,15 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg width="12px" height="16px" viewBox="0 0 12 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <svg width="12px" height="16px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: sketchtool 53 (72520) - https://sketchapp.com --> <symbol id="icon" viewBox="0 0 12 16">
<title>728D143F-562C-4AE5-80DA-9DBBD9D647D8</title> <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<desc>Created with sketchtool.</desc> <g transform="translate(-770.000000, -481.000000)" fill="currentColor">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g transform="translate(744.000000, 350.000000)">
<g id="Send_Sending" transform="translate(-770.000000, -481.000000)" fill="#0060DF"> <g transform="translate(26.000000, 131.000000)">
<g id="List-Item-3" transform="translate(744.000000, 350.000000)"> <path d="M5.293,12.707 C5.6835,13.097382 6.316501,13.097383 6.707001,12.707 L11.707,7.707 C12.08597,7.31462 12.08054,6.69092 11.69481,6.305189 C11.30908,5.91946 10.68538,5.91403 10.293,6.293 L7,9.586 L7,1 C7,0.44772 6.552285,0 6,0 C5.447715,0 5,0.44772 5,1 L5,9.586 L1.707,6.293 C1.314621,5.91403 0.690915,5.91945 0.305181,6.305182 C-0.080553,6.690915 -0.085973,7.314622 0.293,7.707001 L5.293,12.707 Z M11,14 L1,14 C0.447715,14 0,14.447715 0,15 C0,15.5522852 0.447715,16 1,16 L11,16 C11.55228,16 12,15.5522852 12,15 C12,14.447715 11.55229,14 11,14 Z"></path>
<g id="Download-Icon" transform="translate(26.000000, 131.000000)">
<path d="M5.293,12.707 C5.6835,13.097382 6.316501,13.097383 6.707001,12.707 L11.707,7.707 C12.08597,7.31462 12.08054,6.69092 11.69481,6.305189 C11.30908,5.91946 10.68538,5.91403 10.293,6.293 L7,9.586 L7,1 C7,0.44772 6.552285,0 6,0 C5.447715,0 5,0.44772 5,1 L5,9.586 L1.707,6.293 C1.314621,5.91403 0.690915,5.91945 0.305181,6.305182 C-0.080553,6.690915 -0.085973,7.314622 0.293,7.707001 L5.293,12.707 Z M11,14 L1,14 C0.447715,14 0,14.447715 0,15 C0,15.5522852 0.447715,16 1,16 L11,16 C11.55228,16 12,15.5522852 12,15 C12,14.447715 11.55229,14 11,14 Z" id="Fill-1"></path>
</g> </g>
</g> </g>
</g> </g>
</g> </g>
</symbol>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

41
assets/icon.svg Normal file
View File

@@ -0,0 +1,41 @@
<svg viewBox="0 0 65 64" height="64" width="65" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="linear-gradient" x1="46.37" y1="59.71" x2="15.42" y2="6.11" gradientTransform="matrix(1, 0, 0, -1, 0, 64)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#ff980e"/>
<stop offset="0.21" stop-color="#ff7139"/>
<stop offset="0.36" stop-color="#ff5854"/>
<stop offset="0.46" stop-color="#ff4f5e"/>
<stop offset="0.69" stop-color="#ff3750"/>
<stop offset="0.86" stop-color="#f92261"/>
<stop offset="1" stop-color="#f5156c"/>
</linearGradient>
<linearGradient id="linear-gradient-2" x1="46.37" y1="59.71" x2="15.42" y2="6.11" gradientTransform="matrix(1, 0, 0, -1, 0, 64)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#fff44f" stop-opacity="0.8"/>
<stop offset="0.09" stop-color="#fff44f" stop-opacity="0.7"/>
<stop offset="0.75" stop-color="#fff44f" stop-opacity="0"/>
</linearGradient>
<linearGradient id="linear-gradient-3" x1="40.19" y1="26.08" x2="54.32" y2="50.55" gradientTransform="matrix(1, 0, 0, -1, 0, 64)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#3a8ee6"/>
<stop offset="0.24" stop-color="#5c79f0"/>
<stop offset="0.63" stop-color="#9059ff"/>
<stop offset="1" stop-color="#c139e6"/>
</linearGradient>
<linearGradient id="linear-gradient-4" x1="54.32" y1="50.58" x2="48.39" y2="40.31" gradientTransform="matrix(1, 0, 0, -1, 0, 64)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#6e008b" stop-opacity="0.5"/>
<stop offset="0.5" stop-color="#c846cb" stop-opacity="0"/>
</linearGradient>
<linearGradient id="linear-gradient-5" x1="56.96" y1="22.5" x2="41.98" y2="37.46" gradientTransform="matrix(1, 0, 0, -1, 0, 64)" gradientUnits="userSpaceOnUse">
<stop offset="0.14" stop-color="#6a2bea" stop-opacity="0"/>
<stop offset="0.34" stop-color="#642de4" stop-opacity="0.03"/>
<stop offset="0.55" stop-color="#5131d3" stop-opacity="0.12"/>
<stop offset="0.76" stop-color="#3139b7" stop-opacity="0.27"/>
<stop offset="0.98" stop-color="#054490" stop-opacity="0.48"/>
<stop offset="1" stop-color="#00458b" stop-opacity="0.5"/>
</linearGradient>
</defs>
<path d="M32.56,0C14.61,0,0,14.33,0,31.94a3.42,3.42,0,0,0,3.42,3.42H29.14V52.3l-8-8a3.42,3.42,0,1,0-4.84,4.84L30.14,63a2.73,2.73,0,0,0,.25.23l.23.17h.05l.24.14.27.13.28.1.29.07L32,64h1.27l.29-.07.29-.1.27-.13.24-.14.24-.17L35,63,48.8,49.18A3.43,3.43,0,0,0,44,44.34l-8,8v-17H61.7a3.42,3.42,0,0,0,3.42-3.42h0C65.12,14.33,50.51,0,32.56,0ZM7.09,28.51A25.54,25.54,0,0,1,32.56,6.85,25.55,25.55,0,0,1,58,28.51Z" fill="url(#linear-gradient)"/>
<path d="M32.56,0C14.61,0,0,14.33,0,31.94a3.42,3.42,0,0,0,3.42,3.42H29.14V52.3l-8-8a3.42,3.42,0,1,0-4.84,4.84L30.14,63a2.73,2.73,0,0,0,.25.23l.23.17h.05l.24.14.27.13.28.1.29.07L32,64h1.27l.29-.07.29-.1.27-.13.24-.14.24-.17L35,63,48.8,49.18A3.43,3.43,0,0,0,44,44.34l-8,8v-17H61.7a3.42,3.42,0,0,0,3.42-3.42h0C65.12,14.33,50.51,0,32.56,0ZM7.09,28.51A25.54,25.54,0,0,1,32.56,6.85,25.55,25.55,0,0,1,58,28.51Z" fill="url(#linear-gradient-2)"/>
<path d="M36,7.08A25.45,25.45,0,0,1,58,28.51H42.85A6.85,6.85,0,0,0,36,35.36H61.7a3.43,3.43,0,0,0,3.42-3.43c0-12.2-8.63-18.13-16-21.59A35.75,35.75,0,0,0,36,7.08Z" fill="url(#linear-gradient-3)"/>
<path d="M57.89,27.76c2.31,1.86,4.63,3.71,6.9,5.61a3.27,3.27,0,0,0,.33-1.44c0-12.2-8.63-18.13-16-21.59A35.75,35.75,0,0,0,36,7.08,25.47,25.47,0,0,1,57.89,27.76Z" fill="url(#linear-gradient-4)"/>
<path d="M57.5,28.51H42.85A6.85,6.85,0,0,0,36,35.36H61.7a3.36,3.36,0,0,0,2.64-1.28C62.09,32.19,59.79,30.36,57.5,28.51Z" opacity=".9" fill="url(#linear-gradient-5)"/>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg width="8px" height="6px" viewBox="0 0 8 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <svg width="8px" height="6px" viewBox="0 0 8 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: sketchtool 53 (72520) - https://sketchapp.com -->
<title>37845F0A-2932-4C2D-98E1-89BE1B168092</title>
<desc>Created with sketchtool.</desc>
<defs> <defs>
<path d="M6,8.48771202 C5.73480519,8.48765538 5.48049273,8.3822614 5.293,8.19471202 L2.293,5.19471202 C1.91402779,4.80233313 1.91944763,4.17862724 2.30518142,3.79289345 C2.69091522,3.40715965 3.31462111,3.40173981 3.707,3.78071202 L6,6.07371202 L8.293,3.78071202 C8.68537889,3.40173981 9.30908478,3.40715965 9.69481858,3.79289345 C10.0805524,4.17862724 10.0859722,4.80233313 9.707,5.19471202 L6.707,8.19471202 C6.51950727,8.3822614 6.26519481,8.48765538 6,8.48771202 Z" id="path-1"></path> <path d="M6,8.48771202 C5.73480519,8.48765538 5.48049273,8.3822614 5.293,8.19471202 L2.293,5.19471202 C1.91402779,4.80233313 1.91944763,4.17862724 2.30518142,3.79289345 C2.69091522,3.40715965 3.31462111,3.40173981 3.707,3.78071202 L6,6.07371202 L8.293,3.78071202 C8.68537889,3.40173981 9.30908478,3.40715965 9.69481858,3.79289345 C10.0805524,4.17862724 10.0859722,4.80233313 9.707,5.19471202 L6.707,8.19471202 C6.51950727,8.3822614 6.26519481,8.48765538 6,8.48771202 Z" id="path-1"></path>
</defs> </defs>
@@ -14,7 +11,7 @@
<mask id="mask-2" fill="white"> <mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use> <use xlink:href="#path-1"></use>
</mask> </mask>
<use id="Shape" fill="#0C0C0D" fill-rule="nonzero" opacity="0.599283854" xlink:href="#path-1"></use> <use id="Shape" fill="#b1b1b3" fill-rule="nonzero" opacity="0.599283854" xlink:href="#path-1"></use>
</g> </g>
</g> </g>
</g> </g>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,4 +1,5 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public <!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this - License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. --> - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M18 9a3 3 0 1 0-2.977-2.63l-6.94 3.47a3 3 0 1 0 0 4.319l6.94 3.47a3 3 0 1 0 .895-1.789l-6.94-3.47a3.03 3.03 0 0 0 0-.74l6.94-3.47C16.456 8.68 17.19 9 18 9z" fill="#0060df" fill-opacity=".8"></path></svg> <svg xmlns="http://www.w3.org/2000/svg">
<symbol id="icon" viewBox="0 0 24 24"><path fill-rule="evenodd" clip-rule="evenodd" d="M18 9a3 3 0 1 0-2.977-2.63l-6.94 3.47a3 3 0 1 0 0 4.319l6.94 3.47a3 3 0 1 0 .895-1.789l-6.94-3.47a3.03 3.03 0 0 0 0-.74l6.94-3.47C16.456 8.68 17.19 9 18 9z" fill="currentColor"></path></symbol></svg>

Before

Width:  |  Height:  |  Size: 559 B

After

Width:  |  Height:  |  Size: 539 B

6
assets/wordmark.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="logo" viewBox="66 0 340 64">
<path d="M84,48h5.83V35.87H103.3V30.45H89.83V23.51H103.3V18H84Zm23.57,0h5.79V25.81h-5.79Zm2.88-32.12a3.46,3.46,0,0,0-2.59,1,3.62,3.62,0,0,0-1,2.65,3.57,3.57,0,0,0,1,2.59,3.52,3.52,0,0,0,2.61,1,3.46,3.46,0,0,0,3.65-3.26c0-.12,0-.23,0-.35a3.71,3.71,0,0,0-1-2.65,3.5,3.5,0,0,0-2.67-1Zm19.14,9.53a7.22,7.22,0,0,0-3.72.93,5.82,5.82,0,0,0-2.4,2.89V25.81h-5.59V48h5.63V36.29a5.27,5.27,0,0,1,1.31-4,4.94,4.94,0,0,1,3.49-1.21,6.33,6.33,0,0,1,1.73.23,4,4,0,0,1,1.23.55l2-5.59a7.51,7.51,0,0,0-1.66-.61,8.11,8.11,0,0,0-2-.26Zm23.94,3.19a11.15,11.15,0,0,0-3.61-2.37,12.08,12.08,0,0,0-4.6-.86,11.62,11.62,0,0,0-8.3,3.37,11.17,11.17,0,0,0-2.44,3.67,11.59,11.59,0,0,0-.89,4.54,12.24,12.24,0,0,0,.83,4.52,10.52,10.52,0,0,0,2.36,3.66,10.93,10.93,0,0,0,3.71,2.44,12.75,12.75,0,0,0,4.85.88,12.15,12.15,0,0,0,6.12-1.39,13.25,13.25,0,0,0,4.11-3.74L151,40.6a6.23,6.23,0,0,1-2.18,2.15,6.36,6.36,0,0,1-3.33.8,6.7,6.7,0,0,1-4.13-1.25,6,6,0,0,1-2.23-3.43h17.62V36.74a11.71,11.71,0,0,0-.87-4.56,10.5,10.5,0,0,0-2.35-3.59Zm-14.21,5.85a6.38,6.38,0,0,1,2.26-3.12,6.11,6.11,0,0,1,3.74-1.15,6.26,6.26,0,0,1,3.73,1.08,5.56,5.56,0,0,1,2.1,3.19ZM167,16.08a6.05,6.05,0,0,0-2.91,1.54,6.15,6.15,0,0,0-1.56,2.89,18.1,18.1,0,0,0-.48,4.52v.78H158.4v5.1h3.65V48h5.63V30.91H173v-5.1h-5.3V24.75a13.34,13.34,0,0,1,.12-2,2,2,0,0,1,.6-1.19,2.45,2.45,0,0,1,1.33-.57,15.25,15.25,0,0,1,2.34-.15H173V15.63h-1.48A19.06,19.06,0,0,0,167,16.08Zm27.4,12.65a12,12,0,0,0-16.72,0,10.87,10.87,0,0,0-2.46,3.67,11.61,11.61,0,0,0-.89,4.5,11.46,11.46,0,0,0,7.07,10.64,11.73,11.73,0,0,0,4.64.9,12,12,0,0,0,4.66-.9,11.26,11.26,0,0,0,3.72-2.49,11.83,11.83,0,0,0,2.46-3.67,11.31,11.31,0,0,0,.9-4.48A11.43,11.43,0,0,0,194.4,28.73ZM191.7,39.3a5.88,5.88,0,0,1-1.29,2,6.53,6.53,0,0,1-1.93,1.31,6,6,0,0,1-4.76,0,6.34,6.34,0,0,1-1.93-1.31,6.06,6.06,0,0,1-1.3-2,6.48,6.48,0,0,1,0-4.86,5.76,5.76,0,0,1,1.3-2,6.08,6.08,0,0,1,1.93-1.32,6,6,0,0,1,4.76,0,6.37,6.37,0,0,1,1.93,1.32,5.73,5.73,0,0,1,1.29,2A6.39,6.39,0,0,1,191.7,39.3Zm29.47-13.49h-6.65l-4.68,6.57-4.64-6.57h-6.74l7.84,10.8L198,48h6.82l5-6.94L214.89,48h6.86l-8.46-11.34Zm34,7.46a12.88,12.88,0,0,0-3.37-1.44c-1.25-.34-2.46-.63-3.63-.88l-3.08-.7a10.64,10.64,0,0,1-2.51-.86A4.54,4.54,0,0,1,240.87,28a3.61,3.61,0,0,1-.62-2.19,4.8,4.8,0,0,1,1.58-3.7c1.06-1,2.73-1.44,5-1.44a9.84,9.84,0,0,1,5.07,1.17,10.47,10.47,0,0,1,3.39,3.23l2.79-2.18A15.22,15.22,0,0,0,253.45,19a13.8,13.8,0,0,0-6.59-1.44,12.13,12.13,0,0,0-4.14.66A10.33,10.33,0,0,0,239.53,20a7.53,7.53,0,0,0-2.05,2.63,7.41,7.41,0,0,0-.72,3.24,6.7,6.7,0,0,0,.84,3.53,7.06,7.06,0,0,0,2.2,2.22A11.11,11.11,0,0,0,242.86,33c1.13.32,2.29.6,3.47.84l3.26.74a12.63,12.63,0,0,1,2.8,1,5.86,5.86,0,0,1,2,1.56,3.88,3.88,0,0,1,.74,2.42,5.2,5.2,0,0,1-1.81,4.09A7.83,7.83,0,0,1,248,45.2a11,11,0,0,1-9.89-5.38l-3,2.34a15.86,15.86,0,0,0,5.23,4.54,16.06,16.06,0,0,0,7.7,1.7,12.58,12.58,0,0,0,4.38-.72,10.14,10.14,0,0,0,3.3-2,8.79,8.79,0,0,0,2.1-2.85,8.09,8.09,0,0,0,.74-3.39,6.94,6.94,0,0,0-1-3.8,7.71,7.71,0,0,0-2.42-2.37Zm27.51-4.72a10.53,10.53,0,0,0-3.58-2.34,11.89,11.89,0,0,0-4.49-.84,11.6,11.6,0,0,0-4.62.9,11.35,11.35,0,0,0-3.66,2.46A11.84,11.84,0,0,0,263,37a12.21,12.21,0,0,0,.82,4.51,10.53,10.53,0,0,0,2.36,3.64,11.24,11.24,0,0,0,3.7,2.42,12.41,12.41,0,0,0,4.82.88A11.68,11.68,0,0,0,280.82,47,12.84,12.84,0,0,0,285,42.82l-2.88-1.69a7.85,7.85,0,0,1-7.43,4.27,9,9,0,0,1-3.22-.53,8.21,8.21,0,0,1-2.55-1.5,8,8,0,0,1-1.78-2.28,7.79,7.79,0,0,1-.87-2.91h19.59V36.66a11.75,11.75,0,0,0-.86-4.54,10.92,10.92,0,0,0-2.35-3.57ZM266.4,35.22a8.88,8.88,0,0,1,1-2.73,8.55,8.55,0,0,1,1.79-2.18,8,8,0,0,1,2.44-1.43,8.31,8.31,0,0,1,3-.52,7.45,7.45,0,0,1,7.84,6.86ZM308.82,28a8.11,8.11,0,0,0-3-2,10.89,10.89,0,0,0-3.92-.67,9.06,9.06,0,0,0-4.58,1.14,8.76,8.76,0,0,0-3.14,3V25.82h-3.29V48h3.37V35.67a7.92,7.92,0,0,1,.53-2.93,7,7,0,0,1,1.48-2.3,6.46,6.46,0,0,1,2.22-1.5,7,7,0,0,1,2.75-.54,6.33,6.33,0,0,1,5,1.93A7.46,7.46,0,0,1,308,35.51V48h3.41V35.34a12.46,12.46,0,0,0-.66-4.19A8.68,8.68,0,0,0,308.82,28Zm27-12.42v14.1a8.14,8.14,0,0,0-1.58-1.83,10.08,10.08,0,0,0-2-1.36,10.39,10.39,0,0,0-2.3-.84,10.22,10.22,0,0,0-2.4-.28,11.63,11.63,0,0,0-4.4.84,11.09,11.09,0,0,0-3.59,2.38,11.3,11.3,0,0,0-2.42,3.65,12.81,12.81,0,0,0,0,9.32,11.56,11.56,0,0,0,2.4,3.66,10.58,10.58,0,0,0,3.59,2.38,11.77,11.77,0,0,0,4.42.84,9.69,9.69,0,0,0,2.4-.31,11,11,0,0,0,2.3-.86,9.72,9.72,0,0,0,2-1.37,8.75,8.75,0,0,0,1.58-1.85v4h3.33V15.59Zm-.37,24.58a8.3,8.3,0,0,1-10.85,4.47h0a7.68,7.68,0,0,1-2.6-1.76,7.88,7.88,0,0,1-1.73-2.67,8.93,8.93,0,0,1-.62-3.35,8.67,8.67,0,0,1,.62-3.3A8,8,0,0,1,322,30.89a8.17,8.17,0,0,1,2.6-1.79,8.27,8.27,0,0,1,6.51,0,8.64,8.64,0,0,1,2.63,1.81,7.85,7.85,0,0,1,1.72,2.67,8.67,8.67,0,0,1,.62,3.26,8.86,8.86,0,0,1-.65,3.33Z" fill="currentColor"/>
</symbol>
<use xlink:href="#logo"/>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -1,8 +1,8 @@
# Custom Loaders # Custom Loaders
## Generate Asset Map ## Android Index Plugin
This loader enumerates all the files in `assets/` so that `common/assets.js` can provide mappings from the source filename to the hashed filename used on the site. Generates the `index.html` page for the native android client
## Version Plugin ## Version Plugin

View File

@@ -1,4 +1,4 @@
const genmap = require('../build/generate_asset_map'); const genmap = require('./generate_asset_map');
const isServer = typeof genmap === 'function'; const isServer = typeof genmap === 'function';
let prefix = ''; let prefix = '';
let manifest = {}; let manifest = {};

View File

@@ -1,3 +1,7 @@
# Common Code # Common Code
This directory contains code loaded by both the frontend `app` and backend `server`. The code here can be challenging to understand at first because the contexts for the two (three counting the dev server) environments that include them are quite different, but the purpose of these modules are quite simple, to provide mappings from the source assets (`copy-16.png`) to the concrete production assets (`copy-16.db66e0bf.svg`). This directory contains code loaded by both the frontend `app` and backend `server`. The code here can be challenging to understand at first because the contexts for the two (three counting the dev server) environments that include them are quite different, but the purpose of these modules are quite simple, to provide mappings from the source assets (`copy-16.png`) to the concrete production assets (`copy-16.db66e0bf.svg`).
## Generate Asset Map
This loader enumerates all the files in `assets/` so that `common/assets.js` can provide mappings from the source filename to the hashed filename used on the site.

View File

@@ -1,13 +1,6 @@
## Setup ## Setup
Before building the Docker image, you must build the production assets: Run `docker build -t send:latest .` to create an image or `docker-compose up` to run a full testable stack. *We don't recommend using docker-compose for production.*
```sh
npm run build
```
Then you can run either `docker build` or `docker-compose up`.
## Environment variables: ## Environment variables:

2924
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{ {
"name": "firefox-send", "name": "firefox-send",
"description": "File Sharing Experiment", "description": "File Sharing Experiment",
"version": "3.0.15", "version": "3.0.20",
"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/",
@@ -35,7 +35,8 @@
"hooks": { "hooks": {
"pre-commit": "lint-staged", "pre-commit": "lint-staged",
"pre-push": "npm test", "pre-push": "npm test",
"post-merge": "npm install" "post-merge": "npm install",
"post-checkout": "scripts/sync-npm-dependencies.sh"
} }
}, },
"lint-staged": { "lint-staged": {
@@ -57,33 +58,33 @@
"cache": true "cache": true
}, },
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0 <11.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.5.5", "@babel/core": "^7.6.4",
"@babel/plugin-proposal-class-properties": "^7.5.5", "@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.5.5", "@babel/preset-env": "^7.6.3",
"@dannycoates/webcrypto-liner": "^0.1.37", "@dannycoates/webcrypto-liner": "^0.1.37",
"@fullhuman/postcss-purgecss": "^1.2.0", "@fullhuman/postcss-purgecss": "^1.3.0",
"@mattiasbuelens/web-streams-polyfill": "0.2.1", "@mattiasbuelens/web-streams-polyfill": "0.2.1",
"@sentry/browser": "^5.6.1", "@sentry/browser": "^5.7.1",
"asmcrypto.js": "^0.22.0", "asmcrypto.js": "^0.22.0",
"babel-loader": "^8.0.6", "babel-loader": "^8.0.6",
"babel-plugin-istanbul": "^5.2.0", "babel-plugin-istanbul": "^5.2.0",
"base64-js": "^1.3.1", "base64-js": "^1.3.1",
"content-disposition": "^0.5.3", "content-disposition": "^0.5.3",
"copy-webpack-plugin": "^5.0.4", "copy-webpack-plugin": "^5.0.4",
"core-js": "^3.1.4", "core-js": "^3.3.3",
"crc": "^3.8.0", "crc": "^3.8.0",
"cross-env": "^5.2.0", "cross-env": "^6.0.3",
"css-loader": "^3.2.0", "css-loader": "^3.2.0",
"css-mqpacker": "^7.0.0", "css-mqpacker": "^7.0.0",
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
"eslint": "^6.1.0", "eslint": "^6.5.1",
"eslint-config-prettier": "^6.0.0", "eslint-config-prettier": "^6.4.0",
"eslint-plugin-mocha": "^6.0.0", "eslint-plugin-mocha": "^6.2.0",
"eslint-plugin-node": "^9.1.0", "eslint-plugin-node": "^10.0.0",
"eslint-plugin-security": "^1.4.0", "eslint-plugin-security": "^1.4.0",
"expose-loader": "^0.7.5", "expose-loader": "^0.7.5",
"extract-loader": "^3.1.0", "extract-loader": "^3.1.0",
@@ -93,33 +94,33 @@
"git-rev-sync": "^1.12.0", "git-rev-sync": "^1.12.0",
"html-loader": "^0.5.5", "html-loader": "^0.5.5",
"http_ece": "^1.1.0", "http_ece": "^1.1.0",
"husky": "^3.0.3", "husky": "^3.0.9",
"intl-pluralrules": "^1.0.3", "intl-pluralrules": "^1.1.1",
"lint-staged": "^9.2.1", "lint-staged": "^9.4.2",
"mocha": "^6.2.0", "mocha": "^6.2.2",
"morgan": "^1.9.1", "morgan": "^1.9.1",
"nanobus": "^4.4.0", "nanobus": "^4.4.0",
"nanohtml": "^1.6.3", "nanohtml": "^1.8.1",
"nanotiming": "^7.3.1", "nanotiming": "^7.3.1",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"nyc": "^14.1.1", "nyc": "^14.1.1",
"postcss-loader": "^3.0.0", "postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.7.0", "postcss-preset-env": "^6.7.0",
"prettier": "^1.18.2", "prettier": "^1.18.2",
"proxyquire": "^2.1.1", "proxyquire": "^2.1.3",
"puppeteer": "^1.19.0", "puppeteer": "^1.20.0",
"raw-loader": "^3.1.0", "raw-loader": "^3.1.0",
"redis-mock": "^0.45.0", "redis-mock": "^0.46.0",
"rimraf": "^2.6.3", "rimraf": "^3.0.0",
"script-loader": "^0.7.2", "script-loader": "^0.7.2",
"sinon": "^7.4.1", "sinon": "^7.5.0",
"string-hash": "^1.1.3", "string-hash": "^1.1.3",
"stylelint": "^10.1.0", "stylelint": "^11.1.1",
"stylelint-config-standard": "^18.3.0", "stylelint-config-standard": "^19.0.0",
"stylelint-no-unsupported-browser-features": "^3.0.2", "stylelint-no-unsupported-browser-features": "^3.0.2",
"svgo": "^1.3.0", "svgo": "^1.3.0",
"svgo-loader": "^2.2.1", "svgo-loader": "^2.2.1",
"tailwindcss": "^1.1.0", "tailwindcss": "^1.1.2",
"val-loader": "^1.1.1", "val-loader": "^1.1.1",
"wdio-docker-service": "^1.4.2", "wdio-docker-service": "^1.4.2",
"wdio-dot-reporter": "0.0.10", "wdio-dot-reporter": "0.0.10",
@@ -130,26 +131,27 @@
"wdio-spec-reporter": "^0.1.5", "wdio-spec-reporter": "^0.1.5",
"webdriverio": "^4.14.4", "webdriverio": "^4.14.4",
"webpack": "4.38.0", "webpack": "4.38.0",
"webpack-cli": "^3.3.6", "webpack-cli": "^3.3.9",
"webpack-dev-middleware": "^3.7.0", "webpack-dev-middleware": "^3.7.2",
"webpack-dev-server": "^3.7.2", "webpack-dev-server": "^3.8.2",
"webpack-manifest-plugin": "^2.0.4", "webpack-manifest-plugin": "^2.2.0",
"webpack-unassert-loader": "^1.2.0" "webpack-unassert-loader": "^1.2.0"
}, },
"dependencies": { "dependencies": {
"@dannycoates/express-ws": "^5.0.3", "@dannycoates/express-ws": "^5.0.3",
"@fluent/bundle": "^0.13.0", "@fluent/bundle": "^0.13.0",
"@fluent/langneg": "^0.3.0", "@fluent/langneg": "^0.3.0",
"@google-cloud/storage": "^3.0.4", "@google-cloud/storage": "^4.0.0",
"@sentry/node": "^5.6.1", "@sentry/node": "^5.7.1",
"aws-sdk": "^2.506.0", "aws-sdk": "^2.553.0",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"choo": "^6.13.3", "choo": "^7.0.0",
"cldr-core": "^35.1.0", "cldr-core": "^35.1.0",
"convict": "^5.1.0", "configstore": "github:dannycoates/configstore#master",
"convict": "^5.2.0",
"express": "^4.17.1", "express": "^4.17.1",
"fxa-geodb": "^1.0.4", "fxa-geodb": "^1.0.4",
"helmet": "^3.20.0", "helmet": "^3.21.1",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"mozlog": "^2.2.0", "mozlog": "^2.2.0",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
@@ -178,6 +180,7 @@
"es-ES", "es-ES",
"es-MX", "es-MX",
"et", "et",
"eu",
"fi", "fi",
"fr", "fr",
"fy-NL", "fy-NL",
@@ -194,8 +197,10 @@
"ko", "ko",
"lt", "lt",
"ml", "ml",
"nb-NO",
"nl", "nl",
"nn-NO", "nn-NO",
"oc",
"pa-IN", "pa-IN",
"pl", "pl",
"pt-BR", "pt-BR",
@@ -208,6 +213,7 @@
"sr", "sr",
"su", "su",
"sv-SE", "sv-SE",
"te",
"th", "th",
"tr", "tr",
"uk", "uk",

View File

@@ -182,4 +182,5 @@ shareLinkDescription = شارِك الرابط الذي يصل إلى الملف
shareLinkButton = شارِك الرابط shareLinkButton = شارِك الرابط
# $name is the name of the file # $name is the name of the file
shareMessage = نزِّل ”{ $name }“ عبر { -send-brand }: خدمة لمشاركة الملفات بلا عناء وبخصوصية تامة shareMessage = نزِّل ”{ $name }“ عبر { -send-brand }: خدمة لمشاركة الملفات بلا عناء وبخصوصية تامة
trailheadPromo = يمكنك حماية خصوصيتك، طبعا. انضم إلى فَيَرفُكس.
learnMore = اطّلع على المزيد. learnMore = اطّلع على المزيد.

View File

@@ -151,3 +151,5 @@ shareLinkDescription = Compartiu l'enllaç al vostre fitxer:
shareLinkButton = Comparteix l'enllaç shareLinkButton = Comparteix l'enllaç
# $name is the name of the file # $name is the name of the file
shareMessage = Baixeu «{ $name }» amb el { -send-brand }: compartició de fitxers senzilla i segura shareMessage = Baixeu «{ $name }» amb el { -send-brand }: compartició de fitxers senzilla i segura
trailheadPromo = Hi ha una manera de protegir la vostra privadesa. Uniu-vos al Firefox.
learnMore = Més informació.

View File

@@ -151,3 +151,5 @@ shareLinkDescription = Nakomonij ri ximonel rik'in ri awokisab'al:
shareLinkButton = Tikomonïx ximonel shareLinkButton = Tikomonïx ximonel
# $name is the name of the file # $name is the name of the file
shareMessage = Tiqasäx "{ $name }" rik'in { -send-brand }: man k'ayew ta chuqa' ütz kikomonik ri yakb'äl shareMessage = Tiqasäx "{ $name }" rik'in { -send-brand }: man k'ayew ta chuqa' ütz kikomonik ri yakb'äl
trailheadPromo = K'o jun rub'anikil richin nachajij ri awichinanem. Tatunu' awi' rik'in ri Firefox.
learnMore = Tetamäx ch'aqa' chik.

View File

@@ -126,7 +126,7 @@ addPassword = Protegido con contraseña
emailPlaceholder = Ingresa tu correo electrónico emailPlaceholder = Ingresa tu correo electrónico
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB") # $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
signInSizeBump = Iniciar sesión para enviar hasta { $size } signInSizeBump = Iniciar sesión para enviar hasta { $size }
signInButton = Iniciar sesión/registrarse signInOnlyButton = Iniciar sesión
accountBenefitTitle = Crear una cuenta de { -firefox } o iniciar sesión accountBenefitTitle = Crear una cuenta de { -firefox } o iniciar sesión
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB") # $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
accountBenefitLargeFiles = Compartir archivos de hasta { $size } accountBenefitLargeFiles = Compartir archivos de hasta { $size }
@@ -145,3 +145,11 @@ noStreamsWarning = Puede que este navegador no pueda descifrar un archivo tan gr
noStreamsOptionCopy = Copiar el enlace para abrir en otro navegador noStreamsOptionCopy = Copiar el enlace para abrir en otro navegador
noStreamsOptionFirefox = Prueba nuestro navegador favorito noStreamsOptionFirefox = Prueba nuestro navegador favorito
noStreamsOptionDownload = Continuar con este navegador noStreamsOptionDownload = Continuar con este navegador
downloadFirefoxPromo = { -send-short-brand } te lo ofrece el nuevo { -firefox }.
# the next line after the colon contains a file name
shareLinkDescription = Comparte el enlace a tu archivo:
shareLinkButton = Enlace para compartir
# $name is the name of the file
shareMessage = Descarga «{ $name }» con { -send-brand }: es sencillo y seguro
trailheadPromo = Existe una forma de proteger tu privacidad. Únete a Firefox.
learnMore = Saber más.

View File

@@ -151,3 +151,5 @@ shareLinkDescription = Jaga linki failile:
shareLinkButton = Jaga linki shareLinkButton = Jaga linki
# $name is the name of the file # $name is the name of the file
shareMessage = Laadi “{ $name }” alla teenusega { -send-brand }, mis pakub lihtsat ja turvalist failijagamist shareMessage = Laadi “{ $name }” alla teenusega { -send-brand }, mis pakub lihtsat ja turvalist failijagamist
trailheadPromo = Oma privaatsust on võimalik kaitsta. Liitu Firefoxiga.
learnMore = Rohkem teavet.

View File

@@ -53,6 +53,7 @@ passwordSetError = امکان ثبت این گذواژه نیست
-send-short-brand = ارسال -send-short-brand = ارسال
-firefox = فایرفاکس -firefox = فایرفاکس
-mozilla = موزیلا -mozilla = موزیلا
introTitle = اشتراک‌گذاری ساده و خصوصیِ پرونده‌ها
# byte abbreviation # byte abbreviation
bytes = B bytes = B
# kibibyte abbreviation # kibibyte abbreviation

View File

@@ -1,19 +1,19 @@
# Firefox Send is a brand name and should not be localized. # Firefox Send is a brand name and should not be localized.
title = Firefox Send title = Firefox Send
siteFeedback = משוב siteFeedback = משוב
importingFile = מתבצע ייבוא... importingFile = מתבצע ייבוא
encryptingFile = מתבצעת הצפנה... encryptingFile = מתבצעת הצפנה...
decryptingFile = מתבצע פענוח... decryptingFile = מתבצע פענוח...
downloadCount = downloadCount =
{ $num -> { $num ->
[one] הורדה אחת [one] הורדה אחת
*[other] { $number } הורדות *[other] { $num } הורדות
} }
timespanHours = timespanHours =
{ $num -> { $num ->
[one] שעה אחת [one] שעה אחת
[two] שעתיים [two] שעתיים
*[other] { $number } שעות *[other] { $num } שעות
} }
copiedUrl = הועתק! copiedUrl = הועתק!
unlockInputPlaceholder = ססמה unlockInputPlaceholder = ססמה

View File

@@ -123,7 +123,7 @@ dragAndDropFiles = Traher e deponer files
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB") # $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
orClickWithSize = o cliccar pro inviar usque { $size } orClickWithSize = o cliccar pro inviar usque { $size }
addPassword = Proteger per contrasigno addPassword = Proteger per contrasigno
emailPlaceholder = Insere tu adresse email emailPlaceholder = Insere tu adresse de e-mail
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB") # $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
signInSizeBump = Accede pro inviar usque { $size } signInSizeBump = Accede pro inviar usque { $size }
signInOnlyButton = Authentica te signInOnlyButton = Authentica te

View File

@@ -140,4 +140,5 @@ shareLinkDescription = ファイルへのリンクを共有しましょう:
shareLinkButton = リンクを共有 shareLinkButton = リンクを共有
# $name is the name of the file # $name is the name of the file
shareMessage = { -send-brand } で "{ $name }" をダウンロード: シンプルで安全なファイル共有 shareMessage = { -send-brand } で "{ $name }" をダウンロード: シンプルで安全なファイル共有
trailheadPromo = プライバシーを保護する方法があります。Firefox を試してください。
learnMore = 詳細情報 learnMore = 詳細情報

View File

@@ -54,7 +54,7 @@ passwordSetError = Awal-agi uffir ur izmir ara ad ittwabaded
-firefox = Firefox -firefox = Firefox
-mozilla = Mozilla -mozilla = Mozilla
introTitle = Afessas, beṭṭu n ifuyla s wudem uslig introTitle = Afessas, beṭṭu n ifuyla s wudem uslig
introDescription = { -send-brand } ad k(yeǧǧ ad tebḍuḍ ifuyla iwgelhanensi ṭṭerf ɣer ṭṭerf akked useɣwen ara yemmten s wudem awurman. Daɣen, ad tizmireḍ ad tḥ€rzeḍ ayen i tbeṭṭuḍ s wudem uslig daɣen ad temneḍ imi agbur-ik ur yettɣimi ara srid i lebda. introDescription = { -send-brand } ad k(kem)-yeǧǧ ad tebḍuḍ ifuyla iwgelhanensi ṭṭerf ɣer ṭṭerf akked useɣwen ara yemmten s wudem awurman. Daɣen, ad tizmireḍ ad tḥ€rzeḍ ayen i tbeṭṭuḍ s wudem uslig daɣen ad temneḍ imi agbur-ik ur yettɣimi ara srid i lebda.
notifyUploadEncryptDone = Afaylu-ik yewgelhen daɣen ihegga i tuzna notifyUploadEncryptDone = Afaylu-ik yewgelhen daɣen ihegga i tuzna
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes' # downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
archiveExpiryInfo = Ad yemmet deffir { $downloadCount } neɣ { $timespan } archiveExpiryInfo = Ad yemmet deffir { $downloadCount } neɣ { $timespan }

View File

@@ -5,7 +5,7 @@ importingFile = 가져오는 중…
encryptingFile = 암호화 중… encryptingFile = 암호화 중…
decryptingFile = 복호화 중… decryptingFile = 복호화 중…
downloadCount = 다운로드 { $num }회 downloadCount = 다운로드 { $num }회
timespanHours = 1 시간 timespanHours = { $num }시간
copiedUrl = 복사 완료! copiedUrl = 복사 완료!
unlockInputPlaceholder = 비밀번호 unlockInputPlaceholder = 비밀번호
unlockButtonLabel = 잠금 해제 unlockButtonLabel = 잠금 해제

View File

@@ -54,6 +54,7 @@ passwordSetError = Dette passordet kunne ikke settes
-firefox = Firefox -firefox = Firefox
-mozilla = Mozilla -mozilla = Mozilla
introTitle = Enkel, privat fildeling introTitle = Enkel, privat fildeling
introDescription = { -send-brand } lar deg dele filer via en tidsbegrenset lenke med ende-til-ende-kryptering. På den måten kan du dele filer privat og samtidig være trygg på at filene dine ikke blir liggende på nettet for alltid.
notifyUploadEncryptDone = Filen din er kryptert og klar til å sende notifyUploadEncryptDone = Filen din er kryptert og klar til å sende
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes' # downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
archiveExpiryInfo = Utløper etter { $downloadCount } eller { $timespan } archiveExpiryInfo = Utløper etter { $downloadCount } eller { $timespan }
@@ -77,9 +78,78 @@ fileCount =
[one] 1 fil [one] 1 fil
*[other] { $num } filer *[other] { $num } filer
} }
# size is a localized number followed by a unit of bytes, ex. 2.5GB # byte abbreviation
bytes = B
# kibibyte abbreviation
kb = KB
# mebibyte abbreviation
mb = MB
# gibibyte abbreviation
gb = GB
# localized number and byte abbreviation. example "2.5MB"
fileSize = { $num }{ $units }
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
totalSize = Total størrelse: { $size } totalSize = Total størrelse: { $size }
# the next line after the colon contains a file name # the next line after the colon contains a file name
copyLinkDescription = Kopier lenken for å dele filen din: copyLinkDescription = Kopier lenken for å dele filen din:
copyLinkButton = Kopier lenke copyLinkButton = Kopier lenke
downloadTitle = Last ned filer downloadTitle = Last ned filer
downloadDescription = Denne filen ble delt via { -send-brand } med ende-til-ende-kryptering og en lenke som automatisk utløper.
trySendDescription = Prøv { -send-brand } for enkel, sikker fildeling.
# count will always be > 10
tooManyFiles =
{ $count ->
[one] Kun 1 fil kan lastes opp om gangen.
*[other] Kun { $count } filer kan lastes opp om gangen.
}
# count will always be > 10
tooManyArchives =
{ $count ->
[one] Kun 1 arkiv er tillatt.
*[other] Kun { $count } arkiver er tillatt.
}
expiredTitle = Denne lenken er utløpt.
notSupportedDescription = { -send-brand } virker ikke med denne nettleseren. { -send-short-brand } fungerer best med den nyeste versjonen av { -firefox }, og vil fungere med den nyeste versjonen av de fleste nettlesere.
downloadFirefox = Last ned { -firefox }
legalTitle = { -send-short-brand } Personvernerklæring
legalDateStamp = Versjon 1.0, datert den 12. mars 2019
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
expiresDaysHoursMinutes = { $days }d { $hours }t { $minutes }m
addFilesButton = Velg filer du vil laste opp
uploadButton = Last opp
# the first part of the string 'Drag and drop files or click to send up to 1GB'
dragAndDropFiles = Dra og slipp filer
# the second part of the string 'Drag and drop files or click to send up to 1GB'
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
orClickWithSize = eller klikk for å sende filer på opptil { $size }
addPassword = Beskytt med passord
emailPlaceholder = Skriv inn e-postadressen din
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
signInSizeBump = Logg inn for å sende opptil { $size }
signInOnlyButton = Logg inn
accountBenefitTitle = Opprett en { -firefox }-konto eller logg inn
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
accountBenefitLargeFiles = Del filer på opptil { $size }
accountBenefitDownloadCount = Del filer med flere personer
accountBenefitTimeLimit =
{ $count ->
[one] Hold lenker aktiv opptil 1 dag
*[other] Hold lenker aktiv opptil { $count } dager
}
accountBenefitSync = Behandle delte filer fra en hvilken som helst enhet
accountBenefitMoz = Les om andre { -mozilla }-tjenester
signOut = Logg ut
okButton = OK
downloadingTitle = Laster ned
noStreamsWarning = Denne nettleseren kan kanskje ikke dekryptere en så stor fil.
noStreamsOptionCopy = Kopier lenken for å åpne den i en annen nettleser
noStreamsOptionFirefox = Prøv favorittnettleseren vår
noStreamsOptionDownload = Fortsett med denne nettleseren
downloadFirefoxPromo = { -send-short-brand } presenteres for deg av den helt nye { -firefox }.
# the next line after the colon contains a file name
shareLinkDescription = Del lenken til filen din:
shareLinkButton = Del lenke
# $name is the name of the file
shareMessage = Last ned { $name } med { -send-brand }: enkel, trygg fildeling
trailheadPromo = Det finnes en måte å ta vare på personvernet ditt. Bruk Firefox.
learnMore = Les mer.

View File

@@ -36,11 +36,11 @@ footerLinkCookies = Cookies
passwordTryAgain = Senha incorreta. Tente novamente. passwordTryAgain = Senha incorreta. Tente novamente.
javascriptRequired = O Firefox Send requer JavaScript javascriptRequired = O Firefox Send requer JavaScript
whyJavascript = Por que o Firefox Send precisa do JavaScript? whyJavascript = Por que o Firefox Send precisa do JavaScript?
enableJavascript = Habilite o JavaScript e tente novamente. enableJavascript = Ative o JavaScript e tente novamente.
# A short representation of a countdown timer containing the number of hours and minutes remaining as digits, example "13h 47m" # A short representation of a countdown timer containing the number of hours and minutes remaining as digits, example "13h 47m"
expiresHoursMinutes = { $hours }h { $minutes }m expiresHoursMinutes = { $hours }h { $minutes }min
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m" # A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
expiresMinutes = { $minutes }m expiresMinutes = { $minutes }min
# A short status message shown when the user enters a long password # A short status message shown when the user enters a long password
maxPasswordLength = Tamanho máximo da senha: { $length } maxPasswordLength = Tamanho máximo da senha: { $length }
# A short status message shown when there was an error setting the password # A short status message shown when there was an error setting the password
@@ -54,7 +54,7 @@ passwordSetError = Essa senha não pôde ser definida
-firefox = Firefox -firefox = Firefox
-mozilla = Mozilla -mozilla = Mozilla
introTitle = Compartilhamento de arquivos fácil e privativo introTitle = Compartilhamento de arquivos fácil e privativo
introDescription = O { -send-brand } permite compartilhar arquivos com criptografia ponto a ponto e um link que expira automaticamente. Assim você pode manter o que compartilha privativo e ter certeza que suas coisas não ficarão online para sempre. introDescription = O { -send-brand } permite compartilhar arquivos com criptografia de ponta a ponta e um link que expira automaticamente. Assim você pode manter o que compartilha privativo e ter certeza que suas coisas não ficarão online para sempre.
notifyUploadEncryptDone = Seu arquivo foi criptografado e está pronto para ser enviado notifyUploadEncryptDone = Seu arquivo foi criptografado e está pronto para ser enviado
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes' # downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
archiveExpiryInfo = Expirar após { $downloadCount } ou { $timespan } archiveExpiryInfo = Expirar após { $downloadCount } ou { $timespan }
@@ -94,8 +94,8 @@ totalSize = Tamanho total: { $size }
copyLinkDescription = Copie o link para compartilhar seu arquivo: copyLinkDescription = Copie o link para compartilhar seu arquivo:
copyLinkButton = Copiar link copyLinkButton = Copiar link
downloadTitle = Baixar arquivos downloadTitle = Baixar arquivos
downloadDescription = Este arquivo foi compartilhado via { -send-brand } com criptografia ponto a ponto e um link que expira automaticamente. downloadDescription = Este arquivo foi compartilhado via { -send-brand } com criptografia de ponta a ponta e um link que expira automaticamente.
trySendDescription = Experimente o { -send-brand } para compartilhamento de arquivos simples e seguro. trySendDescription = Experimente o { -send-brand } para compartilhar arquivos com simplicidade e segurança.
# count will always be > 10 # count will always be > 10
tooManyFiles = tooManyFiles =
{ $count -> { $count ->
@@ -127,17 +127,17 @@ emailPlaceholder = Informe seu e-mail
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB") # $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
signInSizeBump = Entre na sua conta para enviar até { $size } signInSizeBump = Entre na sua conta para enviar até { $size }
signInOnlyButton = Entrar signInOnlyButton = Entrar
accountBenefitTitle = Crie uma Conta { -firefox } ou entre na sua conta accountBenefitTitle = Crie uma Conta { -firefox } ou entre se já tiver
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB") # $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
accountBenefitLargeFiles = Compartilhe arquivos até { $size } accountBenefitLargeFiles = Compartilhe arquivos até { $size }.
accountBenefitDownloadCount = Compartilhe arquivos com mais pessoas accountBenefitDownloadCount = Compartilhe arquivos com mais pessoas.
accountBenefitTimeLimit = accountBenefitTimeLimit =
{ $count -> { $count ->
[one] Mantenha links ativos por até 1 dia [one] Mantenha links ativos por até 1 dia.
*[other] Mantenha links ativos por até { $count } dias *[other] Mantenha links ativos por até { $count } dias.
} }
accountBenefitSync = Gerencie arquivos compartilhados a partir de qualquer dispositivo accountBenefitSync = Gerencie arquivos compartilhados a partir de qualquer dispositivo.
accountBenefitMoz = Conheça outros serviços da { -mozilla } accountBenefitMoz = Conheça outros serviços da { -mozilla }.
signOut = Sair signOut = Sair
okButton = OK okButton = OK
downloadingTitle = Baixando downloadingTitle = Baixando

View File

@@ -141,7 +141,7 @@ accountBenefitMoz = Läs om andra { -mozilla }-tjänster
signOut = Logga ut signOut = Logga ut
okButton = OK okButton = OK
downloadingTitle = Laddar ner downloadingTitle = Laddar ner
noStreamsWarning = Den här webbläsaren kanske inte kan dekryptera en fil så stor. noStreamsWarning = Den här webbläsaren kanske inte kan dekryptera en så stor fil.
noStreamsOptionCopy = Kopiera länken för att öppna i en annan webbläsare noStreamsOptionCopy = Kopiera länken för att öppna i en annan webbläsare
noStreamsOptionFirefox = Prova vår favoritwebbläsare noStreamsOptionFirefox = Prova vår favoritwebbläsare
noStreamsOptionDownload = Fortsätt med den här webbläsaren noStreamsOptionDownload = Fortsätt med den här webbläsaren

View File

@@ -89,6 +89,7 @@ totalSize = మొత్తం పరిమాణం: { $size }
copyLinkDescription = మీ ఫైలును భాగస్వామ్యం చేయడానికి ఈ లంకెను నకలు చేయండి: copyLinkDescription = మీ ఫైలును భాగస్వామ్యం చేయడానికి ఈ లంకెను నకలు చేయండి:
copyLinkButton = లంకెను నకలుతీయి copyLinkButton = లంకెను నకలుతీయి
downloadTitle = ఫైళ్లను దింపుకోండి downloadTitle = ఫైళ్లను దింపుకోండి
expiredTitle = ఈ లంకె గడువు ముగిసింది.
downloadFirefox = { -firefox } ను దింపుకోండి downloadFirefox = { -firefox } ను దింపుకోండి
legalTitle = { -send-short-brand } గోప్యతా నోటీసు legalTitle = { -send-short-brand } గోప్యతా నోటీసు
legalDateStamp = వెర్షన్ 1.0, మార్చి 12, 2019 నాటిది legalDateStamp = వెర్షన్ 1.0, మార్చి 12, 2019 నాటిది
@@ -96,6 +97,11 @@ legalDateStamp = వెర్షన్ 1.0, మార్చి 12, 2019 నా
expiresDaysHoursMinutes = { $days }d { $hours }h { $minutes }m expiresDaysHoursMinutes = { $days }d { $hours }h { $minutes }m
addFilesButton = ఎక్కించడానికి ఫైళ్ళను ఎంచుకోండి addFilesButton = ఎక్కించడానికి ఫైళ్ళను ఎంచుకోండి
uploadButton = ఎక్కించు uploadButton = ఎక్కించు
# the first part of the string 'Drag and drop files or click to send up to 1GB'
dragAndDropFiles = ఫైళ్ళను లాగండి మరియు వదలండి
# the second part of the string 'Drag and drop files or click to send up to 1GB'
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
orClickWithSize = లేదా { $size } వరకు పంపడానికి నొక్కండి
addPassword = సంకేతపదంతో రక్షించండి addPassword = సంకేతపదంతో రక్షించండి
emailPlaceholder = ఈ ఈమెయిలును ఇవ్వండి emailPlaceholder = ఈ ఈమెయిలును ఇవ్వండి
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB") # $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
@@ -105,6 +111,7 @@ accountBenefitTitle = ఒక { -firefox } ఖాతాని సృష్టి
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB") # $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
accountBenefitLargeFiles = { $size } పరిమాణం ఫైళ్ళ వరకు పంచుకోండి accountBenefitLargeFiles = { $size } పరిమాణం ఫైళ్ళ వరకు పంచుకోండి
accountBenefitDownloadCount = ఫైళ్లను ఎక్కువ మందితో పంచుకోండి accountBenefitDownloadCount = ఫైళ్లను ఎక్కువ మందితో పంచుకోండి
accountBenefitSync = ఏదైనా పరికరం నుండి పంచుకున్న ఫైళ్ళను నిర్వహించండి
signOut = నిష్క్రమించు signOut = నిష్క్రమించు
okButton = సరే okButton = సరే
downloadingTitle = దింపుకుంటోంది downloadingTitle = దింపుకుంటోంది

View File

@@ -141,9 +141,9 @@ accountBenefitLargeFiles = Обмінюйтесь файлами розміро
accountBenefitDownloadCount = Обмінюйтесь файлами з більшою кількістю людей accountBenefitDownloadCount = Обмінюйтесь файлами з більшою кількістю людей
accountBenefitTimeLimit = accountBenefitTimeLimit =
{ $count -> { $count ->
[one] Зберігати посилання активними протягом 1 дня [one] Термін дії посилання 1 день
[few] Зберігати посилання активними протягом { $count } днів [few] Термін дії посилання { $count } дні
*[other] Зберігати посилання активними протягом { $count } днів *[many] Термін дії посилання { $count } днів
} }
accountBenefitSync = Керуйте спільними файлами з буль-якого пристрою accountBenefitSync = Керуйте спільними файлами з буль-якого пристрою
accountBenefitMoz = Дізнайтеся про інші сервіси { -mozilla } accountBenefitMoz = Дізнайтеся про інші сервіси { -mozilla }

View File

@@ -87,7 +87,7 @@ totalSize = Tổng kích thước: { $size }
# the next line after the colon contains a file name # the next line after the colon contains a file name
copyLinkDescription = Sao chép liên kết để chia sẻ tập tin của bạn: copyLinkDescription = Sao chép liên kết để chia sẻ tập tin của bạn:
copyLinkButton = Sao chép liên kết copyLinkButton = Sao chép liên kết
downloadTitle = Tải tập tin downloadTitle = Tải xuống tập tin
downloadDescription = Tập tin này đã được chia sẻ qua { -send-brand } với mã hóa đầu cuối và liên kết tự động hết hạn. downloadDescription = Tập tin này đã được chia sẻ qua { -send-brand } với mã hóa đầu cuối và liên kết tự động hết hạn.
trySendDescription = Hãy thử { -send-brand } để chia sẻ tập tin đơn giản, an toàn. trySendDescription = Hãy thử { -send-brand } để chia sẻ tập tin đơn giản, an toàn.
# count will always be > 10 # count will always be > 10

View File

@@ -53,7 +53,7 @@ passwordSetError = 未能设置此密码
-mozilla = Mozilla -mozilla = Mozilla
introTitle = 简单、私密的文件分享服务 introTitle = 简单、私密的文件分享服务
introDescription = 使用 { -send-brand } 端到端加密分享文件,链接到期即焚。分享更私密,文件到期真正无痕迹。 introDescription = 使用 { -send-brand } 端到端加密分享文件,链接到期即焚。分享更私密,文件到期真正无痕迹。
notifyUploadEncryptDone = 您的文件已加密可以发送 notifyUploadEncryptDone = 您的文件已加密,现在可以发送
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes' # downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
archiveExpiryInfo = { $downloadCount }或 { $timespan }后过期 archiveExpiryInfo = { $downloadCount }或 { $timespan }后过期
timespanMinutes = timespanMinutes =
@@ -109,7 +109,7 @@ expiredTitle = 此链接已过期。
notSupportedDescription = { -send-brand } 无法在此浏览器上正常工作。{ -send-short-brand } 与最新版本 { -firefox } 配合使用体验最佳,也适用于目前的大多数浏览器。 notSupportedDescription = { -send-brand } 无法在此浏览器上正常工作。{ -send-short-brand } 与最新版本 { -firefox } 配合使用体验最佳,也适用于目前的大多数浏览器。
downloadFirefox = 下载 { -firefox } downloadFirefox = 下载 { -firefox }
legalTitle = { -send-short-brand } 隐私声明 legalTitle = { -send-short-brand } 隐私声明
legalDateStamp = 版本 1.0日期 2019年3月12日 legalDateStamp = 版本 1.0 2019年3月12日
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m" # A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
expiresDaysHoursMinutes = { $days } 天 { $hours } 小时 { $minutes } 分钟 expiresDaysHoursMinutes = { $days } 天 { $hours } 小时 { $minutes } 分钟
addFilesButton = 选择要上传的文件 addFilesButton = 选择要上传的文件
@@ -127,7 +127,7 @@ signInOnlyButton = 登录
accountBenefitTitle = 创建一个 { -firefox } 账户或登录 accountBenefitTitle = 创建一个 { -firefox } 账户或登录
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB") # $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
accountBenefitLargeFiles = 分享最大 { $size } 文件 accountBenefitLargeFiles = 分享最大 { $size } 文件
accountBenefitDownloadCount = 与更多人分享文件 accountBenefitDownloadCount = 可以与更多人分享
accountBenefitTimeLimit = accountBenefitTimeLimit =
{ $count -> { $count ->
[one] 链接有效期延至 1 天 [one] 链接有效期延至 1 天
@@ -140,7 +140,7 @@ okButton = 确定
downloadingTitle = 正在下载 downloadingTitle = 正在下载
noStreamsWarning = 此浏览器可能无法解密这么大的文件。 noStreamsWarning = 此浏览器可能无法解密这么大的文件。
noStreamsOptionCopy = 复制链接以在其他浏览器中打开 noStreamsOptionCopy = 复制链接以在其他浏览器中打开
noStreamsOptionFirefox = 试试大家最爱的浏览器 noStreamsOptionFirefox = 试试大家最爱的浏览器
noStreamsOptionDownload = 使用此浏览器继续 noStreamsOptionDownload = 使用此浏览器继续
downloadFirefoxPromo = { -send-short-brand } 由焕然一新的 { -firefox } 为您奉上。 downloadFirefoxPromo = { -send-short-brand } 由焕然一新的 { -firefox } 为您奉上。
# the next line after the colon contains a file name # the next line after the colon contains a file name

View File

@@ -0,0 +1,13 @@
#!/bin/bash
echo "checking package-lock.json for changes"
IFS=' '
read -ra G_PARAMS <<< "$HUSKY_GIT_PARAMS"
PREV=${G_PARAMS[0]}
NEXT=${G_PARAMS[1]}
if [ "$PREV" != "$NEXT" ]; then
DIFF=$(git diff $PREV $NEXT package-lock.json)
if [ "$DIFF" != "" ]; then
npm install
fi
fi

View File

@@ -67,7 +67,10 @@ module.exports = function(app) {
} }
app.use(function(req, res, next) { app.use(function(req, res, next) {
res.set('Pragma', 'no-cache'); res.set('Pragma', 'no-cache');
res.set('Cache-Control', 'no-cache'); res.set(
'Cache-Control',
'private, no-cache, no-store, must-revalidate, max-age=0'
);
next(); next();
}); });
app.use(bodyParser.json()); app.use(bodyParser.json());

View File

@@ -1,89 +1,103 @@
const colors = { const colors = {
transparent: 'transparent', transparent: 'transparent',
black: '#22292f', black: '#000000',
'grey-darkest': '#4a4a4f', 'grey-90': '#0c0c0d',
'grey-darker': '#606f7b', 'grey-80': '#2a2a2e',
'grey-dark': '#8795a1', 'grey-70': '#38383d',
grey: '#B1B1B3', 'grey-60': '#4a4a4f',
'grey-light': '#dae1e7', 'grey-50': '#737373',
grey: '#b1b1b3',
'grey-40': '#b1b1b3',
'grey-30': '#d7d7db',
'grey-banner': '#f0f0f4', 'grey-banner': '#f0f0f4',
'grey-transparent': 'hsla(250, 13%, 9%, .2)', 'grey-transparent': 'hsla(250, 13%, 9%, .2)',
'grey-lighter': '#f1f5f8', 'grey-20': '#ededf0',
'grey-lightest': '#F9F9FA', 'grey-10': '#f9f9fa',
white: '#ffffff', white: '#ffffff',
'red-darkest': '#3b0d0c', 'red-90': '#3e0200',
'red-darker': '#621b18', 'red-80': '#5a0002',
'red-dark': '#cc1f1a', 'red-70': '#a4000f',
red: '#e3342f', 'red-60': '#d70022',
'red-light': '#ef5753', red: '#d70022',
'red-lighter': '#f9acaa', 'red-50': '#ff0039',
'red-lightest': '#fcebea', // unspec
'red-40': '#ff3363',
'red-30': '#ff99aa',
'orange-darkest': '#462a16', 'orange-90': '#3e1300',
'orange-darker': '#613b1f', 'orange-80': '#712b00',
'orange-dark': '#de751f', 'orange-70': '#a44900',
orange: '#f6993f', 'orange-60': '#d76e00',
'orange-light': '#faad63', 'orange-50': '#ff9400',
'orange-lighter': '#fcd9b6', // unspec
'orange-lightest': '#fff5eb', 'orange-40': '#ffb24c',
'orange-30': '#ffd399',
'yellow-darkest': '#453411', 'yellow-90': '#3e2800',
'yellow-darker': '#684f1d', 'yellow-80': '#715100',
'yellow-dark': '#f2d024', 'yellow-70': '#a47f00',
yellow: '#ffed4a', 'yellow-60': '#d7b600',
'yellow-light': '#fff382', yellow: '#d7b600',
'yellow-lighter': '#fff9c2', 'yellow-50': '#ffe900',
'yellow-lightest': '#fcfbeb', 'yellow-40': '#ffed4c',
'yellow-30': '#fff599',
'green-darkest': '#003706', // 'green-darkest': '#003706',
'green-darker': '#006504', // 'green-darker': '#006504',
'green-dark': '#058b00', // 'green-dark': '#058b00',
green: '#12bc00', // green: '#12bc00',
'green-light': '#51d88a', // 'green-light': '#51d88a',
'green-lighter': '#a2f5bf', // 'green-lighter': '#a2f5bf',
'green-lightest': '#e3fcec', // 'green-lightest': '#e3fcec',
'teal-darkest': '#0d3331', // 'teal-darkest': '#0d3331',
'teal-darker': '#20504f', // 'teal-darker': '#20504f',
'teal-dark': '#38a89d', // 'teal-dark': '#38a89d',
teal: '#4dc0b5', // teal: '#4dc0b5',
'teal-light': '#64d5ca', // 'teal-light': '#64d5ca',
'teal-lighter': '#a0f0ed', // 'teal-lighter': '#a0f0ed',
'teal-lightest': '#e8fffe', // 'teal-lightest': '#e8fffe',
'blue-darkest': '#002275', 'blue-90': '#000f40',
'blue-darker': '#003eaa', 'blue-80': '#002275',
'blue-dark': '#0060df', 'blue-70': '#003eaa',
'blue-60': '#0060df',
'blue-50': '#0a84ff',
blue: '#0a84ff', blue: '#0a84ff',
'blue-light': '#6cb2eb', 'blue-40': '#45a1ff',
'blue-lighter': '#bcdefa', 'blue-30': '#99ccff',
'blue-lightest': '#eff8ff', 'blue-20': '#cce6ff',
'indigo-darkest': '#191e38', 'ink-90': '#0f1126',
'indigo-darker': '#2f365f', 'ink-80': '#202340',
'indigo-dark': '#5661b3', 'ink-70': '#363959',
indigo: '#6574cd',
'indigo-light': '#7886d7',
'indigo-lighter': '#b2b7ff',
'indigo-lightest': '#e6e8ff',
'purple-darkest': '#21183c', // 'indigo-darkest': '#191e38',
'purple-darker': '#382b5f', // 'indigo-darker': '#2f365f',
'purple-dark': '#794acf', // 'indigo-dark': '#5661b3',
purple: '#9561e2', // indigo: '#6574cd',
'purple-light': '#a779e9', // 'indigo-light': '#7886d7',
'purple-lighter': '#d6bbfc', // 'indigo-lighter': '#b2b7ff',
'purple-lightest': '#f3ebff', // 'indigo-lightest': '#e6e8ff',
'pink-darkest': '#451225', 'purple-90': '#25003e',
'pink-darker': '#6f213f', 'purple-80': '#440071',
'pink-dark': '#eb5286', 'purple-70': '#6200a4',
pink: '#f66d9b', 'purple-60': '#8000d7',
'pink-light': '#fa7ea8', 'purple-50': '#9400ff',
'pink-lighter': '#ffbbca', 'purple-40': '#ad3bff',
'pink-lightest': '#ffebef', 'purple-30': '#c069ff',
'purple-20': '#d7a3ff',
// 'pink-darkest': '#451225',
// 'pink-darker': '#6f213f',
// 'pink-dark': '#eb5286',
// pink: '#f66d9b',
// 'pink-light': '#fa7ea8',
// 'pink-lighter': '#ffbbca',
// 'pink-lightest': '#ffebef',
cloud: 'rgba(255, 255, 255, 0.8)', cloud: 'rgba(255, 255, 255, 0.8)',
violet: 'hsl(258, 57%, 35%)' violet: 'hsl(258, 57%, 35%)'
}; };
@@ -95,7 +109,8 @@ module.exports = {
sm: '576px', sm: '576px',
md: '768px', md: '768px',
lg: '992px', lg: '992px',
xl: '1200px' xl: '1200px',
dark: { raw: '(prefers-color-scheme: dark)' }
}, },
fontFamily: { fontFamily: {
sans: [ sans: [
@@ -181,10 +196,7 @@ module.exports = {
'4': '4px', '4': '4px',
'8': '8px' '8': '8px'
}, },
borderColor: global.Object.assign( borderColor: global.Object.assign({ default: colors['grey-30'] }, colors),
{ default: colors['grey-light'] },
colors
),
borderRadius: { borderRadius: {
none: '0', none: '0',
sm: '.125rem', sm: '.125rem',

View File

@@ -82,4 +82,29 @@ describe('Firefox Send', function() {
// check if upload and download file sizes are equal // check if upload and download file sizes are equal
assert.equal(uploadSize, downloadSize); assert.equal(uploadSize, downloadSize);
}); });
it(`should upload and download file with added tracking parameter`, function() {
const trackingUrl =
'?fbclid=IaMFak3Tr4ck1ng1d_SDlP0shBk8SM2EN3cCLFKpHVl-k-Pvv0sf9Zy0tnTu9srqVY';
const password = 'strongpassword';
browser.chooseFile(
homePage.uploadInput,
`${testFilesPath}/${testFiles[0]}`
);
browser.waitForExist(homePage.addPassword);
browser.click(homePage.addPassword);
browser.waitForExist(homePage.passwordInput);
browser.setValue(homePage.passwordInput, password);
browser.click(homePage.uploadButton);
browser.waitForExist(homePage.shareUrl);
const shareUrl = browser.getValue(homePage.shareUrl);
const downloadPage = new DownloadPage(
shareUrl.replace('#', `${trackingUrl}#`)
);
downloadPage.open();
downloadPage.downloadUsingPassword(password);
browser.waitForExist(downloadPage.downloadComplete);
assert.ok(fs.existsSync(path.join(downloadDir, testFiles[0])));
});
}); });

View File

@@ -4,23 +4,22 @@ const Page = require('./page');
class DownloadPage extends Page { class DownloadPage extends Page {
constructor(path) { constructor(path) {
super(path); super(path);
this.fileId = /download\/(\w+)\/#/.exec(path)[1]; this.fileId = /download\/(\w+)\/\??.*#/.exec(path)[1];
this.downloadButton = '#download-btn'; this.downloadButton = '#download-btn';
this.downloadComplete = '#download-complete'; this.downloadComplete = '#download-complete';
this.passwordInput = '#password-input';
this.passwordButton = '#password-btn';
} }
/** downloadUsingPassword(password) {
* @function waitForPageToLoad browser.waitForExist(this.passwordInput);
* @returns {Object} An object representing the page. browser.setValue(this.passwordInput, password);
* @throws ElementNotFound browser.click(this.passwordButton);
*/ return browser.click(this.downloadButton);
waitForPageToLoad() {
super.waitForPageToLoad();
browser.waitForExist(this.downloadButton);
return this;
} }
download() { download() {
browser.waitForExist(this.downloadButton);
return browser.click(this.downloadButton); return browser.click(this.downloadButton);
} }
} }

View File

@@ -10,6 +10,9 @@ class HomePage extends Page {
this.progress = 'progress'; this.progress = 'progress';
this.shareUrl = '#share-url'; this.shareUrl = '#share-url';
this.downloadCountSelect = '#expire-after-dl-count-select'; this.downloadCountSelect = '#expire-after-dl-count-select';
this.addPassword = '#add-password';
this.passwordInput = '#password-input';
this.passwordButton = '#password-btn';
} }
waitForPageToLoad() { waitForPageToLoad() {

View File

@@ -67,7 +67,7 @@ const serviceWorker = {
}, },
{ {
// loads all assets from assets/ for use by common/assets.js // loads all assets from assets/ for use by common/assets.js
test: require.resolve('./build/generate_asset_map.js'), test: require.resolve('./common/generate_asset_map.js'),
use: ['babel-loader', 'val-loader'] use: ['babel-loader', 'val-loader']
} }
] ]
@@ -142,6 +142,7 @@ const web = {
loader: 'svgo-loader', loader: 'svgo-loader',
options: { options: {
plugins: [ plugins: [
{ cleanupIDs: false },
{ removeViewBox: false }, // true causes stretched images { removeViewBox: false }, // true causes stretched images
{ convertStyleToAttrs: true }, // for CSP, no unsafe-eval { convertStyleToAttrs: true }, // for CSP, no unsafe-eval
{ removeTitle: true } // for smallness { removeTitle: true } // for smallness
@@ -176,7 +177,7 @@ const web = {
}, },
{ {
// loads all assets from assets/ for use by common/assets.js // loads all assets from assets/ for use by common/assets.js
test: require.resolve('./build/generate_asset_map.js'), test: require.resolve('./common/generate_asset_map.js'),
use: ['babel-loader', 'val-loader'] use: ['babel-loader', 'val-loader']
} }
] ]