Compare commits

...

108 commits

Author SHA1 Message Date
timvisee
e0a3d2bf2c
Bump version to 3.4.27 2025-07-01 08:50:51 +02:00
timvisee
b93256316b
Move icon styles into stylesheet 2025-07-01 08:50:18 +02:00
timvisee
8a82e53e82
Bump version to 3.4.26 2025-06-30 23:51:56 +02:00
Tim Visée
6215bb1555 Merge branch 'add-thunderbird-sponsor-banner' into 'master'
Add Thunderbird sponsor banner

See merge request timvisee/send!37
2025-06-30 23:50:14 +02:00
timvisee
d7e929a0d1
Merge branch 'master' of github.com:timvisee/send 2025-06-30 23:30:05 +02:00
timvisee
154a8a90c1
Add sponsored by Thunderbird label to translations 2025-06-30 23:25:51 +02:00
timvisee
0a6bf39353
Add Thunderbird sponsorship banner to home, uploads and download page 2025-06-30 23:12:54 +02:00
Raymond Hear
c0cf7bbda2 fix: use Authorization header 2025-05-23 17:30:29 +02:00
timvisee
197b0bcf59
Update contribute.json 2025-04-23 21:01:10 +02:00
timvisee
56a0e830bd
Bump version to 3.4.25 2025-04-23 10:47:15 +02:00
timvisee
b3317df707
Move main notice on top of text 2025-04-23 10:46:26 +02:00
Tim Visée
9931074905 Merge branch 'more-customizable-notices' into 'master'
More customizable notices

See merge request timvisee/send!36
2025-04-23 10:37:44 +02:00
timvisee
0088a4ccc0
Add class to underline text 2025-04-23 10:12:16 +02:00
timvisee
11aad6eac5
Rename downloads list to uploads list 2025-04-23 10:09:51 +02:00
timvisee
1fb2f45285
Rename existing warnings to notices 2025-04-23 10:08:11 +02:00
timvisee
d0f21e8078
Add customizable notice on main page and in downloads list 2025-04-23 10:07:40 +02:00
timvisee
c71100c82a
Bump version to 3.4.24 2025-04-22 22:03:29 +02:00
Tim Visée
4f2dd96708 Merge branch 'update-dependencies' into 'master'
Update dependencies

See merge request timvisee/send!35
2025-04-22 21:59:01 +02:00
Tim Visée
d8456c2c51 Merge branch 'add-custom-upload-download-warnings' into 'master'
Add customizable warnings shown on upload and download pages

See merge request timvisee/send!34
2025-04-22 21:55:25 +02:00
timvisee
b7324f3a5b
Update dependencies 2025-04-22 21:35:39 +02:00
timvisee
6890165f67
Add customizable warnings shown on upload and download pages 2025-04-22 21:31:23 +02:00
Tim Visée
5124572dba Merge branch 'fix-node-18-crypto' into 'master'
Fix build failure due to crypto when using Node 18 or higher

See merge request timvisee/send!33
2025-02-04 19:32:41 +00:00
timvisee
0c1819bb15
Fix build failure due to crypto when using Node 18 or higher 2025-02-04 20:08:03 +01:00
LOLSALT
906990991e Update send.ftl 2024-12-20 11:34:42 +01:00
LOLSALT
48bdf734c5 Update send.ftl 2024-12-20 11:34:42 +01:00
LOLSALT
cf63e0e804 Update send.ftl 2024-12-20 11:34:42 +01:00
LOLSALT
ec66c2dc4e Update send.ftl 2024-12-20 11:34:42 +01:00
LOLSALT
67dfc94ef3 Update send.ftl 2024-12-20 11:34:42 +01:00
Filip Znachor
f54f3ccaa2 Update CS send.ftl
Improved Czech translations
2024-04-19 12:12:13 +02:00
DeAlexPesh
a35e2e58a3 Update RU send.ftl 2024-03-13 17:14:17 +01:00
Tim Visée
6ad2885a16 Merge branch 'aron9861623-master-patch-24529' into 'master'
Fixed docker.md first example

See merge request timvisee/send!32
2023-06-09 13:31:51 +00:00
Aron Tecsi
70662888b1 Fixed docker.md first example 2023-06-09 11:19:42 +00:00
timvisee
9f09a79986
Merge branch 'emilstahl-patch-1' into master
See https://github.com/timvisee/send/pull/149
2023-02-27 21:45:59 +01:00
Emil Stahl
db64c0467a
Small typo 2023-02-27 21:02:53 +01:00
Tim Visée
ca52f84aa5 Merge branch 'master' into 'master'
Add build for arm64v8

See merge request timvisee/send!27
2023-02-22 11:40:25 +00:00
timvisee
6fff664947
Bump version to 3.4.23 2023-02-14 13:42:39 +01:00
timvisee
439ac0ab7c
Update dependencies 2023-02-14 13:41:10 +01:00
timvisee
dee6b3e9cc
Merge branch 'tdulcet-passphrase' into master
See https://github.com/timvisee/send/pull/147
2023-02-14 13:38:30 +01:00
Teal Dulcet
dc9d072472 Increased password length limit to support passphrases. 2023-02-14 04:36:19 -08:00
simepy
91773832c1 Updated from timvisee/send master 2023-02-03 14:29:30 +01:00
timvisee
65730db0db
Bump version to 3.4.22 2023-01-16 17:23:07 +01:00
timvisee
a86221b1cc
Update dependencies 2023-01-16 17:00:14 +01:00
dependabot[bot]
bcc53f73c6
Bump decode-uri-component from 0.2.0 to 0.2.2
Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2.
- [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases)
- [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2)

---
updated-dependencies:
- dependency-name: decode-uri-component
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-11 11:27:01 +00:00
dependabot[bot]
b0444f488b
Bump convict from 6.2.3 to 6.2.4
Bumps [convict](https://github.com/mozilla/node-convict) from 6.2.3 to 6.2.4.
- [Release notes](https://github.com/mozilla/node-convict/releases)
- [Changelog](https://github.com/mozilla/node-convict/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mozilla/node-convict/commits)

---
updated-dependencies:
- dependency-name: convict
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-10 22:22:09 +00:00
Tim Visée
70a11e5300 Merge branch 'reset-dlimit-to-default' into 'master'
Reset download limit to default after uploading files

See merge request timvisee/send!30
2023-01-10 20:50:13 +00:00
Jun Omae
f62a99882d Reset download limit to default after uplaoding files 2023-01-06 17:42:45 +09:00
timvisee
309c7d63ac
Change GitLab CI test image to node 16, add missing packages for testing 2022-12-20 20:04:45 +01:00
dependabot[bot]
1d75366f66
Bump loader-utils from 1.4.1 to 1.4.2
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.1 to 1.4.2.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.2/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.1...v1.4.2)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 00:43:28 +00:00
timvisee
0a849fb7c6
Revert "Bump node-forge and webpack-dev-server"
This reverts commit 88725df09d.
2022-11-14 19:43:09 +01:00
dependabot[bot]
88725df09d
Bump node-forge and webpack-dev-server
Bumps [node-forge](https://github.com/digitalbazaar/forge) to 1.3.1 and updates ancestor dependency [webpack-dev-server](https://github.com/webpack/webpack-dev-server). These dependencies need to be updated together.


Updates `node-forge` from 0.10.0 to 1.3.1
- [Release notes](https://github.com/digitalbazaar/forge/releases)
- [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md)
- [Commits](https://github.com/digitalbazaar/forge/compare/0.10.0...v1.3.1)

Updates `webpack-dev-server` from 3.11.3 to 4.11.1
- [Release notes](https://github.com/webpack/webpack-dev-server/releases)
- [Changelog](https://github.com/webpack/webpack-dev-server/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-server/compare/v3.11.3...v4.11.1)

---
updated-dependencies:
- dependency-name: node-forge
  dependency-type: indirect
- dependency-name: webpack-dev-server
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-14 18:35:44 +00:00
dependabot[bot]
5a92e7e5e7
Bump minimatch and mocha
Bumps [minimatch](https://github.com/isaacs/minimatch) to 3.1.2 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together.


Updates `minimatch` from 3.0.4 to 3.1.2
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2)

Updates `mocha` from 6.2.3 to 10.1.0
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v6.2.3...v10.1.0)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
- dependency-name: mocha
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-14 18:32:13 +00:00
dependabot[bot]
71541fc2b6
Bump loader-utils from 1.4.0 to 1.4.1
Bumps [loader-utils](https://github.com/webpack/loader-utils) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/webpack/loader-utils/releases)
- [Changelog](https://github.com/webpack/loader-utils/blob/v1.4.1/CHANGELOG.md)
- [Commits](https://github.com/webpack/loader-utils/compare/v1.4.0...v1.4.1)

---
updated-dependencies:
- dependency-name: loader-utils
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-09 03:16:30 +00:00
Simon PERA
c524804c63 Add build for arm64v8 2022-10-25 19:08:27 +02:00
timvisee
5b4c0d2540
Merge branch 'JoshAtticus-patch-1' into master
See https://github.com/timvisee/send/pull/115
2022-10-05 16:05:01 +02:00
Josh
e7f3c91d0b
Update config.js 2022-09-19 15:46:47 +08:00
Josh
8bb198b73e
Remove firefox link 2022-09-17 12:33:03 +08:00
Tim Visée
9e188bc76c Merge branch 'registry-credentials' into 'master'
Refactor CI

See merge request timvisee/send!26
2022-09-14 14:37:33 +00:00
Marian Hähnlein
1353a54c49
Refactor CI 2022-09-12 13:53:00 +02:00
Tim Visée
4ae007167d Merge branch 'custom-css-undefined' into 'master'
Change default value for custom css to empty string

See merge request timvisee/send!25
2022-09-09 12:34:16 +00:00
Marian Hähnlein
660f36e584
Change default value for custom css to empty string 2022-09-08 14:16:00 +02:00
timvisee
3dede083cd
Bump version to 3.4.21 2022-09-04 12:48:04 +02:00
timvisee
26e81455ff
Update dependencies 2022-09-04 12:47:40 +02:00
timvisee
4ceac20623
Revert "Remove some polyfills"
This reverts commit 64644b57e3.
2022-09-04 12:26:12 +02:00
timvisee
073accfe65
Revert "Update eslint & plugins"
This reverts commit 38746b86fd.
2022-09-04 12:26:10 +02:00
timvisee
6306a433e8
Revert "More dependency cleanups"
This reverts commit e1d6224570.
2022-09-04 12:26:09 +02:00
timvisee
1da317bcc1
Revert "Further dependency cleanup"
This reverts commit 1725ff434e.
2022-09-04 12:26:07 +02:00
timvisee
08f597405c
Revert "Remove double-ended-queue"
This reverts commit 9b8b11ffc3.
2022-09-04 12:26:05 +02:00
timvisee
c624766edc
Revert "Remove asmcrypto.js"
This reverts commit c619be58ae.
2022-09-04 12:26:03 +02:00
Tim Visée
e030c46a9c Merge branch 'fix-csp' into 'master'
Fix CSP

Closes #29

See merge request timvisee/send!24
2022-08-22 15:27:03 +00:00
Marian Hähnlein
d081affa38
Move injection of custom CSS from client to server 2022-08-19 13:17:59 +02:00
Marian Hähnlein
71372fcbc1
Replace tabs with spaces to maintain consistency 2022-08-19 13:11:30 +02:00
HrBingR
671390ca24 Added the ability for a user to define and set a custom locale
New environment variable CUSTOM_LOCALE allows a user to define a locale per the /public/locales directory (this should be listed in the docs, will create a pull request for that too).

If the environment variable is blank or invalid it reverts to previous behaviour of system + default locale. Fully tested the above as follows:

CUSTOM_LOCALE = 'nl' < This works correctly, translating to nl.
CUSTOM_LOCALE = 'HelloThere' < This reverts to previous behavior
CUSTOM_LOCALE = '' < Also reverts
#CUSTOM_LOCALE = < Also reverts
2022-08-13 02:25:19 +02:00
HrBingR
9221b86660
Merge branch 'timvisee:master' into master 2022-08-13 02:20:33 +02:00
HrBingR
fd2e954b3e Updated docs to include custom CSS and custom footer. 2022-08-12 21:57:14 +02:00
timvisee
c528ad3147
Merge branch 'HrBingR-master' into master
See https://github.com/timvisee/send/pull/103
2022-08-12 12:35:56 +02:00
HrBingR
df9c7ea734
Merge branch 'timvisee:master' into master 2022-08-11 23:06:47 +02:00
HrBingR
e32ea7d0aa Added the ability to define a custom footer via environment variables
Added the CUSTOM_FOOTER_TEXT and CUSTOM_FOOTER_URL environment variables.

If undefined, the default translated footer will display.

If only CUSTOM_FOOTER_TEXT is defined, only this defined text will display in place of the normal footer text.

If only CUSTOM_FOOTER_URL is defined then the defined URL will display.

If both variables are defined, the defined text will display as a link to the defined URL.
2022-08-11 23:04:45 +02:00
timvisee
55ad08fd96
Merge branch 'HrBingR-master' into master
See https://github.com/timvisee/send/pull/100
2022-08-11 10:07:14 +02:00
timvisee
96d53e4118
Merge branch 'master' of github.com:HrBingR/send into HrBingR-master 2022-08-11 10:06:45 +02:00
HrBingR
bce861bcaf Added if check to see if user is using custom CSS 2022-08-10 22:55:51 +02:00
timvisee
643287e235
Merge branch 'AaronDewes-chore/cleanup-dependencies' into master
See https://github.com/timvisee/send/pull/101
2022-08-10 19:04:33 +02:00
AaronDewes
c619be58ae Remove asmcrypto.js 2022-08-09 16:18:16 +00:00
AaronDewes
9b8b11ffc3 Remove double-ended-queue
Not required anymore since node-redis 3.0
2022-08-09 15:39:41 +00:00
AaronDewes
1725ff434e Further dependency cleanup 2022-08-09 15:37:16 +00:00
AaronDewes
e1d6224570 More dependency cleanups 2022-08-09 15:29:54 +00:00
AaronDewes
38746b86fd Update eslint & plugins
Also replace eslint-plugin-node with the maintained eslint-plugin-n
2022-08-09 15:26:25 +00:00
AaronDewes
64644b57e3 Remove some polyfills
This should reduce the runtime size & load times somewhat by removing polyfills for older browsers which are not used much
2022-08-09 15:17:38 +00:00
timvisee
625fdf5bca
Merge branch 'AaronDewes-update-deps' into master
See https://github.com/timvisee/send/pull/98
2022-08-09 16:20:33 +02:00
AaronDewes
951c613095 Fix stylelint errors 2022-08-09 09:12:32 +00:00
AaronDewes
16e78847a2 Fix style problems 2022-08-09 09:00:43 +00:00
HrBingR
310271c10f Added new environment variables for custom css, custom title, and custom description.
Fully tested using the Dockerfile, example can be found on https://fileshare.thenextweb.co.za
2022-08-08 00:37:17 +02:00
AaronDewes
55344f8a9d Drop mkdirp 2022-07-26 17:23:19 +00:00
AaronDewes
2b22e8cd05 Update more dependencies 2022-07-26 17:21:12 +00:00
AaronDewes
47ff32fc9f Modernize CSS 2022-07-26 16:52:29 +00:00
AaronDewes
b598a1c090 Update svgo 2022-07-26 11:56:20 +00:00
AaronDewes
3ae9e6adeb Update git-rev-sync 2022-07-26 11:18:17 +00:00
AaronDewes
33e7e0f5ba npm audit fix 2022-07-26 11:15:12 +00:00
AaronDewes
ca3b5cf7ca Update more packages 2022-07-26 11:05:53 +00:00
AaronDewes
44a25e4156 Update fluent 2022-07-26 11:03:10 +00:00
timvisee
000854104f
Merge branch 'NamPNQ-master' into master
See https://github.com/timvisee/send/pull/94
2022-07-04 18:40:45 +02:00
Nam PHAM
1a0ddf9a05 Disable check user when fxa is not enabled 2022-07-02 23:48:04 +02:00
dependabot[bot]
0ac1eeed2c
Bump got from 11.8.3 to 11.8.5
Bumps [got](https://github.com/sindresorhus/got) from 11.8.3 to 11.8.5.
- [Release notes](https://github.com/sindresorhus/got/releases)
- [Commits](https://github.com/sindresorhus/got/compare/v11.8.3...v11.8.5)

---
updated-dependencies:
- dependency-name: got
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-24 05:02:22 +00:00
dependabot[bot]
2457545502
Bump eventsource from 1.1.0 to 1.1.1
Bumps [eventsource](https://github.com/EventSource/eventsource) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/EventSource/eventsource/releases)
- [Changelog](https://github.com/EventSource/eventsource/blob/master/HISTORY.md)
- [Commits](https://github.com/EventSource/eventsource/compare/v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: eventsource
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-01 20:39:30 +00:00
dependabot[bot]
75637807eb
Bump convict from 6.2.2 to 6.2.3
Bumps [convict](https://github.com/mozilla/node-convict) from 6.2.2 to 6.2.3.
- [Release notes](https://github.com/mozilla/node-convict/releases)
- [Changelog](https://github.com/mozilla/node-convict/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mozilla/node-convict/compare/v6.2.2...v6.2.3)

---
updated-dependencies:
- dependency-name: convict
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-26 02:57:43 +00:00
timvisee
3b0ef1c0d6
Bump version to 3.4.20 2022-05-12 21:57:02 +02:00
timvisee
22c9560855
Update package-lock.json 2022-05-12 21:56:10 +02:00
Tim Visée
dda964ebf9 Merge branch 'feature/branding' into 'master'
Add ability to change the branding

See merge request timvisee/send!23
2022-05-12 19:52:46 +00:00
Marian Hähnlein
560747106b
Add ability to change the branding 2022-05-02 13:38:16 +02:00
57 changed files with 10078 additions and 25355 deletions

View file

@ -1,105 +1,72 @@
image: "node:15-slim"
stages:
- test
- artifact
- release
before_script:
# Install dependencies
- apt-get update
- apt-get install -y git python3 build-essential libxtst6
# Prepare Chrome for puppeteer
- apt-get install -y wget gnupg
- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
- sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
- apt-get update
- apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 --no-install-recommends
# Build Send, run npm tests
test:
stage: test
image: "node:16-slim"
only:
- api
- branches
- chat
- merge_requests
- pushes
- schedules
- tags
- triggers
- web
before_script:
# Install dependencies
- apt-get update
- apt-get install -y git python3 build-essential libxtst6
# Prepare Chrome for puppeteer
- apt-get install -y wget gnupg
- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
- sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
- apt-get update
- apt-get install -y gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils
- apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst fonts-freefont-ttf libxss1 --no-install-recommends
script:
- npm ci
- npm run lint
- npm test
# Build Docker image, export Docker image artifact
artifact-docker:
stage: artifact
image: docker:latest
needs: []
services:
- docker:dind
variables:
IMG_FILE: "send:git-$CI_COMMIT_SHORT_SHA.tar"
IMG_NAME: "send:git-$CI_COMMIT_SHORT_SHA"
before_script: []
script:
- docker build -t $IMG_NAME .
- docker image save -o $IMG_FILE $IMG_NAME
artifacts:
name: artifact-docker
paths:
- $IMG_FILE
expire_in: 1 week
# Release public Docker image for the master branch
release-docker-master:
stage: release
image: docker:latest
dependencies:
- artifact-docker
services:
- docker:dind
only:
- master
variables:
IMG_IMPORT_FILE: "send:git-$CI_COMMIT_SHORT_SHA.tar"
IMG_IMPORT_NAME: "send:git-$CI_COMMIT_SHORT_SHA"
IMG_NAME: "registry.gitlab.com/timvisee/send:master-$CI_COMMIT_SHORT_SHA"
before_script: []
script:
# Login in to registry
- 'docker login registry.gitlab.com -u $DOCKER_USER -p $DOCKER_PASS'
# Load existing, retag for new image images
- docker image load -i $IMG_IMPORT_FILE
- docker tag $IMG_IMPORT_NAME $IMG_NAME
# Publish tagged image
- docker push $IMG_NAME
- 'echo "Docker image artifact published, available as:" && echo " docker pull $IMG_NAME"'
# Release public Docker image for a version tag
release-docker:
stage: release
image: docker:latest
dependencies:
- artifact-docker
services:
- docker:dind
only:
- /^v(\d+\.)*\d+$/
variables:
IMG_IMPORT_FILE: "send:git-$CI_COMMIT_SHORT_SHA.tar"
IMG_IMPORT_NAME: "send:git-$CI_COMMIT_SHORT_SHA"
IMG_NAME: "registry.gitlab.com/timvisee/send:$CI_COMMIT_REF_NAME"
IMG_NAME_LATEST: "registry.gitlab.com/timvisee/send:latest"
before_script: []
- api
- branches
- chat
- merge_requests
- pushes
- schedules
- tags
- triggers
- web
script:
# Login in to registry
- 'docker login registry.gitlab.com -u $DOCKER_USER -p $DOCKER_PASS'
# Load existing, retag for new image images
- docker image load -i $IMG_IMPORT_FILE
- docker tag $IMG_IMPORT_NAME $IMG_NAME
- docker tag $IMG_IMPORT_NAME $IMG_NAME_LATEST
# Publish tagged image
- docker push $IMG_NAME
- docker push $IMG_NAME_LATEST
- 'echo "Docker image artifact published, available as:" && echo " docker pull $IMG_NAME_LATEST" && echo " docker pull $IMG_NAME"'
- docker login "$CI_REGISTRY" -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
- docker buildx create --name sendBuilder
- docker buildx use sendBuilder
- |
if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then
IMAGE_NAMES="$CI_REGISTRY_IMAGE/mr:$CI_MERGE_REQUEST_IID"
elif [ "$CI_COMMIT_TAG" != "" ]; then
IMAGE_NAMES="$CI_REGISTRY_IMAGE:$CI_COMMIT_TAG $CI_REGISTRY_IMAGE:latest"
else
IMAGE_NAMES="$CI_REGISTRY_IMAGE/$CI_COMMIT_BRANCH:$CI_COMMIT_SHORT_SHA"
fi
- |
for image in $IMAGE_NAMES; do
docker buildx build --platform linux/amd64,linux/arm64 -t $image . --push
done
- |
echo "Container image pushed. You can pull it with";
for image in $IMAGE_NAMES; do
echo "docker pull $image"
done

View file

@ -11,3 +11,5 @@ rules:
selector-list-comma-newline-after: null
value-list-comma-newline-after: null
at-rule-no-unknown: null
# Conflicts with prettier
string-quotes: null

View file

@ -152,7 +152,7 @@ AWS example using Ubuntu Server `20.04`: [docs/AWS.md](docs/AWS.md)
- Web: _this repository_
- Command-line: [`ffsend`](https://github.com/timvisee/ffsend)
- Android: _see [Android](#android) section_
- Thunderbird: [FileLink provider for Send](https://addons.thunderbird.net/en-US/thunderbird/addon/filelink-provider-for-send/)
- Thunderbird: [FileLink provider for Send](https://addons.thunderbird.net/thunderbird/addon/filelink-provider-for-send/)
#### Android

View file

@ -43,7 +43,7 @@ function post(obj, bearerToken) {
'Content-Type': 'application/json'
};
if (bearerToken) {
h['Authentication'] = `Bearer ${bearerToken}`;
h['Authorization'] = `Bearer ${bearerToken}`;
}
return {
method: 'POST',

View file

@ -17,6 +17,7 @@ export default class Archive {
constructor(files = [], defaultTimeLimit = 86400, defaultDownloadLimit = 1) {
this.files = Array.from(files);
this.defaultTimeLimit = defaultTimeLimit;
this.defaultDownloadLimit = defaultDownloadLimit;
this.timeLimit = defaultTimeLimit;
this.dlimit = defaultDownloadLimit;
this.password = null;
@ -76,7 +77,7 @@ export default class Archive {
clear() {
this.files = [];
this.dlimit = 1;
this.dlimit = this.defaultDownloadLimit;
this.timeLimit = this.defaultTimeLimit;
this.password = null;
}

View file

@ -7,7 +7,7 @@ const experiments = {
return true;
},
variant: function() {
return ['white-blue', 'blue', 'white-violet', 'violet'][
return ['white-primary', 'primary', 'white-violet', 'violet'][
Math.floor(Math.random() * 4)
];
},

View file

@ -1,8 +1,8 @@
import { FluentBundle } from '@fluent/bundle';
import { FluentBundle, FluentResource } from '@fluent/bundle';
function makeBundle(locale, ftl) {
const bundle = new FluentBundle(locale, { useIsolating: false });
bundle.addMessages(ftl);
bundle.addResource(new FluentResource(ftl));
return bundle;
}
@ -19,7 +19,7 @@ export async function getTranslator(locale) {
return function(id, data) {
for (let bundle of bundles) {
if (bundle.hasMessage(id)) {
return bundle.format(bundle.getMessage(id), data);
return bundle.formatPattern(bundle.getMessage(id).value, data);
}
}
};

View file

@ -7,17 +7,14 @@ html {
@tailwind components;
:not(input) {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
:root {
--violet-gradient: linear-gradient(
-180deg,
rgba(144, 89, 255, 0.8) 0%,
rgba(144, 89, 255, 0.4) 100%
rgb(144 89 255 / 80%) 0%,
rgb(144 89 255 / 40%) 100%
);
}
@ -39,7 +36,7 @@ body {
}
.btn {
@apply bg-blue-60;
@apply bg-primary;
@apply text-white;
@apply cursor-pointer;
@apply py-4;
@ -48,11 +45,11 @@ body {
}
.btn:hover {
@apply bg-blue-70;
@apply bg-primary_accent;
}
.btn:focus {
@apply bg-blue-70;
@apply bg-primary_accent;
}
.checkbox {
@ -71,7 +68,7 @@ body {
.checkbox > label::before {
/* @apply bg-grey-10; */
@apply border;
@apply border-default;
@apply rounded-sm;
content: '';
@ -82,16 +79,16 @@ body {
}
.checkbox > label:hover::before {
@apply border-blue-50;
@apply border-primary;
}
.checkbox > input:focus + label::before {
@apply border-blue-50;
@apply border-primary;
}
.checkbox > input:checked + label::before {
@apply bg-blue-50;
@apply border-blue-50;
@apply bg-primary;
@apply border-primary;
background-image: url('../assets/lock.svg');
background-position: center;
@ -104,8 +101,8 @@ body {
}
.checkbox > input:disabled + label::before {
@apply bg-blue-50;
@apply border-blue-50;
@apply bg-primary;
@apply border-primary;
background-image: url('../assets/lock.svg');
background-position: center;
@ -153,16 +150,16 @@ footer li a:hover {
white-space: nowrap;
}
.link-blue {
@apply text-blue-60;
.link-primary {
@apply text-primary;
}
.link-blue:hover {
@apply text-blue-70;
.link-primary:hover {
@apply text-primary_accent;
}
.link-blue:focus {
@apply text-blue-70;
.link-primary:focus {
@apply text-primary_accent;
}
.main-header img {
@ -170,6 +167,22 @@ footer li a:hover {
width: auto;
}
.text-underline {
text-decoration: underline;
}
.d-block {
display: block;
}
.d-inline-block {
display: inline-block;
}
.align-middle {
vertical-align: middle;
}
.main {
display: flex;
position: relative;
@ -204,19 +217,18 @@ progress::-webkit-progress-value {
background-image: -webkit-linear-gradient(
-45deg,
transparent 20%,
rgba(255, 255, 255, 0.4) 20%,
rgba(255, 255, 255, 0.4) 40%,
rgb(255 255 255 / 40%) 20%,
rgb(255 255 255 / 40%) 40%,
transparent 40%,
transparent 60%,
rgba(255, 255, 255, 0.4) 60%,
rgba(255, 255, 255, 0.4) 80%,
rgb(255 255 255 / 40%) 60%,
rgb(255 255 255 / 40%) 80%,
transparent 80%
),
-webkit-linear-gradient(left, #0a84ff, #0a84ff);
-webkit-linear-gradient(left, var(--color-primary), var(--color-primary));
/* stylelint-enable */
border-radius: 2px;
background-size: 21px 20px, 100% 100%, 100% 100%;
-webkit-animation: animate-stripes 1s linear infinite;
}
progress::-moz-progress-bar {
@ -224,27 +236,21 @@ progress::-moz-progress-bar {
background-image: -moz-linear-gradient(
135deg,
transparent 20%,
rgba(255, 255, 255, 0.4) 20%,
rgba(255, 255, 255, 0.4) 40%,
rgb(255 255 255 / 40%) 20%,
rgb(255 255 255 / 40%) 40%,
transparent 40%,
transparent 60%,
rgba(255, 255, 255, 0.4) 60%,
rgba(255, 255, 255, 0.4) 80%,
rgb(255 255 255 / 40%) 60%,
rgb(255 255 255 / 40%) 80%,
transparent 80%
),
-moz-linear-gradient(left, #0a84ff, #0a84ff);
-moz-linear-gradient(left, var(--color-primary), var(--color-primary));
/* stylelint-enable */
border-radius: 2px;
background-size: 21px 20px, 100% 100%, 100% 100%;
animation: animate-stripes 1s linear infinite;
}
@-webkit-keyframes animate-stripes {
100% {
background-position: -21px 0;
}
}
@keyframes animate-stripes {
100% {
background-position: -21px 0;
@ -283,28 +289,28 @@ select {
}
.btn {
@apply bg-blue-40;
@apply bg-primary;
@apply text-white;
}
.btn:hover {
@apply bg-blue-50;
@apply bg-primary_accent;
}
.btn:focus {
@apply bg-blue-50;
@apply bg-primary_accent;
}
.link-blue {
@apply text-blue-40;
.link-primary {
@apply text-primary;
}
.link-blue:hover {
@apply text-blue-50;
.link-primary:hover {
@apply text-primary_accent;
}
.link-blue:focus {
@apply text-blue-50;
.link-primary:focus {
@apply text-primary_accent;
}
.main > section {
@ -313,7 +319,7 @@ select {
@screen md {
.main > section {
@apply border;
@apply border-default;
@apply border-grey-80;
}
}
@ -323,13 +329,12 @@ select {
@responsive {
.shadow-light {
box-shadow: 0 0 8px 0 rgba(12, 12, 13, 0.1);
box-shadow: 0 0 8px 0 rgb(12 12 13 / 10%);
}
.shadow-big {
box-shadow: 0 12px 18px 2px rgba(34, 0, 51, 0.04),
0 6px 22px 4px rgba(7, 48, 114, 0.12),
0 6px 10px -4px rgba(14, 13, 26, 0.12);
box-shadow: 0 12px 18px 2px rgb(34 0 51 / 4%),
0 6px 22px 4px rgb(7 48 114 / 12%), 0 6px 10px -4px rgb(14 13 26 / 12%);
}
}
@ -363,20 +368,20 @@ select {
/* begin signin button color experiment */
.white-blue {
@apply border-blue-60;
.white-primary {
@apply border-primary;
@apply border-2;
@apply text-blue-60;
@apply text-primary;
}
.white-blue:hover,
.white-blue:focus {
@apply bg-blue-60;
.white-primary:hover,
.white-primary:focus {
@apply bg-primary;
@apply text-white;
}
.blue {
@apply bg-blue-60;
.primary {
@apply bg-primary;
@apply text-white;
}

View file

@ -69,7 +69,7 @@ class Account extends Component {
return html`
<send-account>
<button
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"
class="px-4 py-2 md:px-8 md:py-4 focus:outline signin border-2 link-primary border-primary hover:border-primary dark:border-primary dark:hover:border-primary"
onclick="${e => this.login(e)}"
title="${translate('signInOnlyButton')}"
>
@ -83,19 +83,19 @@ class Account extends Component {
<input
type="image"
alt="${user.email}"
class="w-8 h-8 rounded-full border text-blue-50 md:text-white focus:outline"
class="w-8 h-8 rounded-full border-default text-primary 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 dark:bg-grey-80"
class="invisible absolute top-0 right-0 mt-10 pt-2 pb-2 bg-white shadow-md whitespace-nowrap outline-none z-50 dark:bg-grey-80"
onblur="${e => this.hideMenu(e)}"
>
<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-80 dark:text-grey-30 hover:bg-blue-50 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-primary hover:text-white cursor-pointer focus:outline"
onclick="${e => this.logout(e)}"
title="${translate('signOut')}"
>

View file

@ -26,7 +26,7 @@ function expiryInfo(translate, archive) {
}
function password(state) {
const MAX_LENGTH = 32;
const MAX_LENGTH = 4096;
return html`
<div class="mb-2 px-1">
@ -53,7 +53,7 @@ function password(state) {
id="password-input"
class="${state.archive.password
? ''
: 'invisible'} border rounded focus:border-blue-60 leading-normal my-1 py-1 px-2 h-8 dark:bg-grey-80"
: 'invisible'} border-default rounded-default focus:border-primary leading-normal my-1 py-1 px-2 h-8 dark:bg-grey-80"
autocomplete="off"
maxlength="${MAX_LENGTH}"
type="password"
@ -150,7 +150,7 @@ function password(state) {
function fileInfo(file, action) {
return html`
<send-file class="flex flex-row items-center p-3 w-full">
<svg class="h-8 w-8 text-white dark:text-grey-90">
<svg class="h-8 w-8 text-primary">
<use xlink:href="${assets.get('blue_file.svg')}#icon"/>
</svg>
<p class="ml-4 w-full">
@ -166,7 +166,7 @@ function fileInfo(file, action) {
function archiveInfo(archive, action) {
return html`
<p class="w-full flex items-center">
<svg class="h-8 w-6 mr-3 flex-shrink-0 text-white dark:text-grey-90">
<svg class="h-8 w-6 mr-3 flex-shrink-0 text-primary">
<use xlink:href="${assets.get('blue_file.svg')}#icon"/>
</svg>
<p class="flex-grow">
@ -188,7 +188,7 @@ function archiveDetails(translate, archive) {
ontoggle="${toggled}"
>
<summary
class="flex items-center link-blue text-sm cursor-pointer outline-none"
class="flex items-center link-primary text-sm cursor-pointer outline-none"
>
<svg
class="fill-current w-4 h-4 mr-1"
@ -218,7 +218,7 @@ module.exports = function(state, emit, archive) {
state.capabilities.share || platform() === 'android'
? html`
<button
class="link-blue self-end flex items-start"
class="link-primary self-end flex items-start"
onclick=${share}
title="Share link"
>
@ -230,7 +230,7 @@ module.exports = function(state, emit, archive) {
`
: html`
<button
class="link-blue focus:outline self-end flex items-center"
class="link-primary focus:outline self-end flex items-center"
onclick=${copy}
title="${state.translate('copyLinkButton')}"
>
@ -244,7 +244,7 @@ module.exports = function(state, emit, archive) {
platform() === 'web'
? html`
<a
class="flex items-baseline link-blue"
class="flex items-baseline link-primary"
href="${archive.url}"
title="${state.translate('downloadButtonLabel')}"
tabindex="0"
@ -261,7 +261,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 dark:bg-grey-90 dark:border dark:border-grey-70"
class="flex flex-col items-start rounded-default shadow-light bg-white p-4 w-full dark:bg-grey-90 dark:border-default dark:border-grey-70"
>
${archiveInfo(
archive,
@ -335,7 +335,7 @@ module.exports.wip = function(state, emit) {
fileInfo(f, remove(f, state.translate('deleteButtonHover')))
),
'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'
'bg-white px-2 my-2 shadow-light rounded-default dark:bg-grey-90 dark:border-default dark:border-grey-80'
)}
<div
class="flex-shrink-0 flex-grow flex items-end p-4 bg-grey-10 rounded-b mb-1 font-medium dark:bg-grey-90"
@ -358,7 +358,7 @@ module.exports.wip = function(state, emit) {
class="flex items-center cursor-pointer"
title="${state.translate('addFilesButton')}"
>
<svg class="w-6 h-6 mr-2 link-blue">
<svg class="w-6 h-6 mr-2 link-primary">
<use xlink:href="${assets.get('addfiles.svg')}#plus" />
</svg>
${state.translate('addFilesButton')}
@ -438,7 +438,7 @@ 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 dark:bg-grey-90"
class="flex flex-col items-start rounded-default shadow-light bg-white p-4 w-full dark:bg-grey-90"
>
${archiveInfo(archive)}
<div class="text-xs opacity-75 w-full mt-2 mb-2">
@ -448,12 +448,12 @@ module.exports.uploading = function(state, emit) {
expiresAt: Date.now() + 500 + state.archive.timeLimit * 1000
})}
</div>
<div class="link-blue text-sm font-medium mt-2">
<div class="link-primary text-sm font-medium mt-2">
${progressPercent}
</div>
<progress class="my-3" value="${progress}">${progressPercent}</progress>
<button
class="link-blue self-end font-medium"
class="link-primary self-end font-medium"
onclick=${cancel}
title="${state.translate('deletePopupCancel')}"
>
@ -475,7 +475,7 @@ module.exports.empty = function(state, emit) {
? ''
: html`
<button
class="center font-medium text-sm link-blue mt-4 mb-2"
class="center font-medium text-sm link-primary mt-4 mb-2"
onclick="${event => {
event.stopPropagation();
emit('signup-cta', 'drop');
@ -486,16 +486,26 @@ module.exports.empty = function(state, emit) {
})}
</button>
`;
const uploadNotice = state.WEB_UI.UPLOAD_AREA_NOTICE_HTML
? html`
<p
class="w-full mt-8 p-2 border-default dark:border-grey-70 rounded-default text-orange-60 bg-yellow-40 text-center leading-normal"
>
${raw(state.WEB_UI.UPLOAD_AREA_NOTICE_HTML)}
</p>
`
: '';
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 dark:border-grey-60"
class="flex flex-col items-center justify-center border-2 border-dashed border-grey-transparent rounded-default px-6 py-16 h-full w-full dark:border-grey-60"
onclick="${e => {
if (e.target.tagName !== 'LABEL') {
document.getElementById('file-upload').click();
}
}}"
>
<svg class="w-10 h-10 link-blue">
<svg class="w-10 h-10 link-primary">
<use xlink:href="/${assets.get('addfiles.svg')}#plus" />
</svg>
<div class="pt-6 pb-2 text-center text-lg font-bold tracking-wide">
@ -526,16 +536,16 @@ module.exports.empty = function(state, emit) {
>
${state.translate('addFilesButton')}
</label>
${upsell}
${upsell} ${uploadNotice}
</send-upload-area>
`;
function focus(event) {
event.target.nextElementSibling.classList.add('bg-blue-70', 'outline');
event.target.nextElementSibling.classList.add('bg-primary', 'outline');
}
function blur(event) {
event.target.nextElementSibling.classList.remove('bg-blue-70', 'outline');
event.target.nextElementSibling.classList.remove('bg-primary', 'outline');
}
function add(event) {
@ -559,11 +569,43 @@ module.exports.preview = function(state, emit) {
${archiveDetails(state.translate, archive)}
</div>
`;
const notice = state.WEB_UI.DOWNLOAD_NOTICE_HTML
? html`
<p
class="w-full mt-4 p-2 border-default dark:border-grey-70 rounded-default text-orange-60 bg-yellow-40 text-center leading-normal"
>
${raw(state.WEB_UI.DOWNLOAD_NOTICE_HTML)}
</p>
`
: '';
const sponsor = state.WEB_UI.SHOW_THUNDERBIRD_SPONSOR
? html`
<a
class="w-full mt-5 mb-2 p-2 border-default dark:border-grey-70 rounded-default text-orange-60 bg-yellow-40 text-center leading-normal"
href="https://www.thunderbird.net/"
>
<svg
width="30"
height="30"
class="m-2 mr-3 d-inline-block align-middle"
>
<image
xlink:href="${assets.get('thunderbird-icon.svg')}"
src="${assets.get('thunderbird-icon.svg')}"
width="30"
height="30"
/>
</svg>
${state.translate('sponsoredByThunderbird')}
</a>
`
: '';
return html`
<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">
<div class="border-default rounded-default py-3 px-6 dark:border-grey-70">
${archiveInfo(archive)} ${details}
</div>
<button
@ -574,6 +616,7 @@ module.exports.preview = function(state, emit) {
>
${state.translate('downloadButtonLabel')}
</button>
${notice} ${sponsor}
</send-archive>
`;
@ -590,10 +633,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 dark:bg-grey-90"
class="flex flex-col bg-white rounded-default shadow-light p-4 w-full max-w-sm md:w-128 dark:bg-grey-90"
>
${archiveInfo(archive)}
<div class="link-blue text-sm font-medium mt-2">
<div class="link-primary text-sm font-medium mt-2">
${progressPercent}
</div>
<progress class="my-3" value="${progress}">${progressPercent}</progress>

View file

@ -21,7 +21,7 @@ module.exports = function(name, url) {
<input
type="text"
id="share-url"
class="block w-full my-4 border rounded-lg leading-loose h-12 px-2 py-1 dark:bg-grey-80"
class="block w-full my-4 border-default rounded-lg leading-loose h-12 px-2 py-1 dark:bg-grey-80"
value="${url}"
readonly="true"
/>
@ -42,7 +42,7 @@ module.exports = function(name, url) {
${state.translate('copyLinkButton')}
</button>
<button
class="link-blue my-4 font-medium cursor-pointer focus:outline"
class="link-primary my-4 font-medium cursor-pointer focus:outline"
onclick="${close}"
title="${state.translate('okButton')}"
>

View file

@ -11,7 +11,9 @@ module.exports = function(state) {
<h1 class="text-center text-3xl font-bold my-2">
${state.translate('downloadFinish')}
</h1>
<img src="${assets.get('completed.svg')}" class="my-8 h-48" />
<svg class="my-8 h-48 text-primary">
<use xlink:href="${assets.get('completed.svg')}#Page-1" />
</svg>
<p
class="text-grey-80 leading-normal dark:text-grey-40 ${state.user
.loggedIn

View file

@ -17,7 +17,7 @@ module.exports = function(state, emit) {
${state.translate('downloadDescription')}
</p>
<form
class="flex flex-row flex-no-wrap w-full md:w-4/5"
class="flex flex-row flex-nowrap w-full md:w-4/5"
onsubmit="${checkPassword}"
data-no-csrf
>
@ -32,7 +32,7 @@ module.exports = function(state, emit) {
class="w-full border-l border-t border-b rounded-l-lg rounded-r-none ${invalid
? 'border-red dark:border-red-40'
: 'border-grey'} leading-loose px-2 py-1 dark:bg-grey-80"
maxlength="32"
maxlength="4096"
autocomplete="off"
placeholder="${state.translate('unlockInputPlaceholder')}"
oninput="${inputChanged}"

View file

@ -13,7 +13,9 @@ module.exports = function(state, emit) {
<h1 class="text-center text-3xl font-bold my-2">
${state.translate('errorPageHeader')}
</h1>
<img class="my-12 h-48" src="${assets.get('error.svg')}" />
<svg class="text-primary my-12 h-48">
<use xlink:href="${assets.get('error.svg')}#svg114" />
</svg>
<p
class="max-w-md text-center text-grey-80 leading-normal dark:text-grey-40 ${state
.user.loggedIn

View file

@ -1,9 +1,11 @@
/*global WEB_UI*/
const { platform } = require('../utils');
const assets = require('../../common/assets');
const size = 32;
const loaderWidth = 5;
const loaderColor = '#0090ed';
const loaderColor = WEB_UI.COLORS.PRIMARY;
function drawCircle(canvas, context, color, lineWidth, outerWidth, percent) {
canvas.width = canvas.height = outerWidth;
@ -32,7 +34,10 @@ module.exports.updateFavicon = function(progressRatio) {
const progress = progressRatio * 100;
if (progress === 0 || progress === 100) {
link.type = 'image/png';
link.href = assets.get('favicon-32x32.png');
link.href =
WEB_UI.CUSTOM_ASSETS.favicon_32px !== ''
? WEB_UI.CUSTOM_ASSETS.favicon_32px
: assets.get('favicon-32x32.png');
return;
}

View file

@ -65,6 +65,45 @@ class Footer extends Component {
`);
}
// Defining a custom footer
var footer = [];
if (this.state != undefined && this.state.WEB_UI != undefined) {
const WEB_UI = this.state.WEB_UI;
if (WEB_UI.CUSTOM_FOOTER_URL != '' && WEB_UI.CUSTOM_FOOTER_TEXT != '') {
footer.push(html`
<li class="m-2">
<a href="${WEB_UI.CUSTOM_FOOTER_URL}" target="_blank">
${WEB_UI.CUSTOM_FOOTER_TEXT}
</a>
</li>
`);
}
else if (WEB_UI.CUSTOM_FOOTER_URL != '') {
footer.push(html`
<li class="m-2">
<a href="${WEB_UI.CUSTOM_FOOTER_URL}" target="_blank">
${WEB_UI.CUSTOM_FOOTER_URL}
</a>
</li>
`);
}
else if (WEB_UI.CUSTOM_FOOTER_TEXT != '') {
footer.push(html`
<li class="m-2">
${WEB_UI.CUSTOM_FOOTER_TEXT}
</li>
`)
}
else {
footer.push(html`
<li class="m-2">
${translate('footerText')}
</li>
`);
}
}
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-60 dark:text-grey-40 md:items-center justify-between"
@ -72,7 +111,7 @@ class Footer extends Component {
<ul
class="flex flex-col md:flex-row items-start md:items-center md:justify-start"
>
<li class="m-2">${translate('footerText')}</li>
${footer}
</ul>
<ul
class="flex flex-col md:flex-row items-start md:items-center md:justify-end"

View file

@ -18,13 +18,26 @@ class Header extends Component {
}
createElement() {
let assetMap = {};
if (this.state.ui !== undefined) assetMap = this.state.ui.assets;
else
assetMap = {
icon:
this.state.WEB_UI.CUSTOM_ASSETS.icon !== ''
? this.state.WEB_UI.CUSTOM_ASSETS.icon
: assets.get('icon.svg'),
wordmark:
this.state.WEB_UI.CUSTOM_ASSETS.wordmark !== ''
? this.state.WEB_UI.CUSTOM_ASSETS.wordmark
: assets.get('wordmark.svg') + '#logo'
};
const title =
platform() === 'android'
? html`
<a class="flex flex-row items-center">
<img src="${assets.get('icon.svg')}" />
<img src="${assetMap.icon}" />
<svg class="w-48">
<use xlink:href="${assets.get('wordmark.svg')}#logo" />
<use xlink:href="${assetMap.wordmark}" />
</svg>
</a>
`
@ -32,10 +45,10 @@ class Header extends Component {
<a class="flex flex-row items-center" href="/">
<img
alt="${this.state.translate('title')}"
src="${assets.get('icon.svg')}"
src="${assetMap.icon}"
/>
<svg viewBox="66 0 340 64" class="w-48 md:w-64">
<use xlink:href="${assets.get('wordmark.svg')}#logo" />
<use xlink:href="${assetMap.wordmark}" />
</svg>
</a>
`;

View file

@ -1,8 +1,10 @@
const html = require('choo/html');
const raw = require('choo/html/raw');
const { list } = require('../utils');
const archiveTile = require('./archiveTile');
const modal = require('./modal');
const intro = require('./intro');
const assets = require('../../common/assets');
module.exports = function(state, emit) {
const archives = state.storage.files
@ -16,7 +18,42 @@ module.exports = function(state, emit) {
} else {
left = archiveTile.empty(state, emit);
}
if (archives.length > 0 && state.WEB_UI.UPLOADS_LIST_NOTICE_HTML) {
archives.push(html`
<p
class="w-full p-2 border-default dark:border-grey-70 rounded-default text-orange-60 bg-yellow-40 text-center leading-normal"
>
${raw(state.WEB_UI.UPLOADS_LIST_NOTICE_HTML)}
</p>
`);
}
archives.reverse();
if (archives.length > 0 && state.WEB_UI.SHOW_THUNDERBIRD_SPONSOR) {
archives.push(html`
<a
class="w-full p-2 border-default dark:border-grey-70 rounded-default text-orange-60 bg-yellow-40 text-center leading-normal d-block"
href="https://www.thunderbird.net/"
>
<svg
width="30"
height="30"
class="m-2 mr-3 d-inline-block align-middle"
>
<image
xlink:href="${assets.get('thunderbird-icon.svg')}"
src="${assets.get('thunderbird-icon.svg')}"
width="30"
height="30"
/>
</svg>
Sponsored by Thunderbird
</a>
`);
}
const right =
archives.length === 0
? intro(state)

View file

@ -1,10 +1,46 @@
const html = require('choo/html');
const raw = require('choo/html/raw');
const assets = require('../../common/assets');
module.exports = function intro(state) {
const notice = state.WEB_UI.MAIN_NOTICE_HTML
? html`
<p
class="w-full mt-2 p-2 border-default dark:border-grey-70 rounded-default text-orange-60 bg-yellow-40 text-center leading-normal"
>
${raw(state.WEB_UI.MAIN_NOTICE_HTML)}
</p>
`
: '';
const sponsor = state.WEB_UI.SHOW_THUNDERBIRD_SPONSOR
? html`
<a
class="w-full mt-5 mb-2 p-2 border-default dark:border-grey-70 rounded-default text-orange-60 bg-yellow-40 text-center leading-normal"
href="https://www.thunderbird.net/"
>
<svg
width="30"
height="30"
class="m-2 mr-3 d-inline-block align-middle"
>
<image
xlink:href="${assets.get('thunderbird-icon.svg')}"
src="${assets.get('thunderbird-icon.svg')}"
width="30"
height="30"
/>
</svg>
Sponsored by Thunderbird
</a>
`
: '';
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 dark:bg-grey-90"
>
${notice}
<div class="mt-12 flex flex-col h-full">
<h1 class="text-3xl font-bold md:pb-2">
${state.translate('introTitle')}
@ -13,6 +49,7 @@ module.exports = function intro(state) {
${state.translate('introDescription')}
</p>
</div>
${sponsor}
</send-intro>
`;
};

View file

@ -12,14 +12,14 @@ module.exports = function(state, emit) {
'downloadTitle'
)}</h1>
<p
class="w-full p-2 border border-yellow-50 rounded md:w-4/5 text-orange-60 bg-yellow-40 text-center leading-normal"
class="w-full p-2 border-default border-yellow-50 rounded-default md:w-4/5 text-orange-60 bg-yellow-40 text-center leading-normal"
>
${state.translate('noStreamsWarning')}
</p>
<form class="md:w-128" onsubmit=${submit}>
<fieldset class="border rounded p-4 my-4" onchange=${optionChanged}>
<fieldset class="border-default rounded-default p-4 my-4" onchange=${optionChanged}>
<div class="flex items-center mb-2">
<svg class="h-8 w-6 mr-3 flex-shrink-0 text-white dark:text-grey-90">
<svg class="h-8 w-6 mr-3 flex-shrink-0 text-primary">
<use xlink:href="${assets.get('blue_file.svg')}#icon"/>
</svg>
<p class="flex-grow">

View file

@ -13,7 +13,9 @@ module.exports = function(state, emit) {
<h1 class="text-center text-3xl font-bold my-2">
${state.translate('expiredTitle')}
</h1>
<img src="${assets.get('notFound.svg')}" class="my-12" />
<svg class="text-primary my-12">
<use xlink:href="${assets.get('notFound.svg')}#svg124" />
</svg>
<p
class="max-w-md text-center text-grey-80 leading-normal dark:text-grey-40 ${state
.user.loggedIn

View file

@ -3,15 +3,22 @@ const html = require('choo/html');
module.exports = function(selected, options, translate, changed, htmlId) {
function choose(event) {
if (event.target.value != selected) {
console.log('Selected new value from dropdown', htmlId, ':', selected, '->', event.target.value)
console.log(
'Selected new value from dropdown',
htmlId,
':',
selected,
'->',
event.target.value
);
changed(event.target.value);
}
}
return html`
<select
id="${htmlId}"
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"
class="appearance-none cursor-pointer border-default rounded-default bg-grey-10 hover:border-primary focus:border-primary pl-1 pr-8 py-1 my-1 h-8 dark:bg-grey-80"
data-selected="${selected}"
onchange="${choose}"
>

View file

@ -18,7 +18,7 @@ module.exports = function(name, url) {
<input
type="text"
id="share-url"
class="w-full my-4 border rounded-lg leading-loose h-12 px-2 py-1 dark:bg-grey-80"
class="w-full my-4 border-default rounded-lg leading-loose h-12 px-2 py-1 dark:bg-grey-80"
value="${url}"
readonly="true"
/>
@ -30,7 +30,7 @@ module.exports = function(name, url) {
${state.translate('shareLinkButton')}
</button>
<button
class="link-blue my-4 font-medium cursor-pointer focus:outline"
class="link-primary my-4 font-medium cursor-pointer focus:outline"
onclick="${close}"
title="${state.translate('okButton')}"
>

View file

@ -35,7 +35,7 @@ module.exports = function() {
<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-70 leading-loose dark:bg-grey-80 dark:text-white"
class="hidden border-default 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
@ -50,7 +50,7 @@ module.exports = function() {
? ''
: html`
<button
class="my-3 link-blue font-medium"
class="my-3 link-primary font-medium"
title="${state.translate('deletePopupCancel')}"
onclick=${cancel}
>

View file

@ -30,7 +30,7 @@ module.exports = function() {
Give feedback
</a>
<button
class="link-blue font-medium cursor-pointer focus:outline"
class="link-primary font-medium cursor-pointer focus:outline"
onclick="${close}"
title="Skip"
>

View file

@ -10,7 +10,7 @@ module.exports = function(state, emit) {
strings = unsupportedStrings(state);
why = html`
<a
class="text-blue"
class="text-primary"
href="https://github.com/timvisee/send/blob/master/docs/faq.md#why-is-my-browser-not-supported"
>
${state.translate('notSupportedLink')}
@ -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-30 md:border-none md:px-12 md:py-16 shadow w-full md:h-full dark:bg-grey-90"
class="flex flex-col items-center justify-center text-center bg-white m-6 px-6 py-8 border-default border-grey-30 md:border-none md:px-12 md:py-16 shadow-default 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,26 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<!--
This would be the elegant way, but chrome cannot handle masks in external SVGs.
See https://bugs.chromium.org/p/chromium/issues/detail?id=109212
-->
<!--
<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>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Send_Ready_to_Send-Spec" transform="translate(-277.000000, -206.000000)">
<g id="List-Item-1" transform="translate(253.000000, 192.000000)">
<g id="Locked-File-Icon" transform="translate(24.000000, 14.000000)">
<g id="File-Icon">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<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 id="Fire-Icon">
<mask id="mask">
<rect x="0" y="0" width="100" height="100" fill="white"/>
<path d="M7.2830232,8.93885547 L8.91906464,8.93885547" stroke="black" stroke-width="2" stroke-linecap="round"/>
<path d="M7.2830232,15.7798836 L17.5412669,15.7798836" stroke="black" stroke-width="2" stroke-linecap="round"/>
<path d="M7.2830232,22.6209117 L17.5412669,22.6209117" stroke="black" stroke-width="2" stroke-linecap="round"/>
<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-linecap="square" stroke="black" stroke-width="2" fill="none"/>
</mask>
<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" fill="currentColor" mask="url(#mask)" />
</g>
</g>
</symbol>
</svg>
-->
<symbol id="icon" viewBox="0 0 26 32">
<path d="m 15 0 c 0.7 0.1 1.233 0.331 1.7 0.8 l 7.1 7.1 c 0.5 0.5 0.8 1.1 0.8 1.8 h -7.9 c -1 0 -1.7 -0.8 -1.7 -1.7 V 0.4 z M 24.65 11.647 v 17.23 c 0 1.5 -1.2 2.8 -2.8 2.8 h -19 c -1.234 -0.017 -2.694 -1.094 -2.7 -2.8 V 2.8 C 0.1 1.2 1.4 0 2.9 0 h 10.15 v 7.5 c -0.135 2.533 1.669 4.119 3.7 4.15 h 7.9 z M 6.3 8.9 c 0 0.6 0.4 1 1 1 h 1.6 c 0.5 0 1 -0.4 1 -1 c 0 -0.5 -0.5 -1 -1 -1 H 7.3 C 6.7 7.9 6.3 8.4 6.3 8.9 z M 18.5 22.6 c 0 -0.5 -0.4 -1 -1 -1 H 7.3 c -0.6 0 -1 0.5 -1 1 s 0.4 1 1 1 h 10.3 C 18.1 23.6 18.5 23.2 18.5 22.6 z M 18.5 15.8 c 0 -0.6 -0.4 -1 -1 -1 H 7.3 c -0.6 0 -1 0.4 -1 1 s 0.4 1 1 1 h 10.3 C 18.1 16.8 18.5 16.3 18.5 15.8 z" fill="currentColor" />
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

View file

@ -253,7 +253,7 @@
<path
id="cloud-check"
d="m 240.12048,110.31165 a 39.582604,39.582604 0 0 1 -10.23938,26.55813 33.935974,33.935974 0 0 1 -20.28366,10.27635 39.949372,39.949372 0 0 0 0.80301,-16.48404 16.944722,16.944722 0 0 0 7.65405,-4.47239 23.665469,23.665469 0 0 0 6.1311,-15.87805 26.589359,26.589359 0 0 0 -26.55812,-26.558123 c -0.87568,0 -5.3742,0.56186 -8.11085,0.91445 a 2.6398778,2.6398778 0 0 1 -2.83769,-1.77451 l -1.08155,-3.155106 A 32.772357,32.772357 0 0 0 158.37085,57.356128 31.757517,31.757517 0 0 0 124.14114,96.347867 l 1.13419,4.851433 a 2.6558127,2.6558127 0 0 1 -1.8179,3.14687 l -4.77313,1.44232 a 15.788381,15.788381 0 0 0 -11.35445,15.14642 10.699791,10.699791 0 0 0 2.19933,6.52543 12.871343,12.871343 0 0 0 9.50281,4.09782 h 7.25749 a 40.137987,40.137987 0 0 0 1.02966,15.93487 h -8.28715 A 28.433555,28.433555 0 0 1 96.535402,136.68302 26.739094,26.739094 0 0 1 91.39497,120.93491 31.54075,31.54075 0 0 1 107.53217,93.318597 c -0.13492,-1.42644 -0.20238,-2.84772 -0.20238,-4.25345 a 47.786197,47.786197 0 0 1 90.59848,-21.246498 42.542454,42.542454 0 0 1 42.19216,42.493001 z m -39.83719,26.55813 a 31.869752,31.869752 0 1 1 -31.86975,-31.86975 31.869752,31.869752 0 0 1 31.86975,31.86975 z m -15.15067,-11.86394 -2.71673,-2.01199 a 1.5763311,1.5763311 0 0 0 -2.00127,0.14182 l -16.73162,15.72576 -9.38033,-4.48657 a 1.7144864,1.7144864 0 0 0 -2.00221,0.5062 l -2.30275,2.94497 a 1.576756,1.576756 0 0 0 0.14182,2.00158 l 11.86234,11.8768 a 4.410933,4.410933 0 0 0 6.89242,-0.53116 l 16.51629,-24.2992 a 1.346922,1.346922 0 0 0 -0.27833,-1.86831 z"
style="fill:#45a1ff;fill-opacity:1;stroke-width:5.31163" />
style="fill-opacity:1;stroke-width:5.31163" fill="currentColor" />
</g>
</g>
</g>

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before After
Before After

View file

@ -5,8 +5,6 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="356px"
height="210px"
viewBox="0 0 356 210"
version="1.1"
id="svg114">
@ -256,5 +254,5 @@
<path
id="cloud-alert"
d="m 254.54362,110.61709 a 41.858804,41.858804 0 0 1 -10.8282,28.08534 35.887465,35.887465 0 0 1 -21.45007,10.8673 42.246663,42.246663 0 0 0 0.84918,-17.43196 17.919131,17.919131 0 0 0 8.09421,-4.72957 25.026353,25.026353 0 0 0 6.48366,-16.79111 28.118382,28.118382 0 0 0 -28.08535,-28.085359 c -0.92602,0 -5.68324,0.594174 -8.57727,0.967035 a 2.7916842,2.7916842 0 0 1 -3.0008,-1.876551 l -1.14369,-3.336147 A 34.656989,34.656989 0 0 0 168.09302,54.616462 33.58368,33.58368 0 0 0 131.89488,95.850311 l 1.19942,5.130409 a 2.8085354,2.8085354 0 0 1 -1.92244,3.32783 l -5.04762,1.52526 a 16.696293,16.696293 0 0 0 -12.00739,16.01742 11.315083,11.315083 0 0 0 2.32581,6.90069 13.611511,13.611511 0 0 0 10.04928,4.33345 h 7.67482 a 42.446125,42.446125 0 0 0 1.08887,16.85122 h -8.76369 A 30.06863,30.06863 0 0 1 102.70166,138.50495 28.276728,28.276728 0 0 1 97.265633,121.85123 33.354503,33.354503 0 0 1 114.33081,92.64684 c -0.14268,-1.508465 -0.21401,-3.01148 -0.21401,-4.498037 a 50.534146,50.534146 0 0 1 95.80834,-22.468284 44.988861,44.988861 0 0 1 44.61843,44.936571 z m -42.12804,28.08534 a 33.702425,33.702425 0 1 1 -33.70241,-33.70242 33.702425,33.702425 0 0 1 33.70241,33.70242 z m -28.08535,14.04269 a 2.8085354,2.8085354 0 0 0 -2.80853,-2.80853 h -5.61707 a 2.8085354,2.8085354 0 0 0 -2.80853,2.80853 v 5.61706 a 2.8085354,2.8085354 0 0 0 2.80853,2.80855 h 5.61707 a 2.8085354,2.8085354 0 0 0 2.80853,-2.80855 z m 0,-33.70243 a 2.8166239,2.8166239 0 0 0 -2.80853,-2.80853 h -5.61707 a 2.8166239,2.8166239 0 0 0 -2.80853,2.80853 v 11.23415 a 22.144684,22.144684 0 0 0 0.83447,5.49022 l 2.24351,7.21126 a 2.0333796,2.0333796 0 0 0 1.82117,1.34118 h 1.43583 a 2.0333796,2.0333796 0 0 0 1.82118,-1.34118 l 2.2435,-7.21126 a 22.144684,22.144684 0 0 0 0.83447,-5.49022 z"
style="stroke-width:5.61707;fill:#45a1ff;fill-opacity:1" />
style="stroke-width:5.61707;fill:currentColor;fill-opacity:1" />
</svg>

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Before After
Before After

View file

@ -5,8 +5,6 @@
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="348px"
height="210px"
viewBox="0 0 348 210"
version="1.1"
id="svg124">
@ -272,5 +270,5 @@
<path
id="cloud-off"
d="M 232.66609,50.155807 A 8.2118103,8.2118103 0 0 0 221.05286,38.54253 l -24.58739,24.587284 a 49.087021,49.087021 0 0 0 -82.69072,35.970548 c 0,1.448998 0.0696,2.914018 0.20861,4.384368 a 32.511588,32.511588 0 0 0 -16.633903,28.46635 27.562135,27.562135 0 0 0 5.298643,16.23286 22.799931,22.799931 0 0 0 4.2838,4.4793 l -7.176402,7.17673 a 8.2118072,8.2118072 0 1 0 11.613272,11.61322 z M 118.72657,140.86955 a 8.5946237,8.5946237 0 0 1 -2.68479,-2.19217 11.029135,11.029135 0 0 1 -2.26703,-6.7263 16.274355,16.274355 0 0 1 11.70415,-15.61263 l 4.92005,-1.48644 a 2.738162,2.738162 0 0 0 1.8737,-3.24418 l -1.16893,-5.00059 a 32.735029,32.735029 0 0 1 35.28314,-40.191861 31.860268,31.860268 0 0 1 18.36694,8.426592 z m 131.92616,-19.86871 a 40.800975,40.800975 0 0 1 -10.55455,27.3756 35.587128,35.587128 0 0 1 -25.2904,10.95024 h -71.10166 l 16.42536,-16.42536 h 54.6763 a 19.17354,19.17354 0 0 0 13.09966,-5.53393 24.393903,24.393903 0 0 0 6.31993,-16.36655 27.319807,27.319807 0 0 0 -25.05414,-27.140158 l 13.61114,-13.61313 a 43.833807,43.833807 0 0 1 27.86836,40.753288 z"
style="fill:#45a1ff;fill-opacity:1;stroke-width:5.47512" />
style="fill:currentColor;fill-opacity:1;stroke-width:5.47512" />
</svg>

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Before After
Before After

View file

@ -0,0 +1,65 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 750 750">
<path fill="url(#a)" d="m 314.805,154.949 h 0.06 c 22.04,-77.0499 118.08,-114.6599 215.95,-114.6599 67.63,0 128.341,21.41 169.961,55.4 -24.838,1.1712 -49.362,6.0449 -72.76,14.4599 33.63,12.5 62.519,31.73 83.929,55.52 -16.153,-2.78 -32.532,-4.019 -48.919,-3.7 40.276,58.343 61.794,127.585 61.68,198.48 0,193.3 -156.701,350 -350.001,350 -190.32,0 -349.9999,-159.35 -349.9999,-350 0,-30.11 4,-61.2 11.77,-90.36 2.04,-6.12 4.88,-11.99 8.65,-14.14 4.72,-2.69 9.02,5.33 9.71,7.94 5.1177,19.17 12.0039,37.823 20.57,55.72 -0.75,-39.96 16.32,-76.36 39.7999,-107.84 15.66,-20.99 30.18,-40.44 36.88,-96.57 0.45,-3.77 4.02,-6.48 7.63,-5.3 50.96,16.68 78.2,101.54 73.97,172.5 28.15,4.03 28.02,-25.38 28.02,-25.38 -9,-27.66 -3,-79.07 53,-102.07 z"/>
<path fill="url(#b)" d="m 713.254,271.32 c 8.51,192.5 -149.74,358.47 -342.71,358.47 -180.65,0 -328.6792,-139.63 -342.0692,-316.85 -2.3889,16.596 -3.6452,33.334 -3.76,50.1 1.37,189.62 160.6592,347.41 349.9992,347.41 193.3,0 350,-156.7 350,-350 0,-30.8 -3.99,-60.67 -11.46,-89.13 z" opacity="0.9"/>
<path fill="url(#c)" d="m 366.175,180.459 c -3.77,-6.67 -21.18,-16.54 -28.79,-18.26 28.8,-92.2499 175.521,-120.5699 265.321,-104.2499 37.37,6.8 83.91,27.16 98.07,37.74 -41.62,-33.99 -102.341,-55.4 -169.961,-55.4 -97.87,0 -193.91,37.61 -215.95,114.6599 h -0.16 c -56,23 -62,74.43 -53,102.08 8.64,-32.99 49.75,-73.53 104.47,-76.57 z" style="mix-blend-mode:screen"/>
<path fill="url(#d)" d="m 467.885,116.748 c -78.62,15.47 -104.31,20.53 -130.62,45.54 29.55,-78.2297 104.98,-94.0897 194.86,-58.43 -21.391,4.41 -42.805,8.71 -64.24,12.9 z"/>
<path fill="url(#e)" d="m 43.7049,259.38 c -21.48,87.94 -4.88,191.3 92.6991,278.04 -29.05,-31.77 -64.5191,-149.07 13.75,-232.87 5.27,-5.65 14.34,-1.5 14.63,6.22 6.45,174.16 146.98,280.53 309,260.64 -50.2,-2.82 -216.22,-60.97 -92.72,-83.97 64.55,-12.03 165.76,-30.88 165.76,-121.7 0,-147.22 -113.83,-190.26 -182.86,-183.86 -47.24,4.38 -89.29,34.36 -102.23,75.13 4.97,16.07 -14.84,27.32 -28.05,25.43 4.24,-70.95 -23,-155.86 -73.97,-172.54 -3.6,-1.18 -7.18,1.53 -7.63,5.3 -6.7,56.13 -21.22,75.58 -36.87,96.57 -23.4891,31.49 -40.5591,67.88 -39.8091,107.84 -8.5659,-17.897 -15.4521,-36.55 -20.57,-55.72 -0.57,-2.16 -3.7,-8.19 -7.48,-8.47 -2.05,-0.15 -3.14,1.85 -3.65,3.96 z"/>
<path fill="url(#f)" d="m 337.695,496.349 c 95.04,77.17 286.17,19.31 286.17,-168.32 -77.16,116.96 -175.44,197.64 -286.16,168.32 z" style="mix-blend-mode:screen"/>
<path fill="url(#g)" d="m 150.155,304.55 c 0.864,-0.967 1.953,-1.706 3.17,-2.153 1.217,-0.446 2.526,-0.586 3.81,-0.407 -70.0595,85.45 -13.549,235.52 25.231,272.39 2.17,6.14 -36.791,-25.79 -42.161,-33.26 -29.5,-25.03 -71.7795,-149.06 9.95,-236.57 z" style="mix-blend-mode:screen"/>
<path fill="url(#h)" d="m 374.705,503.419 c 95.06,0 172.13,-62.879 172.13,-140.449 0,-77.57 -77.07,-140.45 -172.13,-140.45 -81.1,0 -172.17,52.76 -172.13,142.5 0.04,138.67 146.54,218.45 271.42,206.37 -9.38,-1.09 -67.9,-4.2 -107.45,-48.94 -3.57,-4.03 -9.76,-11.07 -6.95,-15.64 2.8,-4.57 10.52,-3.4 15.1,-3.4 z"/>
<path fill="#fff" d="m 528.085,299.15 -136.04,130.18 c -12.07,8.58 -24.92,9.2 -37.6,1.42 L 221.015,299.63 c 3.807,-6.118 8.087,-11.929 12.8,-17.38 l 14,13.1 c 35.04,32.84 63.37,59.37 103.3,93.45 18.02,15.38 23.62,15.08 41.3,0 45.68,-39 79.09,-68.5 122.52,-107.29 4.841,5.526 9.235,11.428 13.14,17.65 z" opacity="0.6"/>
<mask id="i" width="345" height="276" x="202" y="297" maskUnits="userSpaceOnUse">
<path fill="#fff" d="m 546.835,362.969 c 0,77.57 -77.07,140.45 -172.13,140.45 -4.59,0 -12.3,-1.18 -15.11,3.4 -2.81,4.56 3.38,11.6 6.95,15.63 37.16,42.04 91.07,47.33 105.22,48.72 l 2.23,0.22 c -124.88,12.08 -271.38,-67.7 -271.42,-206.37 -0.131,-23.089 6.295,-45.74 18.53,-65.32 l 134.08,121.78 c 9.54,8.66 25.61,8.66 35.15,0 l 136.62,-124.09 c 12.7,19.58 19.88,41.9 19.88,65.58 z"/>
</mask>
<g mask="url(#i)">
<path fill="url(#j)" d="m 162.705,200.979 h 435.07 v 394.47 h -435.07 z" opacity="0.7"/>
<g filter="url(#k)">
<path fill="#458fcd" fill-rule="evenodd" d="m 334.745,422.298 c -25.35,-26.38 -101.27,-114.03 -101.27,-114.03 l 5.87,0.26 118.86,88.77 c 8.9,6.47 21.6,6.4 30.42,-0.15 l 116.55,-88.5 6.18,-0.49 c 0,0 -73.44,85.57 -101.57,113.76 -28.13,28.19 -49.69,26.76 -75.04,0.38 z" clip-rule="evenodd"/>
</g>
</g>
<path fill="#fff" d="m 398.855,152.258 c 18.42,-5.8 16.8,-24.03 16.8,-24.03 0,0 -9.21,-10.85 -27.46,-4.84 -17.08,5.63 -19.73,17.8 -19.73,17.8 0,0 9.33,17.7 30.39,11.07 z"/>
<defs>
<linearGradient id="a" x1="146.185" x2="639.58502" y1="155.649" y2="615.86902" gradientUnits="userSpaceOnUse">
<stop stop-color="#1B91F3"/>
<stop offset="1" stop-color="#0B68CB"/>
</linearGradient>
<linearGradient id="d" x1="283.47501" x2="461.01501" y1="273.45801" y2="75.818298" gradientUnits="userSpaceOnUse">
<stop stop-color="#0F5DB0"/>
<stop offset="1" stop-color="#0F5DB0" stop-opacity="0"/>
</linearGradient>
<linearGradient id="f" x1="594.625" x2="512.07501" y1="416.55899" y2="619.24902" gradientUnits="userSpaceOnUse">
<stop stop-color="#E247C4" stop-opacity="0"/>
<stop offset="1" stop-color="#E247C4" stop-opacity="0.64"/>
</linearGradient>
<linearGradient id="g" x1="82.7155" x2="155.44501" y1="234.78999" y2="527.51001" gradientUnits="userSpaceOnUse">
<stop offset="0.1" stop-color="#EF3ACC"/>
<stop offset="1" stop-color="#EF3ACC" stop-opacity="0"/>
</linearGradient>
<linearGradient id="h" x1="374.70499" x2="374.70499" y1="273.95001" y2="569.94897" gradientUnits="userSpaceOnUse">
<stop stop-color="#fff"/>
<stop offset="0.91" stop-color="#BEE1FE"/>
<stop offset="1" stop-color="#96CEFD"/>
</linearGradient>
<linearGradient id="j" x1="380.245" x2="380.245" y1="441.44901" y2="565.44897" gradientUnits="userSpaceOnUse">
<stop stop-color="#BCE0FD"/>
<stop offset="1" stop-color="#88CCFC"/>
</linearGradient>
<radialGradient id="b" cx="0" cy="0" r="1" gradientTransform="matrix(117.92992,271.44954,-260.03887,112.97261,145.274,314)" gradientUnits="userSpaceOnUse">
<stop offset="0.53" stop-color="#0B4186" stop-opacity="0"/>
<stop offset="1" stop-color="#0B4186" stop-opacity="0.45"/>
</radialGradient>
<radialGradient id="c" cx="0" cy="0" r="1" gradientTransform="matrix(-38.950414,-49.859637,82.506525,-64.454205,383.705,192.449)" gradientUnits="userSpaceOnUse">
<stop stop-color="#EF3ACC" stop-opacity="0"/>
<stop offset="1" stop-color="#EF3ACC" stop-opacity="0.64"/>
</radialGradient>
<radialGradient id="e" cx="0" cy="0" r="1" gradientTransform="matrix(200.50032,-415.91019,513.77136,247.67684,242.704,551.15)" gradientUnits="userSpaceOnUse">
<stop offset="0.02" stop-color="#094188"/>
<stop offset="0.97" stop-color="#0B4186" stop-opacity="0"/>
</radialGradient>
<filter id="k" width="341.88" height="198.416" x="201.47501" y="276.15799" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur result="effect1_foregroundBlur_106_1002" stdDeviation="16"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

View file

@ -9,6 +9,7 @@ docker pull registry.gitlab.com/timvisee/send:latest
docker run -v $PWD/uploads:/uploads -p 1443:1443 \
-e 'DETECT_BASE_URL=true' \
-e 'REDIS_HOST=localhost' \
-e 'FILE_DIR=/uploads' \
registry.gitlab.com/timvisee/send:latest
```
@ -33,7 +34,7 @@ Config options expecting array values (e.g. `EXPIRE_TIMES_SECONDS`, `DOWNLOAD_CO
| `PORT` | Port the server will listen on (defaults to `1443`)
| `NODE_ENV` | Run in `development` mode (unsafe) or `production` mode (the default)
| `SEND_FOOTER_DMCA_URL` | A URL to a contact page for DMCA requests (empty / not shown by default)
| `SENTRY_CLIENT`, `SENTRY_DSN` | Sentry Client ID and DNS for error tracking (optional, disabled by default)
| `SENTRY_CLIENT`, `SENTRY_DSN` | Sentry Client ID and DSN for error tracking (optional, disabled by default)
*Note: more options can be found here: https://github.com/timvisee/send/blob/master/server/config.js*
@ -77,6 +78,31 @@ Redis is used as the metadata database for the backend and is required no matter
*Note: more options can be found here: https://github.com/timvisee/send/blob/master/server/config.js*
## Branding
To change the look the colors aswell as some graphics can be changed via environment variables.
See the table below for the variables and their default values.
| Name | Default | Description |
|---|---|---|
| UI_COLOR_PRIMARY | #0a84ff | The primary color |
| UI_COLOR_ACCENT | #003eaa | The accent color (eg. for hover-effects) |
| UI_CUSTOM_ASSETS_ANDROID_CHROME_192PX | | A custom icon for Android (192x192px) |
| UI_CUSTOM_ASSETS_ANDROID_CHROME_512PX | | A custom icon for Android (512x512px) |
| UI_CUSTOM_ASSETS_APPLE_TOUCH_ICON | | A custom icon for Apple |
| UI_CUSTOM_ASSETS_FAVICON_16PX | | A custom favicon (16x16px) |
| UI_CUSTOM_ASSETS_FAVICON_32PX | | A custom favicon (32x32px) |
| UI_CUSTOM_ASSETS_ICON | | A custom icon (Logo on the top-left of the UI) |
| UI_CUSTOM_ASSETS_SAFARI_PINNED_TAB | | A custom icon for Safari |
| UI_CUSTOM_ASSETS_FACEBOOK | | A custom header image for Facebook |
| UI_CUSTOM_ASSETS_TWITTER | | A custom header image for Twitter |
| UI_CUSTOM_ASSETS_WORDMARK | | A custom wordmark (Text next to the logo) |
| UI_CUSTOM_CSS | | Allows you to define a custom CSS file for custom styling |
| CUSTOM_FOOTER_TEXT | | Allows you to define a custom footer |
| CUSTOM_FOOTER_URL | | Allows you to define a custom URL in your footer |
Side note: If you define a custom URL and a custom footer, only the footer text will display, but will be hyperlinked to the URL.
## Examples
**Run using an Amazon Elasticache for the Redis DB, Amazon S3 for the storage backend, and Sentry for error reporting.**
@ -115,6 +141,18 @@ Then open http://localhost:1443 to view the UI. (change the `localhost` to your
To run with HTTPS, you will need to set up a reverse proxy with SSL termination in front of the backend. See Docker Compose below for an example setup.
**Run with custom branding.**
```bash
$ docker run -p 1443:1443 \
-v $PWD/custom_assets:/app/dist/custom_assets \
-e 'UI_COLOR_PRIMARY=#f00' \
-e 'UI_COLOR_ACCENT=#a00' \
-e 'UI_CUSTOM_ASSETS_ICON=custom_assets/logo.svg' \
registry.gitlab.com/timvisee/send:latest
```
## Docker Compose
For a Docker compose configuration example, see:

34118
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{
"name": "send",
"description": "File Sharing Experiment",
"version": "3.4.19",
"version": "3.4.27",
"author": "Mozilla (https://mozilla.org)",
"contributors": [
"Tim Visee <3a4fb3964f@sinenomine.email> (https://timvisee.com)"
@ -67,7 +67,7 @@
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.16.11",
"@dannycoates/webcrypto-liner": "^0.1.37",
"@fullhuman/postcss-purgecss": "^1.3.0",
"@fullhuman/postcss-purgecss": "^4.1.3",
"@mattiasbuelens/web-streams-polyfill": "0.2.1",
"@sentry/browser": "^5.30.0",
"asmcrypto.js": "^0.22.0",
@ -75,13 +75,13 @@
"babel-plugin-istanbul": "^5.2.0",
"base64-js": "^1.5.1",
"content-disposition": "^0.5.4",
"copy-webpack-plugin": "^5.1.2",
"copy-webpack-plugin": "^6.4.0",
"core-js": "^3.21.1",
"crc": "^3.8.0",
"cross-env": "^6.0.3",
"css-loader": "^3.6.0",
"css-loader": "^5.2.7",
"css-mqpacker": "^7.0.0",
"cssnano": "^4.1.11",
"cssnano": "^5.1.12",
"eslint": "^6.6.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-mocha": "^6.2.1",
@ -91,22 +91,23 @@
"extract-loader": "^3.2.0",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"fast-text-encoding": "^1.0.3",
"file-loader": "^4.2.0",
"git-rev-sync": "^1.12.0",
"file-loader": "^6.2.0",
"git-rev-sync": "^3.0.2",
"html-loader": "^0.5.5",
"http_ece": "^1.1.0",
"husky": "^3.0.9",
"intl-pluralrules": "^1.3.1",
"lint-staged": "^9.4.2",
"mocha": "^6.2.2",
"mocha": "^10.1.0",
"morgan": "^1.9.1",
"nanobus": "^4.5.0",
"nanohtml": "^1.9.0",
"nanotiming": "^7.3.1",
"npm-run-all": "^4.1.5",
"nyc": "^14.1.1",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.7.1",
"postcss": "^8.4.14",
"postcss-loader": "^4.2.0",
"postcss-preset-env": "^7.7.2",
"prettier": "^1.19.1",
"proxyquire": "^2.1.3",
"puppeteer": "^2.0.0",
@ -115,13 +116,13 @@
"script-loader": "^0.7.2",
"sinon": "^7.5.0",
"string-hash": "^1.1.3",
"stylelint": "^13.13.1",
"stylelint-config-standard": "^19.0.0",
"stylelint-no-unsupported-browser-features": "^4.1.4",
"svgo": "^1.3.2",
"svgo-loader": "^2.2.2",
"tailwindcss": "^1.9.6",
"val-loader": "^1.1.1",
"stylelint": "^14.9.1",
"stylelint-config-standard": "^26.0.0",
"stylelint-no-unsupported-browser-features": "^5.0.3",
"svgo": "^2.8.0",
"svgo-loader": "^3.0.1",
"tailwindcss": "^2",
"val-loader": "^2.1.2",
"webpack": "4.38.0",
"webpack-cli": "^3.3.12",
"webpack-dev-middleware": "^3.7.3",
@ -131,22 +132,21 @@
},
"dependencies": {
"@dannycoates/express-ws": "^5.0.3",
"@fluent/bundle": "^0.13.0",
"@fluent/langneg": "^0.3.0",
"@google-cloud/storage": "^5.19.0",
"@sentry/node": "^5.30.0",
"@fluent/bundle": "^0.17.1",
"@fluent/langneg": "^0.6.2",
"@google-cloud/storage": "^6.2.3",
"@sentry/node": "^7.7.0",
"aws-sdk": "^2.1109.0",
"body-parser": "^1.20.0",
"choo": "^7.0.0",
"cldr-core": "^35.1.0",
"configstore": "github:dannycoates/configstore#master",
"convict": "^6.2.2",
"convict": "^6.2.4",
"convict-format-with-validator": "^6.2.0",
"double-ended-queue": "^2.1.0-0",
"express": "^4.17.3",
"helmet": "^3.23.3",
"mkdirp": "^0.5.6",
"mozlog": "^2.2.0",
"mozlog": "^3.0.1",
"node-fetch": "^2.6.7",
"redis": "^3.1.1",
"redis-mock": "^0.47.0",

View file

@ -1,8 +1,6 @@
class TailwindExtractor {
static extract(content) {
return content.match(/[A-Za-z0-9-_:/]+/g) || [];
}
}
const TailwindExtractor = content => {
return content.match(/[A-Za-z0-9-_:/]+/g) || [];
};
const options = {
plugins: [

View file

@ -1,17 +1,17 @@
{
"name": "firefox-send",
"name": "send",
"description": "File Sharing Experiment",
"repository": {
"url": "https://github.com/send/send/",
"url": "https://github.com/timvisee/send/",
"license": "MPL-2.0"
},
"participate": {
"home": "https://github.com/send/send/blob/master/README.md",
"docs": "https://github.com/send/send/blob/master/README.md"
"home": "https://github.om/timvisee/send/blob/master/README.md",
"docs": "https://github.com/timvisee/send/blob/master/README.md"
},
"bugs": {
"list": "https://gitlab.com/send/send/issues",
"report": "https://gitlab.com/send/send/issues/new"
"list": "https://github.com/timvisee/send/issues",
"report": "https://github.com/timvisee/send/issues/new"
},
"keywords": [
"JavaScript",

View file

@ -48,12 +48,12 @@ passwordSetError = Toto heslo nemohlo být nastaveno
-send-brand =
{ $case ->
*[nom] Send
[gen] Send
[dat] Send
[gen] Sendu
[dat] Sendu
[acc] Send
[voc] Send
[loc] Send
[ins] Send
[voc] Sende
[loc] Sendu
[ins] Sendem
}
-send-short-brand =
{ $case ->
@ -86,7 +86,7 @@ passwordSetError = Toto heslo nemohlo být nastaveno
[ins] Mozillou
}
introTitle = Jednoduché a soukromé sdílení souborů
introDescription = S { -send-brand(case: "ins") } jsou sdílené soubory šifrované end-to-end, takže ani my nevíme, co sdílíte. Platnost odkazů je navíc omezená. Soubory tak můžete sdílet soukromě a s jistotou, že se nezůstanou na internetu válet navždy.
introDescription = Se { -send-brand(case: "ins") } jsou sdílené soubory šifrované end-to-end, takže ani my nevíme, co sdílíte. Platnost odkazů je navíc omezená. Soubory tak můžete sdílet soukromě a s jistotou, že se nezůstanou na internetu válet navždy.
notifyUploadEncryptDone = Váš soubor je zašifrovaný a připraven k odeslání
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
archiveExpiryInfo = Platnost vyprší po { $downloadCount } nebo za { $timespan }
@ -131,7 +131,7 @@ copyLinkDescription = Soubor můžete sdílet tímto odkazem:
copyLinkButton = Zkopírovat odkaz
downloadTitle = Stáhnout soubory
downloadDescription = Tento soubor byl sdílen přes { -send-brand(case: "acc") } s end-to-end šifrováním a odkazem s omezenou platností.
trySendDescription = Vyzkoušejte jednoduché a bezpečné sdílení souborů s { -send-brand(case: "ins") }
trySendDescription = Vyzkoušejte jednoduché a bezpečné sdílení souborů se { -send-brand(case: "ins") }
# count will always be > 10
tooManyFiles =
{ $count ->
@ -189,6 +189,6 @@ downloadFirefoxPromo = { -send-short-brand } od aplikace { -firefox }.
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ů
shareMessage = Stáhněte si soubor „{ $name }“ se { -send-brand(case: "ins") } - jednoduché a bezpečné sdílení souborů
trailheadPromo = Existuje způsob, jak ochránit své soukromí. Používejte Firefox.
learnMore = Zjistit více.

View file

@ -147,3 +147,5 @@ shareLinkButton = Share link
shareMessage = Download “{ $name }” with { -send-brand }: simple, safe file sharing
trailheadPromo = There is a way to protect your privacy. Join Firefox.
learnMore = Learn more.
sponsoredByThunderbird = Sponsored by Thunderbird

View file

@ -152,3 +152,5 @@ shareLinkButton = Share link
shareMessage = Download “{ $name }” with { -send-brand }: simple, safe file sharing
trailheadPromo = There is a way to protect your privacy. Join Firefox.
learnMore = Learn more.
sponsoredByThunderbird = Sponsored by Thunderbird

View file

@ -143,3 +143,5 @@ shareLinkButton = Share link
# $name is the name of the file
shareMessage = Download “{ $name }” with { -send-brand }: simple, safe file sharing
learnMore = Learn more.
sponsoredByThunderbird = Sponsored by Thunderbird

View file

@ -52,7 +52,7 @@ passwordSetError = Dit wachtwoord kon niet worden ingesteld
-send-short-brand = Send
-firefox = Firefox
-mozilla = Mozilla
introTitle = Bestanden delen, eenvoudig en privé
introTitle = Bestanden delen, eenvoudig en privé
introDescription = Met { -send-brand } kunt u bestanden delen met end-to-endversleuteling en een koppeling die automatisch verloopt. Hierdoor kunt u privé houden wat u wilt delen en er zeker van zijn dat uw zaken niet voor altijd online blijven.
notifyUploadEncryptDone = Uw bestand is versleuteld en klaar voor verzending
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
@ -152,3 +152,5 @@ shareLinkButton = Koppeling delen
shareMessage = Download { $name } met { -send-brand }: eenvoudig, veilig bestanden delen
trailheadPromo = Er is een manier om uw privacy te beschermen. Doe mee met Firefox.
learnMore = Meer info.
sponsoredByThunderbird = Gesponsord door Thunderbird

View file

@ -53,7 +53,7 @@ introTitle = Простой и безопасный обмен файлами
introDescription = { -send-brand } позволяет вам делиться файлами со сквозным шифрованием и ограниченным сроком действия ссылки на загрузку. Так что, вы сможете делиться файлами приватно и они не останутся в сети навсегда.
notifyUploadEncryptDone = Ваш файл зашифрован и готов к отправке
# downloadCount is from the downloadCount string and timespan is a timespanMinutes string. ex. 'Expires after 2 downloads or 25 minutes'
archiveExpiryInfo = Срок хранения истекает после { $downloadCount } или через { $timespan }
archiveExpiryInfo = Удалить после { $downloadCount } или через { $timespan }
timespanMinutes =
{ $num ->
[one] { $num } минуту
@ -89,7 +89,7 @@ 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 = Общий размер: { $size }
totalSize = Всего: { $size }
# the next line after the colon contains a file name
copyLinkDescription = Скопируйте ссылку, чтобы поделиться своим файлом:
copyLinkButton = Копировать ссылку
@ -117,13 +117,13 @@ legalTitle = Уведомление о конфиденциальности { -s
legalDateStamp = Версия 1.0, от 12 марта 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 } дн. { $hours } ч. { $minutes } мин.
addFilesButton = Выберите файлы для выгрузки
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 })
orClickWithSize = или кликните сюда для отправки файлов до { $size }
addPassword = Защитить паролем
emailPlaceholder = Введите ваш адрес электронной почты
# $size is the size of the file, displayed using the fileSize message as format (e.g. "2.5MB")

View file

@ -2,12 +2,12 @@ title = Send
importingFile = 正在导入…
encryptingFile = 正在加密…
decryptingFile = 正在解密…
downloadCount =
{ $num ->
downloadCount = { $num ->
[one] 1 次下载
*[other] { $num } 次下载
}
timespanHours =
{ $num ->
timespanHours = { $num ->
[one] 1 小时
*[other] { $num } 小时
}
copiedUrl = 已复制!
@ -26,6 +26,11 @@ notSupportedOutdatedDetail = 很可惜,此版本的 Firefox 不支持 Send 所
updateFirefox = 更新 Firefox
deletePopupCancel = 取消
deleteButtonHover = 删除
footerText = 不附属于 Mozilla 或 Firefox。
footerLinkDonate = 捐助
footerLinkCli = 命令行
footerLinkDmca = DMCA
footerLinkSource = 源代码
passwordTryAgain = 密码不正确。请重试。
javascriptRequired = Send 需要 JavaScript
whyJavascript = 为什么 Send 需要 JavaScript
@ -142,5 +147,4 @@ shareLinkDescription = 您的文件链接:
shareLinkButton = 分享链接
# $name is the name of the file
shareMessage = 使用 { -send-brand } 下载“{ $name }”:简单、安全的文件分享服务
trailheadPromo = 捍卫隐私不是幻想。加入 Firefox 一同抗争。
learnMore = 详细了解。

View file

@ -2,12 +2,12 @@ title = Send
importingFile = 匯入中…
encryptingFile = 加密中…
decryptingFile = 解密中…
downloadCount =
{ $num ->
downloadCount = { $num ->
[one] 1 次下載
*[other] { $num } 次下載
}
timespanHours =
{ $num ->
timespanHours = { $num ->
[one] 1 小時
*[other] { $num } 小時
}
copiedUrl = 已複製!
@ -26,6 +26,11 @@ notSupportedOutdatedDetail = 很可惜,此版本的 Firefox 不支援 Send 所
updateFirefox = 更新 Firefox
deletePopupCancel = 取消
deleteButtonHover = 刪除
footerText = 不隸屬於 Mozilla 或 Firefox。
footerLinkDonate = 捐助
footerLinkCli = 命令列
footerLinkDmca = DMCA
footerLinkSource = 原始碼
passwordTryAgain = 密碼不正確,請再試一次。
javascriptRequired = Send 需要開啟 JavaScript 功能
whyJavascript = 為什麼 Send 需要 JavaScript 才能使用?
@ -45,27 +50,28 @@ passwordSetError = 無法設定此密碼
-send-short-brand = Send
-firefox = Firefox
-mozilla = Mozilla
introTitle = 簡單而私密的檔案共享服務
introDescription = { -send-brand } 讓您可透過點對點加密的方式來分享檔案,並提供會自動失效的鏈結。這樣一來就可以保留分享時的隱私,也確保檔案不會永久保存於網路上。
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 =
{ $num ->
timespanMinutes = { $num ->
[one] 1 分鐘
*[other] { $num } 分鐘
}
timespanDays =
{ $num ->
timespanDays = { $num ->
[one] 1 天
*[other] { $num } 天
}
timespanWeeks =
{ $num ->
timespanWeeks = { $num ->
[one] 1 週
*[other] { $num } 週
}
fileCount =
{ $num ->
*[other] { $num } 個檔案
}
fileCount = { $num ->
[one] 1 個檔案
*[other] { $num } 個檔案
}
# byte abbreviation
bytes = 位元組
# kibibyte abbreviation
@ -85,15 +91,15 @@ downloadTitle = 下載檔案
downloadDescription = 此檔案是透過 { -send-brand } 進行分享,以點對點加密的方式來分享檔案,並提供會自動失效的鏈結。
trySendDescription = 快試試 { -send-brand },簡單安全的檔案分享機制。
# count will always be > 10
tooManyFiles =
{ $count ->
*[other] 一次僅能上傳 { $count } 個檔案。
}
tooManyFiles = { $count ->
[one] 一次僅能上傳 1 個檔案。
*[other] 一次僅能上傳 { $count } 個檔案。
}
# count will always be > 10
tooManyArchives =
{ $count ->
*[other] 僅允許 { $count } 個壓縮檔。
}
tooManyArchives = { $count ->
[one] 僅允許 1 個壓縮檔。
*[other] 僅允許 { $count } 個壓縮檔。
}
expiredTitle = 此鏈結已經失效。
notSupportedDescription = 無法於此瀏覽器使用 { -send-brand }。在最新版的 { -firefox } 中使用 { -send-short-brand } 會有最佳效果,也可在大部分瀏覽器的最新版本當中使用。
downloadFirefox = 下載 { -firefox }
@ -136,5 +142,4 @@ shareLinkDescription = 您的檔案鏈結:
shareLinkButton = 分享鏈結
# $name is the name of the file
shareMessage = 使用 { -send-brand } 下載「{ $name }」: 簡單安全的檔案分享機制
trailheadPromo = 有種方法可以保護您的隱私,加入 Firefox。
learnMore = 了解更多。

View file

@ -12,7 +12,19 @@ module.exports = {
FOOTER_DONATE_URL: config.footer_donate_url,
FOOTER_CLI_URL: config.footer_cli_url,
FOOTER_DMCA_URL: config.footer_dmca_url,
FOOTER_SOURCE_URL: config.footer_source_url
FOOTER_SOURCE_URL: config.footer_source_url,
CUSTOM_FOOTER_TEXT: config.custom_footer_text,
CUSTOM_FOOTER_URL: config.custom_footer_url,
MAIN_NOTICE_HTML: config.main_notice_html,
UPLOAD_AREA_NOTICE_HTML: config.upload_area_notice_html,
UPLOADS_LIST_NOTICE_HTML: config.uploads_list_notice_html,
DOWNLOAD_NOTICE_HTML: config.download_notice_html,
SHOW_THUNDERBIRD_SPONSOR: config.show_thunderbird_sponsor,
COLORS: {
PRIMARY: config.ui_color_primary,
ACCENT: config.ui_color_accent
},
CUSTOM_ASSETS: config.ui_custom_assets
},
DEFAULTS: {
DOWNLOADS: config.default_downloads,

View file

@ -165,9 +165,20 @@ const conf = convict({
},
base_url: {
format: 'url',
default: 'https://send.firefox.com',
default: 'https://send.example.com',
env: 'BASE_URL'
},
custom_title: {
format: String,
default: 'Send',
env: 'CUSTOM_TITLE'
},
custom_description: {
format: String,
default:
'Encrypt and send files with a link that automatically expires to ensure your important documents dont stay online forever.',
env: 'CUSTOM_DESCRIPTION'
},
detect_base_url: {
format: Boolean,
default: false,
@ -242,6 +253,113 @@ const conf = convict({
format: String,
default: 'https://github.com/timvisee/send',
env: 'SEND_FOOTER_SOURCE_URL'
},
custom_footer_text: {
format: String,
default: '',
env: 'CUSTOM_FOOTER_TEXT'
},
custom_footer_url: {
format: String,
default: '',
env: 'CUSTOM_FOOTER_URL'
},
main_notice_html: {
format: String,
default: '',
env: 'SEND_MAIN_NOTICE_HTML'
},
upload_area_notice_html: {
format: String,
default: '',
env: 'SEND_UPLOAD_AREA_NOTICE_HTML'
},
uploads_list_notice_html: {
format: String,
default: '',
env: 'SEND_UPLOADS_LIST_NOTICE_HTML'
},
download_notice_html: {
format: String,
default: '',
env: 'SEND_DOWNLOAD_NOTICE_HTML'
},
show_thunderbird_sponsor: {
format: Boolean,
default: false,
env: 'SHOW_THUNDERBIRD_SPONSOR'
},
ui_color_primary: {
format: String,
default: '#0a84ff',
env: 'UI_COLOR_PRIMARY'
},
ui_color_accent: {
format: String,
default: '#003eaa',
env: 'UI_COLOR_ACCENT'
},
custom_locale: {
format: String,
default: '',
env: 'CUSTOM_LOCALE'
},
ui_custom_assets: {
android_chrome_192px: {
format: String,
default: '',
env: 'UI_CUSTOM_ASSETS_ANDROID_CHROME_192PX'
},
android_chrome_512px: {
format: String,
default: '',
env: 'UI_CUSTOM_ASSETS_ANDROID_CHROME_512PX'
},
apple_touch_icon: {
format: String,
default: '',
env: 'UI_CUSTOM_ASSETS_APPLE_TOUCH_ICON'
},
favicon_16px: {
format: String,
default: '',
env: 'UI_CUSTOM_ASSETS_FAVICON_16PX'
},
favicon_32px: {
format: String,
default: '',
env: 'UI_CUSTOM_ASSETS_FAVICON_32PX'
},
icon: {
format: String,
default: '',
env: 'UI_CUSTOM_ASSETS_ICON'
},
safari_pinned_tab: {
format: String,
default: '',
env: 'UI_CUSTOM_ASSETS_SAFARI_PINNED_TAB'
},
facebook: {
format: String,
default: '',
env: 'UI_CUSTOM_ASSETS_FACEBOOK'
},
twitter: {
format: String,
default: '',
env: 'UI_CUSTOM_ASSETS_TWITTER'
},
wordmark: {
format: String,
default: '',
env: 'UI_CUSTOM_ASSETS_WORDMARK'
},
custom_css: {
format: String,
default: '',
env: 'UI_CUSTOM_CSS'
}
}
});

View file

@ -3,6 +3,10 @@ const assets = require('../common/assets');
const initScript = require('./initScript');
module.exports = function(state, body = '') {
const custom_css = state.ui.assets.custom_css !== ''
? html`<link rel="stylesheet" type="text/css" href="${state.ui.assets.custom_css}" />`
: ''
return html`
<!DOCTYPE html>
<html lang="${state.locale}">
@ -21,45 +25,46 @@ module.exports = function(state, body = '') {
<meta property="og:description" content="${state.description}" />
<meta name="twitter:description" content="${state.description}" />
<meta name="twitter:card" content="summary" />
<meta
property="og:image"
content="${state.baseUrl}/${assets.get('send-fb.jpg')}"
/>
<meta
name="twitter:image"
content="${state.baseUrl}/${assets.get('send-twitter.jpg')}"
/>
<meta property="og:image" content="${state.ui.assets.facebook}" />
<meta name="twitter:image" content="${state.ui.assets.twitter}" />
<meta property="og:url" content="${state.baseUrl}" />
<meta name="theme-color" content="#220033" />
<meta name="msapplication-TileColor" content="#220033" />
<link rel="manifest" href="/app.webmanifest" />
<link rel="stylesheet" type="text/css" href="/inter.css" />
<style nonce=${state.cspNonce}>
:root {
--color-primary: ${state.ui.colors.primary};
--color-primary-accent: ${state.ui.colors.accent};
}
</style>
<link
rel="stylesheet"
type="text/css"
href="${assets.get('app.css')}"
/>
${custom_css}
<link
rel="apple-touch-icon"
sizes="180x180"
href="${assets.get('apple-touch-icon.png')}"
href="${state.ui.assets.apple_touch_icon}"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="${assets.get('favicon-32x32.png')}"
href="${state.ui.assets.favicon_32px}"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="${assets.get('favicon-16x16.png')}"
href="${state.ui.assets.favicon_16px}"
/>
<link
rel="mask-icon"
href="${assets.get('safari-pinned-tab.svg')}"
href="${state.ui.assets.safari_pinned_tab}"
color="#838383"
/>
<script defer src="${assets.get('app.js')}"></script>

View file

@ -1,13 +1,15 @@
const fs = require('fs');
const path = require('path');
const { FluentBundle } = require('@fluent/bundle');
const { FluentBundle, FluentResource } = require('@fluent/bundle');
const localesPath = path.resolve(__dirname, '../public/locales');
const locales = fs.readdirSync(localesPath);
function makeBundle(locale) {
const bundle = new FluentBundle(locale, { useIsolating: false });
bundle.addMessages(
fs.readFileSync(path.resolve(localesPath, locale, 'send.ftl'), 'utf8')
bundle.addResource(
new FluentResource(
fs.readFileSync(path.resolve(localesPath, locale, 'send.ftl'), 'utf8')
)
);
return [locale, bundle];
}
@ -19,8 +21,11 @@ module.exports = function getTranslator(locale) {
const bundle = bundles.get(locale) || defaultBundle;
return function(id, data) {
if (bundle.hasMessage(id)) {
return bundle.format(bundle.getMessage(id), data);
return bundle.formatPattern(bundle.getMessage(id).value, data);
}
return defaultBundle.format(defaultBundle.getMessage(id), data);
return defaultBundle.formatPattern(
defaultBundle.getMessage(id).value,
data
);
};
};

View file

@ -1,6 +1,7 @@
const assert = require('assert');
const crypto = require('crypto');
const storage = require('../storage');
const config = require('../config');
const fxa = require('../fxa');
module.exports = {
@ -70,10 +71,11 @@ module.exports = {
const token = authHeader.split(' ')[1];
req.user = await fxa.verify(token);
}
if (req.user) {
next();
} else {
if (config.fxa_required && !req.user) {
res.sendStatus(401);
} else {
next();
}
}
};

View file

@ -50,6 +50,12 @@ module.exports = function(app) {
return `'nonce-${req.cspNonce}'`;
}
],
styleSrc: [
"'self'",
function(req) {
return `'nonce-${req.cspNonce}'`;
}
],
formAction: ["'none'"],
frameAncestors: ["'none'"],
objectSrc: ["'none'"],

View file

@ -1,18 +1,20 @@
const assets = require('../../common/assets');
const state = require('../state');
module.exports = async function(req, res) {
const appState = await state(req);
module.exports = function(req, res) {
const manifest = {
name: 'Send',
short_name: 'Send',
lang: req.language,
icons: [
{
src: assets.get('android-chrome-192x192.png'),
src: appState.ui.assets.android_chrome_192px,
type: 'image/png',
sizes: '192x192'
},
{
src: assets.get('android-chrome-512x512.png'),
src: appState.ui.assets.android_chrome_512px,
type: 'image/png',
sizes: '512x512'
}

View file

@ -3,9 +3,18 @@ const layout = require('./layout');
const assets = require('../common/assets');
const getTranslator = require('./locale');
const { getFxaConfig } = require('./fxa');
const fs = require('fs');
const path = require('path');
module.exports = async function(req) {
const locale = req.language || 'en-US';
const locale = (() => {
if (config.custom_locale != '' && fs.existsSync(path.join(__dirname,'../public/locales',config.custom_locale))) {
return config.custom_locale;
}
else {
return req.language || 'en-US';
}
})();
let authConfig = null;
let robots = 'none';
if (req.route && req.route.path === '/') {
@ -24,6 +33,23 @@ module.exports = async function(req) {
prefs.surveyUrl = config.survey_url;
}
const baseUrl = config.deriveBaseUrl(req);
const uiAssets = {
android_chrome_192px: assets.get('android-chrome-192x192.png'),
android_chrome_512px: assets.get('android-chrome-512x512.png'),
apple_touch_icon: assets.get('apple-touch-icon.png'),
favicon_16px: assets.get('favicon-16x16.png'),
favicon_32px: assets.get('favicon-32x32.png'),
icon: assets.get('icon.svg'),
safari_pinned_tab: assets.get('safari-pinned-tab.svg'),
facebook: baseUrl + '/' + assets.get('send-fb.jpg'),
twitter: baseUrl + '/' + assets.get('send-twitter.jpg'),
wordmark: assets.get('wordmark.svg') + '#logo',
custom_css: ''
};
Object.keys(uiAssets).forEach(index => {
if (config.ui_custom_assets[index] !== '')
uiAssets[index] = config.ui_custom_assets[index];
});
return {
archive: {
numFiles: 0
@ -31,11 +57,16 @@ module.exports = async function(req) {
locale,
capabilities: { account: false },
translate: getTranslator(locale),
title: 'Send',
description:
'Encrypt and send files with a link that automatically expires to ensure your important documents dont stay online forever.',
title: config.custom_title,
description: config.custom_description,
baseUrl,
ui: {},
ui: {
colors: {
primary: config.ui_color_primary,
accent: config.ui_color_accent
},
assets: uiAssets
},
storage: {
files: []
},

View file

@ -1,7 +1,6 @@
const fs = require('fs');
const path = require('path');
const promisify = require('util').promisify;
const mkdirp = require('mkdirp');
const stat = promisify(fs.stat);
@ -9,7 +8,9 @@ class FSStorage {
constructor(config, log) {
this.log = log;
this.dir = config.file_dir;
mkdirp.sync(this.dir);
fs.mkdirSync(this.dir, {
recursive: true
});
}
async length(id) {

View file

@ -1,5 +1,7 @@
const colors = {
transparent: 'transparent',
primary: 'var(--color-primary)',
primary_accent: 'var(--color-primary-accent)',
black: '#000000',
'grey-90': '#0c0c0d',
@ -16,93 +18,12 @@ const colors = {
'grey-10': '#f9f9fa',
white: '#ffffff',
'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-90': '#3e1300',
'orange-80': '#712b00',
'orange-70': '#a44900',
'orange-60': '#d76e00',
'orange-50': '#ff9400',
// unspec
'orange-40': '#ffb24c',
'orange-30': '#ffd399',
'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',
// 'teal-darkest': '#0d3331',
// 'teal-darker': '#20504f',
// 'teal-dark': '#38a89d',
// teal: '#4dc0b5',
// 'teal-light': '#64d5ca',
// 'teal-lighter': '#a0f0ed',
// 'teal-lightest': '#e8fffe',
'blue-90': '#000f40',
'blue-80': '#002275',
'blue-70': '#003eaa',
'blue-60': '#0060df',
'blue-50': '#0a84ff',
blue: '#0a84ff',
'blue-40': '#45a1ff',
'blue-30': '#99ccff',
'blue-20': '#cce6ff',
'ink-90': '#0f1126',
'ink-80': '#202340',
'ink-70': '#363959',
// 'indigo-darkest': '#191e38',
// 'indigo-darker': '#2f365f',
// 'indigo-dark': '#5661b3',
// indigo: '#6574cd',
// 'indigo-light': '#7886d7',
// 'indigo-lighter': '#b2b7ff',
// 'indigo-lightest': '#e6e8ff',
'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%)'
};
module.exports = {
purge: false,
theme: {
colors: colors,
screens: {

View file

@ -1,7 +1,6 @@
/* eslint-disable no-undef, no-process-exit */
const fs = require('fs');
const path = require('path');
const mkdirp = require('mkdirp');
const puppeteer = require('puppeteer');
const webpack = require('webpack');
const config = require('../../webpack.config');
@ -44,7 +43,9 @@ const server = app.listen(async function() {
const coverage = await page.evaluate(() => __coverage__);
if (coverage) {
const dir = path.resolve(__dirname, '../../.nyc_output');
mkdirp.sync(dir);
fs.mkdirSync(dir, {
recursive: true
});
fs.writeFileSync(
path.resolve(dir, 'frontend.json'),
JSON.stringify(coverage)

View file

@ -1,9 +1,11 @@
const path = require('path');
const mkdirp = require('mkdirp');
const fs = require('fs');
const rimraf = require('rimraf');
const dir = path.join(__dirname, 'integration', 'downloads');
mkdirp.sync(dir);
fs.mkdirSync(dir, {
recursive: true
});
rimraf.sync(`${dir}${path.sep}*`);
exports.config = {

View file

@ -6,6 +6,13 @@ const VersionPlugin = require('./build/version_plugin');
const AndroidIndexPlugin = require('./build/android_index_plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
// Fix for node 18+
// See: <https://stackoverflow.com/a/78005686/1000145>
const crypto = require('crypto');
const crypto_orig_createHash = crypto.createHash;
crypto.createHash = algorithm =>
crypto_orig_createHash(algorithm == 'md4' ? 'sha256' : algorithm);
const webJsOptions = {
babelrc: false,
presets: [
@ -42,7 +49,8 @@ const serviceWorker = {
test: /\.(png|jpg)$/,
loader: 'file-loader',
options: {
name: '[name].[contenthash:8].[ext]'
name: '[name].[contenthash:8].[ext]',
esModule: false
}
},
{
@ -51,16 +59,26 @@ const serviceWorker = {
{
loader: 'file-loader',
options: {
name: '[name].[contenthash:8].[ext]'
name: '[name].[contenthash:8].[ext]',
esModule: false
}
},
{
loader: 'svgo-loader',
options: {
plugins: [
{ removeViewBox: false }, // true causes stretched images
{ convertStyleToAttrs: true }, // for CSP, no unsafe-eval
{ removeTitle: true } // for smallness
{
name: 'removeViewBox',
active: false // true causes stretched images
},
{
name: 'convertStyleToAttrs',
active: true // for CSP, no unsafe-eval
},
{
name: 'removeTitle',
active: true // for smallness
}
]
}
}
@ -127,7 +145,8 @@ const web = {
test: /\.(png|jpg)$/,
loader: 'file-loader',
options: {
name: '[name].[contenthash:8].[ext]'
name: '[name].[contenthash:8].[ext]',
esModule: false
}
},
{
@ -136,17 +155,30 @@ const web = {
{
loader: 'file-loader',
options: {
name: '[name].[contenthash:8].[ext]'
name: '[name].[contenthash:8].[ext]',
esModule: false
}
},
{
loader: 'svgo-loader',
options: {
plugins: [
{ cleanupIDs: false },
{ removeViewBox: false }, // true causes stretched images
{ convertStyleToAttrs: true }, // for CSP, no unsafe-eval
{ removeTitle: true } // for smallness
{
name: 'cleanupIDs',
active: false
},
{
name: 'removeViewBox',
active: false // true causes stretched images
},
{
name: 'convertStyleToAttrs',
active: true // for CSP, no unsafe-eval
},
{
name: 'removeTitle',
active: true // for smallness
}
]
}
}
@ -160,7 +192,8 @@ const web = {
{
loader: 'css-loader',
options: {
importLoaders: 1
importLoaders: 1,
esModule: false
}
},
'postcss-loader'
@ -184,12 +217,14 @@ const web = {
]
},
plugins: [
new CopyPlugin([
{
context: 'public',
from: '*.*'
}
]),
new CopyPlugin({
patterns: [
{
context: 'public',
from: '*.*'
}
]
}),
new webpack.EnvironmentPlugin(['NODE_ENV']),
new webpack.IgnorePlugin(/\.\.\/dist/), // used in common/*.js
new ExtractTextPlugin({