Compare commits

...

76 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
Danny Coates
8df339b66d v3.0.15 2019-08-09 12:26:09 -07:00
Danny Coates
8702fda651 handle websocket construction exceptions 2019-08-09 11:47:44 -07:00
Danny Coates
807ecff471 updated sentry libs from raven to @sentry 2019-08-09 11:06:21 -07:00
Danny Coates
927c981cd7 added size/time info to up/download error reporting 2019-08-09 10:09:34 -07:00
Danny Coates
7073cc8ce6 added download hang detection and error reporting 2019-08-08 13:54:02 -07:00
Danny Coates
c925fae696 updated deps 2019-08-08 13:01:57 -07:00
Danny Coates
966d7a5e35 create configstore dir in docker container 2019-08-08 10:42:57 -07:00
Danny Coates
96c750c098 added size and duration to connection error reporting 2019-08-08 09:52:22 -07:00
Danny Coates
0729064753 Merge pull request #1378 from mozilla/new-ws
Use resumable uploads to GCS
2019-08-08 08:54:00 -07:00
Joergen
259a5a5f24 Pontoon: Update Danish (da) localization of Firefox Send
Localization authors:
- Joergen <joergenr@stofanet.dk>
2019-08-08 14:02:32 +00:00
Danny Coates
27be72e0cd refactored client side upload loop 2019-08-07 13:51:23 -07:00
Danny Coates
e4231bbc0f updated deps 2019-08-07 13:47:26 -07:00
Danny Coates
1d184f06bf revert webpack for broken css extraction 2019-08-07 12:14:27 -07:00
Quentí
f7b46a99ac Pontoon: Update Occitan (oc) localization of Firefox Send
Localization authors:
- Quentí <quentinantonin@free.fr>
2019-08-07 18:12:20 +00:00
Quentí
3fadb489c7 Pontoon: Update Occitan (oc) localization of Firefox Send
Localization authors:
- Quentí <quentinantonin@free.fr>
2019-08-07 17:13:10 +00:00
Danny Coates
6378676c2d use resumable uploads to GCS 2019-08-07 10:10:42 -07:00
Quentí
014d84e4c7 Pontoon: Update Occitan (oc) localization of Firefox Send
Localization authors:
- Quentí <quentinantonin@free.fr>
2019-08-07 16:54:33 +00:00
Quentí
a08d8435a9 Pontoon: Update Occitan (oc) localization of Firefox Send
Localization authors:
- Quentí <quentinantonin@free.fr>
2019-08-07 07:12:56 +00:00
Quentí
40a05c9ecf Pontoon: Update Occitan (oc) localization of Firefox Send
Localization authors:
- Quentí <quentinantonin@free.fr>
2019-08-07 06:52:27 +00:00
Danny Coates
527040afef updated ws dependency and slightly improved client side error handling, hung uploads will error instead of hang forever 2019-08-06 14:47:21 -07:00
Michal Stanke
a48a447808 Pontoon: Update Czech (cs) localization of Firefox Send
Localization authors:
- Michal Stanke <mstanke@mozilla.cz>
2019-08-06 12:14:20 +00:00
julen
f3569d7f98 Pontoon: Update Basque (eu) localization of Firefox Send
Localization authors:
- julen <julenx@gmail.com>
- Ander Elortondo <ander.elor@gmail.com>
2019-08-05 08:52:40 +00:00
صفا الفليج
6ca7d11efb Pontoon: Update Arabic (ar) localization of Firefox Send
Localization authors:
- صفا الفليج <safa1996alfulaij@gmail.com>
2019-08-05 08:52:37 +00:00
julen
b71ae4a0ff Pontoon: Update Basque (eu) localization of Firefox Send
Localization authors:
- p.sanroman.bengoetxea <p.sanroman.bengoetxea@gmail.com>
- julen <julenx@gmail.com>
- Ander Elortondo <ander.elor@gmail.com>
2019-08-05 08:34:11 +00:00
Aman Alam
7ba25664b5 Pontoon: Update Punjabi (pa-IN) localization of Firefox Send
Localization authors:
- Aman Alam <amanpreet.alam@gmail.com>
2019-08-05 00:52:41 +00:00
93 changed files with 2930 additions and 1774 deletions

View File

@@ -1,10 +1,8 @@
node_modules
.git
.tox
.DS_Store
firefox
assets
docs
test
coverage
.circleci
.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/node-builtins: off
node/no-unpublished-require: off
node/no-unpublished-import: off
security/detect-non-literal-fs-filename: off
security/detect-object-injection: off

View File

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

View File

@@ -1,18 +1,59 @@
FROM node:10 AS builder
RUN addgroup --gid 10001 app && adduser --disabled-password --gecos '' --gid 10001 --home /app --uid 10001 app
COPY package*.json /app/
WORKDIR /app
RUN npm install --production
##
# Firefox Send - Mozilla
#
# License https://github.com/mozilla/send/blob/master/LICENSE
##
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
WORKDIR /app
COPY --chown=app:app --from=builder /app .
COPY --chown=app:app . .
RUN ls -la
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 ln -s dist/version.json version.json
ENV PORT=1443
EXPOSE $PORT
EXPOSE ${PORT}
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)
@@ -30,7 +30,7 @@ A file sharing experiment which allows you to send encrypted files to other user
## Requirements
- [Node.js 10.0+](https://nodejs.org/)
- [Node.js 10.x](https://nodejs.org/)
- [Redis server](https://redis.io/) (optional for development)
- [AWS S3](https://aws.amazon.com/s3/) or compatible service. (optional)

View File

@@ -1,7 +1,7 @@
import 'intl-pluralrules';
import choo from 'choo';
import html from 'choo/html';
import Raven from 'raven-js';
import * as Sentry from '@sentry/browser';
import { setApiUrlPrefix, getConstants } from '../app/api';
import metrics from '../app/metrics';
@@ -60,9 +60,7 @@ function body(main) {
</a>`;
*/
return html`
<body
class="flex flex-col items-center font-sans bg-grey-lightest h-screen"
>
<body class="flex flex-col items-center font-sans bg-grey-10 h-screen">
${state.cache(Header, 'header').render()} ${main(state, emit)}
</body>
`;
@@ -82,7 +80,7 @@ function body(main) {
state.archive = new Archive([], DEFAULTS.EXPIRE_SECONDS);
state.storage = storage;
state.user = new User(storage, LIMITS);
state.raven = Raven;
state.sentry = Sentry;
});
app.use(metrics);
app.route('/', body(home));

View File

@@ -25,7 +25,7 @@ module.exports = function(state, emit) {
let content = '';
let button = html`
<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"
onclick="${onclick}"
>

View File

@@ -12,7 +12,7 @@ export default function initialState(state, emitter) {
getAsset(name) {
return `${state.prefix}/${name}`;
},
raven: {
sentry: {
captureException: e => {
console.error('ERROR ' + e + ' ' + e.stack);
}

View File

@@ -11,6 +11,15 @@ if (!fileProtocolWssUrl) {
fileProtocolWssUrl = 'wss://send.firefox.com/api/ws';
}
export class ConnectionError extends Error {
constructor(cancelled, duration, size) {
super(cancelled ? '0' : 'connection closed');
this.cancelled = cancelled;
this.duration = duration;
this.size = size;
}
}
export function setFileProtocolWssUrl(url) {
localStorage && localStorage.setItem('wssURL', url);
fileProtocolWssUrl = url;
@@ -137,17 +146,25 @@ export async function setPassword(id, owner_token, keychain) {
}
function asyncInitWebSocket(server) {
return new Promise(resolve => {
const ws = new WebSocket(server);
ws.onopen = () => {
resolve(ws);
};
return new Promise((resolve, reject) => {
try {
const ws = new WebSocket(server);
ws.addEventListener('open', () => resolve(ws), { once: true });
} catch (e) {
reject(new ConnectionError(false));
}
});
}
function listenForResponse(ws, canceller) {
return new Promise((resolve, reject) => {
function handleClose(event) {
// a 'close' event before a 'message' event means the request failed
ws.removeEventListener('message', handleMessage);
reject(new ConnectionError(canceller.cancelled));
}
function handleMessage(msg) {
ws.removeEventListener('close', handleClose);
try {
const response = JSON.parse(msg.data);
if (response.error) {
@@ -156,13 +173,11 @@ function listenForResponse(ws, canceller) {
resolve(response);
}
} catch (e) {
ws.close();
canceller.cancelled = true;
canceller.error = e;
reject(e);
}
}
ws.addEventListener('message', handleMessage, { once: true });
ws.addEventListener('close', handleClose, { once: true });
});
}
@@ -176,6 +191,8 @@ async function upload(
onprogress,
canceller
) {
let size = 0;
const start = Date.now();
const host = window.location.hostname;
const port = window.location.port;
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
@@ -203,31 +220,41 @@ async function upload(
const reader = stream.getReader();
let state = await reader.read();
let size = 0;
while (!state.done) {
const buf = state.value;
if (canceller.cancelled) {
throw canceller.error;
ws.close();
}
if (ws.readyState !== WebSocket.OPEN) {
break;
}
const buf = state.value;
ws.send(buf);
onprogress(size);
size += buf.length;
state = await reader.read();
while (ws.bufferedAmount > ECE_RECORD_SIZE * 2) {
while (
ws.bufferedAmount > ECE_RECORD_SIZE * 2 &&
ws.readyState === WebSocket.OPEN &&
!canceller.cancelled
) {
await delay();
}
}
const footer = new Uint8Array([0]);
ws.send(footer);
if (ws.readyState === WebSocket.OPEN) {
ws.send(new Uint8Array([0])); //EOF
}
await completedResponse;
ws.close();
uploadInfo.duration = Date.now() - start;
return uploadInfo;
} catch (e) {
ws.close(4000);
e.size = size;
e.duration = Date.now() - start;
throw e;
} finally {
if (![WebSocket.CLOSED, WebSocket.CLOSING].includes(ws.readyState)) {
ws.close();
}
}
}
@@ -244,7 +271,6 @@ export function uploadWs(
return {
cancel: function() {
canceller.error = new Error(0);
canceller.cancelled = true;
},
@@ -284,7 +310,7 @@ async function downloadS(id, keychain, signal) {
return response.body;
}
async function tryDownloadStream(id, keychain, signal, tries = 1) {
async function tryDownloadStream(id, keychain, signal, tries = 2) {
try {
const result = await downloadS(id, keychain, signal);
return result;
@@ -306,7 +332,7 @@ export function downloadStream(id, keychain) {
}
return {
cancel,
result: tryDownloadStream(id, keychain, controller.signal, 2)
result: tryDownloadStream(id, keychain, controller.signal)
};
}
@@ -346,7 +372,7 @@ async function download(id, keychain, onprogress, canceller) {
});
}
async function tryDownload(id, keychain, onprogress, canceller, tries = 1) {
async function tryDownload(id, keychain, onprogress, canceller, tries = 2) {
try {
const result = await download(id, keychain, onprogress, canceller);
return result;
@@ -367,7 +393,7 @@ export function downloadFile(id, keychain, onprogress) {
}
return {
cancel,
result: tryDownload(id, keychain, onprogress, canceller, 2)
result: tryDownload(id, keychain, onprogress, canceller)
};
}

View File

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

View File

@@ -76,7 +76,7 @@ export default function(state, emitter) {
state.storage.remove(ownedFile.id);
await ownedFile.del();
} catch (e) {
state.raven.captureException(e);
state.sentry.captureException(e);
}
render();
});
@@ -176,14 +176,17 @@ export default function(state, emitter) {
} catch (err) {
if (err.message === '0') {
//cancelled. do nothing
const duration = Date.now() - start;
metrics.cancelledUpload(archive, duration);
metrics.cancelledUpload(archive, err.duration);
render();
} else {
// eslint-disable-next-line no-console
console.error(err);
state.raven.captureException(err);
metrics.stoppedUpload(archive);
state.sentry.withScope(scope => {
scope.setExtra('duration', err.duration);
scope.setExtra('size', err.size);
state.sentry.captureException(err);
});
metrics.stoppedUpload(archive, err.duration);
emitter.emit('pushState', '/error');
}
} finally {
@@ -262,7 +265,12 @@ export default function(state, emitter) {
state.transfer = null;
const location = err.message === '404' ? '/404' : '/error';
if (location === '/error') {
state.raven.captureException(err);
state.sentry.withScope(scope => {
scope.setExtra('duration', err.duration);
scope.setExtra('size', err.size);
scope.setExtra('progress', err.progress);
state.sentry.captureException(err);
});
const duration = Date.now() - start;
metrics.stoppedDownload({
size,

View File

@@ -112,6 +112,7 @@ export default class FileReceiver extends Nanobus {
}
async downloadStream(noSave = false) {
const start = Date.now();
const onprogress = p => {
this.progress = [p, this.fileInfo.size];
this.emit('progress');
@@ -153,7 +154,7 @@ export default class FileReceiver extends Nanobus {
const downloadPath = `/api/download/${this.fileInfo.id}`;
let downloadUrl = getApiUrl(downloadPath);
if (downloadUrl === downloadPath) {
downloadUrl = `${location.protocol}//${location.host}/api/download/${this.fileInfo.id}`;
downloadUrl = `${location.protocol}//${location.host}${downloadPath}`;
}
const a = document.createElement('a');
a.href = downloadUrl;
@@ -162,11 +163,29 @@ export default class FileReceiver extends Nanobus {
}
let prog = 0;
let hangs = 0;
while (prog < this.fileInfo.size) {
const msg = await this.sendMessageToSw({
request: 'progress',
id: this.fileInfo.id
});
if (msg.progress === prog) {
hangs++;
} else {
hangs = 0;
}
if (hangs > 30) {
// TODO: On Chrome we don't get a cancel
// signal so one is indistinguishable from
// a hang. We may be able to detect
// which end is hung in the service worker
// to improve on this.
const e = new Error('hung download');
e.duration = Date.now() - start;
e.size = this.fileInfo.size;
e.progress = prog;
throw e;
}
prog = msg.progress;
onprogress(prog);
await delay(1000);

View File

@@ -44,7 +44,6 @@ export default class FileSender extends Nanobus {
}
async upload(archive, bearerToken) {
const start = Date.now();
if (this.cancelled) {
throw new Error(0);
}
@@ -76,7 +75,6 @@ export default class FileSender extends Nanobus {
this.emit('progress'); // HACK to kick MS Edge
try {
const result = await this.uploadRequest.result;
const time = Date.now() - start;
this.msg = 'notifyUploadEncryptDone';
this.uploadRequest = null;
this.progress = [1, 1];
@@ -87,8 +85,8 @@ export default class FileSender extends Nanobus {
name: archive.name,
size: archive.size,
manifest: archive.manifest,
time: time,
speed: archive.size / (time / 1000),
time: result.duration,
speed: archive.size / (result.duration / 1000),
createdAt: Date.now(),
expiresAt: Date.now() + archive.timeLimit * 1000,
secretKey: secretKey,

View File

@@ -39,7 +39,7 @@ body {
}
.btn {
@apply bg-blue-dark;
@apply bg-blue-60;
@apply text-white;
@apply cursor-pointer;
@apply py-4;
@@ -48,11 +48,11 @@ body {
}
.btn:hover {
@apply bg-blue-darker;
@apply bg-blue-70;
}
.btn:focus {
@apply bg-blue-darker;
@apply bg-blue-70;
}
.checkbox {
@@ -70,7 +70,7 @@ body {
}
.checkbox > label::before {
/* @apply bg-grey-lightest; */
/* @apply bg-grey-10; */
@apply border;
@apply rounded-sm;
@@ -82,16 +82,16 @@ body {
}
.checkbox > label:hover::before {
@apply border-blue-dark;
@apply border-blue-50;
}
.checkbox > input:focus + label::before {
@apply border-blue-dark;
@apply border-blue-50;
}
.checkbox > input:checked + label::before {
@apply bg-blue-dark;
@apply border-blue-dark;
@apply bg-blue-50;
@apply border-blue-50;
background-image: url('../assets/lock.svg');
background-position: center;
@@ -104,8 +104,8 @@ body {
}
.checkbox > input:disabled + label::before {
@apply bg-blue-dark;
@apply border-blue-dark;
@apply bg-blue-50;
@apply border-blue-50;
background-image: url('../assets/lock.svg');
background-position: center;
@@ -153,9 +153,21 @@ footer li:hover {
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 {
height: 32px;
width: 170px;
width: auto;
}
.intro {
@@ -193,14 +205,14 @@ footer li:hover {
}
progress {
@apply bg-grey-light;
@apply bg-grey-30;
@apply rounded-sm;
@apply w-full;
@apply h-1;
}
progress::-webkit-progress-bar {
@apply bg-grey-light;
@apply bg-grey-30;
@apply rounded-sm;
@apply w-full;
@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;
@responsive {
@@ -325,8 +386,6 @@ select {
.signin:hover,
.signin:focus {
@apply shadow-btn;
transform: scale(1.0625);
}
@@ -337,19 +396,19 @@ select {
/* begin signin button color experiment */
.white-blue {
@apply border-blue-dark;
@apply border-blue-60;
@apply border-2;
@apply text-blue-dark;
@apply text-blue-60;
}
.white-blue:hover,
.white-blue:focus {
@apply bg-blue-dark;
@apply bg-blue-60;
@apply text-white;
}
.blue {
@apply bg-blue-dark;
@apply bg-blue-60;
@apply text-white;
}

View File

@@ -12,15 +12,15 @@ import pasteManager from './pasteManager';
import storage from './storage';
import metrics from './metrics';
import experiments from './experiments';
import Raven from 'raven-js';
import * as Sentry from '@sentry/browser';
import './main.css';
import User from './user';
import { getTranslator } from './locale';
import Archive from './archive';
import { setTranslate, locale } from './utils';
if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) {
Raven.config(window.SENTRY_ID, window.RAVEN_CONFIG).install();
if (navigator.doNotTrack !== '1' && window.SENTRY_CONFIG) {
Sentry.init(window.SENTRY_CONFIG);
}
if (process.env.NODE_ENV === 'production') {
@@ -56,13 +56,13 @@ if (process.env.NODE_ENV === 'production') {
capabilities,
translate,
storage,
raven: Raven,
sentry: Sentry,
user: new User(storage, LIMITS, window.AUTH_CONFIG),
transfer: null,
fileInfo: null
};
const app = routes(choo());
const app = routes(choo({ hash: true }));
// eslint-disable-next-line require-atomic-updates
window.app = app;
app.use(experiments);

View File

@@ -107,9 +107,10 @@ function completedUpload(archive, duration) {
});
}
function stoppedUpload(archive) {
function stoppedUpload(archive, duration = 0) {
return addEvent('client_upload', {
download_limit: archive.dlimit,
duration: sizeOrder(duration),
file_count: archive.numFiles,
password_protected: !!archive.password,
size: sizeOrder(archive.size),

View File

@@ -2,7 +2,7 @@ const choo = require('choo');
const download = require('./ui/download');
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('/download/:id', 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 VERSIONED_ASSET = /\.[A-Fa-f0-9]{8}\.(js|css|png|svg|jpg)$/;
const DOWNLOAD_URL = /\/api\/download\/([A-Fa-f0-9]{4,})/;
const FONT = /\.woff2?$/;
self.addEventListener('install', event => {
event.waitUntil(precache());
self.addEventListener('install', () => {
self.skipWaiting();
});
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim());
event.waitUntil(self.clients.claim().then(precache));
});
async function decryptStream(id) {
@@ -83,16 +84,28 @@ async function decryptStream(id) {
}
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();
for (const c of oldCaches) {
if (c !== version) {
await caches.delete(c);
}
}
const cache = await caches.open(version);
const images = assets.match(IMAGES);
await cache.addAll(images);
return self.skipWaiting();
}
function cacheable(url) {
return VERSIONED_ASSET.test(url) || FONT.test(url);
}
async function cachedOrFetched(req) {
@@ -102,7 +115,7 @@ async function cachedOrFetched(req) {
return cached;
}
const fetched = await fetch(req);
if (fetched.ok && VERSIONED_ASSET.test(req.url)) {
if (fetched.ok && cacheable(req.url)) {
cache.put(req, fetched.clone());
}
return fetched;
@@ -115,7 +128,7 @@ self.onfetch = event => {
const dlmatch = DOWNLOAD_URL.exec(url.pathname);
if (dlmatch) {
event.respondWith(decryptStream(dlmatch[1]));
} else if (VERSIONED_ASSET.test(url.pathname)) {
} else if (cacheable(url.pathname)) {
event.respondWith(cachedOrFetched(req));
}
};

View File

@@ -64,8 +64,7 @@ class Account extends Component {
return html`
<send-account>
<button
class="px-4 py-2 md:px-8 md:py-4 focus:outline signin ${this
.buttonClass}"
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"
onclick="${e => this.login(e)}"
title="${translate('signInOnlyButton')}"
>
@@ -79,19 +78,19 @@ class Account extends Component {
<input
type="image"
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}"
onclick="${e => this.avatarClick(e)}"
/>
<ul
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)}"
>
<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>
<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)}"
title="${translate('signOut')}"
>

View File

@@ -46,7 +46,7 @@ function password(state) {
id="password-input"
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"
maxlength="${MAX_LENGTH}"
type="password"
@@ -58,7 +58,7 @@ function password(state) {
<label
id="password-msg"
for="password-input"
class="block text-xs text-grey-darker"
class="block text-xs text-grey-70"
></label>
</div>
`;
@@ -106,7 +106,9 @@ function password(state) {
function fileInfo(file, action) {
return html`
<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">
<h1 class="text-base font-medium word-break-all">${file.name}</h1>
<div class="text-sm font-normal opacity-75 pt-1">${bytes(
@@ -120,7 +122,9 @@ function fileInfo(file, action) {
function archiveInfo(archive, action) {
return html`
<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">
<h1 class="text-base font-medium word-break-all">${archive.name}</h1>
<div class="text-sm font-normal opacity-75 pt-1">${bytes(
@@ -140,7 +144,7 @@ function archiveDetails(translate, archive) {
ontoggle="${toggled}"
>
<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
class="fill-current w-4 h-4 mr-1"
@@ -170,20 +174,25 @@ module.exports = function(state, emit, archive) {
state.capabilities.share || platform() === 'android'
? html`
<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}
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>
`
: html`
<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}
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')}
</button>
`;
@@ -191,12 +200,14 @@ module.exports = function(state, emit, archive) {
platform() === 'web'
? html`
<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}"
title="${state.translate('downloadButtonLabel')}"
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')}
</a>
`
@@ -206,7 +217,7 @@ module.exports = function(state, emit, archive) {
return html`
<send-archive
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(
archive,
@@ -225,7 +236,7 @@ module.exports = function(state, emit, archive) {
${expiryInfo(state.translate, archive)}
</div>
${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">
${dl} ${copyOrShare}
</div>
@@ -269,18 +280,21 @@ module.exports = function(state, emit, archive) {
module.exports.wip = function(state, emit) {
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(
Array.from(state.archive.files)
.reverse()
.map(f =>
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',
'bg-white px-2 my-2 shadow-light rounded'
'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 dark:bg-grey-90 dark:border dark:border-grey-80'
)}
<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
id="file-upload"
@@ -300,10 +314,12 @@ module.exports.wip = function(state, emit) {
class="flex items-center cursor-pointer"
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')}
</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', {
size: bytes(state.archive.size)
})}
@@ -378,22 +394,22 @@ module.exports.uploading = function(state, emit) {
return html`
<send-upload-area
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)}
<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, {
dlimit: state.archive.dlimit,
dtotal: 0,
expiresAt: Date.now() + 500 + state.archive.timeLimit * 1000
})}
</div>
<div class="text-blue-dark text-sm font-medium mt-2">
<div class="link-blue text-sm font-medium mt-2">
${progressPercent}
</div>
<progress class="my-3" value="${progress}">${progressPercent}</progress>
<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}
title="${state.translate('deletePopupCancel')}"
>
@@ -415,7 +431,7 @@ module.exports.empty = function(state, emit) {
? ''
: html`
<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 => {
event.stopPropagation();
emit('signup-cta', 'drop');
@@ -428,14 +444,16 @@ module.exports.empty = function(state, emit) {
`;
return html`
<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 => {
if (e.target.tagName !== 'LABEL') {
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">
${state.translate('dragAndDropFiles')}
</div>
@@ -469,14 +487,11 @@ module.exports.empty = function(state, emit) {
`;
function focus(event) {
event.target.nextElementSibling.classList.add('bg-blue-darker', 'outline');
event.target.nextElementSibling.classList.add('bg-blue-70', 'outline');
}
function blur(event) {
event.target.nextElementSibling.classList.remove(
'bg-blue-darker',
'outline'
);
event.target.nextElementSibling.classList.remove('bg-blue-70', 'outline');
}
function add(event) {
@@ -501,8 +516,10 @@ module.exports.preview = function(state, emit) {
</div>
`;
return html`
<send-archive class="flex flex-col max-h-full bg-white p-4 w-full md:w-128">
<div class="border rounded py-3 px-6">
<send-archive
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}
</div>
<button
@@ -529,10 +546,10 @@ module.exports.downloading = function(state) {
const progressPercent = percent(progress);
return html`
<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)}
<div class="text-blue-dark text-sm font-medium mt-2">
<div class="link-blue text-sm font-medium mt-2">
${progressPercent}
</div>
<progress class="my-3" value="${progress}">${progressPercent}</progress>

View File

@@ -18,7 +18,7 @@ module.exports = function body(main) {
return function(state, emit) {
const b = html`
<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()}
${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">
${state.translate('notifyUploadEncryptDone')}
</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 />
${name}
</p>
<input
type="text"
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}"
readonly="true"
/>
@@ -29,7 +31,7 @@ module.exports = function(name, url) {
${state.translate('copyLinkButton')}
</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}"
title="${state.translate('okButton')}"
>

View File

@@ -41,7 +41,9 @@ function preview(state, emit) {
<h1 class="text-3xl font-bold mb-4">
${state.translate('downloadTitle')}
</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')}
</p>
${archiveTile.preview(state, emit)}

View File

@@ -5,13 +5,13 @@ module.exports = function(state) {
return html`
<div
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">
${state.translate('downloadFinish')}
</h1>
<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')}
</p>
<p class="my-5">

View File

@@ -6,12 +6,14 @@ module.exports = function(state, emit) {
const div = html`
<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">
${state.translate('downloadTitle')}
</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')}
</p>
<form
@@ -22,8 +24,8 @@ module.exports = function(state, emit) {
<input
id="password-input"
class="w-full border-l border-t border-b rounded-l-lg rounded-r-none ${invalid
? 'border-red'
: 'border-grey'} leading-loose px-2 py-1"
? 'border-red dark:border-red-40'
: 'border-grey'} leading-loose px-2 py-1 dark:bg-grey-80"
maxlength="32"
autocomplete="off"
placeholder="${state.translate('unlockInputPlaceholder')}"
@@ -34,7 +36,7 @@ module.exports = function(state, emit) {
type="submit"
id="password-btn"
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')}"
title="${state.translate('unlockButtonLabel')}"
@@ -42,7 +44,7 @@ module.exports = function(state, emit) {
</form>
<label
id="password-error"
class="${invalid ? '' : 'invisible'} text-red my-4"
class="${invalid ? '' : 'invisible'} text-red dark:text-red-40 my-4"
for="password-input"
>
${state.translate('passwordTryAgain')}
@@ -72,7 +74,9 @@ module.exports = function(state, emit) {
const password = el.value;
if (password.length > 0) {
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;
emit('getMetadata');
}

View File

@@ -13,7 +13,7 @@ module.exports = function(state, emit) {
${state.translate('errorPageHeader')}
</h1>
<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')}
</p>
<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}`;
return html`
<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
class="mozilla-logo pb-10 md:pb-0 m-2"
href="https://www.mozilla.org/"
>
<a class="mozilla-logo m-2" href="https://www.mozilla.org/">
Mozilla
</a>
<ul

View File

@@ -16,15 +16,27 @@ class Header extends Component {
this.account.render();
return false;
}
createElement() {
const title =
platform() === 'android'
? 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`
<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`
<header

View File

@@ -4,7 +4,7 @@ const assets = require('../../common/assets');
module.exports = function intro(state) {
return html`
<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">
<h1 class="text-3xl font-bold md:pb-2">

View File

@@ -6,7 +6,7 @@ module.exports = function(state, emit) {
<main class="main">
${state.modal && modal(state, emit)}
<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">
${state.translate('legalTitle')}
@@ -19,7 +19,7 @@ module.exports = function(state, emit) {
href="https://www.mozilla.org/privacy/"
target="__blank"
rel="noopener noreferrer"
class="text-blue-dark hover:underline"
class="link-blue hover:underline"
>Mozilla Privacy Policy</a
>
<span
@@ -31,7 +31,7 @@ module.exports = function(state, emit) {
href="https://github.com/mozilla/send/blob/master/docs/metrics.md"
target="__blank"
rel="noopener noreferrer"
class="text-blue-dark hover:underline"
class="link-blue hover:underline"
>here</a
>.
</p>

View File

@@ -3,13 +3,12 @@ const html = require('choo/html');
module.exports = function(state, emit) {
return html`
<send-modal
class="absolute inset-0 flex items-center justify-center overflow-hidden z-40 bg-white md:rounded-xl md:my-8"
onclick="${close}"
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"
>
<div
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)}
</div>
</div>

View File

@@ -12,7 +12,7 @@ module.exports = function(state, emit) {
'downloadTitle'
)}</h1>
<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')} ⚠️
</p>

View File

@@ -13,7 +13,7 @@ module.exports = function(state, emit) {
${state.translate('expiredTitle')}
</h1>
<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')}
</p>
<p class="my-5">

View File

@@ -15,7 +15,7 @@ class Promo extends Component {
createElement() {
return html`
<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">
<img
@@ -26,7 +26,7 @@ class Promo extends Component {
<span class="ml-2 sm:ml-4 text-xs sm:text-base">
${this.state.translate('trailheadPromo')}${' '}
<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"
>${this.state.translate('learnMore')}</a
>

View File

@@ -6,7 +6,7 @@ module.exports = function(selected, options, translate, changed, htmlId) {
return html`
<select
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}"
>
${options.map(

View File

@@ -9,14 +9,16 @@ module.exports = function(name, url) {
<h1 class="text-3xl font-bold my-4">
${state.translate('notifyUploadEncryptDone')}
</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 />
${name}
</p>
<input
type="text"
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}"
readonly="true"
/>
@@ -28,7 +30,7 @@ module.exports = function(name, url) {
${state.translate('shareLinkButton')}
</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}"
title="${state.translate('okButton')}"
>

View File

@@ -20,7 +20,7 @@ module.exports = function(trigger) {
${state.translate('accountBenefitTitle')}
</h1>
<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>
${state.translate('accountBenefitLargeFiles', {
@@ -42,7 +42,7 @@ module.exports = function(trigger) {
<input
id="email-input"
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')}
/>
<input
@@ -54,7 +54,7 @@ module.exports = function(trigger) {
/>
</form>
<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')}"
onclick=${cancel}
>

View File

@@ -16,7 +16,7 @@ module.exports = function() {
<h1 class="text-3xl font-bold my-4">
Tell us what you think.
</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
it better.
</p>
@@ -30,7 +30,7 @@ module.exports = function() {
Give feedback
</a>
<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}"
title="Skip"
>

View File

@@ -27,7 +27,7 @@ module.exports = function(state, emit) {
<main class="main">
${state.modal && modal(state, emit)}
<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>
<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">
<defs>
<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>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="plus" viewBox="0 0 24 24">
<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"/>
<use fill="#0060df" xlink:href="#addfiles-a"/>
<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"/>
<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>
</symbol>
<use xlink:href="#plus"/>
</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"?>
<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">
<!-- Generator: sketchtool 53 (72520) - https://sketchapp.com -->
<title>6AF7DAB4-6456-44F2-AABE-F001D910B641</title>
<desc>Created with sketchtool.</desc>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="icon" viewBox="0 0 26 32">
<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>
</defs>
@@ -14,14 +12,15 @@
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Mask" fill="#45A1FF" opacity="0.6" 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="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,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,22.6209117 L17.5412669,22.6209117" id="Path" stroke="#0060DF" stroke-width="2" stroke-linecap="round" mask="url(#mask-2)"></path>
<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="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="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="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="currentColor" stroke-width="2" stroke-linecap="round" mask="url(#mask-2)"></path>
</g>
</g>
</g>
</g>
</g>
</symbol>
</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"?>
<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">
<!-- Generator: sketchtool 53 (72520) - https://sketchapp.com -->
<title>728D143F-562C-4AE5-80DA-9DBBD9D647D8</title>
<desc>Created with sketchtool.</desc>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Send_Sending" transform="translate(-770.000000, -481.000000)" fill="#0060DF">
<g id="List-Item-3" transform="translate(744.000000, 350.000000)">
<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>
<svg width="12px" height="16px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="icon" viewBox="0 0 12 16">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-770.000000, -481.000000)" fill="currentColor">
<g transform="translate(744.000000, 350.000000)">
<g 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"></path>
</g>
</g>
</g>
</g>
</symbol>
</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"?>
<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>
<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>
@@ -14,7 +11,7 @@
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</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>

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
- 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/. -->
<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
## 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

View File

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

View File

@@ -1,3 +1,7 @@
# 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
Before building the Docker image, you must build the production assets:
```sh
npm run build
```
Then you can run either `docker build` or `docker-compose up`.
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.*
## Environment variables:

3234
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -151,3 +151,5 @@ shareLinkDescription = Compartiu l'enllaç al vostre fitxer:
shareLinkButton = Comparteix l'enllaç
# $name is the name of the file
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
# $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
trailheadPromo = K'o jun rub'anikil richin nachajij ri awichinanem. Tatunu' awi' rik'in ri Firefox.
learnMore = Tetamäx ch'aqa' chik.

View File

@@ -196,5 +196,5 @@ shareLinkDescription = Sdílet odkaz na soubor:
shareLinkButton = Sdílet odkaz
# $name is the name of the file
shareMessage = Stáhněte si soubor „{ $name }“ s { -send-brand(case: "ins") } - jednoduché a bezpečné sdílení souborů
trailheadPromo = Existuje snadný způsob pro ochranu vašeho soukromí. Používejte Firefox.
trailheadPromo = Existuje způsob, jak ochránit své soukromí. Používejte Firefox.
learnMore = Zjistit více.

View File

@@ -151,3 +151,5 @@ shareLinkDescription = Del linket til din fil:
shareLinkButton = Del link
# $name is the name of the file
shareMessage = Hent { $name } med { -send-brand } - simpel og sikker fildeling
trailheadPromo = Beskyt dine digitale rettigheder. Slut dig til Firefox.
learnMore = Læs mere.

View File

@@ -126,7 +126,7 @@ addPassword = Protegido con contraseña
emailPlaceholder = Ingresa tu correo electrónico
# $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 }
signInButton = Iniciar sesión/registrarse
signInOnlyButton = 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")
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
noStreamsOptionFirefox = Prueba nuestro navegador favorito
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
# $name is the name of the file
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

@@ -23,7 +23,7 @@ fileSizeProgress = ({ $totalSize } / { $partialSize })
sendYourFilesLink = Probatu Firefox Send
errorPageHeader = Zerbait gaizki joan da!
fileTooBig = Fitxategia handiegia da kargatzeko. { $size } baino txikiagoa izan behar du.
linkExpiredAlt = Lotura iraungita
linkExpiredAlt = Lotura iraungi da
notSupportedHeader = Zure nabigatzailea ez da onartzen.
notSupportedLink = Zergatik ez da nire nabigatzailea onartzen?
notSupportedOutdatedDetail = Zoritxarrez Firefox bertsio honek ez du Firefox Send-ek behar duen web teknologia onartzen. Zure nabigatzailea eguneratu behar duzu.
@@ -54,7 +54,30 @@ passwordSetError = Pasahitz hau ezin da ezarri
-firefox = Firefox
-mozilla = Mozilla
introTitle = Partekatu fitxategiak modu sinple eta pribatuan
introDescription = { -send-brand } tresna fitxategiak partekatzeko da, muturretik muturrera zifratuta eta automatikoki iraungitzen diren loturekin. Hortaz, partekatzen duzuna pribatua izango da eta ziur egon zaitezke zure fitxategiak ez direla online egongo betirako.
notifyUploadEncryptDone = Zure fitxategia zifratuta eta bidaltzeko prest dago
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
archiveExpiryInfo = { $downloadCount } edo { $timespan } ondoren iraungiko da
timespanMinutes =
{ $num ->
[one] minutu 1
*[other] { $num } minutu
}
timespanDays =
{ $num ->
[one] egun 1
*[other] { $num } egun
}
timespanWeeks =
{ $num ->
[one] aste 1
*[other] { $num } aste
}
fileCount =
{ $num ->
[one] fitxategi 1
*[other] { $num } fitxategi
}
# byte abbreviation
bytes = B
# kibibyte abbreviation
@@ -65,9 +88,33 @@ mb = MB
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 = Tamaina guztira: { $size }
# the next line after the colon contains a file name
copyLinkDescription = Kopiatu fitxategia partekatzeko lotura:
copyLinkButton = Kopiatu lotura
downloadTitle = Deskargatu fitxategiak
downloadDescription = { -send-brand } bidez partekatu da fitxategia muturretik muturrera zifratuta eta automatikoki iraungitzen den lotura batekin.
trySendDescription = Probatu { -send-brand } fitxategiak partekatzeko modu sinple eta segururako.
# count will always be > 10
tooManyFiles =
{ $count ->
[one] Soilik fitxategi bakarra igo daiteke aldi berean.
*[other] Soilik { $count } fitxategi igo daitezke aldi berean.
}
# count will always be > 10
tooManyArchives =
{ $count ->
[one] Soilik artxibo bakarra onartzen da.
*[other] Soilik { $count } artxibo onartzen dira.
}
expiredTitle = Lotura hau iraungi da.
notSupportedDescription = { -send-brand } ez da nabigatzaile honetan ibiliko. { -send-short-brand } hobeto dabil { -firefox }(r)en azken bertsioarekin; halaber, nabigatzaile gehienen azken bertsioarekin ibiliko da.
downloadFirefox = Deskargatu { -firefox }
legalTitle = { -send-short-brand } pribatutasun-oharra
legalDateStamp = 1.0 bertsioa, 2019ko martxoaren 12koa.
# A short representation of a countdown timer containing the number of days, hours, and minutes remaining as digits, example "2d 11h 56m"
expiresDaysHoursMinutes = { $days }e { $hours }h { $minutes }m
addFilesButton = Hautatu igotzeko fitxategiak
uploadButton = Igo
# the first part of the string 'Drag and drop files or click to send up to 1GB'
@@ -77,7 +124,32 @@ dragAndDropFiles = Arrastatu eta jaregin fitxategiak
orClickWithSize = edo egin klik { $size } arte igotzeko
addPassword = Babestu pasahitzarekin
emailPlaceholder = Idatzi zure helbide elektronikoa
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
signInSizeBump = Hasi saioa { $size } arte bidaltzeko
signInOnlyButton = Hasi saioa
accountBenefitTitle = Sortu { -firefox } kontu bat edo hasi saioa
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
accountBenefitLargeFiles = Partekatu { $size } arteko fitxategiak
accountBenefitDownloadCount = Partekatu fitxategiak jende gehiagorekin
accountBenefitTimeLimit =
{ $count ->
[one] Utzi loturak erabilgarri egun batez
*[other] Utzi loturak erabilgarri { $count } egunez
}
accountBenefitSync = Kudeatu partekatutako fitxategiak edozein gailutatik
accountBenefitMoz = { -mozilla }ren beste zerbitzuei buruzko argibide gehiago
signOut = Amaitu saioa
okButton = Ados
downloadingTitle = Deskargatzen
noStreamsWarning = Baliteke nabigatzailea gai ez izatea horrelako tamaina handiko fitxategiak deszifratzeko.
noStreamsOptionCopy = Kopiatu lotura beste nabigatzaile batean irekitzeko
noStreamsOptionFirefox = Probatu gure nabigatzaile gogokoena
noStreamsOptionDownload = Jarraitu nabigatzaile honekin
downloadFirefoxPromo = Erabat berritutako { -firefox }(e)k eskaintzen dizu { -send-short-brand }
# the next line after the colon contains a file name
shareLinkDescription = Partekatu zure fitxategirako lotura:
shareLinkButton = Partekatu lotura
# $name is the name of the file
shareMessage = Deskargatu "{ $name }" { -send-brand } erabiliz: fitxategi-partekatze sinple eta segurua
trailheadPromo = Badago zure pribatutasuna babesteko modua. Egizu bat Firefoxekin.
learnMore = Argibide gehiago.

View File

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

View File

@@ -1,19 +1,19 @@
# Firefox Send is a brand name and should not be localized.
title = Firefox Send
siteFeedback = משוב
importingFile = מתבצע ייבוא...
importingFile = מתבצע ייבוא
encryptingFile = מתבצעת הצפנה...
decryptingFile = מתבצע פענוח...
downloadCount =
{ $num ->
[one] הורדה אחת
*[other] { $number } הורדות
*[other] { $num } הורדות
}
timespanHours =
{ $num ->
[one] שעה אחת
[two] שעתיים
*[other] { $number } שעות
*[other] { $num } שעות
}
copiedUrl = הועתק!
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")
orClickWithSize = o cliccar pro inviar usque { $size }
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")
signInSizeBump = Accede pro inviar usque { $size }
signInOnlyButton = Authentica te

View File

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

View File

@@ -54,7 +54,7 @@ passwordSetError = Awal-agi uffir ur izmir ara ad ittwabaded
-firefox = Firefox
-mozilla = Mozilla
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
# 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 }

View File

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

View File

@@ -54,6 +54,7 @@ passwordSetError = Dette passordet kunne ikke settes
-firefox = Firefox
-mozilla = Mozilla
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
# 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 }
@@ -77,9 +78,78 @@ fileCount =
[one] 1 fil
*[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 }
# the next line after the colon contains a file name
copyLinkDescription = Kopier lenken for å dele filen din:
copyLinkButton = Kopier lenke
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.

155
public/locales/oc/send.ftl Normal file
View File

@@ -0,0 +1,155 @@
# Firefox Send is a brand name and should not be localized.
title = Firefox Send
siteFeedback = Comentaris
importingFile = Importacion…
encryptingFile = Chiframent…
decryptingFile = Deschiframent…
downloadCount =
{ $num ->
[one] 1 telecargament
*[other] { $num } telecargaments
}
timespanHours =
{ $num ->
[one] 1 ora
*[other] { $num } oras
}
copiedUrl = Copiat !
unlockInputPlaceholder = Senhal
unlockButtonLabel = Desverrolhar
downloadButtonLabel = Telecargar
downloadFinish = Telecargament acabat
fileSizeProgress = ({ $partialSize } sus { $totalSize })
sendYourFilesLink = Ensajar Firefox Send
errorPageHeader = I a quicòm que truca.
fileTooBig = Aqueste fichièr es tròp gròs per lenviar. Sa talha deu èsser inferiora a { $size }.
linkExpiredAlt = Lo ligam a expirat
notSupportedHeader = Vòstre navegador es pas compatible.
notSupportedLink = Perqué mon navegador es pas compatible ?
notSupportedOutdatedDetail = Aquesta version de Firefox es pas compatibla amb la tecnologia web amb la quala fonciona Firefox Send. Vos cal metre a jorn lo navegador.
updateFirefox = Metre a jorn Firefox
deletePopupCancel = Anullar
deleteButtonHover = Suprimir
footerLinkLegal = Mencions legalas
footerLinkPrivacy = Vida privada
footerLinkCookies = Cookies
passwordTryAgain = Senhal incorrècte. Tornatz ensajar.
javascriptRequired = Firefox Send requesís JavaScript
whyJavascript = Perque Firefox Send requesís JavaScript ?
enableJavascript = Volgatz activar lo JavaScript e ensajatz tornamai.
# A short representation of a countdown timer containing the number of hours and minutes remaining as digits, example "13h 47m"
expiresHoursMinutes = { $hours } h { $minutes } min
# A short representation of a countdown timer containing the number of minutes remaining as digits, example "56m"
expiresMinutes = { $minutes } min
# A short status message shown when the user enters a long password
maxPasswordLength = Talha maximala del senhal : { $length }
# A short status message shown when there was an error setting the password
passwordSetError = Aqueste senhal a pas pogut èsser definit
## Send version 2 strings
# Firefox Send, Send, Firefox, Mozilla are proper names and should not be localized
-send-brand = Firefox Send
-send-short-brand = Send
-firefox = Firefox
-mozilla = Mozilla
introTitle = Partatge simple e privat de fichièrs
introDescription = { -send-brand } vos permet de partejar de fichièr amb un chiframent del cap a la fin e un ligam quexpira automaticament. Atal podètz gardar privat çò que partejatz e vos assegurar que demorarà pas en linha per totjorn.
notifyUploadEncryptDone = Vòstre fichièr es chifrat e prèst per mandadís
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
archiveExpiryInfo = Expira aprèp { $downloadCount } o { $timespan }
timespanMinutes =
{ $num ->
[one] 1 minuta
*[other] { $num } minutas
}
timespanDays =
{ $num ->
[one] 1 jorn
*[other] { $num } jorns
}
timespanWeeks =
{ $num ->
[one] 1 setmana
*[other] { $num } setmanas
}
fileCount =
{ $num ->
[one] 1 fichièr
*[other] { $num } fichièrs
}
# byte abbreviation
bytes = o
# kibibyte abbreviation
kb = Ko
# mebibyte abbreviation
mb = Mo
# gibibyte abbreviation
gb = Go
# 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 = Talha totala : { $size }
# the next line after the colon contains a file name
copyLinkDescription = Copiatz lo ligam per partejar vòstre fichièr :
copyLinkButton = Copiar lo ligam
downloadTitle = Telecargar los fichièrs
downloadDescription = Aqueste fichièr foguèt partejat via { -send-brand } amb chiframent del cap a la fin e un ligam quexpira automaticament.
trySendDescription = Ensajatz { -send-brand } per un partiment de fichièrs simple e segur.
# count will always be > 10
tooManyFiles =
{ $count ->
[one] Òm pòt pas quenviar 1 fichièr al còp.
*[other] Òm pòt pas quenviar { $count } fichièrs al còp.
}
# count will always be > 10
tooManyArchives =
{ $count ->
[one] Pas quun archiu es autorizat.
*[other] Pas que { $count } archius son autorizats.
}
expiredTitle = Aqueste ligam a expirat.
notSupportedDescription = { -send-brand } foncionarà pas amb aqueste navegador. { -send-short-brand } fonciona melhor amb la darrièra version de { -firefox } e foncionarà amb la version mai recenta de la màger part dels navegadors.
downloadFirefox = Telecargar { -firefox }
legalTitle = Avís de confidencialitat de { -send-short-brand }
legalDateStamp = Version 1.0 del 12 de març de 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 } j { $hours } h { $minutes } min
addFilesButton = Seleccionatz los fichièrs de mandar
uploadButton = Enviar
# the first part of the string 'Drag and drop files or click to send up to 1GB'
dragAndDropFiles = Lissatz-depausatz de fichièrs
# 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 = o clicatz per enviar fins a { $size }
addPassword = Protegir amb un senhal
emailPlaceholder = Picatz vòstra adreça electronica
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
signInSizeBump = Connectatz-vos per enviar fins a { $size }
signInOnlyButton = Connexion
accountBenefitTitle = Creatz un compte { -firefox } o connectatz-vos
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
accountBenefitLargeFiles = Partejatz de fichièrs fins a { $size }
accountBenefitDownloadCount = Partejatz de fichièrs amb mai de personas
accountBenefitTimeLimit =
{ $count ->
[one] Mantenètz los ligams actius fins a 1 jorn
*[other] Mantenètz los ligams actius fins a { $count } jorns
}
accountBenefitSync = Gerissètz los fichièrs partejats de qualque siá periferic estant
accountBenefitMoz = Aprenètz-ne mai suls autres servicis { -mozilla }
signOut = Desconnexion
okButton = D'acòrd
downloadingTitle = Telecargament
noStreamsWarning = Pòt arribar quaqueste navegador pòsca pas deschifrar un fichièr tan gròs.
noStreamsOptionCopy = Copiatz lo ligam per lo dobrir dins un autre navegador
noStreamsOptionFirefox = Ensajatz nòstre navegador preferit
noStreamsOptionDownload = Contunhar amb aqueste navegador
downloadFirefoxPromo = Lo nòu { -firefox } vos provesís { -send-short-brand }.
# the next line after the colon contains a file name
shareLinkDescription = Partejatz lo ligam cap a vòstre fichièr :
shareLinkButton = Partejar lo ligam
# $name is the name of the file
shareMessage = Telecargar « { $name } » amb { -send-brand } : un biais simple e segur de partejar de fichièrs.
trailheadPromo = Existís un biais de protegir vòstra vida privada. Rejonhètz Firefox.
learnMore = Ne saber mai.

View File

@@ -151,3 +151,5 @@ shareLinkDescription = ਆਪਣੀ ਫਾਇਲ ਲਈ ਲਿੰਕ ਸਾਂ
shareLinkButton = ਲਿੰਕ ਸਾਂਝਾ ਕਰੋ
# $name is the name of the file
shareMessage = { -send-brand } ਨਾਲ "{ $name }" ਡਾਊਨਲੋਡ ਕਰੋ: ਸੌਖਾ, ਸੁਰੱਖਿਅਤ ਫਾਇਲ ਸਾਂਝਾ ਕਰਨਾ
trailheadPromo = ਤੁਹਾਡੀ ਪਰਦੇਦਾਰੀ ਦੀ ਸੁਰੱਖਿਆ ਦਾ ਢੰਗ ਹੈ। ਫਾਇਰਫਾਕਸ ਨਾਲ ਜੁੜੋ।
learnMore = ਹੋਰ ਸਿੱਖੋ

View File

@@ -36,11 +36,11 @@ footerLinkCookies = Cookies
passwordTryAgain = Senha incorreta. Tente novamente.
javascriptRequired = O Firefox Send requer 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"
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"
expiresMinutes = { $minutes }m
expiresMinutes = { $minutes }min
# A short status message shown when the user enters a long password
maxPasswordLength = Tamanho máximo da senha: { $length }
# 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
-mozilla = Mozilla
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
# 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 }
@@ -94,8 +94,8 @@ totalSize = Tamanho total: { $size }
copyLinkDescription = Copie o link para compartilhar seu arquivo:
copyLinkButton = Copiar link
downloadTitle = Baixar arquivos
downloadDescription = Este arquivo foi compartilhado via { -send-brand } com criptografia ponto a ponto e um link que expira automaticamente.
trySendDescription = Experimente o { -send-brand } para compartilhamento de arquivos simples e seguro.
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 compartilhar arquivos com simplicidade e segurança.
# count will always be > 10
tooManyFiles =
{ $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")
signInSizeBump = Entre na sua conta para enviar até { $size }
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")
accountBenefitLargeFiles = Compartilhe arquivos até { $size }
accountBenefitDownloadCount = Compartilhe arquivos com mais pessoas
accountBenefitLargeFiles = Compartilhe arquivos até { $size }.
accountBenefitDownloadCount = Compartilhe arquivos com mais pessoas.
accountBenefitTimeLimit =
{ $count ->
[one] Mantenha links ativos por até 1 dia
*[other] Mantenha links ativos por até { $count } dias
[one] Mantenha links ativos por até 1 dia.
*[other] Mantenha links ativos por até { $count } dias.
}
accountBenefitSync = Gerencie arquivos compartilhados a partir de qualquer dispositivo
accountBenefitMoz = Conheça outros serviços da { -mozilla }
accountBenefitSync = Gerencie arquivos compartilhados a partir de qualquer dispositivo.
accountBenefitMoz = Conheça outros serviços da { -mozilla }.
signOut = Sair
okButton = OK
downloadingTitle = Baixando

View File

@@ -141,7 +141,7 @@ accountBenefitMoz = Läs om andra { -mozilla }-tjänster
signOut = Logga ut
okButton = OK
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
noStreamsOptionFirefox = Prova vår favoritwebbläsare
noStreamsOptionDownload = Fortsätt med den här webbläsaren

View File

@@ -89,6 +89,7 @@ totalSize = మొత్తం పరిమాణం: { $size }
copyLinkDescription = మీ ఫైలును భాగస్వామ్యం చేయడానికి ఈ లంకెను నకలు చేయండి:
copyLinkButton = లంకెను నకలుతీయి
downloadTitle = ఫైళ్లను దింపుకోండి
expiredTitle = ఈ లంకె గడువు ముగిసింది.
downloadFirefox = { -firefox } ను దింపుకోండి
legalTitle = { -send-short-brand } గోప్యతా నోటీసు
legalDateStamp = వెర్షన్ 1.0, మార్చి 12, 2019 నాటిది
@@ -96,6 +97,11 @@ legalDateStamp = వెర్షన్ 1.0, మార్చి 12, 2019 నా
expiresDaysHoursMinutes = { $days }d { $hours }h { $minutes }m
addFilesButton = ఎక్కించడానికి ఫైళ్ళను ఎంచుకోండి
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 = సంకేతపదంతో రక్షించండి
emailPlaceholder = ఈ ఈమెయిలును ఇవ్వండి
# $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")
accountBenefitLargeFiles = { $size } పరిమాణం ఫైళ్ళ వరకు పంచుకోండి
accountBenefitDownloadCount = ఫైళ్లను ఎక్కువ మందితో పంచుకోండి
accountBenefitSync = ఏదైనా పరికరం నుండి పంచుకున్న ఫైళ్ళను నిర్వహించండి
signOut = నిష్క్రమించు
okButton = సరే
downloadingTitle = దింపుకుంటోంది

View File

@@ -141,9 +141,9 @@ accountBenefitLargeFiles = Обмінюйтесь файлами розміро
accountBenefitDownloadCount = Обмінюйтесь файлами з більшою кількістю людей
accountBenefitTimeLimit =
{ $count ->
[one] Зберігати посилання активними протягом 1 дня
[few] Зберігати посилання активними протягом { $count } днів
*[other] Зберігати посилання активними протягом { $count } днів
[one] Термін дії посилання 1 день
[few] Термін дії посилання { $count } дні
*[many] Термін дії посилання { $count } днів
}
accountBenefitSync = Керуйте спільними файлами з буль-якого пристрою
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
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
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.
trySendDescription = Hãy thử { -send-brand } để chia sẻ tập tin đơn giản, an toàn.
# count will always be > 10

View File

@@ -53,7 +53,7 @@ passwordSetError = 未能设置此密码
-mozilla = Mozilla
introTitle = 简单、私密的文件分享服务
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'
archiveExpiryInfo = { $downloadCount }或 { $timespan }后过期
timespanMinutes =
@@ -109,7 +109,7 @@ expiredTitle = 此链接已过期。
notSupportedDescription = { -send-brand } 无法在此浏览器上正常工作。{ -send-short-brand } 与最新版本 { -firefox } 配合使用体验最佳,也适用于目前的大多数浏览器。
downloadFirefox = 下载 { -firefox }
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"
expiresDaysHoursMinutes = { $days } 天 { $hours } 小时 { $minutes } 分钟
addFilesButton = 选择要上传的文件
@@ -127,7 +127,7 @@ signInOnlyButton = 登录
accountBenefitTitle = 创建一个 { -firefox } 账户或登录
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")
accountBenefitLargeFiles = 分享最大 { $size } 文件
accountBenefitDownloadCount = 与更多人分享文件
accountBenefitDownloadCount = 可以与更多人分享
accountBenefitTimeLimit =
{ $count ->
[one] 链接有效期延至 1 天
@@ -140,7 +140,7 @@ okButton = 确定
downloadingTitle = 正在下载
noStreamsWarning = 此浏览器可能无法解密这么大的文件。
noStreamsOptionCopy = 复制链接以在其他浏览器中打开
noStreamsOptionFirefox = 试试大家最爱的浏览器
noStreamsOptionFirefox = 试试大家最爱的浏览器
noStreamsOptionDownload = 使用此浏览器继续
downloadFirefoxPromo = { -send-short-brand } 由焕然一新的 { -firefox } 为您奉上。
# 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

@@ -3,7 +3,7 @@ const routes = require('../routes');
const pages = require('../routes/pages');
const tests = require('../../test/frontend/routes');
const express = require('express');
const expressWs = require('express-ws');
const expressWs = require('@dannycoates/express-ws');
const morgan = require('morgan');
const config = require('../config');

View File

@@ -1,13 +1,13 @@
const express = require('express');
const path = require('path');
const Raven = require('raven');
const Sentry = require('@sentry/node');
const config = require('../config');
const routes = require('../routes');
const pages = require('../routes/pages');
const expressWs = require('express-ws');
const expressWs = require('@dannycoates/express-ws');
if (config.sentry_dsn) {
Raven.config(config.sentry_dsn).install();
Sentry.init({ dsn: config.sentry_dsn });
}
const app = express();

View File

@@ -2,7 +2,7 @@ const assets = require('../../common/assets');
const routes = require('../routes');
const pages = require('../routes/pages');
const tests = require('../../test/frontend/routes');
const expressWs = require('express-ws');
const expressWs = require('@dannycoates/express-ws');
module.exports = function(app, devServer) {
assets.setMiddleware(devServer.middleware);

View File

@@ -8,12 +8,10 @@ if (config.sentry_id) {
//eslint-disable-next-line node/no-missing-require
const version = require('../dist/version.json');
sentry = `
var RAVEN_CONFIG = {
var SENTRY_CONFIG = {
dsn: '${config.sentry_id}',
release: '${version.version}',
tags: {
commit: '${version.commit}'
},
dataCallback: function (data) {
beforeSend: function (data) {
var hash = window.location.hash;
if (hash) {
return JSON.parse(JSON.stringify(data).replace(new RegExp(hash.slice(1), 'g'), ''));
@@ -21,7 +19,6 @@ var RAVEN_CONFIG = {
return data;
}
}
var SENTRY_ID = '${config.sentry_id}';
`;
}

View File

@@ -67,7 +67,10 @@ module.exports = function(app) {
}
app.use(function(req, res, next) {
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();
});
app.use(bodyParser.json());

View File

@@ -3,12 +3,11 @@ const storage = require('../storage');
const config = require('../config');
const mozlog = require('../log');
const Limiter = require('../limiter');
const wsStream = require('websocket-stream/stream');
const fxa = require('../fxa');
const { statUploadEvent } = require('../amplitude');
const { encryptedSize } = require('../../app/utils');
const { Duplex } = require('stream');
const { Transform } = require('stream');
const log = mozlog('send.upload');
@@ -76,25 +75,19 @@ module.exports = function(ws, req) {
})
);
const limiter = new Limiter(encryptedSize(maxFileSize));
const flowControl = new Duplex({
read() {
ws.resume();
},
write(chunk, encoding, callback) {
const eof = new Transform({
transform: function(chunk, encoding, callback) {
if (chunk.length === 1 && chunk[0] === 0) {
this.push(null);
} else {
if (!this.push(chunk)) {
ws.pause();
}
this.push(chunk);
}
callback();
}
});
const wsStream = ws.constructor.createWebSocketStream(ws);
fileStream = wsStream(ws, { binary: true })
.pipe(flowControl)
.pipe(limiter); // limiter needs to be the last in the chain
fileStream = wsStream.pipe(eof).pipe(limiter); // limiter needs to be the last in the chain
await storage.set(newId, fileStream, meta, timeLimit);
@@ -126,8 +119,8 @@ module.exports = function(ws, req) {
error: e === 'limit' ? 413 : 500
})
);
ws.close();
}
}
ws.close();
});
};

View File

@@ -22,7 +22,7 @@ class GCSStorage {
.pipe(
this.bucket.file(id).createWriteStream({
validation: false,
resumable: false
resumable: true
})
)
.on('error', reject)

View File

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

View File

@@ -82,4 +82,29 @@ describe('Firefox Send', function() {
// check if upload and download file sizes are equal
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 {
constructor(path) {
super(path);
this.fileId = /download\/(\w+)\/#/.exec(path)[1];
this.fileId = /download\/(\w+)\/\??.*#/.exec(path)[1];
this.downloadButton = '#download-btn';
this.downloadComplete = '#download-complete';
this.passwordInput = '#password-input';
this.passwordButton = '#password-btn';
}
/**
* @function waitForPageToLoad
* @returns {Object} An object representing the page.
* @throws ElementNotFound
*/
waitForPageToLoad() {
super.waitForPageToLoad();
browser.waitForExist(this.downloadButton);
return this;
downloadUsingPassword(password) {
browser.waitForExist(this.passwordInput);
browser.setValue(this.passwordInput, password);
browser.click(this.passwordButton);
return browser.click(this.downloadButton);
}
download() {
browser.waitForExist(this.downloadButton);
return browser.click(this.downloadButton);
}
}

View File

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

View File

@@ -6,7 +6,7 @@ module.exports = {
const webpack = require('webpack');
const middleware = require('webpack-dev-middleware');
const express = require('express');
const expressWs = require('express-ws');
const expressWs = require('@dannycoates/express-ws');
const assets = require('../common/assets');
const routes = require('../server/routes');
const tests = require('./frontend/routes');

View File

@@ -67,7 +67,7 @@ const serviceWorker = {
},
{
// 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']
}
]
@@ -114,6 +114,7 @@ const web = {
exclude: [
path.resolve(__dirname, 'node_modules/crc'),
path.resolve(__dirname, 'node_modules/@fluent'),
path.resolve(__dirname, 'node_modules/@sentry'),
path.resolve(__dirname, 'node_modules/tslib'),
path.resolve(__dirname, 'node_modules/webcrypto-core')
],
@@ -141,6 +142,7 @@ const web = {
loader: 'svgo-loader',
options: {
plugins: [
{ cleanupIDs: false },
{ removeViewBox: false }, // true causes stretched images
{ convertStyleToAttrs: true }, // for CSP, no unsafe-eval
{ removeTitle: true } // for smallness
@@ -175,7 +177,7 @@ const web = {
},
{
// 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']
}
]