Compare commits
842 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
137f474b69 | ||
|
|
8e14d3f8f7 | ||
|
|
07b7bc003a | ||
|
|
df691c1516 | ||
|
|
17e61bb09d | ||
|
|
14e21988b2 | ||
|
|
205de5a633 | ||
|
|
eabdc903b9 | ||
|
|
0628e71ec9 | ||
|
|
ebbcb38c7a | ||
|
|
5c1f535291 | ||
|
|
2c8e488611 | ||
|
|
6f3eac659c | ||
|
|
86bca790bc | ||
|
|
895d196876 | ||
|
|
3d8b38ffe4 | ||
|
|
fddc415c86 | ||
|
|
7a8e9b5de1 | ||
|
|
bbaeb44b26 | ||
|
|
a95f659474 | ||
|
|
4d311b134f | ||
|
|
5f90de577f | ||
|
|
3c32ce946a | ||
|
|
5ca89d0e0d | ||
|
|
781d1f5b0a | ||
|
|
ef9bfae319 | ||
|
|
7abbc60e17 | ||
|
|
15244e1a64 | ||
|
|
4b39d61ff4 | ||
|
|
74718d6361 | ||
|
|
ced640c24a | ||
|
|
cdaa92c86d | ||
|
|
57012f0660 | ||
|
|
6fde6e0a79 | ||
|
|
182bde30fa | ||
|
|
59e2267513 | ||
|
|
01a064ef7f | ||
|
|
9759338e6a | ||
|
|
5ac4560157 | ||
|
|
8e60ca1ac9 | ||
|
|
131a8b5564 | ||
|
|
663023a204 | ||
|
|
2b5c9dfb35 | ||
|
|
a9a34fdd0a | ||
|
|
1655094ce3 | ||
|
|
9ae7e3df11 | ||
|
|
0a31e2d521 | ||
|
|
b6849661a6 | ||
|
|
53e822964e | ||
|
|
b2f76d2df9 | ||
|
|
574a3ce894 | ||
|
|
c68f796891 | ||
|
|
c592f84d7d | ||
|
|
31faaf147e | ||
|
|
09c20f5933 | ||
|
|
fa4ab7bd5c | ||
|
|
de4a24a7f8 | ||
|
|
8f1c404724 | ||
|
|
1b975e7ba7 | ||
|
|
1d7473c489 | ||
|
|
a7d3992ba1 | ||
|
|
d81e9a76db | ||
|
|
0624e59776 | ||
|
|
546064a7ee | ||
|
|
9d49cc876c | ||
|
|
0bf8481fd0 | ||
|
|
ae0758ac14 | ||
|
|
e9405f49ee | ||
|
|
a1d0eef8a5 | ||
|
|
254b806fb4 | ||
|
|
a7aee1450f | ||
|
|
fa5573a5ff | ||
|
|
9714bb0a0a | ||
|
|
ad82d30dd9 | ||
|
|
757ac14d1a | ||
|
|
3e066258c4 | ||
|
|
127f73b4fe | ||
|
|
ae5009e1e3 | ||
|
|
0ab8ddc894 | ||
|
|
b429841534 | ||
|
|
279f6df6f4 | ||
|
|
634e6b2834 | ||
|
|
856b2cdc60 | ||
|
|
41351f877c | ||
|
|
afbb89fbe8 | ||
|
|
b40b45273d | ||
|
|
f1fb877c7f | ||
|
|
9d7ad06b1a | ||
|
|
c6a4b089d9 | ||
|
|
24917f8aa5 | ||
|
|
eada94b262 | ||
|
|
43fa551a64 | ||
|
|
e1137db946 | ||
|
|
c1878649b3 | ||
|
|
30b86b14ed | ||
|
|
e91b341f8a | ||
|
|
70148232c6 | ||
|
|
56e3d5766c | ||
|
|
350e31ae4a | ||
|
|
0794bcc458 | ||
|
|
a6aee8ad62 | ||
|
|
8305d13dab | ||
|
|
441a520765 | ||
|
|
ba84e59f39 | ||
|
|
22a316ab58 | ||
|
|
6b9502d252 | ||
|
|
cdc3a5340d | ||
|
|
f03f7a0286 | ||
|
|
d8a5789701 | ||
|
|
8d26e0e742 | ||
|
|
e142d76cb4 | ||
|
|
c488c1d724 | ||
|
|
bed57af6c5 | ||
|
|
7500bd8326 | ||
|
|
0250924961 | ||
|
|
70813556ad | ||
|
|
2bb9af1943 | ||
|
|
55bd44a8f5 | ||
|
|
d83900f272 | ||
|
|
fa4f9299b2 | ||
|
|
0f7b19c385 | ||
|
|
a9c1dd0180 | ||
|
|
c468e2f34e | ||
|
|
718f42897f | ||
|
|
fb468bd1bc | ||
|
|
dafe00cabb | ||
|
|
98aebb7f70 | ||
|
|
a990d78bc0 | ||
|
|
9b4069be3e | ||
|
|
ff3bc0dd62 | ||
|
|
b39b131928 | ||
|
|
2646fb9b3c | ||
|
|
c2b84650e2 | ||
|
|
fecf938ae7 | ||
|
|
8abf631430 | ||
|
|
d69c535dda | ||
|
|
082ca6c57b | ||
|
|
b263231068 | ||
|
|
947a6d9992 | ||
|
|
1ad7edf5a9 | ||
|
|
0c26204ea1 | ||
|
|
1e3bbee7f1 | ||
|
|
ec80e8e622 | ||
|
|
61e2c0d85b | ||
|
|
80db74fc3a | ||
|
|
30936eb2fa | ||
|
|
31e29d58b9 | ||
|
|
702134b3b1 | ||
|
|
11ae7f857c | ||
|
|
8827556974 | ||
|
|
21b7f16b1e | ||
|
|
314ab237ec | ||
|
|
0fa0416c3f | ||
|
|
09faedf059 | ||
|
|
16aa7983ed | ||
|
|
493bf8dc89 | ||
|
|
46432b9649 | ||
|
|
193664a8e8 | ||
|
|
626e578acb | ||
|
|
51bffe11a8 | ||
|
|
08e2c6c112 | ||
|
|
c38d91db98 | ||
|
|
c13839a522 | ||
|
|
4894d5162f | ||
|
|
77b6fb138f | ||
|
|
9dab74891d | ||
|
|
393d2a0052 | ||
|
|
44ac783f6a | ||
|
|
7ea8712538 | ||
|
|
fb92a793e4 | ||
|
|
87eaba6337 | ||
|
|
7e13f2ab32 | ||
|
|
3214d293ca | ||
|
|
1437116cf3 | ||
|
|
87a8cfba40 | ||
|
|
f929bb2aec | ||
|
|
740001ddde | ||
|
|
aaec16cf52 | ||
|
|
24af3207e9 | ||
|
|
5da43f0da7 | ||
|
|
dffb26349b | ||
|
|
38746078ed | ||
|
|
c4751842fe | ||
|
|
08ec9d98b8 | ||
|
|
5200928d5c | ||
|
|
4c3e37f4b5 | ||
|
|
60eda64c8d | ||
|
|
4db7fc6db3 | ||
|
|
5844a9a03c | ||
|
|
9829e46270 | ||
|
|
9a150ddb22 | ||
|
|
e7b90ea1b9 | ||
|
|
07bcfa2d36 | ||
|
|
dce134744d | ||
|
|
288bc50484 | ||
|
|
09d6c64a9b | ||
|
|
d7a542f2c2 | ||
|
|
aca82dd880 | ||
|
|
aa72a4c72c | ||
|
|
a70dcfc905 | ||
|
|
49731ab8ba | ||
|
|
3d9e01f8e5 | ||
|
|
441fe86186 | ||
|
|
f9283f5f6a | ||
|
|
c8e0b696a6 | ||
|
|
cf5c64a3f8 | ||
|
|
097ff19c5f | ||
|
|
8767b9b6b0 | ||
|
|
4ac7ac2b24 | ||
|
|
4cdce6c841 | ||
|
|
763414c848 | ||
|
|
9172af48fd | ||
|
|
14a4297db8 | ||
|
|
a78475aff4 | ||
|
|
d2b57039bf | ||
|
|
dd5be246d4 | ||
|
|
779005845e | ||
|
|
f3499326bd | ||
|
|
fe10b131fc | ||
|
|
9b6b7aa998 | ||
|
|
e9d5d8ec11 | ||
|
|
73e39ad453 | ||
|
|
c91d24cd86 | ||
|
|
1fc83aa902 | ||
|
|
5ac013ca40 | ||
|
|
6d17b86d28 | ||
|
|
fcea981127 | ||
|
|
bdd7044808 | ||
|
|
96bea84a73 | ||
|
|
9aef7df82c | ||
|
|
b0d36529a1 | ||
|
|
2a7099a7a2 | ||
|
|
4c069949f2 | ||
|
|
699c97a9c0 | ||
|
|
3c640061f0 | ||
|
|
bbd74efc2c | ||
|
|
2dfbee090a | ||
|
|
a03b1b7a9a | ||
|
|
594b584500 | ||
|
|
d74d339e4b | ||
|
|
859554ce21 | ||
|
|
703325f223 | ||
|
|
9a416e3e78 | ||
|
|
8821403a9b | ||
|
|
4a841bf563 | ||
|
|
4d6995536a | ||
|
|
6ef4e86029 | ||
|
|
2408c766ce | ||
|
|
882e13bac6 | ||
|
|
e48c2cf75b | ||
|
|
c8f7e60259 | ||
|
|
432a39d313 | ||
|
|
59ed64698d | ||
|
|
6edfe5146c | ||
|
|
44ea0756ea | ||
|
|
02fc4d74db | ||
|
|
0f77b6d86b | ||
|
|
ae2eb14fda | ||
|
|
455c4f5472 | ||
|
|
7335232680 | ||
|
|
2f9372e8e0 | ||
|
|
80db158ee3 | ||
|
|
6c18f4fb2c | ||
|
|
f28444f4c6 | ||
|
|
93ac742a5e | ||
|
|
6dcbc19315 | ||
|
|
65df0fa9cf | ||
|
|
387e88907c | ||
|
|
9253695f8d | ||
|
|
67635b9151 | ||
|
|
e0abfb5cf7 | ||
|
|
f1de6a14da | ||
|
|
38052c1b85 | ||
|
|
5847faf4e2 | ||
|
|
0c1c8178f5 | ||
|
|
86fbd2a4b5 | ||
|
|
8cfb45944c | ||
|
|
0289409c9c | ||
|
|
b93a33eba4 | ||
|
|
fb41a40128 | ||
|
|
e18fda91fe | ||
|
|
b077635427 | ||
|
|
4d4098b7c9 | ||
|
|
9e4838d121 | ||
|
|
dd439bcdfb | ||
|
|
d5e936b8fc | ||
|
|
376e1efa4c | ||
|
|
09cc047ade | ||
|
|
9b6507bc1b | ||
|
|
27d2927b14 | ||
|
|
21cb8f6608 | ||
|
|
41cb49c99f | ||
|
|
504d475f5d | ||
|
|
926ce972f5 | ||
|
|
2bc7f270f8 | ||
|
|
b03022b924 | ||
|
|
66863ceb1a | ||
|
|
69e91eb4ed | ||
|
|
167bf8a607 | ||
|
|
5e10fd2db6 | ||
|
|
a451ae435e | ||
|
|
125c4232ae | ||
|
|
7f5e33613d | ||
|
|
5576bc0652 | ||
|
|
ebd3a45a2c | ||
|
|
193f54547f | ||
|
|
d344531bda | ||
|
|
4ac07800c4 | ||
|
|
e9fa6ad401 | ||
|
|
95e3ca7a1c | ||
|
|
705289d34b | ||
|
|
4282c93b2b | ||
|
|
434f8b56cc | ||
|
|
5c793dcde8 | ||
|
|
e36f685bd2 | ||
|
|
5a7d05744c | ||
|
|
81999f2fc4 | ||
|
|
c419d29c96 | ||
|
|
8cdfb47f84 | ||
|
|
5e192d0f4a | ||
|
|
1460537169 | ||
|
|
f888ea74b0 | ||
|
|
ea6c78f49a | ||
|
|
3f316fb8b0 | ||
|
|
ee444186e9 | ||
|
|
2b7f06dda2 | ||
|
|
c19b273d4f | ||
|
|
596ad871df | ||
|
|
655f685883 | ||
|
|
bbe111a95e | ||
|
|
b063cf35b8 | ||
|
|
030d65d7af | ||
|
|
aa113fd903 | ||
|
|
caeba94e04 | ||
|
|
a7de951115 | ||
|
|
e17d1f7235 | ||
|
|
51ba253f95 | ||
|
|
fef26e083a | ||
|
|
de826afb9b | ||
|
|
5944b85e67 | ||
|
|
d208a82089 | ||
|
|
a64eced8be | ||
|
|
ada45323e1 | ||
|
|
ced8c24f47 | ||
|
|
5b9e9d5146 | ||
|
|
280a4f65e7 | ||
|
|
d2dd9f4b4d | ||
|
|
2897a39131 | ||
|
|
626b9068a9 | ||
|
|
c3bb876a2c | ||
|
|
48912dd4d4 | ||
|
|
f1c894d14f | ||
|
|
60d61fa52c | ||
|
|
fe313f1001 | ||
|
|
68705f60db | ||
|
|
92303988c0 | ||
|
|
49d578217c | ||
|
|
1abb3b7ebe | ||
|
|
4f3c2498a6 | ||
|
|
33babe6f67 | ||
|
|
a51ee89939 | ||
|
|
bca79489c0 | ||
|
|
ddfbb06e1a | ||
|
|
cd2c944d41 | ||
|
|
5f66496519 | ||
|
|
318964251d | ||
|
|
5effeb16d1 | ||
|
|
c9c7c3182c | ||
|
|
18b95c497f | ||
|
|
80d0f73b06 | ||
|
|
522290dbef | ||
|
|
967100bf50 | ||
|
|
3e52c6f69f | ||
|
|
81be38fbc8 | ||
|
|
566de14016 | ||
|
|
9a285df790 | ||
|
|
02dda0f97e | ||
|
|
6edd4b7f5c | ||
|
|
40d6d1d4e6 | ||
|
|
1c7baed241 | ||
|
|
257924431d | ||
|
|
4a590753c9 | ||
|
|
460e5c6bbf | ||
|
|
51cc366cfa | ||
|
|
78b7bea284 | ||
|
|
65d4f9219b | ||
|
|
6d20f09d0a | ||
|
|
dc83ec1123 | ||
|
|
dff443287c | ||
|
|
8e8b5cefe5 | ||
|
|
616831ebfb | ||
|
|
d8a8087c2c | ||
|
|
85a9ef9539 | ||
|
|
aeacf7f0e7 | ||
|
|
0cd6882e0d | ||
|
|
41f68e2735 | ||
|
|
d42fa37962 | ||
|
|
c327507989 | ||
|
|
2f02fff999 | ||
|
|
b3a97cec2e | ||
|
|
a17744a075 | ||
|
|
8f023e36cf | ||
|
|
da1b0689a5 | ||
|
|
3adea6d815 | ||
|
|
8d1baca60e | ||
|
|
87be7aa64f | ||
|
|
9e91e7349a | ||
|
|
f4b538b8dc | ||
|
|
63d0c2e679 | ||
|
|
52fd555ffc | ||
|
|
3517ad0826 | ||
|
|
4796fbeaa9 | ||
|
|
42ef0facc9 | ||
|
|
a5b5628d88 | ||
|
|
1bf8dd93fd | ||
|
|
ae83e47813 | ||
|
|
83f9853112 | ||
|
|
16bba3ff86 | ||
|
|
a42a54670b | ||
|
|
0586c00aed | ||
|
|
197cd18838 | ||
|
|
f97de2cd31 | ||
|
|
8164f3585e | ||
|
|
f829e90408 | ||
|
|
5e73841952 | ||
|
|
e31f6faa9f | ||
|
|
03e4d7e687 | ||
|
|
a9fdd5b1a5 | ||
|
|
d7be980147 | ||
|
|
abf2a0a9f8 | ||
|
|
c7b3ee6098 | ||
|
|
aded224632 | ||
|
|
2a43477cd4 | ||
|
|
6be94156db | ||
|
|
8cb40effa5 | ||
|
|
4cd4b2a060 | ||
|
|
27fa13caed | ||
|
|
3ee72ca065 | ||
|
|
114a99a358 | ||
|
|
0c59b2330c | ||
|
|
f9410d5698 | ||
|
|
4e9b6e25ca | ||
|
|
82bc6cad74 | ||
|
|
139007bece | ||
|
|
0afd70db8c | ||
|
|
934b98cafd | ||
|
|
7bb85bc5aa | ||
|
|
a1973d8b96 | ||
|
|
84b01ba58b | ||
|
|
188429e03d | ||
|
|
d3003228e7 | ||
|
|
50c7c3bef9 | ||
|
|
07b9545b03 | ||
|
|
0f031e2d8b | ||
|
|
083df44395 | ||
|
|
a932af87b5 | ||
|
|
8d8c2efa23 | ||
|
|
318e1a49bf | ||
|
|
c9e914faba | ||
|
|
7a53ed96ed | ||
|
|
8eae1f282b | ||
|
|
fae6561393 | ||
|
|
6b291ae012 | ||
|
|
303b34a70b | ||
|
|
d7b856f8ca | ||
|
|
6111e71506 | ||
|
|
5b0de9f9b5 | ||
|
|
8cc50e2ecb | ||
|
|
f6f6b4a4e2 | ||
|
|
2de6037a83 | ||
|
|
9d3f6680cb | ||
|
|
462002d84b | ||
|
|
bb6c747297 | ||
|
|
e09385be05 | ||
|
|
11bbf34feb | ||
|
|
8214409ac5 | ||
|
|
098ece066f | ||
|
|
e0e7853882 | ||
|
|
40d8c441db | ||
|
|
bacafb02be | ||
|
|
68ed9a6953 | ||
|
|
cd8b09f900 | ||
|
|
305cbb8a41 | ||
|
|
d5b2b4c4f1 | ||
|
|
f2b4e3f661 | ||
|
|
0d45799202 | ||
|
|
ba66e0a72a | ||
|
|
b5244c75ca | ||
|
|
1f85096422 | ||
|
|
3ecf0e7d29 | ||
|
|
046d4ce142 | ||
|
|
4c2ae4fd6b | ||
|
|
dd62a137d2 | ||
|
|
ea63c4a0bf | ||
|
|
47ee702fcb | ||
|
|
d0c6a18363 | ||
|
|
91dec114a6 | ||
|
|
702a0a7eae | ||
|
|
19eec66ece | ||
|
|
f63496e46c | ||
|
|
e2671e6634 | ||
|
|
d441bb3125 | ||
|
|
13efe45f88 | ||
|
|
137acb54a9 | ||
|
|
d72ba8af03 | ||
|
|
5b178b93f1 | ||
|
|
2f5a1dda5b | ||
|
|
62b1d86f7c | ||
|
|
2e9de12f7a | ||
|
|
5e7c99e0fb | ||
|
|
68f40c773f | ||
|
|
300b0fce18 | ||
|
|
78c58bf4d3 | ||
|
|
e57dbdf95c | ||
|
|
91831ce1dd | ||
|
|
fef9473810 | ||
|
|
b19d71ebc0 | ||
|
|
a84ecf77a2 | ||
|
|
e9ad080e35 | ||
|
|
c024f039c1 | ||
|
|
e6fd97744a | ||
|
|
c880936ba4 | ||
|
|
7eba49027c | ||
|
|
7e0a8f76d5 | ||
|
|
322f8cc168 | ||
|
|
c7ef83b6a1 | ||
|
|
cc47067870 | ||
|
|
41662987a6 | ||
|
|
4557e2fb6f | ||
|
|
3690dbcb14 | ||
|
|
e36c698720 | ||
|
|
245a9a2ddd | ||
|
|
2d938514d3 | ||
|
|
640e3811b4 | ||
|
|
c0a1268df4 | ||
|
|
8d0aaadb7e | ||
|
|
339cddd67b | ||
|
|
dddb9e66b9 | ||
|
|
cd0477d747 | ||
|
|
020b037f69 | ||
|
|
ff5f0040e3 | ||
|
|
7d48c5e793 | ||
|
|
993fa1a3a4 | ||
|
|
9b88d3f5e4 | ||
|
|
cd4df5f6d8 | ||
|
|
7c461eab52 | ||
|
|
1b7e94c2d8 | ||
|
|
dcd3c0b3ff | ||
|
|
bfe16a5300 | ||
|
|
8a1f905831 | ||
|
|
e5b4165eff | ||
|
|
be596e91ef | ||
|
|
f20c995d1a | ||
|
|
5f97c130bd | ||
|
|
13bf765be0 | ||
|
|
443de49db8 | ||
|
|
3d82ce0909 | ||
|
|
b259cba882 | ||
|
|
a138586dd7 | ||
|
|
e427203a45 | ||
|
|
8882024e8f | ||
|
|
581ae224e7 | ||
|
|
dccf3329ca | ||
|
|
1450322585 | ||
|
|
5d1639851b | ||
|
|
77939cc280 | ||
|
|
7fd8fb4914 | ||
|
|
91ede1bdec | ||
|
|
29698a55c4 | ||
|
|
abfc07b1e3 | ||
|
|
a0401b24e8 | ||
|
|
dbf39efd35 | ||
|
|
fe7d71d165 | ||
|
|
977fe65dce | ||
|
|
4e79925c7b | ||
|
|
416e8d81f9 | ||
|
|
215f0f74ad | ||
|
|
93930b91a2 | ||
|
|
65c24990cd | ||
|
|
424eb2c37a | ||
|
|
d10cbcba3e | ||
|
|
553f0958ba | ||
|
|
ae2bae88cf | ||
|
|
313b145297 | ||
|
|
faf5fd17d3 | ||
|
|
dd0ab710de | ||
|
|
c2bcac76e9 | ||
|
|
bf7024c6d9 | ||
|
|
992cdcc70e | ||
|
|
10e446bb41 | ||
|
|
15ac0e1d49 | ||
|
|
4946e9c382 | ||
|
|
ece302342e | ||
|
|
721aa48d53 | ||
|
|
0761fcf902 | ||
|
|
33602f1432 | ||
|
|
74b305442c | ||
|
|
f30393cf33 | ||
|
|
e7688a62c6 | ||
|
|
109617d817 | ||
|
|
8f66db2295 | ||
|
|
57e0d17cbc | ||
|
|
93138773ca | ||
|
|
1bfa6321b1 | ||
|
|
10d489f766 | ||
|
|
4065bbcfd7 | ||
|
|
330da9b258 | ||
|
|
3febcfe1ea | ||
|
|
0cdae11456 | ||
|
|
5996bceef7 | ||
|
|
ba277b9382 | ||
|
|
5046b5022a | ||
|
|
74334433cd | ||
|
|
33bf82e963 | ||
|
|
c72896aeb7 | ||
|
|
b306ffec8d | ||
|
|
e1c21dd9b0 | ||
|
|
9f8cedc0db | ||
|
|
12c02ef6af | ||
|
|
5a564e2c37 | ||
|
|
4b8445191b | ||
|
|
12033edda5 | ||
|
|
8e6d8eaddd | ||
|
|
faaa8afe17 | ||
|
|
84e8abf2c5 | ||
|
|
5db8a20b9d | ||
|
|
117c6ea12d | ||
|
|
83880d97e6 | ||
|
|
c3be5228cb | ||
|
|
ade214c69c | ||
|
|
4cb040d70d | ||
|
|
73ccce627c | ||
|
|
4043d35c8b | ||
|
|
a576cc0198 | ||
|
|
fa1f0208a4 | ||
|
|
193d3b1aef | ||
|
|
3b28ce88bf | ||
|
|
c77983d902 | ||
|
|
6ef9f8fa43 | ||
|
|
1eabc1a11e | ||
|
|
9136694d29 | ||
|
|
ec7f058afc | ||
|
|
62989ee2c9 | ||
|
|
85068e97ae | ||
|
|
eb73dbfe78 | ||
|
|
dde2c4d5a9 | ||
|
|
20cf8d0a15 | ||
|
|
b2bd623a49 | ||
|
|
fc3001978c | ||
|
|
d6823f492d | ||
|
|
c3751c2efc | ||
|
|
70396e2f36 | ||
|
|
b557665d04 | ||
|
|
6393d70a33 | ||
|
|
834df8526f | ||
|
|
f5bd332ff8 | ||
|
|
0d5fb1740d | ||
|
|
5ed4db9689 | ||
|
|
31b810eb7d | ||
|
|
168a711c05 | ||
|
|
7243a10340 | ||
|
|
b18bcd3b6e | ||
|
|
09a6192bf5 | ||
|
|
9585850d6d | ||
|
|
14f3d837f9 | ||
|
|
d660eda64c | ||
|
|
2bbb0f14f3 | ||
|
|
b123b736e9 | ||
|
|
28e496fe05 | ||
|
|
8ebfaf9ad9 | ||
|
|
47fd387799 | ||
|
|
fbf906fe5b | ||
|
|
463393552b | ||
|
|
18a811aa31 | ||
|
|
cb0d69c5cd | ||
|
|
2c77d94af7 | ||
|
|
b9eb653f1f | ||
|
|
37bb6fd982 | ||
|
|
e5d1e8f028 | ||
|
|
99477774cf | ||
|
|
8d419072d7 | ||
|
|
a2fcce9e40 | ||
|
|
55d3d1a792 | ||
|
|
88dbda87dc | ||
|
|
76a6f02eb7 | ||
|
|
34f26fc017 | ||
|
|
4f36f2befa | ||
|
|
f816c0bc12 | ||
|
|
60bfd1b67c | ||
|
|
fc7c7e2c71 | ||
|
|
a9e0ab17e5 | ||
|
|
80cf343516 | ||
|
|
744dbb3a6f | ||
|
|
e4301963a2 | ||
|
|
48da85b12b | ||
|
|
e02bc54172 | ||
|
|
3bb6a6fa44 | ||
|
|
64e7182f30 | ||
|
|
8c1ba8b45a | ||
|
|
85a7be01cb | ||
|
|
262322b9e8 | ||
|
|
88904621b3 | ||
|
|
da8f7c7172 | ||
|
|
caf594877f | ||
|
|
ffc9386221 | ||
|
|
6670d9ad69 | ||
|
|
6d8db25d61 | ||
|
|
a38a27dc60 | ||
|
|
69055a504b | ||
|
|
902010704a | ||
|
|
1992626da8 | ||
|
|
3c8cdbc7df | ||
|
|
72b07b82c9 | ||
|
|
846f5c7254 | ||
|
|
b0e18b29ff | ||
|
|
bbc9cab661 | ||
|
|
6179e07dd8 | ||
|
|
1363f4d6a2 | ||
|
|
3e47556560 | ||
|
|
aa3a2f8c55 | ||
|
|
6e7283664c | ||
|
|
fc89da153d | ||
|
|
8c4cb90b3a | ||
|
|
3cdd207953 | ||
|
|
5b1e2f38f4 | ||
|
|
5822900508 | ||
|
|
e898f35c46 | ||
|
|
7ed30f497b | ||
|
|
e66bc966d2 | ||
|
|
acfcae5dec | ||
|
|
95a83922df | ||
|
|
f7329e3316 | ||
|
|
cde63595e8 | ||
|
|
ca6efdae55 | ||
|
|
b712a9d175 | ||
|
|
45eccc1cad | ||
|
|
4068291f7c | ||
|
|
e4a724422e | ||
|
|
4fa22a6262 | ||
|
|
1fae4cfd8d | ||
|
|
9a6dbee694 | ||
|
|
716555f76f | ||
|
|
cc35206ee4 | ||
|
|
359e77f451 | ||
|
|
b805c78a9a | ||
|
|
a4ee6ad5e5 | ||
|
|
22b1c3a286 | ||
|
|
cd6648be56 | ||
|
|
8d00372824 | ||
|
|
729f716e97 | ||
|
|
93d2e91afa | ||
|
|
26b228a976 | ||
|
|
9735aa62bd | ||
|
|
4122f4dc3e | ||
|
|
b88cf22d8a | ||
|
|
6970e9228a | ||
|
|
5ce0846580 | ||
|
|
61c49fb329 | ||
|
|
2127857790 | ||
|
|
ba348b6839 | ||
|
|
188521f985 | ||
|
|
e0847e08c3 | ||
|
|
d287f67ac0 | ||
|
|
8f327fa439 | ||
|
|
ab60262cc9 | ||
|
|
e5f2b386bb | ||
|
|
61f131af58 | ||
|
|
2cf2fcebc9 | ||
|
|
c2e8139c6e | ||
|
|
ef9b15c1d7 | ||
|
|
e9c49073a8 | ||
|
|
cec3d6b548 | ||
|
|
3f89c2bf0a | ||
|
|
b419a6025f | ||
|
|
b07671719c | ||
|
|
6379a360fe | ||
|
|
89bc51c821 | ||
|
|
5dd5743871 | ||
|
|
91cc82d570 | ||
|
|
fcdb905430 | ||
|
|
9032e42912 | ||
|
|
00462947e3 | ||
|
|
b411447ebb | ||
|
|
52173bf6e7 | ||
|
|
9234bce75d | ||
|
|
b32e63c305 | ||
|
|
ee8ff3d220 | ||
|
|
3138f111e1 | ||
|
|
af0c497aab | ||
|
|
dad6132342 | ||
|
|
3ffdbd863b | ||
|
|
20b9766742 | ||
|
|
1e23548539 | ||
|
|
bfdab156e6 | ||
|
|
395c38b644 | ||
|
|
57c7c475fc | ||
|
|
191a0f93ff | ||
|
|
cdf45de8e2 | ||
|
|
6181ea6463 | ||
|
|
8c907c9029 | ||
|
|
6231385c74 | ||
|
|
109fd671e0 | ||
|
|
2682f95a2b | ||
|
|
fce615842d | ||
|
|
64998de423 | ||
|
|
2031158336 | ||
|
|
6aa79472bf | ||
|
|
c4b7a2bd97 | ||
|
|
6f7930e34d | ||
|
|
dc4682eaf5 | ||
|
|
125e6ecbdb | ||
|
|
412a785819 | ||
|
|
d63e22ab7e | ||
|
|
97d513db5f | ||
|
|
be470c6b6e | ||
|
|
1ce24f7e08 | ||
|
|
7ccf89b43b | ||
|
|
63fe2c7099 | ||
|
|
05da4937a1 | ||
|
|
d1ee285429 | ||
|
|
adf97a83f9 | ||
|
|
cbd1daca1e | ||
|
|
30f2e25903 | ||
|
|
fb41acb438 | ||
|
|
f845dd7d59 | ||
|
|
caa276b33c | ||
|
|
ccd8c2995e | ||
|
|
88ba5352d4 | ||
|
|
2735fa577f | ||
|
|
1908ce084d | ||
|
|
9026702e7b | ||
|
|
421dd30c9d | ||
|
|
a11b4b677c | ||
|
|
10e64000f4 | ||
|
|
67f586b65c | ||
|
|
05fe534e14 | ||
|
|
4cb34844aa | ||
|
|
34c367c49f | ||
|
|
50995238bd | ||
|
|
e00ff0d781 | ||
|
|
5d21c7c705 | ||
|
|
250503b2d3 |
@@ -1,7 +1,8 @@
|
||||
node_modules
|
||||
.git
|
||||
.DS_Store
|
||||
static
|
||||
test
|
||||
scripts
|
||||
firefox
|
||||
assets
|
||||
docs
|
||||
public
|
||||
test
|
||||
|
||||
14
.editorconfig
Normal file
@@ -0,0 +1,14 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{js,html,yml,json,handlebars}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.toml]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
@@ -1,2 +1,3 @@
|
||||
public/bundle.js
|
||||
public/webcrypto-shim.js
|
||||
dist
|
||||
assets
|
||||
firefox
|
||||
|
||||
@@ -19,11 +19,13 @@ rules:
|
||||
security/detect-non-literal-fs-filename: off
|
||||
security/detect-object-injection: off
|
||||
|
||||
eol-last: [error, always]
|
||||
eqeqeq: error
|
||||
no-alert: warn
|
||||
no-console: warn
|
||||
no-path-concat: error
|
||||
no-unused-vars: [error, {argsIgnorePattern: "^_|err|event|next|reject"}]
|
||||
no-var: error
|
||||
one-var: [error, never]
|
||||
prefer-const: error
|
||||
quotes: [error, single]
|
||||
quotes: [error, single, {avoidEscape: true}]
|
||||
|
||||
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
public/locales/* linguist-documentation
|
||||
docs/* linguist-documentation
|
||||
6
.gitignore
vendored
@@ -1,6 +1,2 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
public/bundle.js
|
||||
public/version.json
|
||||
static/*
|
||||
!static/info.txt
|
||||
dist
|
||||
|
||||
2
.prettierignore
Normal file
@@ -0,0 +1,2 @@
|
||||
dist
|
||||
assets/*.js
|
||||
@@ -1,6 +1,12 @@
|
||||
extends: stylelint-config-standard
|
||||
|
||||
plugins:
|
||||
- stylelint-no-unsupported-browser-features
|
||||
|
||||
rules:
|
||||
color-hex-case: upper
|
||||
plugin/no-unsupported-browser-features: [true, {severity: warning}]
|
||||
|
||||
color-hex-case: lower
|
||||
declaration-colon-newline-after: null
|
||||
selector-list-comma-newline-after: null
|
||||
value-list-comma-newline-after: null
|
||||
|
||||
218
CHANGELOG.md
Normal file
@@ -0,0 +1,218 @@
|
||||
## Change Log
|
||||
|
||||
### v1.1.1 (2017/08/17 01:29 +00:00)
|
||||
- [#516](https://github.com/mozilla/send/pull/516) cache assets (@dannycoates)
|
||||
- [#520](https://github.com/mozilla/send/pull/520) fix drag & drop (@dannycoates)
|
||||
- [#515](https://github.com/mozilla/send/pull/515) removed jquery from upload.js (@dannycoates)
|
||||
- [#514](https://github.com/mozilla/send/pull/514) use async and removed jquery from download.js (@dannycoates)
|
||||
- [#513](https://github.com/mozilla/send/pull/513) use svg for progress (@dannycoates)
|
||||
- [#510](https://github.com/mozilla/send/pull/510) added precommit hook for format (@dannycoates)
|
||||
- [#502](https://github.com/mozilla/send/pull/502) extracted filelist into its own file (@dannycoates)
|
||||
- [#428](https://github.com/mozilla/send/pull/428) add twitter and open graph cards (@dannycoates, @johngruen)
|
||||
- [#506](https://github.com/mozilla/send/pull/506) 404 page (@varghesethomase)
|
||||
- [#508](https://github.com/mozilla/send/pull/508) fixes 478 (@abhinadduri)
|
||||
- [#504](https://github.com/mozilla/send/pull/504) fix japanese browse button (@johngruen)
|
||||
- [#503](https://github.com/mozilla/send/pull/503) Added editorconfig (@skystar-p)
|
||||
- [#499](https://github.com/mozilla/send/pull/499) use import/export in the frontend code (@dannycoates)
|
||||
- [#500](https://github.com/mozilla/send/pull/500) fixed build:css on windows (@dannycoates)
|
||||
- [#481](https://github.com/mozilla/send/pull/481) Cater for mobile and desktop (@pdehaan, @hubdotcom)
|
||||
- [#493](https://github.com/mozilla/send/pull/493) added webpack-dev-middleware (@dannycoates)
|
||||
- [#491](https://github.com/mozilla/send/pull/491) added missing exit event cases (@dannycoates)
|
||||
- [#492](https://github.com/mozilla/send/pull/492) make the site mostly work when cookies (localStorage) are disabled (@dannycoates)
|
||||
- [#490](https://github.com/mozilla/send/pull/490) set the mime type in the download blob (@dannycoates)
|
||||
- [#485](https://github.com/mozilla/send/pull/485) added progress to tab title when not in focus (@dannycoates)
|
||||
- [#474](https://github.com/mozilla/send/pull/474) Fixing bug #438 by adding role attribute to anchor tags and alt attribute images (@varghesethomase)
|
||||
- [#480](https://github.com/mozilla/send/pull/480) Increase font weight to 500 on <button>s and <label>s (@pdehaan)
|
||||
- [#419](https://github.com/mozilla/send/pull/419) Add autoprefixer and cssnano support (@pdehaan)
|
||||
|
||||
### v1.1.0 (2017/08/08 03:59 +00:00)
|
||||
- [#473](https://github.com/mozilla/send/pull/473) Sort contributors alphabetically to prevent churn (@pdehaan)
|
||||
- [#472](https://github.com/mozilla/send/pull/472) removed references to checksums in frontend tests (@abhinadduri)
|
||||
- [#470](https://github.com/mozilla/send/pull/470) removed the file sha256 hash (@dannycoates)
|
||||
- [#469](https://github.com/mozilla/send/pull/469) Increase mimimum node version to 8.2.0 (@ehuggett)
|
||||
- [#468](https://github.com/mozilla/send/pull/468) attach delete-file handler only after upload (@dannycoates)
|
||||
- [#466](https://github.com/mozilla/send/pull/466) added webpack (@dannycoates)
|
||||
- [#427](https://github.com/mozilla/send/pull/427) Extended system font list fixes:#408 (@gautamkrishnar)
|
||||
- [#448](https://github.com/mozilla/send/pull/448) Migrate width attribute to CSS (Fixes #436) (@nskins)
|
||||
- [#457](https://github.com/mozilla/send/pull/457) factored out progress into progress.js (@dannycoates)
|
||||
- [#452](https://github.com/mozilla/send/pull/452) refactored metrics (@dannycoates)
|
||||
- [#455](https://github.com/mozilla/send/pull/455) Add a few missing strings from es-CL and tr locales (@pdehaan)
|
||||
- [#444](https://github.com/mozilla/send/pull/444) Chain jQuery calls, do not use events alias and store selectors (@Johann-S)
|
||||
- [#416](https://github.com/mozilla/send/pull/416) WIP: use webcrypto-liner to support Safari 10 (@dannycoates)
|
||||
- [#451](https://github.com/mozilla/send/pull/451) Add rel noopener noreferrer to target='_blank' anchor elements (Fixes #439) (@boopeshmahendran)
|
||||
- [#449](https://github.com/mozilla/send/pull/449) Add X-UA-Compatible meta tag (@kenrick95)
|
||||
- [#433](https://github.com/mozilla/send/pull/433) Prevent download button from being clicked multiple times (@pdehaan)
|
||||
- [#432](https://github.com/mozilla/send/pull/432) Add contributors script (@pdehaan)
|
||||
- [#409](https://github.com/mozilla/send/pull/409) Handle copy clipboard disabled (@Johann-S)
|
||||
|
||||
### v1.0.4 (2017/08/03 23:05 +00:00)
|
||||
- [#418](https://github.com/mozilla/send/pull/418) _blank all footer links (@dannycoates)
|
||||
- [#386](https://github.com/mozilla/send/pull/386) fix percentage view on mobile layout (@ariestiyansyah)
|
||||
- [#414](https://github.com/mozilla/send/pull/414) Add link to FAQ in unsupported view (@pdehaan)
|
||||
- [#415](https://github.com/mozilla/send/pull/415) Only include Fira CSS on /unsupported/* route (@pdehaan)
|
||||
- [#412](https://github.com/mozilla/send/pull/412) throw key errors before download begins (@dannycoates)
|
||||
- [#404](https://github.com/mozilla/send/pull/404) Use async function instead of promise (#325) (@weihanglo)
|
||||
- [#406](https://github.com/mozilla/send/pull/406) Add noscript tag (@pdehaan)
|
||||
- [#325](https://github.com/mozilla/send/pull/325) Use async function instead of promise (#325) (@weihanglo)
|
||||
- [#325](https://github.com/mozilla/send/pull/325) Use async function instead of promise (#325) (@weihanglo)
|
||||
|
||||
### v1.0.3 (2017/08/02 23:59 +00:00)
|
||||
- [#402](https://github.com/mozilla/send/pull/402) filter the hash from error reports (@dannycoates)
|
||||
- [#400](https://github.com/mozilla/send/pull/400) fix link that breaks download by opening in new tab (@johngruen)
|
||||
- [#369](https://github.com/mozilla/send/pull/369) Add ESLint no-alert shame rule (@pdehaan)
|
||||
- [#396](https://github.com/mozilla/send/pull/396) add babel-polyfill (@dannycoates)
|
||||
- [#394](https://github.com/mozilla/send/pull/394) catch JSON.parse errors of storage metadata (@dannycoates)
|
||||
- [#367](https://github.com/mozilla/send/pull/367) Generate production locales using 'compare-locales' (@pdehaan)
|
||||
- [#392](https://github.com/mozilla/send/pull/392) Adjust hover behavior on send-logo (#382)
|
||||
Fixes: #382. (@weihanglo)
|
||||
- [#382](https://github.com/mozilla/send/pull/382) Adjust hover behavior on send-logo (#382) (@weihanglo)
|
||||
- [#382](https://github.com/mozilla/send/pull/382) Adjust hover behavior on send-logo (#382) (@weihanglo)
|
||||
- [#380](https://github.com/mozilla/send/pull/380) Add Pontoon URL to README (@pdehaan)
|
||||
|
||||
### v1.0.2 (2017/07/31 18:58 +00:00)
|
||||
- [#365](https://github.com/mozilla/send/pull/365) revert the IE fix to fix footer on chrome (@dannycoates)
|
||||
|
||||
### v1.0.1 (2017/07/31 17:28 +00:00)
|
||||
- [#353](https://github.com/mozilla/send/pull/353) redirect ie to /unsupported (@abhinadduri, @dannycoates)
|
||||
- [#360](https://github.com/mozilla/send/pull/360) Fix some linting nits (@pdehaan)
|
||||
- [#362](https://github.com/mozilla/send/pull/362) Adjusts category of unsupported event (fixes #350). (@chuckharmston)
|
||||
- [#355](https://github.com/mozilla/send/pull/355) Make order of uploaded files in list consistent (@pdehaan)
|
||||
- [#356](https://github.com/mozilla/send/pull/356) Get rid of console.log statements (@pdehaan)
|
||||
- [#358](https://github.com/mozilla/send/pull/358) Fix some missing .title attributes in dev-only locales (@pdehaan)
|
||||
- [#354](https://github.com/mozilla/send/pull/354) Remove /en-US/ from cookies link in footer (@pdehaan)
|
||||
- [#339](https://github.com/mozilla/send/pull/339) Show error page on firefox v49 and below (@ericawright, @abhinadduri)
|
||||
- [#346](https://github.com/mozilla/send/pull/346) Add docs/CODEOWNERS file (@pdehaan)
|
||||
- [#345](https://github.com/mozilla/send/pull/345) wrap long file names (@dnarcese)
|
||||
- [#344](https://github.com/mozilla/send/pull/344) don't wrap file list headers (@dnarcese)
|
||||
- [#327](https://github.com/mozilla/send/pull/327) Modify popup delete dialog (@youwenliang)
|
||||
- [#341](https://github.com/mozilla/send/pull/341) center percentage text on all browser versions (@dnarcese)
|
||||
- [#340](https://github.com/mozilla/send/pull/340) Remove duplicate entities in localized FTL files (@flodolo)
|
||||
- [#337](https://github.com/mozilla/send/pull/337) support v 50 and 51 by not allowing const in loops (@ericawright)
|
||||
- [#338](https://github.com/mozilla/send/pull/338) Remove duplicated strings in en-US, fix nn-NO file (@flodolo)
|
||||
- [#336](https://github.com/mozilla/send/pull/336) German(de): Fixed missing value for deleteFileButton (#336) (@flodolo)
|
||||
- [#334](https://github.com/mozilla/send/pull/334) fix functionality on firefox 50 and 51 (@dnarcese)
|
||||
|
||||
### v1.0.0 (2017/07/26 19:08 +00:00)
|
||||
- [#323](https://github.com/mozilla/send/pull/323) disable upload/download notifications (@dannycoates)
|
||||
- [#322](https://github.com/mozilla/send/pull/322) fix feedback button jump (@dnarcese)
|
||||
- [#320](https://github.com/mozilla/send/pull/320) fix German footer (@dnarcese)
|
||||
|
||||
### v0.2.2 (2017/07/26 04:50 +00:00)
|
||||
- [#314](https://github.com/mozilla/send/pull/314) added L10N_DEV environment variable for making all languages available (@dannycoates)
|
||||
- [#313](https://github.com/mozilla/send/pull/313) removing timeout limit for front end tests (@abhinadduri)
|
||||
- [#311](https://github.com/mozilla/send/pull/311) expired ids should reject instead of returning null (@dannycoates)
|
||||
- [#302](https://github.com/mozilla/send/pull/302) UX Refine WIP (@youwenliang)
|
||||
- [#310](https://github.com/mozilla/send/pull/310) if the download card is pressed, the expired card shows up properly (@abhinadduri)
|
||||
- [#269](https://github.com/mozilla/send/pull/269) refactored ftl file (@abhinadduri)
|
||||
- [#291](https://github.com/mozilla/send/pull/291) added legal page (@dannycoates)
|
||||
- [#307](https://github.com/mozilla/send/pull/307) don't show error page on upload cancel (@dnarcese)
|
||||
- [#299](https://github.com/mozilla/send/pull/299) use CIRCLE_TAG as version.json version if present (@dannycoates)
|
||||
|
||||
### v0.2.1 (2017/07/24 23:34 +00:00)
|
||||
- [#296](https://github.com/mozilla/send/pull/296) restyle delete popup (@dnarcese)
|
||||
- [#295](https://github.com/mozilla/send/pull/295) renamed environment variables to remove P2P_ prefix (@dannycoates)
|
||||
- [#294](https://github.com/mozilla/send/pull/294) dealing with invalid drag and drops (@abhinadduri)
|
||||
- [#297](https://github.com/mozilla/send/pull/297) added environment variable for expire time (@dannycoates)
|
||||
- [#292](https://github.com/mozilla/send/pull/292) Fixes289 (@abhinadduri)
|
||||
- [#288](https://github.com/mozilla/send/pull/288) fix: Don`t allow upload when not on the upload page. (@ericawright)
|
||||
- [#285](https://github.com/mozilla/send/pull/285) added messages for processing phases (@dannycoates)
|
||||
- [#267](https://github.com/mozilla/send/pull/267) make site responsive and add feedback link (@johngruen)
|
||||
- [#286](https://github.com/mozilla/send/pull/286) Update download progress bar color (@pdehaan)
|
||||
- [#281](https://github.com/mozilla/send/pull/281) Stop ESLint from linting the /public/ directory (@pdehaan)
|
||||
- [#280](https://github.com/mozilla/send/pull/280) created /unsupported page and added gcmCompliant to /download page (@dannycoates)
|
||||
- [#279](https://github.com/mozilla/send/pull/279) create separate js bundles for upload/download pages (@dannycoates)
|
||||
- [#268](https://github.com/mozilla/send/pull/268) Testpilot ga (@abhinadduri)
|
||||
|
||||
### v0.2.0 (2017/07/21 19:27 +00:00)
|
||||
- [#266](https://github.com/mozilla/send/pull/266) abort uploads over maxfilesize (@dannycoates)
|
||||
- [#264](https://github.com/mozilla/send/pull/264) Remove duplicate custom metric. (@chuckharmston)
|
||||
- [#259](https://github.com/mozilla/send/pull/259) add alert when uploading multiple files (@dnarcese)
|
||||
- [#262](https://github.com/mozilla/send/pull/262) sync download progress bar with percentage (@dnarcese)
|
||||
- [#258](https://github.com/mozilla/send/pull/258) better sync percent with progress bar (@dnarcese)
|
||||
- [#257](https://github.com/mozilla/send/pull/257) add a dynamic js script for page config (@dannycoates)
|
||||
- [#256](https://github.com/mozilla/send/pull/256) add file size limit message (@dnarcese)
|
||||
- [#253](https://github.com/mozilla/send/pull/253) Add favicon.ico version of the Send logo (@pdehaan)
|
||||
- [#254](https://github.com/mozilla/send/pull/254) Add nsp check to circle ci (@pdehaan)
|
||||
- [#245](https://github.com/mozilla/send/pull/245) Localization (@abhinadduri)
|
||||
- [#252](https://github.com/mozilla/send/pull/252) only allow drag and drop on upload page (@dnarcese)
|
||||
- [#250](https://github.com/mozilla/send/pull/250) make footer not overlap (@dnarcese)
|
||||
- [#251](https://github.com/mozilla/send/pull/251) minify all images (@ericawright)
|
||||
- [#249](https://github.com/mozilla/send/pull/249) change how the file upload box expands (@dnarcese)
|
||||
- [#246](https://github.com/mozilla/send/pull/246) remove P2P references. Fixes #224 (@clouserw)
|
||||
- [#242](https://github.com/mozilla/send/pull/242) Make only icons clickable in file list (@dnarcese)
|
||||
- [#236](https://github.com/mozilla/send/pull/236) add FAQ. Fixes #186 (@clouserw)
|
||||
- [#235](https://github.com/mozilla/send/pull/235) allow send another file link to open in new tab (@dnarcese)
|
||||
- [#234](https://github.com/mozilla/send/pull/234) fix download svg (@dnarcese)
|
||||
- [#232](https://github.com/mozilla/send/pull/232) escape filename in the ui (@dannycoates)
|
||||
- [#226](https://github.com/mozilla/send/pull/226) added functionality to cancel uploads (@abhinadduri)
|
||||
- [#231](https://github.com/mozilla/send/pull/231) move head and html tags to main template (@dnarcese)
|
||||
- [#228](https://github.com/mozilla/send/pull/228) add send logo (@dnarcese)
|
||||
- [#229](https://github.com/mozilla/send/pull/229) change learn more and github links (@dnarcese)
|
||||
- [#201](https://github.com/mozilla/send/pull/201) Adds metrics documentation (closes #5). (@chuckharmston)
|
||||
- [#223](https://github.com/mozilla/send/pull/223) change size of send another file links (@dnarcese)
|
||||
- [#222](https://github.com/mozilla/send/pull/222) add footer (@dnarcese)
|
||||
- [#197](https://github.com/mozilla/send/pull/197) fixes issues 195 and 192 (@abhinadduri)
|
||||
- [#204](https://github.com/mozilla/send/pull/204) added HSTS header (@dannycoates)
|
||||
- [#193](https://github.com/mozilla/send/pull/193) Frontend tests (@abhinadduri)
|
||||
- [#191](https://github.com/mozilla/send/pull/191) New ui! (@dnarcese)
|
||||
|
||||
### v0.1.4 (2017/07/12 18:21 +00:00)
|
||||
- [#189](https://github.com/mozilla/send/pull/189) Add CSP directives (@dannycoates)
|
||||
- [#188](https://github.com/mozilla/send/pull/188) fixes delete button error (@abhinadduri)
|
||||
- [#185](https://github.com/mozilla/send/pull/185) added loading, hashing, and encrypting events for uploader; decryptin… (@abhinadduri)
|
||||
- [#183](https://github.com/mozilla/send/pull/183) rename to 'Send' (@dannycoates)
|
||||
- [#184](https://github.com/mozilla/send/pull/184) Server tests (@abhinadduri)
|
||||
- [#178](https://github.com/mozilla/send/pull/178) fixed issues in branch title (@abhinadduri)
|
||||
- [#177](https://github.com/mozilla/send/pull/177) Gcm compliance (@abhinadduri)
|
||||
- [#106](https://github.com/mozilla/send/pull/106) Gcm (@abhinadduri, @dannycoates)
|
||||
- [#168](https://github.com/mozilla/send/pull/168) Show error page if upload fails (@dnarcese)
|
||||
- [#148](https://github.com/mozilla/send/pull/148) WIP: Add basic contribute.json (@pdehaan)
|
||||
- [#162](https://github.com/mozilla/send/pull/162) Fix dev server URL in README.md file (@pdehaan)
|
||||
- [#167](https://github.com/mozilla/send/pull/167) build docker image with new name (@relud)
|
||||
- [#164](https://github.com/mozilla/send/pull/164) Add word wraps to table (@dnarcese)
|
||||
- [#149](https://github.com/mozilla/send/pull/149) Add robots.txt (@pdehaan)
|
||||
- [#161](https://github.com/mozilla/send/pull/161) Hide table header on empty list (@dnarcese)
|
||||
- [#154](https://github.com/mozilla/send/pull/154) Remove expired uploads (@dnarcese)
|
||||
- [#146](https://github.com/mozilla/send/pull/146) Update README with some more details (@pdehaan)
|
||||
|
||||
### v0.1.2 (2017/06/24 03:38 +00:00)
|
||||
- [#138](https://github.com/mozilla/send/pull/138) remove notLocalHost (@dannycoates)
|
||||
|
||||
### v0.1.0 (2017/06/24 01:24 +00:00)
|
||||
- [#137](https://github.com/mozilla/send/pull/137) refactored docker build (@dannycoates)
|
||||
- [#132](https://github.com/mozilla/send/pull/132) Add /__version__ route (@pdehaan)
|
||||
- [#135](https://github.com/mozilla/send/pull/135) make dockerfile more dockerflowy (@dannycoates)
|
||||
- [#134](https://github.com/mozilla/send/pull/134) Load previous uploads (@dannycoates, @dnarcese)
|
||||
- [#131](https://github.com/mozilla/send/pull/131) added __heartbeat__ (@dannycoates)
|
||||
- [#133](https://github.com/mozilla/send/pull/133) Add LICENSE file (@pdehaan)
|
||||
- [#130](https://github.com/mozilla/send/pull/130) added sentry to server code (@abhinadduri)
|
||||
- [#124](https://github.com/mozilla/send/pull/124) Remove unused [dev]dependencies (@pdehaan)
|
||||
- [#119](https://github.com/mozilla/send/pull/119) Move cross-env to a dep (@pdehaan)
|
||||
- [#123](https://github.com/mozilla/send/pull/123) removed bitly integration (@abhinadduri)
|
||||
- [#122](https://github.com/mozilla/send/pull/122) fix docker build (@dannycoates)
|
||||
- [#121](https://github.com/mozilla/send/pull/121) added docker service to circle.yml (@dannycoates)
|
||||
- [#120](https://github.com/mozilla/send/pull/120) added sentry (@abhinadduri)
|
||||
- [#118](https://github.com/mozilla/send/pull/118) change docker image name and add builds for tags (@relud)
|
||||
- [#116](https://github.com/mozilla/send/pull/116) add /__lbheartbeat__ endpoint (@relud)
|
||||
- [#79](https://github.com/mozilla/send/pull/79) Optimize/minimize bundle.js for production (@pdehaan)
|
||||
- [#104](https://github.com/mozilla/send/pull/104) Fix a bunch of ESLint and HTMLLint errors (@pdehaan)
|
||||
- [#105](https://github.com/mozilla/send/pull/105) Progress bars (@dnarcese)
|
||||
- [#111](https://github.com/mozilla/send/pull/111) added in anonmyized ip google analytics (@abhinadduri)
|
||||
- [#110](https://github.com/mozilla/send/pull/110) added notifications (@abhinadduri)
|
||||
- [#103](https://github.com/mozilla/send/pull/103) added Dockerfile (@dannycoates)
|
||||
- [#100](https://github.com/mozilla/send/pull/100) Added Helmet Middleware (@abhinadduri)
|
||||
- [#99](https://github.com/mozilla/send/pull/99) Testing (@abhinadduri)
|
||||
- [#77](https://github.com/mozilla/send/pull/77) Fix the linter errors (@pdehaan)
|
||||
- [#54](https://github.com/mozilla/send/pull/54) Adding basic ESLint config (@pdehaan)
|
||||
- [#71](https://github.com/mozilla/send/pull/71) Drag & drop (@dnarcese)
|
||||
- [#72](https://github.com/mozilla/send/pull/72) Logging (@abhinadduri, @dannycoates)
|
||||
- [#45](https://github.com/mozilla/send/pull/45) S3 integration (@abhinadduri, @dannycoates)
|
||||
- [#46](https://github.com/mozilla/send/pull/46) Download page and share link UI (@dnarcese)
|
||||
- [#41](https://github.com/mozilla/send/pull/41) Added upload page and file list UI (@dnarcese)
|
||||
- [#40](https://github.com/mozilla/send/pull/40) Tweak the package.json file (@pdehaan)
|
||||
- [#43](https://github.com/mozilla/send/pull/43) added return (@abhinadduri)
|
||||
- [#42](https://github.com/mozilla/send/pull/42) changed to handle 404 during download, also removing progress listene… (@abhinadduri)
|
||||
- [#39](https://github.com/mozilla/send/pull/39) Refactor riff (@abhinadduri, @dannycoates)
|
||||
- [#36](https://github.com/mozilla/send/pull/36) added prettier for js formatting (@dannycoates)
|
||||
- [#28](https://github.com/mozilla/send/pull/28) Added a UI for the uploader end, made stylistic changes, implemented deleting (@abhinadduri)
|
||||
- [#25](https://github.com/mozilla/send/pull/25) Changed naming for some pages, no longer stores files by name on server (@abhinadduri)
|
||||
92
CONTRIBUTORS
Normal file
@@ -0,0 +1,92 @@
|
||||
Abhinav Adduri
|
||||
Alexander Slovesnik
|
||||
Amin Mahmudian
|
||||
Andreas Pettersson
|
||||
Arash Mousavi
|
||||
Balázs Meskó
|
||||
Belayet Hossain
|
||||
Bjørn I
|
||||
Boopesh Mahendran
|
||||
Chuck Harmston
|
||||
Cláudio Esperança
|
||||
Cynthia Pereira
|
||||
Daniel Thorn
|
||||
Daniela Arcese
|
||||
Danny Coates
|
||||
Emin Mastizada
|
||||
Enol
|
||||
Erica
|
||||
Erica Wright
|
||||
Fjoerfoks
|
||||
Francesco Lodolo
|
||||
Francesco Lodolo [:flod]
|
||||
Gautam krishna.R
|
||||
Håvar Henriksen
|
||||
Jae Hyeon Park
|
||||
Jakub Rychlý
|
||||
Jamie
|
||||
Jim Spentzos
|
||||
Johann-S
|
||||
John Gruen
|
||||
Jon Vadillo
|
||||
Jordi Serratosa
|
||||
Juraj Cigáň
|
||||
Kohei Yoshino
|
||||
Lan Glad
|
||||
Luna Jernberg
|
||||
Marcelo Poli
|
||||
Marco Aurélio
|
||||
Mark Liang
|
||||
Matjaž Horvat
|
||||
Maykon Chagas
|
||||
Michael Köhler
|
||||
Michael Wolf
|
||||
Michal Stanke
|
||||
Michal Vašíček
|
||||
Moḥend Belqasem
|
||||
Nicholas Skinsacos
|
||||
Peter deHaan
|
||||
Pierre Neter
|
||||
Pin-guang Chen
|
||||
Rhoslyn Prys
|
||||
Rizky Ariestiyansyah
|
||||
Roberto Alvarado
|
||||
Rodrigo
|
||||
Rok Žerdin
|
||||
Sahithi
|
||||
Sairam Raavi
|
||||
Sandro
|
||||
Schieck :)
|
||||
Selim Şumlu
|
||||
Slimane Amiri
|
||||
Théo Chevalier
|
||||
Tomáš Zelina
|
||||
Ton
|
||||
Tymur Faradzhev
|
||||
Varghese Thomas
|
||||
Victor Bychek
|
||||
Weihang Lo
|
||||
Wil Clouser
|
||||
YFdyh000
|
||||
You-Wen Liang (Mark)
|
||||
alex_mayorga
|
||||
ariestiyansyah
|
||||
avelper
|
||||
dgadelha
|
||||
ehuggett
|
||||
eljuno
|
||||
erdem cobanoglu
|
||||
gautamkrishnar
|
||||
goofy
|
||||
hi
|
||||
jesferman1993
|
||||
josotrix
|
||||
kenrick95
|
||||
manxmensch
|
||||
ravmn
|
||||
reza.habibi2008
|
||||
siparon
|
||||
skystar-p
|
||||
xcffl
|
||||
Μιχάλης
|
||||
Марко Костић (Marko Kostić)
|
||||
@@ -1,5 +1,6 @@
|
||||
FROM node:8-alpine
|
||||
|
||||
RUN apk add --no-cache git
|
||||
RUN addgroup -S -g 10001 app && adduser -S -D -G app -u 10001 app
|
||||
COPY . /app
|
||||
RUN chown -R app /app
|
||||
@@ -11,4 +12,4 @@ RUN npm install --production && npm cache clean --force
|
||||
ENV PORT=1443
|
||||
EXPOSE $PORT
|
||||
|
||||
CMD ["npm", "start"]
|
||||
CMD ["npm", "run", "prod"]
|
||||
|
||||
85
README.md
@@ -1,3 +1,82 @@
|
||||
* Install the redis server if not installed.
|
||||
* To run the project, make sure you have a redis server running locally: redis-server /usr/local/etc/redis.conf
|
||||
* Follow instructions inside the console on the browser.
|
||||
# Firefox Send
|
||||
|
||||
[](https://circleci.com/gh/mozilla/send)
|
||||
[](https://testpilot.firefox.com/experiments/send)
|
||||
|
||||
**Docs:** [Docker](docs/docker.md), [Metrics](docs/metrics.md)
|
||||
|
||||
---
|
||||
|
||||
## What it does
|
||||
|
||||
A file sharing experiment which allows you to send encrypted files to other users.
|
||||
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
- [Node.js 8.2+](https://nodejs.org/)
|
||||
- [Redis server](https://redis.io/) (optional for development)
|
||||
- [AWS S3](https://aws.amazon.com/s3/) or compatible service. (optional)
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
To start an ephemeral development server run:
|
||||
|
||||
```sh
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
Then browse to http://localhost:8080
|
||||
|
||||
---
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Description |
|
||||
|------------------|-------------|
|
||||
| `npm run format` | Formats the frontend and server code using **prettier**.
|
||||
| `npm run lint` | Lints the CSS and JavaScript code.
|
||||
| `npm test` | Runs the suite of mocha tests.
|
||||
| `npm start` | Runs the server in development configuration.
|
||||
| `npm run build` | Builds the production assets.
|
||||
| `npm run prod` | Runs the server in production configuration.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
The server is configured with environment variables. See [server/config.js](server/config.js) for all options and [docs/docker.md](docs/docker.md) for examples.
|
||||
|
||||
---
|
||||
|
||||
## Localization
|
||||
|
||||
Firefox Send localization is managed via [Pontoon](https://pontoon.mozilla.org/projects/test-pilot-firefox-send/), not direct pull requests to the repository. If you want to fix a typo, add a new language, or simply know more about localization, please get in touch with the [existing localization team](https://pontoon.mozilla.org/teams/) for your language, or Mozilla’s [l10n-drivers](https://wiki.mozilla.org/L10n:Mozilla_Team#Mozilla_Corporation) for guidance.
|
||||
|
||||
---
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are always welcome! Feel free to check out the list of ["good first bugs"](https://github.com/mozilla/send/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+bug%22).
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
| ENVIRONMENT | URL
|
||||
|-------------|-----
|
||||
| Production | <https://send.firefox.com/>
|
||||
| Stage | <https://send.stage.mozaws.net/>
|
||||
| Development | <https://send.dev.mozaws.net/>
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
[Mozilla Public License Version 2.0](LICENSE)
|
||||
|
||||
---
|
||||
|
||||
9
app/.eslintrc.yml
Normal file
@@ -0,0 +1,9 @@
|
||||
env:
|
||||
browser: true
|
||||
node: true
|
||||
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
|
||||
rules:
|
||||
node/no-unsupported-features: off
|
||||
24
app/dragManager.js
Normal file
@@ -0,0 +1,24 @@
|
||||
export default function(state, emitter) {
|
||||
emitter.on('DOMContentLoaded', () => {
|
||||
document.body.addEventListener('dragover', event => {
|
||||
if (state.route === '/') {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
document.body.addEventListener('drop', event => {
|
||||
if (state.route === '/' && !state.transfer) {
|
||||
event.preventDefault();
|
||||
document.querySelector('.upload-window').classList.remove('ondrag');
|
||||
const target = event.dataTransfer;
|
||||
if (target.files.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (target.files.length > 1 || target.files[0].size === 0) {
|
||||
return alert(state.translate('uploadPageMultipleFilesAlert'));
|
||||
}
|
||||
const file = target.files[0];
|
||||
emitter.emit('upload', { file, type: 'drop' });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
76
app/experiments.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import hash from 'string-hash';
|
||||
|
||||
const experiments = {
|
||||
'5YHCzn2CQTmBwWwTmZupBA': {
|
||||
id: '5YHCzn2CQTmBwWwTmZupBA',
|
||||
run: function(variant, state, emitter) {
|
||||
state.experiment = {
|
||||
xid: this.id,
|
||||
xvar: variant
|
||||
};
|
||||
// Beefy UI
|
||||
if (variant === 1) {
|
||||
state.config.uploadWindowStyle = 'upload-window upload-window-b';
|
||||
state.config.uploadButtonStyle = 'btn browse browse-b';
|
||||
} else {
|
||||
state.config.uploadWindowStyle = 'upload-window';
|
||||
state.config.uploadButtonStyle = 'btn browse';
|
||||
}
|
||||
emitter.emit('render');
|
||||
},
|
||||
eligible: function(state) {
|
||||
return this.luckyNumber(state) >= 0.5;
|
||||
},
|
||||
variant: function(state) {
|
||||
return this.luckyNumber(state) < 0.75 ? 0 : 1;
|
||||
},
|
||||
luckyNumber: function(state) {
|
||||
return luckyNumber(
|
||||
`${this.id}:${state.storage.get('testpilot_ga__cid')}`
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Returns a number between 0 and 1
|
||||
function luckyNumber(str) {
|
||||
return hash(str) / 0xffffffff;
|
||||
}
|
||||
|
||||
function checkExperiments(state, emitter) {
|
||||
const all = Object.keys(experiments);
|
||||
const id = all.find(id => experiments[id].eligible(state));
|
||||
if (id) {
|
||||
const variant = experiments[id].variant(state);
|
||||
state.storage.enroll(id, variant);
|
||||
experiments[id].run(variant, state, emitter);
|
||||
}
|
||||
}
|
||||
|
||||
export default function initialize(state, emitter) {
|
||||
emitter.on('DOMContentLoaded', () => {
|
||||
const xp = experiments[state.query.x];
|
||||
if (xp) {
|
||||
xp.run(+state.query.v, state, emitter);
|
||||
}
|
||||
});
|
||||
|
||||
if (!state.storage.get('testpilot_ga__cid')) {
|
||||
// first ever visit. check again after cid is assigned.
|
||||
emitter.on('DOMContentLoaded', () => {
|
||||
checkExperiments(state, emitter);
|
||||
});
|
||||
} else {
|
||||
const enrolled = state.storage.enrolled;
|
||||
enrolled.forEach(([id, variant]) => {
|
||||
const xp = experiments[id];
|
||||
if (xp) {
|
||||
xp.run(variant, state, emitter);
|
||||
}
|
||||
});
|
||||
// single experiment per session for now
|
||||
if (enrolled.length === 0) {
|
||||
checkExperiments(state, emitter);
|
||||
}
|
||||
}
|
||||
}
|
||||
217
app/fileManager.js
Normal file
@@ -0,0 +1,217 @@
|
||||
/* global EXPIRE_SECONDS */
|
||||
import FileSender from './fileSender';
|
||||
import FileReceiver from './fileReceiver';
|
||||
import { copyToClipboard, delay, fadeOut, percent } from './utils';
|
||||
import * as metrics from './metrics';
|
||||
|
||||
function saveFile(file) {
|
||||
const dataView = new DataView(file.plaintext);
|
||||
const blob = new Blob([dataView], { type: file.type });
|
||||
const downloadUrl = URL.createObjectURL(blob);
|
||||
|
||||
if (window.navigator.msSaveBlob) {
|
||||
return window.navigator.msSaveBlob(blob, file.name);
|
||||
}
|
||||
const a = document.createElement('a');
|
||||
a.href = downloadUrl;
|
||||
a.download = file.name;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
URL.revokeObjectURL(downloadUrl);
|
||||
}
|
||||
|
||||
function openLinksInNewTab(links, should = true) {
|
||||
links = links || Array.from(document.querySelectorAll('a:not([target])'));
|
||||
if (should) {
|
||||
links.forEach(l => {
|
||||
l.setAttribute('target', '_blank');
|
||||
l.setAttribute('rel', 'noopener noreferrer');
|
||||
});
|
||||
} else {
|
||||
links.forEach(l => {
|
||||
l.removeAttribute('target');
|
||||
l.removeAttribute('rel');
|
||||
});
|
||||
}
|
||||
return links;
|
||||
}
|
||||
|
||||
function exists(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
|
||||
resolve(xhr.status === 200);
|
||||
}
|
||||
};
|
||||
xhr.onerror = () => resolve(false);
|
||||
xhr.ontimeout = () => resolve(false);
|
||||
xhr.open('get', '/api/exists/' + id);
|
||||
xhr.timeout = 2000;
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
export default function(state, emitter) {
|
||||
let lastRender = 0;
|
||||
let updateTitle = false;
|
||||
|
||||
function render() {
|
||||
emitter.emit('render');
|
||||
}
|
||||
|
||||
async function checkFiles() {
|
||||
const files = state.storage.files;
|
||||
let rerender = false;
|
||||
for (const file of files) {
|
||||
const ok = await exists(file.id);
|
||||
if (!ok) {
|
||||
state.storage.remove(file.id);
|
||||
rerender = true;
|
||||
}
|
||||
}
|
||||
if (rerender) {
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
function updateProgress() {
|
||||
if (updateTitle) {
|
||||
emitter.emit('DOMTitleChange', percent(state.transfer.progressRatio));
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
emitter.on('DOMContentLoaded', () => {
|
||||
document.addEventListener('blur', () => (updateTitle = true));
|
||||
document.addEventListener('focus', () => {
|
||||
updateTitle = false;
|
||||
emitter.emit('DOMTitleChange', 'Firefox Send');
|
||||
});
|
||||
checkFiles();
|
||||
});
|
||||
|
||||
emitter.on('navigate', checkFiles);
|
||||
|
||||
emitter.on('render', () => {
|
||||
lastRender = Date.now();
|
||||
});
|
||||
|
||||
emitter.on('delete', async ({ file, location }) => {
|
||||
try {
|
||||
metrics.deletedUpload({
|
||||
size: file.size,
|
||||
time: file.time,
|
||||
speed: file.speed,
|
||||
type: file.type,
|
||||
ttl: file.expiresAt - Date.now(),
|
||||
location
|
||||
});
|
||||
state.storage.remove(file.id);
|
||||
await FileSender.delete(file.id, file.deleteToken);
|
||||
} catch (e) {
|
||||
state.raven.captureException(e);
|
||||
}
|
||||
state.fileInfo = null;
|
||||
});
|
||||
|
||||
emitter.on('cancel', () => {
|
||||
state.transfer.cancel();
|
||||
});
|
||||
|
||||
emitter.on('upload', async ({ file, type }) => {
|
||||
const size = file.size;
|
||||
const sender = new FileSender(file);
|
||||
sender.on('progress', updateProgress);
|
||||
sender.on('encrypting', render);
|
||||
state.transfer = sender;
|
||||
render();
|
||||
const links = openLinksInNewTab();
|
||||
await delay(200);
|
||||
try {
|
||||
const start = Date.now();
|
||||
metrics.startedUpload({ size, type });
|
||||
const info = await sender.upload();
|
||||
const time = Date.now() - start;
|
||||
const speed = size / (time / 1000);
|
||||
metrics.completedUpload({ size, time, speed, type });
|
||||
await delay(1000);
|
||||
await fadeOut('upload-progress');
|
||||
info.name = file.name;
|
||||
info.size = size;
|
||||
info.type = type;
|
||||
info.time = time;
|
||||
info.speed = speed;
|
||||
info.createdAt = Date.now();
|
||||
info.url = `${info.url}#${info.secretKey}`;
|
||||
info.expiresAt = Date.now() + EXPIRE_SECONDS * 1000;
|
||||
state.fileInfo = info;
|
||||
state.storage.addFile(state.fileInfo);
|
||||
openLinksInNewTab(links, false);
|
||||
state.transfer = null;
|
||||
state.storage.totalUploads += 1;
|
||||
emitter.emit('pushState', `/share/${info.id}`);
|
||||
} catch (err) {
|
||||
state.transfer = null;
|
||||
if (err.message === '0') {
|
||||
//cancelled. do nothing
|
||||
metrics.cancelledUpload({ size, type });
|
||||
return render();
|
||||
}
|
||||
state.raven.captureException(err);
|
||||
metrics.stoppedUpload({ size, type, err });
|
||||
emitter.emit('replaceState', '/error');
|
||||
}
|
||||
});
|
||||
|
||||
emitter.on('download', async file => {
|
||||
const size = file.size;
|
||||
const url = `/api/download/${file.id}`;
|
||||
const receiver = new FileReceiver(url, file.key);
|
||||
receiver.on('progress', updateProgress);
|
||||
receiver.on('decrypting', render);
|
||||
state.transfer = receiver;
|
||||
const links = openLinksInNewTab();
|
||||
render();
|
||||
try {
|
||||
const start = Date.now();
|
||||
metrics.startedDownload({ size: file.size, ttl: file.ttl });
|
||||
const f = await receiver.download();
|
||||
const time = Date.now() - start;
|
||||
const speed = size / (time / 1000);
|
||||
await delay(1000);
|
||||
await fadeOut('download-progress');
|
||||
saveFile(f);
|
||||
state.storage.totalDownloads += 1;
|
||||
metrics.completedDownload({ size, time, speed });
|
||||
emitter.emit('pushState', '/completed');
|
||||
} catch (err) {
|
||||
// TODO cancelled download
|
||||
const location = err.message === 'notfound' ? '/404' : '/error';
|
||||
if (location === '/error') {
|
||||
state.raven.captureException(err);
|
||||
metrics.stoppedDownload({ size, err });
|
||||
}
|
||||
emitter.emit('replaceState', location);
|
||||
} finally {
|
||||
state.transfer = null;
|
||||
openLinksInNewTab(links, false);
|
||||
}
|
||||
});
|
||||
|
||||
emitter.on('copy', ({ url, location }) => {
|
||||
copyToClipboard(url);
|
||||
metrics.copiedLink({ location });
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
// poll for rerendering the file list countdown timers
|
||||
if (
|
||||
state.route === '/' &&
|
||||
state.storage.files.length > 0 &&
|
||||
Date.now() - lastRender > 30000
|
||||
) {
|
||||
render();
|
||||
}
|
||||
}, 60000);
|
||||
}
|
||||
100
app/fileReceiver.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import Nanobus from 'nanobus';
|
||||
import { hexToArray, bytes } from './utils';
|
||||
|
||||
export default class FileReceiver extends Nanobus {
|
||||
constructor(url, k) {
|
||||
super('FileReceiver');
|
||||
this.key = window.crypto.subtle.importKey(
|
||||
'jwk',
|
||||
{
|
||||
k,
|
||||
kty: 'oct',
|
||||
alg: 'A128GCM',
|
||||
ext: true
|
||||
},
|
||||
{
|
||||
name: 'AES-GCM'
|
||||
},
|
||||
false,
|
||||
['decrypt']
|
||||
);
|
||||
this.url = url;
|
||||
this.msg = 'fileSizeProgress';
|
||||
this.progress = [0, 1];
|
||||
}
|
||||
|
||||
get progressRatio() {
|
||||
return this.progress[0] / this.progress[1];
|
||||
}
|
||||
|
||||
get sizes() {
|
||||
return {
|
||||
partialSize: bytes(this.progress[0]),
|
||||
totalSize: bytes(this.progress[1])
|
||||
};
|
||||
}
|
||||
|
||||
cancel() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
downloadFile() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.onprogress = event => {
|
||||
if (event.lengthComputable && event.target.status !== 404) {
|
||||
this.progress = [event.loaded, event.total];
|
||||
this.emit('progress', this.progress);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onload = function(event) {
|
||||
if (xhr.status === 404) {
|
||||
reject(new Error('notfound'));
|
||||
return;
|
||||
}
|
||||
|
||||
const blob = new Blob([this.response]);
|
||||
const meta = JSON.parse(xhr.getResponseHeader('X-File-Metadata'));
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = function() {
|
||||
resolve({
|
||||
data: this.result,
|
||||
name: meta.filename,
|
||||
type: meta.mimeType,
|
||||
iv: meta.id
|
||||
});
|
||||
};
|
||||
|
||||
fileReader.readAsArrayBuffer(blob);
|
||||
};
|
||||
|
||||
xhr.open('get', this.url);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
async download() {
|
||||
const key = await this.key;
|
||||
const file = await this.downloadFile();
|
||||
this.msg = 'decryptingFile';
|
||||
this.emit('decrypting');
|
||||
const plaintext = await window.crypto.subtle.decrypt(
|
||||
{
|
||||
name: 'AES-GCM',
|
||||
iv: hexToArray(file.iv),
|
||||
tagLength: 128
|
||||
},
|
||||
key,
|
||||
file.data
|
||||
);
|
||||
this.msg = 'downloadFinish';
|
||||
return {
|
||||
plaintext,
|
||||
name: decodeURIComponent(file.name),
|
||||
type: file.type
|
||||
};
|
||||
}
|
||||
}
|
||||
146
app/fileSender.js
Normal file
@@ -0,0 +1,146 @@
|
||||
import Nanobus from 'nanobus';
|
||||
import { arrayToHex, bytes } from './utils';
|
||||
|
||||
export default class FileSender extends Nanobus {
|
||||
constructor(file) {
|
||||
super('FileSender');
|
||||
this.file = file;
|
||||
this.msg = 'importingFile';
|
||||
this.progress = [0, 1];
|
||||
this.cancelled = false;
|
||||
this.iv = window.crypto.getRandomValues(new Uint8Array(12));
|
||||
this.uploadXHR = new XMLHttpRequest();
|
||||
this.key = window.crypto.subtle.generateKey(
|
||||
{
|
||||
name: 'AES-GCM',
|
||||
length: 128
|
||||
},
|
||||
true,
|
||||
['encrypt']
|
||||
);
|
||||
}
|
||||
|
||||
static delete(id, token) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!id || !token) {
|
||||
return reject();
|
||||
}
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', `/api/delete/${id}`);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(JSON.stringify({ delete_token: token }));
|
||||
});
|
||||
}
|
||||
|
||||
get progressRatio() {
|
||||
return this.progress[0] / this.progress[1];
|
||||
}
|
||||
|
||||
get sizes() {
|
||||
return {
|
||||
partialSize: bytes(this.progress[0]),
|
||||
totalSize: bytes(this.progress[1])
|
||||
};
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.cancelled = true;
|
||||
if (this.msg === 'fileSizeProgress') {
|
||||
this.uploadXHR.abort();
|
||||
}
|
||||
}
|
||||
|
||||
readFile() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsArrayBuffer(this.file);
|
||||
reader.onload = function(event) {
|
||||
const plaintext = new Uint8Array(this.result);
|
||||
resolve(plaintext);
|
||||
};
|
||||
reader.onerror = function(err) {
|
||||
reject(err);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
uploadFile(encrypted, keydata) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = this.file;
|
||||
const id = arrayToHex(this.iv);
|
||||
const dataView = new DataView(encrypted);
|
||||
const blob = new Blob([dataView], { type: file.type });
|
||||
const fd = new FormData();
|
||||
fd.append('data', blob, file.name);
|
||||
|
||||
const xhr = this.uploadXHR;
|
||||
|
||||
xhr.upload.addEventListener('progress', e => {
|
||||
if (e.lengthComputable) {
|
||||
this.progress = [e.loaded, e.total];
|
||||
this.emit('progress', this.progress);
|
||||
}
|
||||
});
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
if (xhr.status === 200) {
|
||||
this.progress = [1, 1];
|
||||
this.msg = 'notifyUploadDone';
|
||||
const responseObj = JSON.parse(xhr.responseText);
|
||||
return resolve({
|
||||
url: responseObj.url,
|
||||
id: responseObj.id,
|
||||
secretKey: keydata.k,
|
||||
deleteToken: responseObj.delete
|
||||
});
|
||||
}
|
||||
this.msg = 'errorPageHeader';
|
||||
reject(new Error(xhr.status));
|
||||
}
|
||||
};
|
||||
|
||||
xhr.open('post', '/api/upload', true);
|
||||
xhr.setRequestHeader(
|
||||
'X-File-Metadata',
|
||||
JSON.stringify({
|
||||
id: id,
|
||||
filename: encodeURIComponent(file.name)
|
||||
})
|
||||
);
|
||||
xhr.send(fd);
|
||||
this.msg = 'fileSizeProgress';
|
||||
});
|
||||
}
|
||||
|
||||
async upload() {
|
||||
const key = await this.key;
|
||||
const plaintext = await this.readFile();
|
||||
if (this.cancelled) {
|
||||
throw new Error(0);
|
||||
}
|
||||
this.msg = 'encryptingFile';
|
||||
this.emit('encrypting');
|
||||
const encrypted = await window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: 'AES-GCM',
|
||||
iv: this.iv,
|
||||
tagLength: 128
|
||||
},
|
||||
key,
|
||||
plaintext
|
||||
);
|
||||
if (this.cancelled) {
|
||||
throw new Error(0);
|
||||
}
|
||||
const keydata = await window.crypto.subtle.exportKey('jwk', key);
|
||||
return this.uploadFile(encrypted, keydata);
|
||||
}
|
||||
}
|
||||
51
app/main.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import app from './routes';
|
||||
import log from 'choo-log';
|
||||
import locale from '../common/locales';
|
||||
import fileManager from './fileManager';
|
||||
import dragManager from './dragManager';
|
||||
import { canHasSend } from './utils';
|
||||
import assets from '../common/assets';
|
||||
import storage from './storage';
|
||||
import metrics from './metrics';
|
||||
import experiments from './experiments';
|
||||
import Raven from 'raven-js';
|
||||
|
||||
if (navigator.doNotTrack !== '1' && window.RAVEN_CONFIG) {
|
||||
Raven.config(window.SENTRY_ID, window.RAVEN_CONFIG).install();
|
||||
}
|
||||
|
||||
app.use(log());
|
||||
|
||||
app.use((state, emitter) => {
|
||||
// init state
|
||||
state.transfer = null;
|
||||
state.fileInfo = null;
|
||||
state.translate = locale.getTranslator();
|
||||
state.storage = storage;
|
||||
state.raven = Raven;
|
||||
state.config = {
|
||||
uploadWindowStyle: 'upload-window',
|
||||
uploadButtonStyle: 'browse btn'
|
||||
};
|
||||
emitter.on('DOMContentLoaded', async () => {
|
||||
if (
|
||||
/firefox/i.test(navigator.userAgent) &&
|
||||
parseInt(navigator.userAgent.match(/firefox\/*([^\n\r]*)\./i)[1], 10) <=
|
||||
49
|
||||
) {
|
||||
return emitter.emit('replaceState', '/unsupported/outdated');
|
||||
}
|
||||
const ok = await canHasSend(assets.get('cryptofill.js'));
|
||||
if (!ok) {
|
||||
const reason = /firefox/i.test(navigator.userAgent) ? 'outdated' : 'gcm';
|
||||
emitter.emit('replaceState', `/unsupported/${reason}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.use(metrics);
|
||||
app.use(fileManager);
|
||||
app.use(dragManager);
|
||||
app.use(experiments);
|
||||
|
||||
app.mount('#page-one');
|
||||
267
app/metrics.js
Normal file
@@ -0,0 +1,267 @@
|
||||
import testPilotGA from 'testpilot-ga/src/TestPilotGA';
|
||||
import storage from './storage';
|
||||
|
||||
let hasLocalStorage = false;
|
||||
try {
|
||||
hasLocalStorage = typeof localStorage !== 'undefined';
|
||||
} catch (e) {
|
||||
// when disabled, any mention of localStorage throws an error
|
||||
}
|
||||
|
||||
const analytics = new testPilotGA({
|
||||
an: 'Firefox Send',
|
||||
ds: 'web',
|
||||
tid: window.GOOGLE_ANALYTICS_ID
|
||||
});
|
||||
|
||||
let appState = null;
|
||||
let experiment = null;
|
||||
|
||||
export default function initialize(state, emitter) {
|
||||
appState = state;
|
||||
emitter.on('DOMContentLoaded', () => {
|
||||
addExitHandlers();
|
||||
experiment = storage.enrolled[0];
|
||||
sendEvent(category(), 'visit', {
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length,
|
||||
cm7: storage.totalDownloads
|
||||
});
|
||||
//TODO restart handlers... somewhere
|
||||
});
|
||||
}
|
||||
|
||||
function category() {
|
||||
switch (appState.route) {
|
||||
case '/':
|
||||
case '/share/:id':
|
||||
return 'sender';
|
||||
case '/download/:id/:key':
|
||||
case '/download/:id':
|
||||
case '/completed':
|
||||
return 'recipient';
|
||||
default:
|
||||
return 'other';
|
||||
}
|
||||
}
|
||||
|
||||
function sendEvent() {
|
||||
const args = Array.from(arguments);
|
||||
if (experiment && args[2]) {
|
||||
args[2].xid = experiment[0];
|
||||
args[2].xvar = experiment[1];
|
||||
}
|
||||
return (
|
||||
hasLocalStorage && analytics.sendEvent.apply(analytics, args).catch(() => 0)
|
||||
);
|
||||
}
|
||||
|
||||
function urlToMetric(url) {
|
||||
switch (url) {
|
||||
case 'https://www.mozilla.org/':
|
||||
return 'mozilla';
|
||||
case 'https://www.mozilla.org/about/legal':
|
||||
return 'legal';
|
||||
case 'https://testpilot.firefox.com/about':
|
||||
return 'about';
|
||||
case 'https://testpilot.firefox.com/privacy':
|
||||
return 'privacy';
|
||||
case 'https://testpilot.firefox.com/terms':
|
||||
return 'terms';
|
||||
case 'https://www.mozilla.org/privacy/websites/#cookies':
|
||||
return 'cookies';
|
||||
case 'https://github.com/mozilla/send':
|
||||
return 'github';
|
||||
case 'https://twitter.com/FxTestPilot':
|
||||
return 'twitter';
|
||||
case 'https://www.mozilla.org/firefox/new/?scene=2':
|
||||
return 'download-firefox';
|
||||
case 'https://qsurvey.mozilla.com/s3/txp-firefox-send':
|
||||
return 'survey';
|
||||
case 'https://testpilot.firefox.com/':
|
||||
case 'https://testpilot.firefox.com/experiments/send':
|
||||
return 'testpilot';
|
||||
default:
|
||||
return 'other';
|
||||
}
|
||||
}
|
||||
|
||||
function setReferrer(state) {
|
||||
if (category() === 'sender') {
|
||||
if (state) {
|
||||
storage.referrer = `${state}-upload`;
|
||||
}
|
||||
} else if (category() === 'recipient') {
|
||||
if (state) {
|
||||
storage.referrer = `${state}-download`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function externalReferrer() {
|
||||
if (/^https:\/\/testpilot\.firefox\.com/.test(document.referrer)) {
|
||||
return 'testpilot';
|
||||
}
|
||||
return 'external';
|
||||
}
|
||||
|
||||
function takeReferrer() {
|
||||
const referrer = storage.referrer || externalReferrer();
|
||||
storage.referrer = null;
|
||||
return referrer;
|
||||
}
|
||||
|
||||
function startedUpload(params) {
|
||||
return sendEvent('sender', 'upload-started', {
|
||||
cm1: params.size,
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length + 1,
|
||||
cm7: storage.totalDownloads,
|
||||
cd1: params.type,
|
||||
cd5: takeReferrer()
|
||||
});
|
||||
}
|
||||
|
||||
function cancelledUpload(params) {
|
||||
setReferrer('cancelled');
|
||||
return sendEvent('sender', 'upload-stopped', {
|
||||
cm1: params.size,
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length,
|
||||
cm7: storage.totalDownloads,
|
||||
cd1: params.type,
|
||||
cd2: 'cancelled'
|
||||
});
|
||||
}
|
||||
|
||||
function completedUpload(params) {
|
||||
return sendEvent('sender', 'upload-stopped', {
|
||||
cm1: params.size,
|
||||
cm2: params.time,
|
||||
cm3: params.speed,
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length,
|
||||
cm7: storage.totalDownloads,
|
||||
cd1: params.type,
|
||||
cd2: 'completed'
|
||||
});
|
||||
}
|
||||
|
||||
function startedDownload(params) {
|
||||
return sendEvent('recipient', 'download-started', {
|
||||
cm1: params.size,
|
||||
cm4: params.ttl,
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length,
|
||||
cm7: storage.totalDownloads
|
||||
});
|
||||
}
|
||||
|
||||
function stoppedDownload(params) {
|
||||
return sendEvent('recipient', 'download-stopped', {
|
||||
cm1: params.size,
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length,
|
||||
cm7: storage.totalDownloads,
|
||||
cd2: 'errored',
|
||||
cd6: params.err
|
||||
});
|
||||
}
|
||||
|
||||
function cancelledDownload(params) {
|
||||
setReferrer('cancelled');
|
||||
return sendEvent('recipient', 'download-stopped', {
|
||||
cm1: params.size,
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length,
|
||||
cm7: storage.totalDownloads,
|
||||
cd2: 'cancelled'
|
||||
});
|
||||
}
|
||||
|
||||
function stoppedUpload(params) {
|
||||
return sendEvent('sender', 'upload-stopped', {
|
||||
cm1: params.size,
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length,
|
||||
cm7: storage.totalDownloads,
|
||||
cd1: params.type,
|
||||
cd2: 'errored',
|
||||
cd6: params.err
|
||||
});
|
||||
}
|
||||
|
||||
function completedDownload(params) {
|
||||
return sendEvent('recipient', 'download-stopped', {
|
||||
cm1: params.size,
|
||||
cm2: params.time,
|
||||
cm3: params.speed,
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length,
|
||||
cm7: storage.totalDownloads,
|
||||
cd2: 'completed'
|
||||
});
|
||||
}
|
||||
|
||||
function deletedUpload(params) {
|
||||
return sendEvent(category(), 'upload-deleted', {
|
||||
cm1: params.size,
|
||||
cm2: params.time,
|
||||
cm3: params.speed,
|
||||
cm4: params.ttl,
|
||||
cm5: storage.totalUploads,
|
||||
cm6: storage.files.length,
|
||||
cm7: storage.totalDownloads,
|
||||
cd1: params.type,
|
||||
cd4: params.location
|
||||
});
|
||||
}
|
||||
|
||||
function unsupported(params) {
|
||||
return sendEvent(category(), 'unsupported', {
|
||||
cd6: params.err
|
||||
});
|
||||
}
|
||||
|
||||
function copiedLink(params) {
|
||||
return sendEvent('sender', 'copied', {
|
||||
cd4: params.location
|
||||
});
|
||||
}
|
||||
|
||||
function exitEvent(target) {
|
||||
return sendEvent(category(), 'exited', {
|
||||
cd3: urlToMetric(target.currentTarget.href)
|
||||
});
|
||||
}
|
||||
|
||||
function addExitHandlers() {
|
||||
const links = Array.from(document.querySelectorAll('a'));
|
||||
links.forEach(l => {
|
||||
if (/^http/.test(l.getAttribute('href'))) {
|
||||
l.addEventListener('click', exitEvent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function restart(state) {
|
||||
setReferrer(state);
|
||||
return sendEvent(category(), 'restarted', {
|
||||
cd2: state
|
||||
});
|
||||
}
|
||||
|
||||
export {
|
||||
copiedLink,
|
||||
startedUpload,
|
||||
cancelledUpload,
|
||||
stoppedUpload,
|
||||
completedUpload,
|
||||
deletedUpload,
|
||||
startedDownload,
|
||||
cancelledDownload,
|
||||
stoppedDownload,
|
||||
completedDownload,
|
||||
restart,
|
||||
unsupported
|
||||
};
|
||||
9
app/routes/download.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const preview = require('../templates/preview');
|
||||
const download = require('../templates/download');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
if (state.transfer) {
|
||||
return download(state, emit);
|
||||
}
|
||||
return preview(state, emit);
|
||||
};
|
||||
9
app/routes/home.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const welcome = require('../templates/welcome');
|
||||
const upload = require('../templates/upload');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
if (state.transfer) {
|
||||
return upload(state, emit);
|
||||
}
|
||||
return welcome(state, emit);
|
||||
};
|
||||
17
app/routes/index.js
Normal file
@@ -0,0 +1,17 @@
|
||||
const choo = require('choo');
|
||||
const download = require('./download');
|
||||
|
||||
const app = choo();
|
||||
|
||||
app.route('/', require('./home'));
|
||||
app.route('/share/:id', require('../templates/share'));
|
||||
app.route('/download/:id', download);
|
||||
app.route('/download/:id/:key', download);
|
||||
app.route('/completed', require('../templates/completed'));
|
||||
app.route('/unsupported/:reason', require('../templates/unsupported'));
|
||||
app.route('/legal', require('../templates/legal'));
|
||||
app.route('/error', require('../templates/error'));
|
||||
app.route('/blank', require('../templates/blank'));
|
||||
app.route('*', require('../templates/notFound'));
|
||||
|
||||
module.exports = app;
|
||||
119
app/storage.js
Normal file
@@ -0,0 +1,119 @@
|
||||
import { isFile } from './utils';
|
||||
|
||||
class Mem {
|
||||
constructor() {
|
||||
this.items = new Map();
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this.items.size;
|
||||
}
|
||||
|
||||
getItem(key) {
|
||||
return this.items.get(key);
|
||||
}
|
||||
|
||||
setItem(key, value) {
|
||||
return this.items.set(key, value);
|
||||
}
|
||||
|
||||
removeItem(key) {
|
||||
return this.items.delete(key);
|
||||
}
|
||||
|
||||
key(i) {
|
||||
return this.items.keys()[i];
|
||||
}
|
||||
}
|
||||
|
||||
class Storage {
|
||||
constructor() {
|
||||
try {
|
||||
this.engine = localStorage || new Mem();
|
||||
} catch (e) {
|
||||
this.engine = new Mem();
|
||||
}
|
||||
this._files = this.loadFiles();
|
||||
}
|
||||
|
||||
loadFiles() {
|
||||
const fs = [];
|
||||
for (let i = 0; i < this.engine.length; i++) {
|
||||
const k = this.engine.key(i);
|
||||
if (isFile(k)) {
|
||||
try {
|
||||
const f = JSON.parse(this.engine.getItem(k));
|
||||
if (!f.id) {
|
||||
f.id = f.fileId;
|
||||
}
|
||||
fs.push(f);
|
||||
} catch (err) {
|
||||
// obviously you're not a golfer
|
||||
this.engine.removeItem(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fs.sort((a, b) => a.createdAt - b.createdAt);
|
||||
}
|
||||
|
||||
get totalDownloads() {
|
||||
return Number(this.engine.getItem('totalDownloads'));
|
||||
}
|
||||
set totalDownloads(n) {
|
||||
this.engine.setItem('totalDownloads', n);
|
||||
}
|
||||
get totalUploads() {
|
||||
return Number(this.engine.getItem('totalUploads'));
|
||||
}
|
||||
set totalUploads(n) {
|
||||
this.engine.setItem('totalUploads', n);
|
||||
}
|
||||
get referrer() {
|
||||
return this.engine.getItem('referrer');
|
||||
}
|
||||
set referrer(str) {
|
||||
this.engine.setItem('referrer', str);
|
||||
}
|
||||
get enrolled() {
|
||||
return JSON.parse(this.engine.getItem('experiments') || '[]');
|
||||
}
|
||||
|
||||
enroll(id, variant) {
|
||||
const enrolled = this.enrolled;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
if (!enrolled.find(([i, v]) => i === id)) {
|
||||
enrolled.push([id, variant]);
|
||||
this.engine.setItem('experiments', JSON.stringify(enrolled));
|
||||
}
|
||||
}
|
||||
|
||||
get files() {
|
||||
return this._files;
|
||||
}
|
||||
|
||||
getFileById(id) {
|
||||
try {
|
||||
return JSON.parse(this.engine.getItem(id));
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
get(id) {
|
||||
return this.engine.getItem(id);
|
||||
}
|
||||
|
||||
remove(property) {
|
||||
if (isFile(property)) {
|
||||
this._files.splice(this._files.findIndex(f => f.id === property), 1);
|
||||
}
|
||||
this.engine.removeItem(property);
|
||||
}
|
||||
|
||||
addFile(file) {
|
||||
this._files.push(file);
|
||||
this.engine.setItem(file.id, JSON.stringify(file));
|
||||
}
|
||||
}
|
||||
|
||||
export default new Storage();
|
||||
9
app/templates/blank.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const html = require('choo/html');
|
||||
|
||||
module.exports = function(state) {
|
||||
const div = html`<div id="page-one"></div>`;
|
||||
if (state.layout) {
|
||||
return state.layout(state, div);
|
||||
}
|
||||
return div;
|
||||
};
|
||||
31
app/templates/completed.js
Normal file
@@ -0,0 +1,31 @@
|
||||
const html = require('choo/html');
|
||||
const progress = require('./progress');
|
||||
const { fadeOut } = require('../utils');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
const div = html`
|
||||
<div id="download" class="fadeIn">
|
||||
<div id="download-progress">
|
||||
<div id="dl-title" class="title">${state.translate(
|
||||
'downloadFinish'
|
||||
)}</div>
|
||||
<div class="description"></div>
|
||||
${progress(1)}
|
||||
<div class="upload">
|
||||
<div class="progress-text"></div>
|
||||
</div>
|
||||
</div>
|
||||
<a class="send-new" data-state="completed" href="/" onclick=${sendNew}>${state.translate(
|
||||
'sendYourFilesLink'
|
||||
)}</a>
|
||||
</div>
|
||||
`;
|
||||
|
||||
async function sendNew(e) {
|
||||
e.preventDefault();
|
||||
await fadeOut('download');
|
||||
emit('pushState', '/');
|
||||
}
|
||||
|
||||
return div;
|
||||
};
|
||||
28
app/templates/download.js
Normal file
@@ -0,0 +1,28 @@
|
||||
const html = require('choo/html');
|
||||
const progress = require('./progress');
|
||||
const { bytes } = require('../utils');
|
||||
|
||||
module.exports = function(state) {
|
||||
const transfer = state.transfer;
|
||||
const div = html`
|
||||
<div id="download-progress" class="fadeIn">
|
||||
<div id="dl-title" class="title">${state.translate(
|
||||
'downloadingPageProgress',
|
||||
{
|
||||
filename: state.fileInfo.name,
|
||||
size: bytes(state.fileInfo.size)
|
||||
}
|
||||
)}</div>
|
||||
<div class="description">${state.translate('downloadingPageMessage')}</div>
|
||||
${progress(transfer.progressRatio)}
|
||||
<div class="upload">
|
||||
<div class="progress-text">${state.translate(
|
||||
transfer.msg,
|
||||
transfer.sizes
|
||||
)}</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return div;
|
||||
};
|
||||
10
app/templates/error.js
Normal file
@@ -0,0 +1,10 @@
|
||||
const html = require('choo/html');
|
||||
const assets = require('../../common/assets');
|
||||
|
||||
module.exports = function(state) {
|
||||
return html`
|
||||
<div id="upload-error">
|
||||
<div class="title">${state.translate('errorPageHeader')}</div>
|
||||
<img id="upload-error-img" src="${assets.get('illustration_error.svg')}"/>
|
||||
</div>`;
|
||||
};
|
||||
84
app/templates/file.js
Normal file
@@ -0,0 +1,84 @@
|
||||
const html = require('choo/html');
|
||||
const assets = require('../../common/assets');
|
||||
|
||||
function timeLeft(milliseconds) {
|
||||
const minutes = Math.floor(milliseconds / 1000 / 60);
|
||||
const hours = Math.floor(minutes / 60);
|
||||
const seconds = Math.floor((milliseconds / 1000) % 60);
|
||||
if (hours >= 1) {
|
||||
return `${hours}h ${minutes % 60}m`;
|
||||
} else if (hours === 0) {
|
||||
return `${minutes}m ${seconds}s`;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports = function(file, state, emit) {
|
||||
const ttl = file.expiresAt - Date.now();
|
||||
const remaining = timeLeft(ttl) || state.translate('linkExpiredAlt');
|
||||
const row = html`
|
||||
<tr id="${file.id}">
|
||||
<td class="overflow-col" title="${file.name}">${file.name}</td>
|
||||
<td class="center-col">
|
||||
<img onclick=${copyClick} src="${assets.get(
|
||||
'copy-16.svg'
|
||||
)}" class="icon-copy" title="${state.translate('copyUrlHover')}">
|
||||
<span class="text-copied" hidden="true">${state.translate(
|
||||
'copiedUrl'
|
||||
)}</span>
|
||||
</td>
|
||||
<td>${remaining}</td>
|
||||
<td class="center-col">
|
||||
<img onclick=${showPopup} src="${assets.get(
|
||||
'close-16.svg'
|
||||
)}" class="icon-delete" title="${state.translate('deleteButtonHover')}">
|
||||
<div class="popup">
|
||||
<div class="popuptext" onblur=${cancel} tabindex="-1">
|
||||
<div class="popup-message">${state.translate('deletePopupText')}</div>
|
||||
<div class="popup-action">
|
||||
<span class="popup-no" onclick=${cancel}>${state.translate(
|
||||
'deletePopupCancel'
|
||||
)}</span>
|
||||
<span class="popup-yes" onclick=${deleteFile}>${state.translate(
|
||||
'deletePopupYes'
|
||||
)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
|
||||
function copyClick(e) {
|
||||
emit('copy', { url: file.url, location: 'upload-list' });
|
||||
const icon = e.target;
|
||||
const text = e.target.nextSibling;
|
||||
icon.hidden = true;
|
||||
text.hidden = false;
|
||||
setTimeout(() => {
|
||||
icon.hidden = false;
|
||||
text.hidden = true;
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function showPopup() {
|
||||
const tr = document.getElementById(file.id);
|
||||
const popup = tr.querySelector('.popuptext');
|
||||
popup.classList.add('show');
|
||||
popup.focus();
|
||||
}
|
||||
|
||||
function cancel(e) {
|
||||
e.stopPropagation();
|
||||
const tr = document.getElementById(file.id);
|
||||
const popup = tr.querySelector('.popuptext');
|
||||
popup.classList.remove('show');
|
||||
}
|
||||
|
||||
function deleteFile() {
|
||||
emit('delete', { file, location: 'upload-list' });
|
||||
emit('render');
|
||||
}
|
||||
|
||||
return row;
|
||||
};
|
||||
32
app/templates/fileList.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const html = require('choo/html');
|
||||
const file = require('./file');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
let table = '';
|
||||
if (state.storage.files.length) {
|
||||
table = html`
|
||||
<table id="uploaded-files">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="uploaded-file">${state.translate('uploadedFile')}</th>
|
||||
<th id="copy-file-list" class="center-col">${state.translate(
|
||||
'copyFileList'
|
||||
)}</th>
|
||||
<th id="expiry-file-list">${state.translate('expiryFileList')}</th>
|
||||
<th id="delete-file-list" class="center-col">${state.translate(
|
||||
'deleteFileList'
|
||||
)}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${state.storage.files.map(f => file(f, state, emit))}
|
||||
</tbody>
|
||||
</table>
|
||||
`;
|
||||
}
|
||||
return html`
|
||||
<div id="file-list">
|
||||
${table}
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
38
app/templates/legal.js
Normal file
@@ -0,0 +1,38 @@
|
||||
const html = require('choo/html');
|
||||
|
||||
function replaceLinks(str, urls) {
|
||||
let i = -1;
|
||||
const s = str.replace(/<a>([^<]+)<\/a>/g, (m, v) => {
|
||||
i++;
|
||||
return `<a href="${urls[i]}">${v}</a>`;
|
||||
});
|
||||
return [`<div class="description">${s}</div>`];
|
||||
}
|
||||
|
||||
module.exports = function(state) {
|
||||
const div = html`
|
||||
<div id="page-one">
|
||||
<div id="legal">
|
||||
<div class="title">${state.translate('legalHeader')}</div>
|
||||
${html(
|
||||
replaceLinks(state.translate('legalNoticeTestPilot'), [
|
||||
'https://testpilot.firefox.com/terms',
|
||||
'https://testpilot.firefox.com/privacy',
|
||||
'https://testpilot.firefox.com/experiments/send'
|
||||
])
|
||||
)}
|
||||
${html(
|
||||
replaceLinks(state.translate('legalNoticeMozilla'), [
|
||||
'https://www.mozilla.org/privacy/websites/',
|
||||
'https://www.mozilla.org/about/legal/terms/mozilla/'
|
||||
])
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
if (state.layout) {
|
||||
return state.layout(state, div);
|
||||
}
|
||||
return div;
|
||||
};
|
||||
25
app/templates/notFound.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const html = require('choo/html');
|
||||
const assets = require('../../common/assets');
|
||||
|
||||
module.exports = function(state) {
|
||||
const div = html`
|
||||
<div id="page-one">
|
||||
<div id="download">
|
||||
<div class="title">${state.translate('expiredPageHeader')}</div>
|
||||
<div class="share-window">
|
||||
<img src="${assets.get('illustration_expired.svg')}" id="expired-img">
|
||||
</div>
|
||||
<div class="expired-description">${state.translate(
|
||||
'uploadPageExplainer'
|
||||
)}</div>
|
||||
<a class="send-new" href="/" data-state="notfound">${state.translate(
|
||||
'sendYourFilesLink'
|
||||
)}</a>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
if (state.layout) {
|
||||
return state.layout(state, div);
|
||||
}
|
||||
return div;
|
||||
};
|
||||
70
app/templates/preview.js
Normal file
@@ -0,0 +1,70 @@
|
||||
const html = require('choo/html');
|
||||
const assets = require('../../common/assets');
|
||||
const notFound = require('./notFound');
|
||||
const { bytes } = require('../utils');
|
||||
|
||||
function getFileFromDOM() {
|
||||
const el = document.getElementById('dl-file');
|
||||
if (!el) {
|
||||
return null;
|
||||
}
|
||||
const data = el.dataset;
|
||||
return {
|
||||
name: data.name,
|
||||
size: parseInt(data.size, 10),
|
||||
ttl: parseInt(data.ttl, 10)
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
state.fileInfo = state.fileInfo || getFileFromDOM();
|
||||
if (!state.fileInfo) {
|
||||
return notFound(state, emit);
|
||||
}
|
||||
state.fileInfo.id = state.params.id;
|
||||
state.fileInfo.key = state.params.key;
|
||||
const fileInfo = state.fileInfo;
|
||||
const size = bytes(fileInfo.size);
|
||||
const div = html`
|
||||
<div id="page-one">
|
||||
<div id="download">
|
||||
<div id="download-page-one">
|
||||
<div class="title">
|
||||
<span id="dl-file"
|
||||
data-name="${fileInfo.name}"
|
||||
data-size="${fileInfo.size}"
|
||||
data-ttl="${fileInfo.ttl}">${state.translate('downloadFileName', {
|
||||
filename: fileInfo.name
|
||||
})}</span>
|
||||
<span id="dl-filesize">${' ' +
|
||||
state.translate('downloadFileSize', { size })}</span>
|
||||
</div>
|
||||
<div class="description">${state.translate('downloadMessage')}</div>
|
||||
<img
|
||||
src="${assets.get('illustration_download.svg')}"
|
||||
id="download-img"
|
||||
alt="${state.translate('downloadAltText')}"/>
|
||||
<div>
|
||||
<button
|
||||
id="download-btn"
|
||||
class="btn"
|
||||
title="${state.translate('downloadButtonLabel')}"
|
||||
onclick=${download}>${state.translate(
|
||||
'downloadButtonLabel'
|
||||
)}</button>
|
||||
</div>
|
||||
</div>
|
||||
<a class="send-new" href="/">${state.translate('sendYourFilesLink')}</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
function download(event) {
|
||||
event.preventDefault();
|
||||
emit('download', fileInfo);
|
||||
}
|
||||
|
||||
if (state.layout) {
|
||||
return state.layout(state, div);
|
||||
}
|
||||
return div;
|
||||
};
|
||||
21
app/templates/progress.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const html = require('choo/html');
|
||||
|
||||
const radius = 73;
|
||||
const oRadius = radius + 10;
|
||||
const oDiameter = oRadius * 2;
|
||||
const circumference = 2 * Math.PI * radius;
|
||||
|
||||
module.exports = function(progressRatio) {
|
||||
const dashOffset = (1 - progressRatio) * circumference;
|
||||
const percent = Math.floor(progressRatio * 100);
|
||||
const div = html`
|
||||
<div class="progress-bar">
|
||||
<svg id="progress" width="${oDiameter}" height="${oDiameter}" viewPort="0 0 ${oDiameter} ${oDiameter}" version="1.1">
|
||||
<circle r="${radius}" cx="${oRadius}" cy="${oRadius}" fill="transparent"/>
|
||||
<circle id="bar" r="${radius}" cx="${oRadius}" cy="${oRadius}" fill="transparent" transform="rotate(-90 ${oRadius} ${oRadius})" stroke-dasharray="${circumference}" stroke-dashoffset="${dashOffset}"/>
|
||||
<text class="percentage" text-anchor="middle" x="50%" y="98"><tspan class="percent-number">${percent}</tspan><tspan class="percent-sign">%</tspan></text>
|
||||
</svg>
|
||||
</div>
|
||||
`;
|
||||
return div;
|
||||
};
|
||||
64
app/templates/share.js
Normal file
@@ -0,0 +1,64 @@
|
||||
const html = require('choo/html');
|
||||
const assets = require('../../common/assets');
|
||||
const notFound = require('./notFound');
|
||||
const { allowedCopy, delay, fadeOut } = require('../utils');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
const file = state.storage.getFileById(state.params.id);
|
||||
if (!file) {
|
||||
return notFound(state, emit);
|
||||
}
|
||||
const div = html`
|
||||
<div id="share-link" class="fadeIn">
|
||||
<div class="title">${state.translate('uploadSuccessTimingHeader')}</div>
|
||||
<div id="share-window">
|
||||
<div id="copy-text">${state.translate('copyUrlFormLabelWithName', {
|
||||
filename: file.name
|
||||
})}</div>
|
||||
<div id="copy">
|
||||
<input id="link" type="url" value="${file.url}" readonly="true"/>
|
||||
<button id="copy-btn" class="btn" title="${state.translate(
|
||||
'copyUrlFormButton'
|
||||
)}" onclick=${copyLink}>${state.translate('copyUrlFormButton')}</button>
|
||||
</div>
|
||||
<button id="delete-file" class="btn" title="${state.translate(
|
||||
'deleteFileButton'
|
||||
)}" onclick=${deleteFile}>${state.translate('deleteFileButton')}</button>
|
||||
<a class="send-new" data-state="completed" href="/" onclick=${sendNew}>${state.translate(
|
||||
'sendAnotherFileLink'
|
||||
)}</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
async function sendNew(e) {
|
||||
e.preventDefault();
|
||||
await fadeOut('share-link');
|
||||
emit('pushState', '/');
|
||||
}
|
||||
|
||||
async function copyLink() {
|
||||
if (allowedCopy()) {
|
||||
emit('copy', { url: file.url, location: 'success-screen' });
|
||||
const input = document.getElementById('link');
|
||||
input.disabled = true;
|
||||
const copyBtn = document.getElementById('copy-btn');
|
||||
copyBtn.disabled = true;
|
||||
copyBtn.replaceChild(
|
||||
html`<img src="${assets.get('check-16.svg')}" class="icon-check">`,
|
||||
copyBtn.firstChild
|
||||
);
|
||||
await delay(2000);
|
||||
input.disabled = false;
|
||||
copyBtn.disabled = false;
|
||||
copyBtn.textContent = state.translate('copyUrlFormButton');
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteFile() {
|
||||
emit('delete', { file, location: 'success-screen' });
|
||||
await fadeOut('share-link');
|
||||
emit('pushState', '/');
|
||||
}
|
||||
return div;
|
||||
};
|
||||
50
app/templates/unsupported.js
Normal file
@@ -0,0 +1,50 @@
|
||||
const html = require('choo/html');
|
||||
const assets = require('../../common/assets');
|
||||
|
||||
module.exports = function(state) {
|
||||
const msg =
|
||||
state.params.reason === 'outdated'
|
||||
? html`
|
||||
<div id="unsupported-browser">
|
||||
<div class="title">${state.translate('notSupportedHeader')}</div>
|
||||
<div class="description">${state.translate(
|
||||
'notSupportedOutdatedDetail'
|
||||
)}</div>
|
||||
<a id="update-firefox" href="https://support.mozilla.org/kb/update-firefox-latest-version">
|
||||
<img src="${assets.get(
|
||||
'firefox_logo-only.svg'
|
||||
)}" class="firefox-logo" alt="Firefox"/>
|
||||
<div class="unsupported-button-text">${state.translate(
|
||||
'updateFirefox'
|
||||
)}</div>
|
||||
</a>
|
||||
<div class="unsupported-description">${state.translate(
|
||||
'uploadPageExplainer'
|
||||
)}</div>
|
||||
</div>`
|
||||
: html`
|
||||
<div id="unsupported-browser">
|
||||
<div class="title">${state.translate('notSupportedHeader')}</div>
|
||||
<div class="description">${state.translate('notSupportedDetail')}</div>
|
||||
<div class="description"><a href="https://github.com/mozilla/send/blob/master/docs/faq.md#why-is-my-browser-not-supported">${state.translate(
|
||||
'notSupportedLink'
|
||||
)}</a></div>
|
||||
<a id="dl-firefox" href="https://www.mozilla.org/firefox/new/?scene=2">
|
||||
<img src="${assets.get(
|
||||
'firefox_logo-only.svg'
|
||||
)}" class="firefox-logo" alt="Firefox"/>
|
||||
<div class="unsupported-button-text">Firefox<br>
|
||||
<span>${state.translate('downloadFirefoxButtonSub')}</span>
|
||||
</div>
|
||||
</a>
|
||||
<div class="unsupported-description">${state.translate(
|
||||
'uploadPageExplainer'
|
||||
)}</div>
|
||||
</div>`;
|
||||
const div = html`<div id="page-one">${msg}</div>`;
|
||||
|
||||
if (state.layout) {
|
||||
return state.layout(state, div);
|
||||
}
|
||||
return div;
|
||||
};
|
||||
38
app/templates/upload.js
Normal file
@@ -0,0 +1,38 @@
|
||||
const html = require('choo/html');
|
||||
const progress = require('./progress');
|
||||
const { bytes } = require('../utils');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
const transfer = state.transfer;
|
||||
|
||||
const div = html`
|
||||
<div id="upload-progress" class="fadeIn">
|
||||
<div class="title" id="upload-filename">${state.translate(
|
||||
'uploadingPageProgress',
|
||||
{
|
||||
filename: transfer.file.name,
|
||||
size: bytes(transfer.file.size)
|
||||
}
|
||||
)}</div>
|
||||
<div class="description"></div>
|
||||
${progress(transfer.progressRatio)}
|
||||
<div class="upload">
|
||||
<div class="progress-text">${state.translate(
|
||||
transfer.msg,
|
||||
transfer.sizes
|
||||
)}</div>
|
||||
<button id="cancel-upload" title="${state.translate(
|
||||
'uploadingPageCancel'
|
||||
)}" onclick=${cancel}>${state.translate('uploadingPageCancel')}</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
function cancel() {
|
||||
const btn = document.getElementById('cancel-upload');
|
||||
btn.disabled = true;
|
||||
btn.textContent = state.translate('uploadCancelNotification');
|
||||
emit('cancel');
|
||||
}
|
||||
return div;
|
||||
};
|
||||
62
app/templates/welcome.js
Normal file
@@ -0,0 +1,62 @@
|
||||
const html = require('choo/html');
|
||||
const assets = require('../../common/assets');
|
||||
const fileList = require('./fileList');
|
||||
const { fadeOut } = require('../utils');
|
||||
|
||||
module.exports = function(state, emit) {
|
||||
const div = html`
|
||||
<div id="page-one" class="fadeIn">
|
||||
<div class="title">${state.translate('uploadPageHeader')}</div>
|
||||
<div class="description">
|
||||
<div>${state.translate('uploadPageExplainer')}</div>
|
||||
<a href="https://testpilot.firefox.com/experiments/send" class="link">${state.translate(
|
||||
'uploadPageLearnMore'
|
||||
)}</a>
|
||||
</div>
|
||||
<div class="${state.config
|
||||
.uploadWindowStyle}" ondragover=${dragover} ondragleave=${dragleave}>
|
||||
<div id="upload-img"><img src="${assets.get(
|
||||
'upload.svg'
|
||||
)}" title="${state.translate('uploadSvgAlt')}"/></div>
|
||||
<div id="upload-text">${state.translate('uploadPageDropMessage')}</div>
|
||||
<span id="file-size-msg"><em>${state.translate(
|
||||
'uploadPageSizeMessage'
|
||||
)}</em></span>
|
||||
<form method="post" action="upload" enctype="multipart/form-data">
|
||||
<label for="file-upload" id="browse" class="${state.config
|
||||
.uploadButtonStyle}" title="${state.translate(
|
||||
'uploadPageBrowseButton1'
|
||||
)}">${state.translate('uploadPageBrowseButton1')}</label>
|
||||
<input id="file-upload" type="file" name="fileUploaded" onchange=${upload} />
|
||||
</form>
|
||||
</div>
|
||||
${fileList(state, emit)}
|
||||
</div>
|
||||
`;
|
||||
|
||||
function dragover(event) {
|
||||
const div = document.querySelector('.upload-window');
|
||||
div.classList.add('ondrag');
|
||||
}
|
||||
|
||||
function dragleave(event) {
|
||||
const div = document.querySelector('.upload-window');
|
||||
div.classList.remove('ondrag');
|
||||
}
|
||||
|
||||
async function upload(event) {
|
||||
event.preventDefault();
|
||||
const target = event.target;
|
||||
const file = target.files[0];
|
||||
if (file.size === 0) {
|
||||
return;
|
||||
}
|
||||
await fadeOut('page-one');
|
||||
emit('upload', { file, type: 'click' });
|
||||
}
|
||||
|
||||
if (state.layout) {
|
||||
return state.layout(state, div);
|
||||
}
|
||||
return div;
|
||||
};
|
||||
156
app/utils.js
Normal file
@@ -0,0 +1,156 @@
|
||||
function arrayToHex(iv) {
|
||||
let hexStr = '';
|
||||
// eslint-disable-next-line prefer-const
|
||||
for (let i in iv) {
|
||||
if (iv[i] < 16) {
|
||||
hexStr += '0' + iv[i].toString(16);
|
||||
} else {
|
||||
hexStr += iv[i].toString(16);
|
||||
}
|
||||
}
|
||||
return hexStr;
|
||||
}
|
||||
|
||||
function hexToArray(str) {
|
||||
const iv = new Uint8Array(str.length / 2);
|
||||
for (let i = 0; i < str.length; i += 2) {
|
||||
iv[i / 2] = parseInt(str.charAt(i) + str.charAt(i + 1), 16);
|
||||
}
|
||||
|
||||
return iv;
|
||||
}
|
||||
|
||||
function notify(str) {
|
||||
return str;
|
||||
/* TODO: enable once we have an opt-in ui element
|
||||
if (!('Notification' in window)) {
|
||||
return;
|
||||
} else if (Notification.permission === 'granted') {
|
||||
new Notification(str);
|
||||
} else if (Notification.permission !== 'denied') {
|
||||
Notification.requestPermission(function(permission) {
|
||||
if (permission === 'granted') new Notification(str);
|
||||
});
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
function loadShim(polyfill) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const shim = document.createElement('script');
|
||||
shim.src = polyfill;
|
||||
shim.addEventListener('load', () => resolve(true));
|
||||
shim.addEventListener('error', () => resolve(false));
|
||||
document.head.appendChild(shim);
|
||||
});
|
||||
}
|
||||
|
||||
async function canHasSend(polyfill) {
|
||||
try {
|
||||
const key = await window.crypto.subtle.generateKey(
|
||||
{
|
||||
name: 'AES-GCM',
|
||||
length: 128
|
||||
},
|
||||
true,
|
||||
['encrypt', 'decrypt']
|
||||
);
|
||||
|
||||
await window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: 'AES-GCM',
|
||||
iv: window.crypto.getRandomValues(new Uint8Array(12)),
|
||||
tagLength: 128
|
||||
},
|
||||
key,
|
||||
new ArrayBuffer(8)
|
||||
);
|
||||
return true;
|
||||
} catch (err) {
|
||||
return loadShim(polyfill);
|
||||
}
|
||||
}
|
||||
|
||||
function isFile(id) {
|
||||
return /^[0-9a-fA-F]{10}$/.test(id);
|
||||
}
|
||||
|
||||
function copyToClipboard(str) {
|
||||
const aux = document.createElement('input');
|
||||
aux.setAttribute('value', str);
|
||||
aux.contentEditable = true;
|
||||
aux.readOnly = true;
|
||||
document.body.appendChild(aux);
|
||||
if (navigator.userAgent.match(/iphone|ipad|ipod/i)) {
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(aux);
|
||||
const sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(range);
|
||||
aux.setSelectionRange(0, str.length);
|
||||
} else {
|
||||
aux.select();
|
||||
}
|
||||
const result = document.execCommand('copy');
|
||||
document.body.removeChild(aux);
|
||||
return result;
|
||||
}
|
||||
|
||||
const LOCALIZE_NUMBERS = !!(
|
||||
typeof Intl === 'object' &&
|
||||
Intl &&
|
||||
typeof Intl.NumberFormat === 'function' &&
|
||||
typeof navigator === 'object'
|
||||
);
|
||||
|
||||
const UNITS = ['B', 'kB', 'MB', 'GB'];
|
||||
function bytes(num) {
|
||||
const exponent = Math.min(Math.floor(Math.log10(num) / 3), UNITS.length - 1);
|
||||
const n = Number(num / Math.pow(1000, exponent));
|
||||
const nStr = LOCALIZE_NUMBERS
|
||||
? n.toLocaleString(navigator.languages, {
|
||||
minimumFractionDigits: 1,
|
||||
maximumFractionDigits: 1
|
||||
})
|
||||
: n.toFixed(1);
|
||||
return `${nStr}${UNITS[exponent]}`;
|
||||
}
|
||||
|
||||
function percent(ratio) {
|
||||
return LOCALIZE_NUMBERS
|
||||
? ratio.toLocaleString(navigator.languages, { style: 'percent' })
|
||||
: `${Math.floor(ratio * 100)}%`;
|
||||
}
|
||||
|
||||
function allowedCopy() {
|
||||
const support = !!document.queryCommandSupported;
|
||||
return support ? document.queryCommandSupported('copy') : false;
|
||||
}
|
||||
|
||||
function delay(delay = 100) {
|
||||
return new Promise(resolve => setTimeout(resolve, delay));
|
||||
}
|
||||
|
||||
function fadeOut(id) {
|
||||
const classes = document.getElementById(id).classList;
|
||||
classes.remove('fadeIn');
|
||||
classes.add('fadeOut');
|
||||
return delay(300);
|
||||
}
|
||||
|
||||
const ONE_DAY_IN_MS = 86400000;
|
||||
|
||||
module.exports = {
|
||||
fadeOut,
|
||||
delay,
|
||||
allowedCopy,
|
||||
bytes,
|
||||
percent,
|
||||
copyToClipboard,
|
||||
arrayToHex,
|
||||
hexToArray,
|
||||
notify,
|
||||
canHasSend,
|
||||
isFile,
|
||||
ONE_DAY_IN_MS
|
||||
};
|
||||
1
assets/check-16.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 16 16"><path fill="#fff" d="M6 14a1 1 0 0 1-.707-.293l-3-3a1 1 0 0 1 1.414-1.414l2.157 2.157 6.316-9.023a1 1 0 0 1 1.639 1.146l-7 10a1 1 0 0 1-.732.427A.863.863 0 0 1 6 14z"/></svg>
|
||||
|
After Width: | Height: | Size: 257 B |
1
assets/close-16.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 16 16"><path fill="#4A4A4A" d="M9.414 8l5.293-5.293a1 1 0 0 0-1.414-1.414L8 6.586 2.707 1.293a1 1 0 0 0-1.414 1.414L6.586 8l-5.293 5.293a1 1 0 1 0 1.414 1.414L8 9.414l5.293 5.293a1 1 0 0 0 1.414-1.414z"/></svg>
|
||||
|
After Width: | Height: | Size: 287 B |
1
assets/copy-16.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path class="icon-copy" fill="#0A8DFF" d="M14.707 8.293l-3-3A1 1 0 0 0 11 5h-1V4a1 1 0 0 0-.293-.707l-3-3A1 1 0 0 0 6 0H3a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h3v3a2 2 0 0 0 2 2h5a2 2 0 0 0 2-2V9a1 1 0 0 0-.293-.707zM12.586 9H11V7.414zm-5-5H6V2.414zM6 7v2H3V2h2v2.5a.5.5 0 0 0 .5.5H8a2 2 0 0 0-2 2zm2 7V7h2v2.5a.5.5 0 0 0 .5.5H13v4z"/></svg>
|
||||
|
After Width: | Height: | Size: 416 B |
22
assets/cryptofill.js
Normal file
BIN
assets/favicon-32x32.png
Executable file
|
After Width: | Height: | Size: 1.8 KiB |
1
assets/feedback.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="15" height="13" viewBox="0 0 15 13" xmlns="http://www.w3.org/2000/svg"><title>Combined Shape</title><path d="M10.274 9.193a5.957 5.957 0 0 1-2.98.778C4.37 9.97 2 7.963 2 5.485 2 3.008 4.37 1 7.294 1c2.924 0 5.294 2.008 5.294 4.485 0 .843-.274 1.632-.751 2.305l.577 2.21-2.14-.807zm-5.983-2.96a.756.756 0 0 0 .763-.748.756.756 0 0 0-.763-.747.756.756 0 0 0-.764.747c0 .413.342.748.764.748zm3.054 0a.756.756 0 0 0 .764-.748.756.756 0 0 0-.764-.747.756.756 0 0 0-.764.747c0 .413.342.748.764.748zm3.054 0a.756.756 0 0 0 .764-.748.756.756 0 0 0-.764-.747.756.756 0 0 0-.763.747c0 .413.342.748.763.748z" fill="#FFF" fill-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 649 B |
1
assets/firefox_logo-only.svg
Normal file
|
After Width: | Height: | Size: 239 KiB |
1
assets/github-icon.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="438.549" height="438.549" viewBox="0 0 438.549 438.549"><path d="M409.132 114.573c-19.608-33.596-46.205-60.194-79.798-79.8-33.598-19.607-70.277-29.408-110.063-29.408-39.781 0-76.472 9.804-110.063 29.408-33.596 19.605-60.192 46.204-79.8 79.8C9.803 148.168 0 184.854 0 224.63c0 47.78 13.94 90.745 41.827 128.906 27.884 38.164 63.906 64.572 108.063 79.227 5.14.954 8.945.283 11.419-1.996 2.475-2.282 3.711-5.14 3.711-8.562 0-.571-.049-5.708-.144-15.417a2549.81 2549.81 0 0 1-.144-25.406l-6.567 1.136c-4.187.767-9.469 1.092-15.846 1-6.374-.089-12.991-.757-19.842-1.999-6.854-1.231-13.229-4.086-19.13-8.559-5.898-4.473-10.085-10.328-12.56-17.556l-2.855-6.57c-1.903-4.374-4.899-9.233-8.992-14.559-4.093-5.331-8.232-8.945-12.419-10.848l-1.999-1.431c-1.332-.951-2.568-2.098-3.711-3.429-1.142-1.331-1.997-2.663-2.568-3.997-.572-1.335-.098-2.43 1.427-3.289 1.525-.859 4.281-1.276 8.28-1.276l5.708.853c3.807.763 8.516 3.042 14.133 6.851 5.614 3.806 10.229 8.754 13.846 14.842 4.38 7.806 9.657 13.754 15.846 17.847 6.184 4.093 12.419 6.136 18.699 6.136 6.28 0 11.704-.476 16.274-1.423 4.565-.952 8.848-2.383 12.847-4.285 1.713-12.758 6.377-22.559 13.988-29.41-10.848-1.14-20.601-2.857-29.264-5.14-8.658-2.286-17.605-5.996-26.835-11.14-9.235-5.137-16.896-11.516-22.985-19.126-6.09-7.614-11.088-17.61-14.987-29.979-3.901-12.374-5.852-26.648-5.852-42.826 0-23.035 7.52-42.637 22.557-58.817-7.044-17.318-6.379-36.732 1.997-58.24 5.52-1.715 13.706-.428 24.554 3.853 10.85 4.283 18.794 7.952 23.84 10.994 5.046 3.041 9.089 5.618 12.135 7.708 17.705-4.947 35.976-7.421 54.818-7.421s37.117 2.474 54.823 7.421l10.849-6.849c7.419-4.57 16.18-8.758 26.262-12.565 10.088-3.805 17.802-4.853 23.134-3.138 8.562 21.509 9.325 40.922 2.279 58.24 15.036 16.18 22.559 35.787 22.559 58.817 0 16.178-1.958 30.497-5.853 42.966-3.9 12.471-8.941 22.457-15.125 29.979-6.191 7.521-13.901 13.85-23.131 18.986-9.232 5.14-18.182 8.85-26.84 11.136-8.662 2.286-18.415 4.004-29.263 5.146 9.894 8.562 14.842 22.077 14.842 40.539v60.237c0 3.422 1.19 6.279 3.572 8.562 2.379 2.279 6.136 2.95 11.276 1.995 44.163-14.653 80.185-41.062 108.068-79.226 27.88-38.161 41.825-81.126 41.825-128.906-.01-39.771-9.818-76.454-29.414-110.049z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
1
assets/illustration_download.svg
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
1
assets/illustration_error.svg
Normal file
|
After Width: | Height: | Size: 11 KiB |
1
assets/illustration_expired.svg
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
931
assets/main.css
Normal file
@@ -0,0 +1,931 @@
|
||||
/*** index.html ***/
|
||||
html {
|
||||
background: url('./send_bg.svg');
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'segoe ui',
|
||||
'helvetica neue', helvetica, ubuntu, roboto, noto, arial, sans-serif;
|
||||
font-weight: 200;
|
||||
background-size: 110%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center top;
|
||||
height: 100%;
|
||||
max-width: 1440px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'segoe ui',
|
||||
'helvetica neue', helvetica, ubuntu, roboto, noto, arial, sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#progress circle {
|
||||
stroke: #eee;
|
||||
stroke-width: 0.75em;
|
||||
}
|
||||
|
||||
#progress #bar {
|
||||
transition: stroke-dashoffset 300ms linear;
|
||||
stroke: #3b9dff;
|
||||
}
|
||||
|
||||
.header {
|
||||
align-items: flex-start;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 31px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.send-logo {
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.send-logo h1 {
|
||||
transition: color 50ms;
|
||||
}
|
||||
|
||||
.send-logo h1:hover {
|
||||
color: #0297f8;
|
||||
}
|
||||
|
||||
.send-logo > a {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.site-title {
|
||||
color: #3e3d40;
|
||||
font-size: 32px;
|
||||
font-weight: 500;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
top: -1px;
|
||||
letter-spacing: 1px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.site-subtitle {
|
||||
color: #3e3d40;
|
||||
font-size: 12px;
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
.site-subtitle a {
|
||||
font-weight: bold;
|
||||
color: #3e3d40;
|
||||
transition: color 50ms;
|
||||
}
|
||||
|
||||
.site-subtitle a:hover {
|
||||
color: #0297f8;
|
||||
}
|
||||
|
||||
.feedback {
|
||||
background-color: #0297f8;
|
||||
background-image: url('./feedback.svg');
|
||||
background-position: 2px 4px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 18px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #0297f8;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
line-height: 12px;
|
||||
opacity: 0.9;
|
||||
padding: 5px;
|
||||
overflow: hidden;
|
||||
min-width: 12px;
|
||||
max-width: 12px;
|
||||
text-indent: 17px;
|
||||
transition: all 250ms ease-in-out;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.feedback:hover,
|
||||
.feedback:focus {
|
||||
min-width: 30px;
|
||||
max-width: 300px;
|
||||
text-indent: 2px;
|
||||
padding: 5px 5px 5px 20px;
|
||||
background-color: #0287e8;
|
||||
}
|
||||
|
||||
.feedback:active {
|
||||
background-color: #0277d8;
|
||||
}
|
||||
|
||||
.all {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
max-width: 630px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box;
|
||||
width: 96%;
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
button {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/** page-one **/
|
||||
|
||||
.fadeOut {
|
||||
opacity: 0;
|
||||
animation: fadeout 200ms linear;
|
||||
}
|
||||
|
||||
@keyframes fadeout {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.fadeIn {
|
||||
opacity: 1;
|
||||
animation: fadein 200ms linear;
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 33px;
|
||||
line-height: 40px;
|
||||
margin: 20px auto;
|
||||
text-align: center;
|
||||
max-width: 520px;
|
||||
font-family: 'SF Pro Text', sans-serif;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 15px;
|
||||
line-height: 23px;
|
||||
max-width: 630px;
|
||||
text-align: center;
|
||||
margin: 0 auto 60px;
|
||||
color: #0c0c0d;
|
||||
width: 92%;
|
||||
}
|
||||
|
||||
.upload-window {
|
||||
border: 1px dashed rgba(0, 148, 251, 0.5);
|
||||
margin: 0 auto;
|
||||
height: 255px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
transition: transform 150ms;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.upload-window.ondrag {
|
||||
border: 3px dashed rgba(0, 148, 251, 0.5);
|
||||
margin: 0 auto;
|
||||
height: 251px;
|
||||
transform: scale(1.04);
|
||||
border-radius: 4.2px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.upload-window-b {
|
||||
border: 3px dashed rgba(0, 148, 251, 0.5);
|
||||
}
|
||||
|
||||
.upload-window-b.ondrag {
|
||||
border: 5px dashed rgba(0, 148, 251, 0.5);
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #0094fb;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.link:hover {
|
||||
color: #0287e8;
|
||||
}
|
||||
|
||||
#upload-text {
|
||||
font-size: 22px;
|
||||
color: #737373;
|
||||
margin: 20px 0 10px;
|
||||
font-family: 'SF Pro Text', sans-serif;
|
||||
}
|
||||
|
||||
.browse {
|
||||
background: #0297f8;
|
||||
border-radius: 5px;
|
||||
font-size: 15px;
|
||||
color: #fff;
|
||||
min-width: 240px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.browse:hover {
|
||||
background-color: #0287e8;
|
||||
}
|
||||
|
||||
.browse-b {
|
||||
height: 60px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
input[type='file'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#file-size-msg {
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: #737373;
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
|
||||
/** file-list **/
|
||||
th {
|
||||
font-size: 16px;
|
||||
color: #858585;
|
||||
font-weight: lighter;
|
||||
text-align: left;
|
||||
background: rgba(0, 148, 251, 0.05);
|
||||
height: 40px;
|
||||
border-top: 1px solid rgba(0, 148, 251, 0.1);
|
||||
padding: 0 19px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
td {
|
||||
font-size: 15px;
|
||||
vertical-align: top;
|
||||
color: #4a4a4a;
|
||||
padding: 17px 19px 0;
|
||||
line-height: 23px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
font-family: 'Segoe UI', 'SF Pro Text', sans-serif;
|
||||
}
|
||||
|
||||
tbody {
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
#uploaded-files {
|
||||
margin: 45.3px auto;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
#uploaded-file {
|
||||
width: 35%;
|
||||
}
|
||||
|
||||
#copy-file-list {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
#expiry-file-list {
|
||||
width: 21%;
|
||||
}
|
||||
|
||||
#delete-file-list {
|
||||
width: 12%;
|
||||
}
|
||||
|
||||
.overflow-col {
|
||||
text-overflow: ellipsis;
|
||||
max-width: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.center-col {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.icon-delete,
|
||||
.icon-copy,
|
||||
.icon-check {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.icon-copy[disabled='disabled'] {
|
||||
pointer-events: none;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.text-copied {
|
||||
color: #0a8dff;
|
||||
}
|
||||
|
||||
/* Popup container */
|
||||
.popup {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* The actual popup (appears on top) */
|
||||
.popup .popuptext {
|
||||
visibility: hidden;
|
||||
min-width: 204px;
|
||||
min-height: 105px;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
border: 1px solid #d7d7db;
|
||||
padding: 15px 24px;
|
||||
box-sizing: content-box;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 20px;
|
||||
left: -40px;
|
||||
transition: opacity 0.5s;
|
||||
opacity: 0;
|
||||
outline: 0;
|
||||
box-shadow: 3px 3px 7px rgba(136, 136, 136, 0.3);
|
||||
}
|
||||
|
||||
/* Popup arrow */
|
||||
.popup .popuptext::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -11px;
|
||||
left: 20px;
|
||||
background-color: #fff;
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transform: rotate(45deg);
|
||||
border-radius: 0 0 5px;
|
||||
border-right: 1px solid #d7d7db;
|
||||
border-bottom: 1px solid #d7d7db;
|
||||
}
|
||||
|
||||
.popup .show {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.popup-message {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-bottom: 1px #ebebeb solid;
|
||||
color: #0c0c0d;
|
||||
font-size: 15px;
|
||||
font-weight: normal;
|
||||
padding-bottom: 15px;
|
||||
white-space: nowrap;
|
||||
width: calc(100% + 48px);
|
||||
margin-left: -24px;
|
||||
}
|
||||
|
||||
.popup-action {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.popup-yes {
|
||||
color: #fff;
|
||||
background-color: #0297f8;
|
||||
border-radius: 5px;
|
||||
padding: 5px 25px;
|
||||
font-weight: normal;
|
||||
cursor: pointer;
|
||||
min-width: 94px;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.popup-yes:hover {
|
||||
background-color: #0287e8;
|
||||
}
|
||||
|
||||
.popup-no {
|
||||
color: #4a4a4a;
|
||||
background-color: #fbfbfb;
|
||||
border: 1px #c1c1c1 solid;
|
||||
border-radius: 5px;
|
||||
padding: 5px 25px;
|
||||
font-weight: normal;
|
||||
min-width: 94px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.popup-no:hover {
|
||||
background-color: #efeff1;
|
||||
}
|
||||
|
||||
/** upload-progress **/
|
||||
.progress-bar {
|
||||
margin-top: 3px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.percentage {
|
||||
letter-spacing: -0.78px;
|
||||
font-family: 'Segoe UI', 'SF Pro Text', sans-serif;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.percent-number {
|
||||
font-size: 43.2px;
|
||||
line-height: 58px;
|
||||
}
|
||||
|
||||
.percent-sign {
|
||||
font-size: 28.8px;
|
||||
stroke: none;
|
||||
fill: #686868;
|
||||
}
|
||||
|
||||
.upload {
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
letter-spacing: -0.4px;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 74px;
|
||||
}
|
||||
|
||||
#cancel-upload {
|
||||
color: #d70022;
|
||||
background: #fff;
|
||||
font-size: 15px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#cancel-upload:disabled {
|
||||
text-decoration: none;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
/** share-link **/
|
||||
#share-window {
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
max-width: 640px;
|
||||
}
|
||||
|
||||
#share-window-r > div {
|
||||
font-size: 12px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
#copy {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#copy-text {
|
||||
align-self: flex-start;
|
||||
margin-top: 60px;
|
||||
margin-bottom: 10px;
|
||||
color: #0c0c0d;
|
||||
max-width: 614px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#link {
|
||||
flex: 1;
|
||||
height: 56px;
|
||||
border: 1px solid #0297f8;
|
||||
border-radius: 6px 0 0 6px;
|
||||
font-size: 20px;
|
||||
color: #737373;
|
||||
font-family: 'SF Pro Text', sans-serif;
|
||||
letter-spacing: 0;
|
||||
line-height: 23px;
|
||||
font-weight: 300;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#link:disabled {
|
||||
border: 1px solid #05a700;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#copy-btn {
|
||||
flex: 0 1 165px;
|
||||
background: #0297f8;
|
||||
border-radius: 0 6px 6px 0;
|
||||
border: 1px solid #0297f8;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
height: 60px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#copy-btn:hover {
|
||||
background-color: #0287e8;
|
||||
}
|
||||
|
||||
#copy-btn:disabled {
|
||||
background: #05a700;
|
||||
border: 1px solid #05a700;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
#delete-file {
|
||||
width: 176px;
|
||||
height: 44px;
|
||||
background: #fff;
|
||||
border: 1px solid rgba(12, 12, 13, 0.3);
|
||||
border-radius: 5px;
|
||||
font-size: 15px;
|
||||
margin-top: 50px;
|
||||
margin-bottom: 12px;
|
||||
cursor: pointer;
|
||||
color: #313131;
|
||||
}
|
||||
|
||||
#delete-file:hover {
|
||||
background: #efeff1;
|
||||
}
|
||||
|
||||
.send-new {
|
||||
font-size: 15px;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
color: #0094fb;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.send-new:hover,
|
||||
.send-new:focus,
|
||||
.send-new:active {
|
||||
color: #0287e8;
|
||||
}
|
||||
|
||||
/* upload-error */
|
||||
#upload-error {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#upload-error[hidden],
|
||||
#unsupported-browser[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#upload-error-img {
|
||||
margin: 51px 0 71px;
|
||||
}
|
||||
|
||||
/* unsupported-browser */
|
||||
#unsupported-browser {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.unsupported-description {
|
||||
font-size: 13px;
|
||||
line-height: 23px;
|
||||
text-align: center;
|
||||
color: #7d7d7d;
|
||||
margin: 0 auto 23px;
|
||||
}
|
||||
|
||||
.firefox-logo {
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
#dl-firefox,
|
||||
#update-firefox {
|
||||
margin-bottom: 181px;
|
||||
height: 80px;
|
||||
background: #98e02b;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
box-shadow: 0 5px 3px rgb(234, 234, 234);
|
||||
font-family: 'Fira Sans';
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
font-size: 26px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
padding: 0 25px;
|
||||
}
|
||||
|
||||
.unsupported-button-text {
|
||||
text-align: left;
|
||||
margin-left: 20.4px;
|
||||
}
|
||||
|
||||
.unsupported-button-text > span {
|
||||
font-family: 'Fira Sans';
|
||||
font-weight: 300;
|
||||
font-size: 18px;
|
||||
letter-spacing: -0.69px;
|
||||
}
|
||||
|
||||
/** download.html **/
|
||||
#download-btn {
|
||||
font-size: 15px;
|
||||
color: white;
|
||||
width: 180px;
|
||||
height: 44px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 30px;
|
||||
text-align: center;
|
||||
background: #0297f8;
|
||||
border: 1px solid #0297f8;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#download-btn:hover {
|
||||
background-color: #0287e8;
|
||||
}
|
||||
|
||||
#download-btn:disabled {
|
||||
background: #47b04b;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
#download {
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#expired-img {
|
||||
margin: 51px 0 71px;
|
||||
}
|
||||
|
||||
.expired-description {
|
||||
font-size: 15px;
|
||||
line-height: 23px;
|
||||
text-align: center;
|
||||
color: #7d7d7d;
|
||||
margin: 0 auto 23px;
|
||||
}
|
||||
|
||||
#download-progress {
|
||||
width: 590px;
|
||||
}
|
||||
|
||||
#download-progress[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#download-img {
|
||||
width: 283px;
|
||||
height: 196px;
|
||||
}
|
||||
|
||||
/* footer */
|
||||
.footer {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
padding: 50px 31px 41px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.mozilla-logo {
|
||||
width: 112px;
|
||||
height: 32px;
|
||||
margin-bottom: -5px;
|
||||
}
|
||||
|
||||
.legal-links {
|
||||
max-width: 81vw;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.legal-links > a {
|
||||
color: #858585;
|
||||
opacity: 0.9;
|
||||
white-space: nowrap;
|
||||
margin-right: 2vw;
|
||||
}
|
||||
|
||||
.legal-links > a:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.legal-links > a:visited {
|
||||
color: #858585;
|
||||
}
|
||||
|
||||
.social-links {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 94px;
|
||||
}
|
||||
|
||||
.social-links > a {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.social-links > a:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.github,
|
||||
.twitter {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-bottom: -5px;
|
||||
}
|
||||
|
||||
@media (max-device-width: 992px), (max-width: 992px) {
|
||||
.popup .popuptext {
|
||||
left: auto;
|
||||
right: -40px;
|
||||
}
|
||||
|
||||
.popup .popuptext::after {
|
||||
left: auto;
|
||||
right: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-device-width: 768px), (max-width: 768px) {
|
||||
.description {
|
||||
margin: 0 auto 25px;
|
||||
}
|
||||
|
||||
#copy {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#link {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
max-width: 630px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.mozilla-logo {
|
||||
margin-left: -7px;
|
||||
}
|
||||
|
||||
.legal-links {
|
||||
flex-direction: column;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.legal-links > * {
|
||||
display: block;
|
||||
padding: 10px 0;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.social-links {
|
||||
margin-top: 20px;
|
||||
align-self: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-device-width: 520px), (max-width: 520px) {
|
||||
.header {
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.feedback {
|
||||
margin-top: 10px;
|
||||
min-width: 30px;
|
||||
max-width: 300px;
|
||||
text-indent: 2px;
|
||||
padding: 5px 5px 5px 20px;
|
||||
}
|
||||
|
||||
#copy {
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#link {
|
||||
font-size: 22px;
|
||||
padding: 15px 10px;
|
||||
border-radius: 6px 6px 0 0;
|
||||
}
|
||||
|
||||
#copy-btn {
|
||||
border-radius: 0 0 6px 6px;
|
||||
flex: 0 1 65px;
|
||||
}
|
||||
|
||||
th {
|
||||
font-size: 14px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
td {
|
||||
font-size: 13px;
|
||||
padding: 17px 5px 0;
|
||||
}
|
||||
}
|
||||
1
assets/mozilla-logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 578.55 185.54"><path d="M503.5 117.21c0 4.92 2.37 8.82 9 8.82 7.8 0 16.11-5.6 16.61-18.31a80.86 80.86 0 0 0-11-1c-7.83-.01-14.61 2.19-14.61 10.49z"/><path d="M0 0v185.54h578.55V0zm163.78 139.93h-32V96.87c0-13.22-4.41-18.31-13.05-18.31-10.51 0-14.75 7.46-14.75 18.14v26.64h10.12v16.61h-32V96.87c0-13.22-4.4-18.31-13.05-18.31-10.51 0-14.75 7.46-14.75 18.14v26.64h14.54v16.61H22.22v-16.61h10.17V80.09h-11V63.48h32.87V75c4.58-8.13 12.55-13.05 23.22-13.05 11 0 21.19 5.26 24.92 16.45 4.24-10.17 12.88-16.45 24.92-16.45 13.73 0 26.28 8.31 26.28 26.45v34.94h10.17zm48.65 1.69c-23.56 0-39.84-14.41-39.84-38.82 0-22.38 13.56-40.86 41-40.86s40.86 18.48 40.86 39.84c.02 24.42-17.61 39.85-42.02 39.85zm121.72-1.69h-66.8l-2.2-11.53 42-48.32h-23.9l-3.39 11.87-15.77-1.69 2.71-26.79H334L335.69 75l-42.4 48.34H318l3.56-11.87 17.29 1.69zm41.36 0h-22.89v-27.46h22.89zm0-49h-22.89V63.48h22.89zm12 49L420.6 23.34h21.53l-33.06 116.59zm44.42 0L465 23.34h21.53l-33.04 116.59zm113.92 1.69c-10.17 0-15.76-5.94-16.78-15.26-4.41 7.8-12.21 15.26-24.58 15.26-11 0-23.56-5.94-23.56-21.87 0-18.82 18.14-23.22 35.6-23.22a100.23 100.23 0 0 1 12.55.68v-2.54c0-7.8-.17-17.12-12.55-17.12-4.58 0-8.14.34-11.7 2.2L502 90.6l-17.46-1.87 3.39-19.83c13.39-5.43 20.17-7 32.72-7 16.45 0 30.35 8.48 30.35 25.94v33.23c0 4.41 1.69 5.94 5.26 5.94a11.5 11.5 0 0 0 3.22-.51l.17 11.53a29.57 29.57 0 0 1-13.77 3.6z"/><path d="M213.27 78.73c-11.19 0-18.14 8.3-18.14 22.72 0 13.22 6.1 23.39 18 23.39 11.36 0 18.82-9.15 18.82-23.73-.03-15.43-8.33-22.38-18.68-22.38z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/send-fb.jpg
Normal file
|
After Width: | Height: | Size: 312 KiB |
BIN
assets/send-twitter.jpg
Normal file
|
After Width: | Height: | Size: 86 KiB |
1
assets/send_bg.svg
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
1
assets/send_logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="30" height="27" viewBox="0 0 30 27" xmlns="http://www.w3.org/2000/svg"><title>send logo</title><g stroke="#3E3D40" fill="none" fill-rule="evenodd"><path d="M22.364 19.989l-2.153-2.103a2.046 2.046 0 0 0-2.665-.151l3.402 3.323a.531.531 0 0 1 0 .766l-2.466 2.408a.563.563 0 0 1-.784 0l-3.398-3.32a1.932 1.932 0 0 0 .188 2.564l2.153 2.103c.788.77 2.066.77 2.855 0l2.868-2.802a1.94 1.94 0 0 0 0-2.788M8.77 14.745a.534.534 0 0 0 0 .766l3.399 3.32a2.05 2.05 0 0 1-2.625-.184l-2.153-2.102a1.94 1.94 0 0 1 0-2.79l2.869-2.801a2.052 2.052 0 0 1 2.854 0l2.153 2.103c.73.713.775 1.83.154 2.603l-3.401-3.323a.565.565 0 0 0-.784 0L8.77 14.745zm9.464 5.682a.777.777 0 0 1 0 1.118.822.822 0 0 1-1.144 0l-5.6-5.47a.777.777 0 0 1 0-1.118.822.822 0 0 1 1.144 0l5.6 5.47z" stroke-width=".618" fill="#3E3D40"/><path d="M6.065 20.606c-2.913-1.586-3.988-3.656-3.988-6.468 0-2.81 2.265-6.425 5.786-6.289.1.004.55-.006.649 0 .895-3.27 2.508-6.353 6.898-6.353 4.557 0 7.336 3.716 6.75 7.785.08-.005 1.232.17 1.31.186 3.096.644 4.915 3.275 4.915 5.18 0 1.905-.107 3.029-2.023 4.947" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
assets/twitter-icon.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612 612"><path d="M612 116.258a250.714 250.714 0 0 1-72.088 19.772c25.929-15.527 45.777-40.155 55.184-69.411-24.322 14.379-51.169 24.82-79.775 30.48-22.907-24.437-55.49-39.658-91.63-39.658-69.334 0-125.551 56.217-125.551 125.513 0 9.828 1.109 19.427 3.251 28.606-104.326-5.24-196.835-55.223-258.75-131.174-10.823 18.51-16.98 40.078-16.98 63.101 0 43.559 22.181 81.993 55.835 104.479a125.556 125.556 0 0 1-56.867-15.756v1.568c0 60.806 43.291 111.554 100.693 123.104-10.517 2.83-21.607 4.398-33.08 4.398-8.107 0-15.947-.803-23.634-2.333 15.985 49.907 62.336 86.199 117.253 87.194-42.947 33.654-97.099 53.655-155.916 53.655-10.134 0-20.116-.612-29.944-1.721 55.567 35.681 121.536 56.485 192.438 56.485 230.948 0 357.188-191.291 357.188-357.188l-.421-16.253c24.666-17.593 46.005-39.697 62.794-64.861z" fill="#010002"/></svg>
|
||||
|
After Width: | Height: | Size: 873 B |
1
assets/upload.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="57" height="57" viewBox="0 0 57 57" xmlns="http://www.w3.org/2000/svg"><title>upload</title><g transform="translate(1 1)" stroke-width="2" stroke="#7FC9FD" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"><path d="M18 24l10-9 10 9M28 39.545V15"/><circle cx="27.5" cy="27.5" r="27.5"/></g></svg>
|
||||
|
After Width: | Height: | Size: 336 B |
5
browserslist
Normal file
@@ -0,0 +1,5 @@
|
||||
last 2 chrome versions
|
||||
last 2 firefox versions
|
||||
firefox esr
|
||||
ie >= 9
|
||||
safari >= 9
|
||||
38
build/fluent_loader.js
Normal file
@@ -0,0 +1,38 @@
|
||||
const { MessageContext } = require('fluent');
|
||||
|
||||
function toJSON(map) {
|
||||
return JSON.stringify(Array.from(map));
|
||||
}
|
||||
|
||||
module.exports = function(source) {
|
||||
const localeExp = this.options.locale || /([^/]+)\/[^/]+\.ftl$/;
|
||||
const result = localeExp.exec(this.resourcePath);
|
||||
const locale = result && result[1];
|
||||
// pre-parse the ftl
|
||||
const context = new MessageContext(locale);
|
||||
context.addMessages(source);
|
||||
if (!locale) {
|
||||
throw new Error(`couldn't find locale in: ${this.resourcePath}`);
|
||||
}
|
||||
return `
|
||||
module.exports = \`
|
||||
if (typeof window === 'undefined') {
|
||||
var fluent = require('fluent');
|
||||
}
|
||||
var ctx = new fluent.MessageContext('${locale}', {useIsolating: false});
|
||||
ctx._messages = new Map(${toJSON(context._messages)});
|
||||
function translate(id, data) {
|
||||
var msg = ctx.getMessage(id);
|
||||
if (typeof(msg) !== 'string' && !msg.val && msg.attrs) {
|
||||
msg = msg.attrs.title || msg.attrs.alt
|
||||
}
|
||||
return ctx.format(msg, data);
|
||||
}
|
||||
if (typeof window === 'undefined') {
|
||||
module.exports = translate;
|
||||
}
|
||||
else {
|
||||
window.translate = translate;
|
||||
}
|
||||
\``;
|
||||
};
|
||||
19
build/generate_asset_map.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function kv(f) {
|
||||
return `"${f}": require('../assets/${f}')`;
|
||||
}
|
||||
|
||||
module.exports = function() {
|
||||
const files = fs.readdirSync(path.join(__dirname, '..', 'assets'));
|
||||
const code = `module.exports = {
|
||||
"package.json": require('../package.json'),
|
||||
${files.map(kv).join(',\n')}
|
||||
};`;
|
||||
return {
|
||||
code,
|
||||
dependencies: files.map(f => require.resolve('../assets/' + f)),
|
||||
cacheable: false
|
||||
};
|
||||
};
|
||||
22
build/generate_l10n_map.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
function kv(d) {
|
||||
return `"${d}": require('../public/locales/${d}/send.ftl')`;
|
||||
}
|
||||
|
||||
module.exports = function() {
|
||||
const dirs = fs.readdirSync(path.join(__dirname, '..', 'public', 'locales'));
|
||||
const code = `
|
||||
module.exports = {
|
||||
translate: function (id, data) { return window.translate(id, data) },
|
||||
${dirs.map(kv).join(',\n')}
|
||||
};`;
|
||||
return {
|
||||
code,
|
||||
dependencies: dirs.map(d =>
|
||||
require.resolve(`../public/locales/${d}/send.ftl`)
|
||||
),
|
||||
cacheable: false
|
||||
};
|
||||
};
|
||||
11
build/package_json_loader.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const commit = require('git-rev-sync').short();
|
||||
|
||||
module.exports = function(source) {
|
||||
const pkg = JSON.parse(source);
|
||||
const version = {
|
||||
commit,
|
||||
source: pkg.homepage,
|
||||
version: process.env.CIRCLE_TAG || `v${pkg.version}`
|
||||
};
|
||||
return `module.exports = '${JSON.stringify(version)}'`;
|
||||
};
|
||||
20
circle.yml
@@ -3,25 +3,33 @@ machine:
|
||||
version: 8
|
||||
services:
|
||||
- docker
|
||||
- redis
|
||||
environment:
|
||||
PATH: "/home/ubuntu/send/firefox:$PATH"
|
||||
|
||||
dependencies:
|
||||
pre:
|
||||
- npm i -g get-firefox geckodriver nsp
|
||||
- get-firefox --platform linux --extract --target /home/ubuntu/send
|
||||
|
||||
deployment:
|
||||
latest:
|
||||
branch: master
|
||||
commands:
|
||||
- npm run predocker
|
||||
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
|
||||
- docker build -t mozilla/fileshare:latest .
|
||||
- docker push mozilla/fileshare:latest
|
||||
- docker build -t mozilla/send:latest .
|
||||
- docker push mozilla/send:latest
|
||||
tags:
|
||||
tag: /.*/
|
||||
owner: mozilla
|
||||
commands:
|
||||
- npm run predocker
|
||||
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
|
||||
- docker build -t mozilla/fileshare:$CIRCLE_TAG .
|
||||
- docker push mozilla/fileshare:$CIRCLE_TAG
|
||||
- docker build -t mozilla/send:$CIRCLE_TAG .
|
||||
- docker push mozilla/send:$CIRCLE_TAG
|
||||
|
||||
test:
|
||||
override:
|
||||
- npm run build
|
||||
- npm run lint
|
||||
- npm test
|
||||
- nsp check
|
||||
|
||||
32
common/assets.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const genmap = require('../build/generate_asset_map');
|
||||
const isServer = typeof genmap === 'function';
|
||||
const prefix = isServer ? '/' : '';
|
||||
let manifest = {};
|
||||
try {
|
||||
//eslint-disable-next-line node/no-missing-require
|
||||
manifest = require('../dist/manifest.json');
|
||||
} catch (e) {
|
||||
// use middleware
|
||||
}
|
||||
|
||||
const assets = isServer ? manifest : genmap;
|
||||
|
||||
function getAsset(name) {
|
||||
return prefix + assets[name];
|
||||
}
|
||||
|
||||
const instance = {
|
||||
get: getAsset,
|
||||
setMiddleware: function(middleware) {
|
||||
if (middleware) {
|
||||
instance.get = function getAssetWithMiddleware(name) {
|
||||
const f = middleware.fileSystem.readFileSync(
|
||||
middleware.getFilenameFromUrl('/manifest.json')
|
||||
);
|
||||
return prefix + JSON.parse(f)[name];
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = instance;
|
||||
51
common/locales.js
Normal file
@@ -0,0 +1,51 @@
|
||||
const gen = require('../build/generate_l10n_map');
|
||||
|
||||
const isServer = typeof gen === 'function';
|
||||
const prefix = isServer ? '/' : '';
|
||||
let manifest = {};
|
||||
try {
|
||||
//eslint-disable-next-line node/no-missing-require
|
||||
manifest = require('../dist/manifest.json');
|
||||
} catch (e) {
|
||||
// use middleware
|
||||
}
|
||||
|
||||
const locales = isServer ? manifest : gen;
|
||||
|
||||
function getLocale(name) {
|
||||
return prefix + locales[`public/locales/${name}/send.ftl`];
|
||||
}
|
||||
|
||||
function serverTranslator(name) {
|
||||
return require(`../dist/${locales[`public/locales/${name}/send.ftl`]}`);
|
||||
}
|
||||
|
||||
function browserTranslator() {
|
||||
return locales.translate;
|
||||
}
|
||||
|
||||
const translator = isServer ? serverTranslator : browserTranslator;
|
||||
|
||||
const instance = {
|
||||
get: getLocale,
|
||||
getTranslator: translator,
|
||||
setMiddleware: function(middleware) {
|
||||
if (middleware) {
|
||||
const _eval = require('require-from-string');
|
||||
instance.get = function getLocaleWithMiddleware(name) {
|
||||
const f = middleware.fileSystem.readFileSync(
|
||||
middleware.getFilenameFromUrl('/manifest.json')
|
||||
);
|
||||
return prefix + JSON.parse(f)[`public/locales/${name}/send.ftl`];
|
||||
};
|
||||
instance.getTranslator = function(name) {
|
||||
const f = middleware.fileSystem.readFileSync(
|
||||
middleware.getFilenameFromUrl(instance.get(name))
|
||||
);
|
||||
return _eval(f.toString());
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = instance;
|
||||
@@ -7,6 +7,7 @@ services:
|
||||
ports:
|
||||
- "1443:1443"
|
||||
environment:
|
||||
- P2P_REDIS_HOST=redis
|
||||
- REDIS_HOST=redis
|
||||
- NODE_ENV=production
|
||||
redis:
|
||||
image: redis:alpine
|
||||
|
||||
2
docs/CODEOWNERS
Normal file
@@ -0,0 +1,2 @@
|
||||
# flod as main contact for string changes
|
||||
public/locales/en-US/*.ftl @flodolo
|
||||
@@ -1,10 +1,35 @@
|
||||
Environment Variables:
|
||||
## Setup
|
||||
|
||||
PORT - port the server will listen on (defaults to 1443)
|
||||
P2P_S3_BUCKET - the S3 bucket name
|
||||
P2P_REDIS_HOST - host name of the redis server
|
||||
NODE_ENV - production
|
||||
Before building the Docker image, you must build the production assets:
|
||||
|
||||
Example
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
docker run --net=host -e 'NODE_ENV=production' -e 'P2P_S3_BUCKET=testpilot-p2p-dev' -e 'P2P_REDIS_HOST=dyf9s2r4vo3.bolxr4.0001.usw2.cache.amazonaws.com' mozilla/portal:latest
|
||||
Then you can run either `docker build` or `docker-compose up`.
|
||||
|
||||
|
||||
## Environment variables:
|
||||
|
||||
| Name | Description
|
||||
|------------------|-------------|
|
||||
| `PORT` | Port the server will listen on (defaults to 1443).
|
||||
| `S3_BUCKET` | The S3 bucket name.
|
||||
| `REDIS_HOST` | Host name of the Redis server.
|
||||
| `GOOGLE_ANALYTICS_ID` | Google Analytics ID
|
||||
| `SENTRY_CLIENT` | Sentry Client ID
|
||||
| `SENTRY_DSN` | Sentry DSN
|
||||
| `MAX_FILE_SIZE` | in bytes (defaults to 2147483648)
|
||||
| `NODE_ENV` | "production"
|
||||
|
||||
## Example:
|
||||
|
||||
```sh
|
||||
$ docker run --net=host -e 'NODE_ENV=production' \
|
||||
-e 'S3_BUCKET=testpilot-p2p-dev' \
|
||||
-e 'REDIS_HOST=dyf9s2r4vo3.bolxr4.0001.usw2.cache.amazonaws.com' \
|
||||
-e 'GOOGLE_ANALYTICS_ID=UA-35433268-78' \
|
||||
-e 'SENTRY_CLIENT=https://51e23d7263e348a7a3b90a5357c61cb2@sentry.prod.mozaws.net/168' \
|
||||
-e 'SENTRY_DSN=https://51e23d7263e348a7a3b90a5357c61cb2:65e23d7263e348a7a3b90a5357c61c44@sentry.prod.mozaws.net/168' \
|
||||
mozilla/send:latest
|
||||
```
|
||||
|
||||
43
docs/faq.md
Normal file
@@ -0,0 +1,43 @@
|
||||
## How big of a file can I transfer with Firefox Send?
|
||||
|
||||
There is a 2GB file size limit built in to Send, however, in practice you may
|
||||
be unable to send files that large. Send encrypts and decrypts the files in
|
||||
the browser which is great for security but will tax your system resources. In
|
||||
particular you can expect to see your memory usage go up by at least the size
|
||||
of the file when the transfer is processing. You can see [the results of some
|
||||
testing](https://github.com/mozilla/send/issues/170#issuecomment-314107793).
|
||||
For the most reliable operation on common computers, it’s probably best to stay
|
||||
under a few hundred megabytes.
|
||||
|
||||
## Why is my browser not supported?
|
||||
|
||||
We’re using the [Web Cryptography JavaScript API with the AES-GCM
|
||||
algorithm](https://www.w3.org/TR/WebCryptoAPI/#aes-gcm) for our encryption.
|
||||
Many browsers support this standard and should work fine, but some have not
|
||||
implemented it yet (mobile browsers lag behind on this, in
|
||||
particular).
|
||||
|
||||
## Why does Firefox Send require JavaScript?
|
||||
|
||||
Firefox Send uses JavaScript to:
|
||||
|
||||
- Encrypt and decrypt files locally on the client instead of the server.
|
||||
- Render the user interface.
|
||||
- Manage translations on the website into [various different languages](https://github.com/mozilla/send#localization).
|
||||
- Collect data to help us improve Send in accordance with our [Terms & Privacy](https://send.firefox.com/legal).
|
||||
|
||||
Since Send is an open source project, you can see all of the cool ways we use JavaScript by [examining our code](https://github.com/mozilla/send/).
|
||||
|
||||
## How long are files available for?
|
||||
|
||||
Files are available to be downloaded for 24 hours, after which they are removed
|
||||
from the server. They are also removed immediately after a download completes.
|
||||
|
||||
## Can a file be downloaded more than once?
|
||||
|
||||
Not currently, but we're considering multiple download support in a future
|
||||
release.
|
||||
|
||||
|
||||
*Disclaimer: Send is an experiment and under active development. The answers
|
||||
here may change as we get feedback from you and the project matures.*
|
||||
136
docs/metrics.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# Send Metrics
|
||||
The metrics collection and analysis plan for Send, a forthcoming Test Pilot experiment.
|
||||
|
||||
## Analysis
|
||||
Data collected by Send will be used to answer the following high-level questions:
|
||||
|
||||
- Do users send files?
|
||||
- How often? How many?
|
||||
- What is the retention?
|
||||
- What is the distribution of senders?
|
||||
- How do recipients interact with promotional UI elements?
|
||||
- Are file recipients converted to file senders?
|
||||
- Are non-Firefox users converted to Firefox users?
|
||||
- Where does it go wrong?
|
||||
- How often are there errors in uploading or downloading files?
|
||||
- What types of errors to users commonly see?
|
||||
- At what point do errors affect retention?
|
||||
|
||||
## Collection
|
||||
Data will be collected with Google Analytics and follow [Test Pilot standards](https://github.com/mozilla/testpilot/blob/master/docs/experiments/ga.md) for reporting.
|
||||
|
||||
### Custom Metrics
|
||||
- `cm1` - the size of the file, in bytes.
|
||||
- `cm2` - the amount of time it took to complete the file transfer, in milliseconds. Only include if the file completed transferring (ref: `cd2`).
|
||||
- `cm3` - the rate of the file transfer, in bytes per second. This is computed by dividing `cm1` by `cm2`, not by monitoring transfer speeds. Only include if the file completed transferring (ref: `cd2`).
|
||||
- `cm4` - the amount of time until the file will expire, in milliseconds.
|
||||
- `cm5` - the number of files the user has ever uploaded.
|
||||
- `cm6` - the number of unexpired files the user has uploaded.
|
||||
- `cm7` - the number of files the user has ever downloaded.
|
||||
|
||||
### Custom Dimensions
|
||||
- `cd1` - the method by which the user initiated an upload. One of `drag`, `click`.
|
||||
- `cd2` - the reason that the file transfer stopped. One of `completed`, `errored`, `cancelled`.
|
||||
- `cd3` - the destination of a link click. One of `experiment-page`, `download-firefox`, `twitter`, `github`, `cookies`, `terms`, `privacy`, `about`, `legal`, `mozilla`.
|
||||
- `cd4` - the location from which the user copied the URL to an upload file. One of `success-screen`, `upload-list`.
|
||||
- `cd5` - the referring location. One of `completed-download`, `errored-download`, `cancelled-download`, `completed-upload`, `errored-upload`, `cancelled-upload`, `testpilot`, `external`.
|
||||
- `cd6` - identifying information about an error. Exclude if there is no error involved. **TODO:** enumerate a list of possibilities.
|
||||
|
||||
### Events
|
||||
|
||||
_NB:_ due to how files are being tracked, there are no events indicating file expiry. This carries some risk: most notably, we can only derive expiration rates by looking at download rates, which is prone to skew if there are problems in data collection.
|
||||
|
||||
#### `upload-started`
|
||||
Triggered whenever a user begins uploading a file. Includes:
|
||||
|
||||
- `ec` - `sender`
|
||||
- `ea` - `upload-started`
|
||||
- `cm1`
|
||||
- `cm5`
|
||||
- `cm6`
|
||||
- `cm7`
|
||||
- `cd1`
|
||||
- `cd5`
|
||||
|
||||
#### `upload-stopped`
|
||||
Triggered whenever a user stops uploading a file. Includes:
|
||||
|
||||
- `ec` - `sender`
|
||||
- `ea` - `upload-stopped`
|
||||
- `cm1`
|
||||
- `cm2`
|
||||
- `cm3`
|
||||
- `cm5`
|
||||
- `cm6`
|
||||
- `cm7`
|
||||
- `cd1`
|
||||
- `cd2`
|
||||
- `cd6`
|
||||
|
||||
#### `download-started`
|
||||
Triggered whenever a user begins downloading a file. Includes:
|
||||
|
||||
- `ec` - `recipient`
|
||||
- `ea` - `download-started`
|
||||
- `cm1`
|
||||
- `cm4`
|
||||
- `cm5`
|
||||
- `cm6`
|
||||
- `cm7`
|
||||
|
||||
#### `download-stopped`
|
||||
Triggered whenever a user stops downloading a file.
|
||||
|
||||
- `ec` - `recipient`
|
||||
- `ea` - `download-stopped`
|
||||
- `cm1`
|
||||
- `cm2` (if possible and applicable)
|
||||
- `cm3` (if possible and applicable)
|
||||
- `cm5`
|
||||
- `cm6`
|
||||
- `cm7`
|
||||
- `cd2`
|
||||
- `cd6`
|
||||
|
||||
#### `exited`
|
||||
Fired whenever a user follows a link external to Send.
|
||||
|
||||
- `ec` - `recipient`, `sender`, or `other`, as applicable.
|
||||
- `ea` - `exited`
|
||||
- `cd3`
|
||||
|
||||
#### `upload-deleted`
|
||||
Fired whenever a user deletes a file they’ve uploaded.
|
||||
|
||||
- `ec` - `sender`
|
||||
- `ea` - `upload-deleted`
|
||||
- `cm1`
|
||||
- `cm2`
|
||||
- `cm3`
|
||||
- `cm4`
|
||||
- `cm5`
|
||||
- `cm6`
|
||||
- `cm7`
|
||||
- `cd1`
|
||||
- `cd4`
|
||||
|
||||
#### `copied`
|
||||
Fired whenever a user copies the URL of an upload file.
|
||||
|
||||
- `ec` - `sender`
|
||||
- `ea` - `copied`
|
||||
- `cd4`
|
||||
|
||||
#### `restarted`
|
||||
Fired whenever the user interrupts any part of funnel to return to the start of it (e.g. with a “send another file” or “send your own files” link).
|
||||
|
||||
- `ec` - `recipient`, `sender`, or `other`, as applicable.
|
||||
- `ea` - `restarted`
|
||||
- `cd2`
|
||||
|
||||
#### `unsupported`
|
||||
Fired whenever a user is presented a message saying that their browser is unsupported due to missing crypto APIs.
|
||||
|
||||
- `ec` - `recipient` or `sender`, as applicable.
|
||||
- `ea` - `unsupported`
|
||||
- `cd6`
|
||||
@@ -1,3 +0,0 @@
|
||||
env:
|
||||
browser: true
|
||||
jquery: true
|
||||
@@ -1,72 +0,0 @@
|
||||
const FileReceiver = require('./fileReceiver');
|
||||
const { notify } = require('./utils');
|
||||
const $ = require('jquery');
|
||||
|
||||
const Raven = window.Raven;
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#download-progress').hide();
|
||||
$('#send-file').click(() => {
|
||||
window.location.replace(`${window.location.origin}`);
|
||||
});
|
||||
const download = () => {
|
||||
const fileReceiver = new FileReceiver();
|
||||
const name = document.createElement('p');
|
||||
const $btn = $('#download-btn');
|
||||
|
||||
fileReceiver.on('progress', percentComplete => {
|
||||
$('#download-page-one').hide();
|
||||
$('.send-new').hide();
|
||||
$('#download-progress').show();
|
||||
// update progress bar
|
||||
document
|
||||
.querySelector('#progress-bar')
|
||||
.style.setProperty('--progress', percentComplete + '%');
|
||||
$('#progress-text').html(`${percentComplete}%`);
|
||||
//on complete
|
||||
if (percentComplete === 100) {
|
||||
fileReceiver.removeAllListeners('progress');
|
||||
$('#download-text').html('Download complete!');
|
||||
$('.send-new').show();
|
||||
$btn.text('Download complete!');
|
||||
$btn.attr('disabled', 'true');
|
||||
notify('Your download has finished.');
|
||||
}
|
||||
});
|
||||
|
||||
fileReceiver
|
||||
.download()
|
||||
.catch(() => {
|
||||
$('.title').text(
|
||||
'This link has expired or never existed in the first place.'
|
||||
);
|
||||
$('#download-btn').hide();
|
||||
$('#expired-img').show();
|
||||
console.log('The file has expired, or has already been deleted.');
|
||||
return;
|
||||
})
|
||||
.then(([decrypted, fname]) => {
|
||||
name.innerText = fname;
|
||||
const dataView = new DataView(decrypted);
|
||||
const blob = new Blob([dataView]);
|
||||
const downloadUrl = URL.createObjectURL(blob);
|
||||
|
||||
const a = document.createElement('a');
|
||||
a.href = downloadUrl;
|
||||
if (window.navigator.msSaveBlob) {
|
||||
// if we are in microsoft edge or IE
|
||||
window.navigator.msSaveBlob(blob, fname);
|
||||
return;
|
||||
}
|
||||
a.download = fname;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
})
|
||||
.catch(err => {
|
||||
Raven.captureException(err);
|
||||
return Promise.reject(err);
|
||||
});
|
||||
};
|
||||
|
||||
window.download = download;
|
||||
});
|
||||
@@ -1,90 +0,0 @@
|
||||
const EventEmitter = require('events');
|
||||
const { strToIv } = require('./utils');
|
||||
|
||||
const Raven = window.Raven;
|
||||
|
||||
class FileReceiver extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
this.salt = strToIv(location.pathname.slice(10, -1));
|
||||
}
|
||||
|
||||
download() {
|
||||
return Promise.all([
|
||||
new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.onprogress = event => {
|
||||
if (event.lengthComputable) {
|
||||
const percentComplete = Math.floor(
|
||||
event.loaded / event.total * 100
|
||||
);
|
||||
this.emit('progress', percentComplete);
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onload = function(event) {
|
||||
if (xhr.status === 404) {
|
||||
reject(
|
||||
new Error('The file has expired, or has already been deleted.')
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const blob = new Blob([this.response]);
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = function() {
|
||||
resolve({
|
||||
data: this.result,
|
||||
fname: xhr
|
||||
.getResponseHeader('Content-Disposition')
|
||||
.match(/=(.+)/)[1]
|
||||
});
|
||||
};
|
||||
|
||||
fileReader.readAsArrayBuffer(blob);
|
||||
};
|
||||
|
||||
xhr.open('get', '/assets' + location.pathname.slice(0, -1), true);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.send();
|
||||
}),
|
||||
window.crypto.subtle.importKey(
|
||||
'jwk',
|
||||
{
|
||||
kty: 'oct',
|
||||
k: location.hash.slice(1),
|
||||
alg: 'A128CBC',
|
||||
ext: true
|
||||
},
|
||||
{
|
||||
name: 'AES-CBC'
|
||||
},
|
||||
true,
|
||||
['encrypt', 'decrypt']
|
||||
)
|
||||
])
|
||||
.then(([fdata, key]) => {
|
||||
const salt = this.salt;
|
||||
return Promise.all([
|
||||
window.crypto.subtle.decrypt(
|
||||
{
|
||||
name: 'AES-CBC',
|
||||
iv: salt
|
||||
},
|
||||
key,
|
||||
fdata.data
|
||||
),
|
||||
new Promise((resolve, reject) => {
|
||||
resolve(fdata.fname);
|
||||
})
|
||||
]);
|
||||
})
|
||||
.catch(err => {
|
||||
Raven.captureException(err);
|
||||
return Promise.reject(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FileReceiver;
|
||||
@@ -1,112 +0,0 @@
|
||||
const EventEmitter = require('events');
|
||||
const { ivToStr } = require('./utils');
|
||||
|
||||
const Raven = window.Raven;
|
||||
|
||||
class FileSender extends EventEmitter {
|
||||
constructor(file) {
|
||||
super();
|
||||
this.file = file;
|
||||
this.iv = window.crypto.getRandomValues(new Uint8Array(16));
|
||||
}
|
||||
|
||||
static delete(fileId, token) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!fileId || !token) {
|
||||
return reject();
|
||||
}
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('post', '/delete/' + fileId, true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
resolve();
|
||||
}
|
||||
|
||||
if (xhr.status === 200) {
|
||||
console.log('The file was successfully deleted.');
|
||||
} else {
|
||||
console.log('The file has expired, or has already been deleted.');
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(JSON.stringify({ delete_token: token }));
|
||||
});
|
||||
}
|
||||
|
||||
upload() {
|
||||
return Promise.all([
|
||||
window.crypto.subtle.generateKey(
|
||||
{
|
||||
name: 'AES-CBC',
|
||||
length: 128
|
||||
},
|
||||
true,
|
||||
['encrypt', 'decrypt']
|
||||
),
|
||||
new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsArrayBuffer(this.file);
|
||||
reader.onload = function(event) {
|
||||
resolve(new Uint8Array(this.result));
|
||||
};
|
||||
})
|
||||
])
|
||||
.then(([secretKey, plaintext]) => {
|
||||
return Promise.all([
|
||||
window.crypto.subtle.encrypt(
|
||||
{
|
||||
name: 'AES-CBC',
|
||||
iv: this.iv
|
||||
},
|
||||
secretKey,
|
||||
plaintext
|
||||
),
|
||||
window.crypto.subtle.exportKey('jwk', secretKey)
|
||||
]);
|
||||
})
|
||||
.then(([encrypted, keydata]) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = this.file;
|
||||
const fileId = ivToStr(this.iv);
|
||||
const dataView = new DataView(encrypted);
|
||||
const blob = new Blob([dataView], { type: file.type });
|
||||
const fd = new FormData();
|
||||
fd.append('fname', file.name);
|
||||
fd.append('data', blob, file.name);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.upload.addEventListener('progress', e => {
|
||||
if (e.lengthComputable) {
|
||||
const percentComplete = Math.floor(e.loaded / e.total * 100);
|
||||
this.emit('progress', percentComplete);
|
||||
}
|
||||
});
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
// uuid field and url field
|
||||
const responseObj = JSON.parse(xhr.responseText);
|
||||
resolve({
|
||||
url: responseObj.url,
|
||||
fileId: fileId,
|
||||
secretKey: keydata.k,
|
||||
deleteToken: responseObj.uuid
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
xhr.open('post', '/upload/' + fileId, true);
|
||||
xhr.send(fd);
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
Raven.captureException(err);
|
||||
return Promise.reject(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FileSender;
|
||||
@@ -1,5 +0,0 @@
|
||||
window.Raven = require('raven-js');
|
||||
window.Raven.config(window.dsn).install();
|
||||
window.dsn = undefined;
|
||||
require('./upload');
|
||||
require('./download');
|
||||
@@ -1,162 +0,0 @@
|
||||
const FileSender = require('./fileSender');
|
||||
const { notify } = require('./utils');
|
||||
const $ = require('jquery');
|
||||
|
||||
$(document).ready(function() {
|
||||
// reset copy button
|
||||
const $copyBtn = $('#copy-btn');
|
||||
$copyBtn.attr('disabled', false);
|
||||
$copyBtn.html('Copy');
|
||||
|
||||
$('#page-one').show();
|
||||
$('#file-list').show();
|
||||
$('#upload-progress').hide();
|
||||
$('#share-link').hide();
|
||||
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const id = localStorage.key(i);
|
||||
populateFileList(localStorage.getItem(id));
|
||||
}
|
||||
|
||||
// copy link to clipboard
|
||||
$copyBtn.click(() => {
|
||||
const aux = document.createElement('input');
|
||||
aux.setAttribute('value', $('#link').attr('value'));
|
||||
document.body.appendChild(aux);
|
||||
aux.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(aux);
|
||||
//disable button for 3s
|
||||
$copyBtn.attr('disabled', true);
|
||||
$copyBtn.html('Copied!');
|
||||
window.setTimeout(() => {
|
||||
$copyBtn.attr('disabled', false);
|
||||
$copyBtn.html('Copy');
|
||||
}, 3000);
|
||||
});
|
||||
|
||||
// link back to home page
|
||||
$('.send-new').click(() => {
|
||||
$('#page-one').show();
|
||||
$('#file-list').show();
|
||||
$('#upload-progress').hide();
|
||||
$('#share-link').hide();
|
||||
$copyBtn.attr('disabled', false);
|
||||
$copyBtn.html('Copy');
|
||||
});
|
||||
|
||||
// on file upload by browse or drag & drop
|
||||
window.onUpload = event => {
|
||||
event.preventDefault();
|
||||
let file = '';
|
||||
if (event.type === 'drop') {
|
||||
file = event.dataTransfer.files[0];
|
||||
} else {
|
||||
file = event.target.files[0];
|
||||
}
|
||||
|
||||
const fileSender = new FileSender(file);
|
||||
fileSender.on('progress', percentComplete => {
|
||||
$('#page-one').hide();
|
||||
$('#file-list').hide();
|
||||
$('#upload-progress').show();
|
||||
$('#upload-filename').innerHTML += file.name;
|
||||
// update progress bar
|
||||
document
|
||||
.querySelector('#progress-bar')
|
||||
.style.setProperty('--progress', percentComplete + '%');
|
||||
$('#progress-text').html(`${percentComplete}%`);
|
||||
});
|
||||
fileSender.upload().then(info => {
|
||||
const url = info.url.trim() + `#${info.secretKey}`.trim();
|
||||
$('#link').attr('value', url);
|
||||
const fileData = {
|
||||
name: file.name,
|
||||
fileId: info.fileId,
|
||||
url: info.url,
|
||||
secretKey: info.secretKey,
|
||||
deleteToken: info.deleteToken
|
||||
};
|
||||
localStorage.setItem(info.fileId, JSON.stringify(fileData));
|
||||
|
||||
$('#page-one').hide();
|
||||
$('#file-list').hide();
|
||||
$('#upload-progress').hide();
|
||||
$('#share-link').show();
|
||||
|
||||
populateFileList(JSON.stringify(fileData));
|
||||
notify('Your upload has finished.');
|
||||
});
|
||||
};
|
||||
|
||||
window.allowDrop = function(ev) {
|
||||
ev.preventDefault();
|
||||
};
|
||||
|
||||
//update file table with current files in localStorage
|
||||
function populateFileList(file) {
|
||||
try {
|
||||
file = JSON.parse(file);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
const row = document.createElement('tr');
|
||||
const name = document.createElement('td');
|
||||
const link = document.createElement('td');
|
||||
const expiry = document.createElement('td');
|
||||
const del = document.createElement('td');
|
||||
del.setAttribute('align', 'center');
|
||||
const btn = document.createElement('button');
|
||||
const popupDiv = document.createElement('div');
|
||||
const $popupText = $('<span>', { class: 'popuptext' });
|
||||
const cellText = document.createTextNode(file.name);
|
||||
|
||||
name.appendChild(cellText);
|
||||
|
||||
// create delete button
|
||||
btn.innerHTML = 'x';
|
||||
btn.classList.add('delete-btn');
|
||||
link.innerHTML = file.url.trim() + `#${file.secretKey}`.trim();
|
||||
|
||||
// create popup
|
||||
popupDiv.classList.add('popup');
|
||||
$popupText.html(
|
||||
'<span class="del-file">Delete</span><span class="nvm" > Nevermind</span>'
|
||||
);
|
||||
|
||||
// delete file
|
||||
$popupText.find('.del-file').click(e => {
|
||||
FileSender.delete(file.fileId, file.deleteToken).then(() => {
|
||||
$(e.target).parents('tr').remove();
|
||||
localStorage.removeItem(file.fileId);
|
||||
});
|
||||
});
|
||||
|
||||
// add data cells to table row
|
||||
row.appendChild(name);
|
||||
row.appendChild(link);
|
||||
row.appendChild(expiry);
|
||||
popupDiv.appendChild(btn);
|
||||
$(popupDiv).append($popupText);
|
||||
del.appendChild(popupDiv);
|
||||
row.appendChild(del);
|
||||
|
||||
// show popup
|
||||
del.addEventListener('click', toggleShow);
|
||||
// hide popup
|
||||
$popupText.find('.nvm').click(function(e) {
|
||||
e.stopPropagation();
|
||||
toggleShow();
|
||||
});
|
||||
$popupText.click(function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
$('tbody').append(row); //add row to table
|
||||
|
||||
function toggleShow() {
|
||||
$popupText.toggleClass('show');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,39 +0,0 @@
|
||||
function ivToStr(iv) {
|
||||
let hexStr = '';
|
||||
for (const i in iv) {
|
||||
if (iv[i] < 16) {
|
||||
hexStr += '0' + iv[i].toString(16);
|
||||
} else {
|
||||
hexStr += iv[i].toString(16);
|
||||
}
|
||||
}
|
||||
window.hexStr = hexStr;
|
||||
return hexStr;
|
||||
}
|
||||
|
||||
function strToIv(str) {
|
||||
const iv = new Uint8Array(16);
|
||||
for (let i = 0; i < str.length; i += 2) {
|
||||
iv[i / 2] = parseInt(str.charAt(i) + str.charAt(i + 1), 16);
|
||||
}
|
||||
|
||||
return iv;
|
||||
}
|
||||
|
||||
function notify(str) {
|
||||
if (!('Notification' in window)) {
|
||||
return;
|
||||
} else if (Notification.permission === 'granted') {
|
||||
new Notification(str);
|
||||
} else if (Notification.permission !== 'denied') {
|
||||
Notification.requestPermission(function(permission) {
|
||||
if (permission === 'granted') new Notification(str);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ivToStr,
|
||||
strToIv,
|
||||
notify
|
||||
};
|
||||
12
l10n.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
basepath = "."
|
||||
|
||||
[env]
|
||||
l = "{l10n_base}/public/locales/{locale}/"
|
||||
|
||||
[[paths]]
|
||||
reference = "public/locales/en-US/**"
|
||||
l10n = "{l}**"
|
||||
10185
package-lock.json
generated
193
package.json
@@ -1,56 +1,153 @@
|
||||
{
|
||||
"name": "portal-alpha",
|
||||
"name": "firefox-send",
|
||||
"description": "File Sharing Experiment",
|
||||
"version": "0.1.2",
|
||||
"version": "1.2.0",
|
||||
"author": "Mozilla (https://mozilla.org)",
|
||||
"dependencies": {
|
||||
"aws-sdk": "^2.62.0",
|
||||
"body-parser": "^1.17.2",
|
||||
"bytes": "^2.5.0",
|
||||
"connect-busboy": "0.0.2",
|
||||
"convict": "^3.0.0",
|
||||
"cross-env": "^5.0.1",
|
||||
"express": "^4.15.3",
|
||||
"express-handlebars": "^3.0.0",
|
||||
"helmet": "^3.6.1",
|
||||
"jquery": "^3.2.1",
|
||||
"mozlog": "^2.1.1",
|
||||
"raven": "^2.1.0",
|
||||
"raven-js": "^3.16.0",
|
||||
"redis": "^2.7.1",
|
||||
"uglify-es": "3.0.19"
|
||||
"repository": "mozilla/send",
|
||||
"homepage": "https://github.com/mozilla/send/",
|
||||
"license": "MPL-2.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"precommit": "lint-staged",
|
||||
"clean": "rimraf dist",
|
||||
"build": "npm run clean && webpack -p",
|
||||
"lint": "npm-run-all lint:*",
|
||||
"lint:css": "stylelint 'assets/*.css'",
|
||||
"lint:js": "eslint .",
|
||||
"lint-locales": "node scripts/lint-locales",
|
||||
"lint-locales:dev": "npm run lint-locales",
|
||||
"lint-locales:prod": "npm run lint-locales -- --production",
|
||||
"format": "prettier '**/*.js' 'assets/*.css' --single-quote --write",
|
||||
"get-prod-locales": "node scripts/get-prod-locales",
|
||||
"get-prod-locales:write": "npm run get-prod-locales -- --write",
|
||||
"changelog": "github-changes -o mozilla -r send --only-pulls --use-commit-body --no-merges",
|
||||
"contributors": "git shortlog -s | awk -F\\t '{print $2}' > CONTRIBUTORS",
|
||||
"release": "npm-run-all contributors changelog",
|
||||
"test": "mocha test/unit",
|
||||
"start": "cross-env NODE_ENV=development webpack-dev-server",
|
||||
"prod": "node server/prod.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^14.4.0",
|
||||
"eslint": "^4.0.0",
|
||||
"eslint-plugin-mocha": "^4.11.0",
|
||||
"eslint-plugin-node": "^5.0.0",
|
||||
"eslint-plugin-security": "^1.4.0",
|
||||
"git-rev-sync": "^1.9.1",
|
||||
"mocha": "^3.4.2",
|
||||
"npm-run-all": "^4.0.2",
|
||||
"prettier": "^1.4.4",
|
||||
"proxyquire": "^1.8.0",
|
||||
"sinon": "^2.3.5",
|
||||
"stylelint": "^7.11.0",
|
||||
"stylelint-config-standard": "^16.0.0",
|
||||
"watchify": "^3.9.0"
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"prettier --single-quote --write",
|
||||
"eslint",
|
||||
"git add"
|
||||
],
|
||||
"*.css": [
|
||||
"prettier --single-quote --write",
|
||||
"stylelint",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
"node": ">=8.2.0"
|
||||
},
|
||||
"homepage": "https://github.com/mozilla/something-awesome/",
|
||||
"license": "MPL-2.0",
|
||||
"repository": "mozilla/something-awesome",
|
||||
"scripts": {
|
||||
"predocker": "browserify frontend/src/main.js | uglifyjs > public/bundle.js && npm run version",
|
||||
"dev": "npm run version && watchify frontend/src/main.js -o public/bundle.js -d | node server/portal_server",
|
||||
"format": "prettier '{frontend/src/,scripts/,server/,test/}*.js' 'public/*.css' --single-quote --write",
|
||||
"lint": "npm-run-all lint:*",
|
||||
"lint:css": "stylelint 'public/*.css'",
|
||||
"lint:js": "eslint .",
|
||||
"start": "node server/portal_server",
|
||||
"test": "mocha",
|
||||
"version": "node scripts/version"
|
||||
}
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^7.1.4",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-plugin-yo-yoify": "^0.7.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-stage-2": "^6.24.1",
|
||||
"choo-log": "^7.2.1",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"cross-env": "^5.0.5",
|
||||
"css-loader": "^0.28.7",
|
||||
"css-mqpacker": "^6.0.1",
|
||||
"cssnano": "^3.10.0",
|
||||
"eslint": "^4.6.1",
|
||||
"eslint-plugin-mocha": "^4.11.0",
|
||||
"eslint-plugin-node": "^5.1.1",
|
||||
"eslint-plugin-security": "^1.4.0",
|
||||
"expose-loader": "^0.7.3",
|
||||
"extract-loader": "^1.0.1",
|
||||
"file-loader": "^0.11.2",
|
||||
"git-rev-sync": "^1.9.1",
|
||||
"github-changes": "^1.1.0",
|
||||
"html-loader": "^0.5.1",
|
||||
"husky": "^0.14.3",
|
||||
"lint-staged": "^4.1.3",
|
||||
"mocha": "^3.5.3",
|
||||
"nanobus": "^4.2.0",
|
||||
"npm-run-all": "^4.1.1",
|
||||
"postcss-loader": "^2.0.6",
|
||||
"prettier": "^1.6.1",
|
||||
"proxyquire": "^1.8.0",
|
||||
"raven-js": "^3.17.0",
|
||||
"redis-mock": "^0.20.0",
|
||||
"require-from-string": "^1.2.1",
|
||||
"rimraf": "^2.6.2",
|
||||
"selenium-webdriver": "^3.5.0",
|
||||
"sinon": "^3.2.1",
|
||||
"string-hash": "^1.1.3",
|
||||
"stylelint-config-standard": "^17.0.0",
|
||||
"stylelint-no-unsupported-browser-features": "^1.0.0",
|
||||
"supertest": "^3.0.0",
|
||||
"testpilot-ga": "^0.3.0",
|
||||
"val-loader": "^1.0.2",
|
||||
"webpack": "^3.5.6",
|
||||
"webpack-dev-server": "^2.8.0",
|
||||
"webpack-manifest-plugin": "^1.3.1",
|
||||
"webpack-unassert-loader": "^1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"aws-sdk": "^2.114.0",
|
||||
"body-parser": "^1.18.1",
|
||||
"choo": "^6.0.1",
|
||||
"connect-busboy": "0.0.2",
|
||||
"convict": "^4.0.0",
|
||||
"express": "^4.15.4",
|
||||
"express-request-language": "^1.1.12",
|
||||
"fluent": "^0.4.1",
|
||||
"fluent-langneg": "^0.1.0",
|
||||
"helmet": "^3.8.1",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mozlog": "^2.1.1",
|
||||
"raven": "^2.1.2",
|
||||
"redis": "^2.8.0"
|
||||
},
|
||||
"availableLanguages": [
|
||||
"en-US",
|
||||
"ast",
|
||||
"az",
|
||||
"ca",
|
||||
"cak",
|
||||
"cs",
|
||||
"cy",
|
||||
"de",
|
||||
"dsb",
|
||||
"el",
|
||||
"es-AR",
|
||||
"es-CL",
|
||||
"es-ES",
|
||||
"es-MX",
|
||||
"fa",
|
||||
"fr",
|
||||
"fy-NL",
|
||||
"hsb",
|
||||
"hu",
|
||||
"id",
|
||||
"it",
|
||||
"ja",
|
||||
"kab",
|
||||
"ko",
|
||||
"ms",
|
||||
"nb-NO",
|
||||
"nl",
|
||||
"nn-NO",
|
||||
"pt-BR",
|
||||
"pt-PT",
|
||||
"ru",
|
||||
"sk",
|
||||
"sl",
|
||||
"sr",
|
||||
"sv-SE",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zh-CN",
|
||||
"zh-TW"
|
||||
]
|
||||
}
|
||||
|
||||
15
postcss.config.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const autoprefixer = require('autoprefixer');
|
||||
const cssnano = require('cssnano');
|
||||
const mqpacker = require('css-mqpacker');
|
||||
|
||||
const config = require('./server/config');
|
||||
|
||||
const options = {
|
||||
plugins: [autoprefixer, mqpacker, cssnano]
|
||||
};
|
||||
|
||||
if (config.env === 'development') {
|
||||
options.map = { inline: true };
|
||||
}
|
||||
|
||||
module.exports = options;
|
||||
27
public/contribute.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "firefox-send",
|
||||
"description": "File Sharing Experiment",
|
||||
"repository": {
|
||||
"url": "https://github.com/mozilla/send/",
|
||||
"license": "MPL-2.0"
|
||||
},
|
||||
"participate": {
|
||||
"home": "https://github.com/mozilla/send/blob/master/README.md",
|
||||
"docs": "https://github.com/mozilla/send/blob/master/README.md"
|
||||
},
|
||||
"bugs": {
|
||||
"list": "https://github.com/mozilla/send/issues",
|
||||
"report": "https://github.com/mozilla/send/issues/new"
|
||||
},
|
||||
"urls": {
|
||||
"prod": "https://send.firefox.com/",
|
||||
"stage": "https://send.stage.mozaws.net/",
|
||||
"dev": "https://send.dev.mozaws.net/"
|
||||
},
|
||||
"keywords": [
|
||||
"JavaScript",
|
||||
"jQuery",
|
||||
"Node",
|
||||
"Redis"
|
||||
]
|
||||
}
|
||||
82
public/locales/ast/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = esperimentu web
|
||||
siteFeedback = Feedback
|
||||
uploadPageHeader = Compartición privada y cifrada de ficheros
|
||||
uploadPageExplainer = Unvia ficheros pente un enllaz seguru, priváu y cifráu que caduca automáticamente p'asegurar que les tos coses nun queden siempres na rede.
|
||||
uploadPageLearnMore = Deprendi más
|
||||
uploadPageDropMessage = Suelta equí'l to ficheru p'aniciar la xuba
|
||||
uploadPageSizeMessage = Pal meyor funcionamientu, lo meyor ye que'l to ficheru seya menor de 1GB
|
||||
uploadPageBrowseButton = Esbilla un ficheru nel to ordenador
|
||||
uploadPageBrowseButton1 = Esbilla un ficheru pa unviar
|
||||
uploadPageMultipleFilesAlert = Anguaño nun se sofita la xuba múltiple de ficheros o carpetes.
|
||||
uploadPageBrowseButtonTitle = Xubir ficheru
|
||||
uploadingPageProgress = Xubiendo { $filename } ({ $size })
|
||||
importingFile = Importando...
|
||||
verifyingFile = Verificando...
|
||||
encryptingFile = Cifrando...
|
||||
decryptingFile = Descifrando...
|
||||
notifyUploadDone = Finó la to xuba.
|
||||
uploadingPageMessage = Namái que'l ficheru xuba, sedrás a afitar les opciones de caducidá.
|
||||
uploadingPageCancel = Encaboxar xuba
|
||||
uploadCancelNotification = Encaboxóse la to xuba.
|
||||
uploadingPageLargeFileMessage = Esti ficheru ye grande y pue entardar daqué en xubir. ¡Paciencia!
|
||||
uploadingFileNotification = Avísame cuando se complete la xuba.
|
||||
uploadSuccessConfirmHeader = Preparáu pa unviar
|
||||
uploadSvgAlt = Xubir
|
||||
uploadSuccessTimingHeader = L'enllaz del to ficheru caducará dempués d'una descarga o en 24 hores.
|
||||
copyUrlFormLabelWithName = Copia y comparti l'enllaz pa unviar el to ficheru: { $filename }
|
||||
copyUrlFormButton = Copiar al cartafueyu
|
||||
copiedUrl = ¡Copióse!
|
||||
deleteFileButton = Desaniciar ficheru
|
||||
sendAnotherFileLink = Unviar otru ficheru
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Baxar
|
||||
downloadFileName = Baxar { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = El to collaciu unvióte un ficheru usando Firefox Send, un serviciu que te permite compartir ficheros con un enllaz seguru, priváu y cifráu que caduca automáticamente p'asegurar que les to coses nun queden siempres na rede.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Baxar
|
||||
downloadNotification = Completóse la to descarga.
|
||||
downloadFinish = Descarga completada
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } de { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Prueba Firefox Send
|
||||
downloadingPageProgress = Baxando { $filename } ({ $size })
|
||||
downloadingPageMessage = Dexa esta llingüeta abierta entrín vamos en cata del to ficheru y lu desciframos, por favor.
|
||||
errorAltText = Fallu de xuba
|
||||
errorPageHeader = ¡Daqué foi mal!
|
||||
errorPageMessage = Hebo un fallu xubiendo'l ficheru.
|
||||
errorPageLink = Unviar otru ficheru
|
||||
fileTooBig = Esti ficheru ye mui grande como pa xubilu. Debería tener menos de { $size }.
|
||||
linkExpiredAlt = Enllaz caducáu
|
||||
expiredPageHeader = ¡Esti enllaz caducó o enxamás nun esistó!
|
||||
notSupportedHeader = El to restolador nun ta sofitáu.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Desafortunadamente esti restolador nun sofita la teunoloxía web qu'usa Firefox Send. Precisarás d'usar otru restolador. ¡Aconseyámoste Firefox!
|
||||
notSupportedLink = ¿Por qué'l mio restolador nun ta sofitáu?
|
||||
notSupportedOutdatedDetail = Desafortunadamente esta versión de Firefox nun sofita la teunoloxía web qu'usa Firefox Send. Precisarás d'anovar Firefox.
|
||||
updateFirefox = Anovar Firefox
|
||||
downloadFirefoxButtonSub = Descarga de baldre
|
||||
uploadedFile = Ficheru
|
||||
copyFileList = Copiar URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Caduca en
|
||||
deleteFileList = Desaniciar
|
||||
nevermindButton = Nun m'importa
|
||||
legalHeader = Términos y privacidá
|
||||
legalNoticeTestPilot = Anguaño Firefox Send ye un esperimentu de Test Pilot y ta suxetu a los <a>Términos de serviciu</a> y l'<a>Avisu de privacidá</a> de Test Pilot. <a>Equí</a> pues deprender más tocante a esti esperimentu y la so recoyida de datos.
|
||||
legalNoticeMozilla = L'usu de Firefox Send tamién ta suxetu al <a>Avisu de privacidá</a> y a los <a>Términos d'usu de la páxina web</a> de Mozilla.
|
||||
deletePopupText = ¿Desaniciar esti ficheru?
|
||||
deletePopupYes = Sí
|
||||
deletePopupCancel = Encaboxar
|
||||
deleteButtonHover = Desaniciar
|
||||
copyUrlHover = Copiar URL
|
||||
footerLinkLegal = Llegal
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Tocante a Test Pilot
|
||||
footerLinkPrivacy = Privacidá
|
||||
footerLinkTerms = Términos
|
||||
footerLinkCookies = Cookies
|
||||
82
public/locales/az/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = web eksperiment
|
||||
siteFeedback = Geri dönüş
|
||||
uploadPageHeader = Məxfi, Şifrələnmiş Fayl Paylaşma
|
||||
uploadPageExplainer = Fayllarınızı təhlükəsiz, məxfi, şifrələnmiş və daima onlayn qalmaması üçün avtomatik silinən keçidlə göndərin.
|
||||
uploadPageLearnMore = Ətraflı öyrən
|
||||
uploadPageDropMessage = Yükləmək üçün faylınızı buraya daşıyın
|
||||
uploadPageSizeMessage = Xidmətin daha yaxşı işləməsi üçün faylınız 1 GB-dan az olmalıdır
|
||||
uploadPageBrowseButton = Kompüterinizdən fayl seçin
|
||||
uploadPageBrowseButton1 = Yüklənəcək faylı seçin
|
||||
uploadPageMultipleFilesAlert = Birdən çox fayl və ya qovluq yükləmə hələlik dəstəklənmir.
|
||||
uploadPageBrowseButtonTitle = Fayl yüklə
|
||||
uploadingPageProgress = { $filename } ({ $size }) yüklənir
|
||||
importingFile = İdxal edilir…
|
||||
verifyingFile = Təsdiqlənir…
|
||||
encryptingFile = Şifrələnir...
|
||||
decryptingFile = Şifrə açılır...
|
||||
notifyUploadDone = Yükləməniz hazırdır.
|
||||
uploadingPageMessage = Faylınız yükləndikdən sonra vaxtı çıxma seçimlərini qura biləcəksiz.
|
||||
uploadingPageCancel = Yükləməni ləğv et
|
||||
uploadCancelNotification = Yükləməniz ləğv edildi.
|
||||
uploadingPageLargeFileMessage = Fayl böyükdür və yükləmək çox vaxt ala bilər. Səbirli olun!
|
||||
uploadingFileNotification = Yükləmə bitdiyində xəbər ver.
|
||||
uploadSuccessConfirmHeader = Göndərməyə hazır
|
||||
uploadSvgAlt = Yüklə
|
||||
uploadSuccessTimingHeader = Faylınızın keçidinin 1 endirmədən və ya 24 saatdan sonra vaxtı çıxacaq.
|
||||
copyUrlFormLabelWithName = Faylınızı göndərmək üçün keçidi köçürün: { $filename }
|
||||
copyUrlFormButton = Buferə köçür
|
||||
copiedUrl = Köçürüldü!
|
||||
deleteFileButton = Faylı sil
|
||||
sendAnotherFileLink = Başqa fayl göndər
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Endir
|
||||
downloadFileName = { $filename } faylını endir
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Yoldaşınız Firefox Send ilə sizə fayl göndərir, fayllarınızı təhlükəsiz, məxfi, şifrələnmiş və daima onlayn qalmaması üçün avtomatik silən fayl göndərmə xidməti.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Endir
|
||||
downloadNotification = Endirməniz tamamlandı.
|
||||
downloadFinish = Endirmə Tamamlandı
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } / { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Firefox Send Yoxla
|
||||
downloadingPageProgress = { $filename } faylı ({ $size }) endirilir
|
||||
downloadingPageMessage = Lütfən faylı endirib şifrəsini açarkən vərəqi açıq buraxın.
|
||||
errorAltText = Yükləmə xətası
|
||||
errorPageHeader = Nəsə səhv getdi!
|
||||
errorPageMessage = Faylı yüklərkən xəta baş verdi.
|
||||
errorPageLink = Başqa fayl göndər
|
||||
fileTooBig = Fayl yükləmək üçün çox böyükdür. Fayl { $size }-dan az olmalıdır.
|
||||
linkExpiredAlt = Keçidin vaxtı çıxıb
|
||||
expiredPageHeader = Keçidin vaxtı çıxıb və ya heç vaxt olmayıb!
|
||||
notSupportedHeader = Səyyahınız dəstəklənmir.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Heyf ki, bu səyyah Firefox Send-ə güc verən web texnologiyalarını dəstəkləmir. Fərqli bir səyyah yoxlamalısınız. Biz Firefox məsləhət görürük!
|
||||
notSupportedLink = Səyyahım niyə dəstəklənmir?
|
||||
notSupportedOutdatedDetail = Heyf ki, Firefox səyyahının bu versiyası Firefox Send-ə güc verən web texnologiyalarını dəstəkləmir. Səyyahınızı yeniləməlisiniz.
|
||||
updateFirefox = Firefox-u Yenilə
|
||||
downloadFirefoxButtonSub = Pulsuz Endir
|
||||
uploadedFile = Fayl
|
||||
copyFileList = Keçidi Köçürt
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Vaxtı çıxma tarixi
|
||||
deleteFileList = Sil
|
||||
nevermindButton = Vacib deyil
|
||||
legalHeader = Şərtlər və Məxfilik
|
||||
legalNoticeTestPilot = Firefox Send Test Pilot eksperimentidir, Test Pilot <a>Xidmət Şərtləri</a> və <a>Məxfilik Bildirişi</a>-nə tabedir. Bu eksperiment və məlumat yığma haqqında <a>buradan</a> öyrənə bilərsiz.
|
||||
legalNoticeMozilla = Firefox Send saytının istifadəsi həmçinin Mozilla-nın <a>Saytlar üçün Məxfilik Bildirişi</a> və <a>Sayt İstifadə Şərtləri</a>-nə tabedir.
|
||||
deletePopupText = Fayl silinsin?
|
||||
deletePopupYes = Bəli
|
||||
deletePopupCancel = Ləğv et
|
||||
deleteButtonHover = Sil
|
||||
copyUrlHover = Keçidi Köçürt
|
||||
footerLinkLegal = Hüquqi
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Test Pilot Haqqında
|
||||
footerLinkPrivacy = Məxfilik
|
||||
footerLinkTerms = Şərtlər
|
||||
footerLinkCookies = Çərəzlər
|
||||
51
public/locales/bn-BD/send.ftl
Normal file
@@ -0,0 +1,51 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = ওয়েব গবেষণা
|
||||
siteFeedback = প্রতিক্রিয়া
|
||||
uploadPageLearnMore = আরও জানুন
|
||||
uploadPageBrowseButton = আপনার কম্পিউটারে ফাইল নির্বাচন করুন
|
||||
uploadPageBrowseButtonTitle = ফাইল আপলোড
|
||||
importingFile = ইম্পোর্ট হচ্ছে...
|
||||
verifyingFile = যাচাই হচ্ছে...
|
||||
encryptingFile = ইনক্রিপট হচ্ছে...
|
||||
decryptingFile = ডিক্রিপট হচ্ছে...
|
||||
notifyUploadDone = আপনার আপলোড সম্পন্ন হয়েছে।
|
||||
uploadingPageCancel = আপলোড বাতিল করুন
|
||||
uploadCancelNotification = আপনার অাপলোড বাতিল করা হয়েছে।
|
||||
uploadSuccessConfirmHeader = পাঠানোর জন্য প্রস্তুত
|
||||
uploadSvgAlt = আপলোড
|
||||
copyUrlFormButton = ক্লিপবোর্ডে কপি করুন
|
||||
copiedUrl = কপি করা হয়েছে!
|
||||
deleteFileButton = ফাইল মুছুন
|
||||
sendAnotherFileLink = আরেকটি ফাইল পাঠান
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = ডাউনলোড
|
||||
downloadFileName = ডাউনলোড { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = ডাউনলোড
|
||||
downloadNotification = আপনার ডাউনলোড সম্পন্ন হয়েছে।
|
||||
downloadFinish = ডাউনলোড সম্পন্ন
|
||||
errorAltText = আপালোডে ত্রুটি
|
||||
errorPageHeader = কোন সমস্যা হয়েছে!
|
||||
errorPageLink = আরেকটি ফাইল পাঠান
|
||||
updateFirefox = Firefox হালনাগাদ করুন
|
||||
downloadFirefoxButtonSub = বিনামূল্যে ডাউনলোড
|
||||
uploadedFile = ফাইল
|
||||
copyFileList = URL অনুলিপি করুন
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = মেয়াদোত্তীর্ণ তারিখ
|
||||
deleteFileList = মুছে ফেলুন
|
||||
nevermindButton = কিছু মনে করবেন না
|
||||
legalHeader = শর্তাবলী এবং গোপনীয়তা
|
||||
deletePopupText = ফাইলটি মুছতে চান?
|
||||
deletePopupYes = হ্যাঁ
|
||||
deletePopupCancel = বাতিল
|
||||
deleteButtonHover = মুছে ফেলুন
|
||||
copyUrlHover = URL অনুলিপি করুন
|
||||
footerLinkLegal = আইনগত
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Test Pilot পরিচিতি
|
||||
footerLinkPrivacy = গোপনীয়তা
|
||||
footerLinkTerms = শর্তাবলী
|
||||
footerLinkCookies = কুকি
|
||||
82
public/locales/ca/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = experiment web
|
||||
siteFeedback = Comentaris
|
||||
uploadPageHeader = Compartició de fitxers privada i xifrada
|
||||
uploadPageExplainer = Envieu fitxers mitjançant un enllaç segur, privat i xifrat que caduca automàticament per tal que les vostres dades no es conservin a Internet per sempre.
|
||||
uploadPageLearnMore = Més informació
|
||||
uploadPageDropMessage = Arrossegueu el fitxer aquí per començar a pujar-lo
|
||||
uploadPageSizeMessage = Funciona millor quan els fitxers tenen menys d'1 GB
|
||||
uploadPageBrowseButton = Trieu un fitxer de l'ordinador
|
||||
uploadPageBrowseButton1 = Seleccioneu el fitxer que voleu pujar
|
||||
uploadPageMultipleFilesAlert = Actualment no es permet pujar diversos fitxers ni una carpeta.
|
||||
uploadPageBrowseButtonTitle = Puja el fitxer
|
||||
uploadingPageProgress = S'està pujant { $filename } ({ $size })
|
||||
importingFile = S'està important…
|
||||
verifyingFile = S'està verificant…
|
||||
encryptingFile = S'està xifrant…
|
||||
decryptingFile = S'està desxifrant…
|
||||
notifyUploadDone = La pujada ha acabat.
|
||||
uploadingPageMessage = Quan s'hagi acabat de pujat el fitxer, podreu definir les opcions de caducitat.
|
||||
uploadingPageCancel = Cancel·la la pujada
|
||||
uploadCancelNotification = La pujada s'ha cancel·lat.
|
||||
uploadingPageLargeFileMessage = Aquest fitxer és gros i pot trigar una estona a pujar. Espereu assegut…
|
||||
uploadingFileNotification = Notifica'm quan s'acabi de pujar.
|
||||
uploadSuccessConfirmHeader = Llest per enviar
|
||||
uploadSvgAlt = Puja
|
||||
uploadSuccessTimingHeader = L'enllaç al fitxer caducarà quan es baixi una vegada o d'aquí 24 hores.
|
||||
copyUrlFormLabelWithName = Copieu l'enllaç i compartiu-lo per enviar el fitxer: { $filename }
|
||||
copyUrlFormButton = Copia al porta-retalls
|
||||
copiedUrl = Copiat!
|
||||
deleteFileButton = Suprimeix el fitxer
|
||||
sendAnotherFileLink = Envieu un altre fitxer
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Baixa
|
||||
downloadFileName = Baixeu { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Un amic us ha enviat un fitxer amb el Firefox Send, un servei que permet compartir fitxers mitjançant un enllaç segur, privat i xifrat que caduca automàticament per tal que les vostres dades no es conservin a Internet per sempre.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Baixa
|
||||
downloadNotification = La baixada ha acabat.
|
||||
downloadFinish = Ha acabat la baixada
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } de { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Proveu el Firefox Send
|
||||
downloadingPageProgress = S'està baixant { $filename } ({ $size })
|
||||
downloadingPageMessage = Deixeu aquesta pestanya oberta per tal que el fitxer es pugui baixar i desxifrar.
|
||||
errorAltText = S'ha produït un error en pujar
|
||||
errorPageHeader = Hi ha hagut un problema
|
||||
errorPageMessage = S'ha produït un error en pujar el fitxer.
|
||||
errorPageLink = Envieu un altre fitxer
|
||||
fileTooBig = Aquest fitxer és massa gros per pujar-lo. Ha de tenir menys de { $size }.
|
||||
linkExpiredAlt = L'enllaç ha caducat
|
||||
expiredPageHeader = Aquest enllaç ha caducat o no existeix.
|
||||
notSupportedHeader = El vostre navegador no és compatible.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Aquest navegador no admet la tecnologia web amb què funciona el Firefox Send. Haureu d'utilitzar un altre navegador. Us recomanem el Firefox!
|
||||
notSupportedLink = Per què el meu navegador no és compatible?
|
||||
notSupportedOutdatedDetail = Aquesta versió del Firefox no admet la tecnologia web amb què funciona el Firefox Send. Haureu d'actualitzar el navegador.
|
||||
updateFirefox = Actualitza el Firefox
|
||||
downloadFirefoxButtonSub = Baixada gratuïta
|
||||
uploadedFile = Fitxer
|
||||
copyFileList = Copia l'URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Caduca d'aquí
|
||||
deleteFileList = Suprimeix
|
||||
nevermindButton = No, gràcies
|
||||
legalHeader = Condicions d'ús i privadesa
|
||||
legalNoticeTestPilot = Actualment el Firefox Send és un experiment del Test Pilot i està subjecte a les <a>Condicions del servei</a> i a l'<a>Avís de privadesa</a> del Test Pilot. Podeu obtenir més informació sobre aquest experiment i la recollida de dades <a>aquí</a>.
|
||||
legalNoticeMozilla = L'ús del Firefox Send també està subjecte a l'<a>Avís de privadesa de llocs web</a> i a les <a>Condicions d'ús de llocs web</a> de Mozilla.
|
||||
deletePopupText = Voleu suprimir aquest fitxer?
|
||||
deletePopupYes = Sí
|
||||
deletePopupCancel = Cancel·la
|
||||
deleteButtonHover = Suprimeix
|
||||
copyUrlHover = Copia l'URL
|
||||
footerLinkLegal = Avís legal
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Quant al Test Pilot
|
||||
footerLinkPrivacy = Privadesa
|
||||
footerLinkTerms = Condicions d'ús
|
||||
footerLinkCookies = Galetes
|
||||
82
public/locales/cak/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = ajk'amaya'l solna'onem
|
||||
siteFeedback = Rutzijol
|
||||
uploadPageHeader = Kekomonïx Ichinan chuqa' Ewan Kisik'ixik taq Yakb'äl
|
||||
uploadPageExplainer = Ketaq taq yakb'äl rik'in jun ewan rusik'ixik, ichinan chuqa' jikon ximonel, ri ruyonil xtikis ruq'ijul richin ke ri' ri taq atzij man e okel ta pa k'amaya'l junelïk.
|
||||
uploadPageLearnMore = Tetamäx ch'aqa' chik
|
||||
uploadPageDropMessage = Tajik'a' pe ri ayakb'al wawe' richin nachäp kijotob'axik
|
||||
uploadPageSizeMessage = Richin chi ütz nel ri samaj, k'o ta chi ri yakb'äl man tik'o chi re ri 1GB
|
||||
uploadPageBrowseButton = Tacha' jun yakb'äl pan akematz'ib'
|
||||
uploadPageBrowseButton1 = Tacha' jun yakb'äl richin najotob'a'
|
||||
uploadPageMultipleFilesAlert = K'a man nuk'öch ta nijotob'äx jalajöj yakb'äl o jun molwuj.
|
||||
uploadPageBrowseButtonTitle = Tijotob'äx yakb'äl
|
||||
uploadingPageProgress = Tajin nijotob'äx { $filename } ({ $size })
|
||||
importingFile = Tajin nijik…
|
||||
verifyingFile = Tajin nijikib'äx...
|
||||
encryptingFile = Tajin newäx rusik'ixik...
|
||||
decryptingFile = Tajin netamäx rusik'ixik...
|
||||
notifyUploadDone = Xak'is rujotob'axik.
|
||||
uploadingPageMessage = Toq xtijotob'äx ri yakb'äl xkatikïr xtak'ëx pa taq cha'oj ri ruq'ijul xtik'is.
|
||||
uploadingPageCancel = Tiq'at jotob'anïk
|
||||
uploadCancelNotification = Xq'at ri ajotob'anik
|
||||
uploadingPageLargeFileMessage = Yalan nïm re yakb'äl re' ruma ri' toq xtiyoke' richin xtijote'. ¡Man tik'o ak'u'x!
|
||||
uploadingFileNotification = Tiya' pe rutzijol chwe toq xtitz'aqät rujotob'axik.
|
||||
uploadSuccessConfirmHeader = Ütz chik richin Nitaq
|
||||
uploadSvgAlt = Tijotob'äx
|
||||
uploadSuccessTimingHeader = Ri ruximonel yakb'äl xtik'is ruq'ijul toq xtiqasäx jumul o pa 24 ramaj.
|
||||
copyUrlFormLabelWithName = Tiwachib'ëx chuqa' tikomonïx ri ximonel richin nitaq ri ayakb'äl: { $filename }
|
||||
copyUrlFormButton = Tiwachib'ëx pa molwuj
|
||||
copiedUrl = ¡Xwachib'ëx!
|
||||
deleteFileButton = Tiyuj yakb'äl
|
||||
sendAnotherFileLink = Titaq jun chik yakb'äl
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Tiqasäx
|
||||
downloadFileName = Tiqasäx { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Jun awachib'il xutäq jun yakb'äl chawe rik'in ri Firefox Send, jun samaj ri nuya' q'ij chawe ye'akomonij taq yakb'äl rik'in jun jikïl, ichinan chuqa' ewan rusik'ixik ximonel, ri nik'is ruq'ijul pa ruyonil richin chi ri taq awachinaq man junelïk ta e okel pa k'amab'ey.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Tiqasäx
|
||||
downloadNotification = Xtz'aqät ri aqasanik.
|
||||
downloadFinish = Xtz'aqät qasanïk
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } richin { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Titojtob'ëx Firefox Send
|
||||
downloadingPageProgress = Tajin niqasäx { $filename } ({ $size })
|
||||
downloadingPageMessage = Tijaq kan re ruwi' re' richin niqaqasaj ri yakb'äl chuqa' richin niqetamaj rusik'ixik.
|
||||
errorAltText = Xsach toq nijotob'äx
|
||||
errorPageHeader = ¡K'o ri man ütz ta xub'än!
|
||||
errorPageMessage = Xk'ulwachitäj jun sachoj toq tajin nijotob'äx ri yakb'äl.
|
||||
errorPageLink = Titaq jun chik yakb'äl
|
||||
fileTooBig = Yalan nïm re yakb'äl re' richin nijotob'äx. K'o ta chi man nik'o ta chi re ri { $size }.
|
||||
linkExpiredAlt = Xk'is ruq'ijul ri ximonel
|
||||
expiredPageHeader = ¡Xk'is ruq'ijul re ximonel re' o rik'in jub'a' majub'ey xk'oje'!
|
||||
notSupportedHeader = Man koch'el ta ri awokik'amaya'l.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = K'ayew ruma re okik'amaya'l re' man nuköch' ta ajk'amaya'l na'ob'äl nik'atzin chi re ri Firefox Send. K'o chi natojtob'ej jun chik okik'amaya'l. ¡Niqachilab'ej chawe ri Firefox!
|
||||
notSupportedLink = ¿Achike ruma man nikoch' taq ri wokik'amaya'l?
|
||||
notSupportedOutdatedDetail = K'ayew ruma re ruwäch Firefox re' man nuköch' ta ri ajk'amaya'l na'ob'äl nrajo' ri Firefox Send. Rajowaxik nak'ëx ri awokik'amaya'l.
|
||||
updateFirefox = Tik'ex ri Firefox
|
||||
downloadFirefoxButtonSub = Sipan Ruqasaxik
|
||||
uploadedFile = Yakb'äl
|
||||
copyFileList = Tiwachib'ëx URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Nik'is Ruq'ijul Pa
|
||||
deleteFileList = Tiyuj
|
||||
nevermindButton = Junam nub'än
|
||||
legalHeader = Ojqanem chuqa' Ichinanem
|
||||
legalNoticeTestPilot = Firefox Send k'a jun rutojtob'enik Test Pilot, chuqa' rutaqen rutzij ri <a>Rojqanem Samaj</a> chuqa' rik'in ri <a>Rutzijol Ichinanem</a>. Yatikïr nawetamaj ch'aq'a' chik chi rij re solna'oj re' chuqa' ri rumolik tzij <a>wawe'</a>.
|
||||
legalNoticeMozilla = Richin nokisäx ri ruxaq ruk'amaya'l Firefox Send k'o chi nitaqëx ri <a>Rutzijol Richinanem Ajk'amaya'l Ruxaq</a> chuqa' <a>Rojqanem rokisaxik Ajk'amaya'l Ruxaq</a>.
|
||||
deletePopupText = ¿La niyuj el re yakb'äl re'?
|
||||
deletePopupYes = Ja'
|
||||
deletePopupCancel = Tiq'at
|
||||
deleteButtonHover = Tiyuj
|
||||
copyUrlHover = Tiwachib'ëx URL
|
||||
footerLinkLegal = Taqanel tzijol
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Chi rij Test Pilot
|
||||
footerLinkPrivacy = Ichinanem
|
||||
footerLinkTerms = Taq ojqanem
|
||||
footerLinkCookies = Taq kaxlanwey
|
||||
82
public/locales/cs/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = webový experiment
|
||||
siteFeedback = Zpětná vazba
|
||||
uploadPageHeader = Soukromé a šifrované sdílení souborů
|
||||
uploadPageExplainer = Posílejte soubory přes bezpečné, soukromé a šifrované odkazy, které automaticky soubor smažou, aby nezůstal na internetu navěky.
|
||||
uploadPageLearnMore = Zjistit více
|
||||
uploadPageDropMessage = Přesunutím souboru sem spustíte jeho nahrávání
|
||||
uploadPageSizeMessage = Nahrávání funguje nejlépe pro soubory do velikosti 1 GB.
|
||||
uploadPageBrowseButton = Vybrat soubor z počítače
|
||||
uploadPageBrowseButton1 = Zvolte soubor k nahrání
|
||||
uploadPageMultipleFilesAlert = Nahrávání více souborů najednou nebo celých složek zatím není podporováno.
|
||||
uploadPageBrowseButtonTitle = Nahrát soubor
|
||||
uploadingPageProgress = Nahrávání souboru { $filename } ({ $size })
|
||||
importingFile = Probíhá import…
|
||||
verifyingFile = Probíhá ověřování…
|
||||
encryptingFile = Probíhá šifrování…
|
||||
decryptingFile = Probíhá dešifrování…
|
||||
notifyUploadDone = Nahrávání vašeho souboru bylo dokončeno.
|
||||
uploadingPageMessage = Po dokončení nahrávání můžete nastavit dobu expirace souboru.
|
||||
uploadingPageCancel = Zrušit nahrávání
|
||||
uploadCancelNotification = Nahrávání vašeho souboru bylo zrušeno.
|
||||
uploadingPageLargeFileMessage = Tento soubor je veliký a jeho nahrávání může chvíli trvat. Posaďte se na chvilku.
|
||||
uploadingFileNotification = Upozornit, až bude nahrávání dokončeno.
|
||||
uploadSuccessConfirmHeader = Připraveno k odeslání
|
||||
uploadSvgAlt = Nahrát
|
||||
uploadSuccessTimingHeader = Platnost odkazu na váš soubor vyprší po jeho prvním stažení, nebo po 24 hodinách.
|
||||
copyUrlFormLabelWithName = Zkopírujte a sdílejte odkaz na váš soubor: { $filename }
|
||||
copyUrlFormButton = Zkopírovat do schránky
|
||||
copiedUrl = Zkopírováno!
|
||||
deleteFileButton = Smazat soubor
|
||||
sendAnotherFileLink = Poslat další soubor
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Stáhnout
|
||||
downloadFileName = Stáhnout { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Někdo vám posílá soubor pomocí služby Firefox Send, které umožňuje bezpečné, soukromé a šifrované sdílení souborů, které jsou pak automaticky smazány, aby nezůstaly na internetu navěky.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Stáhnout
|
||||
downloadNotification = Stahování bylo dokončeno.
|
||||
downloadFinish = Stahování dokončeno
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } z { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Vyzkoušejte Firefox Send
|
||||
downloadingPageProgress = Stahování { $filename } ({ $size })
|
||||
downloadingPageMessage = Ponechte prosím tento panel otevřený, dokud nepřipravíme váš soubor a nedešifrujeme ho.
|
||||
errorAltText = Chyba při nahrávání souboru
|
||||
errorPageHeader = Nastala chyba!
|
||||
errorPageMessage = Při nahrávání souboru se vyskytl problém.
|
||||
errorPageLink = Poslat další soubor
|
||||
fileTooBig = Tento soubor je příliš veliký. Velikost nahrávaných souborů by neměla překročit { $size }.
|
||||
linkExpiredAlt = Platnost odkazu vypršela
|
||||
expiredPageHeader = Platnost tohoto odkazu buď vypršela, nebo vůbec nikdy neexistoval.
|
||||
notSupportedHeader = Váš prohlížeč není podporován.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Bohužel tento prohlížeč nepodporuje technologii, kterou Firefox Send používá. Zkuste prosím jiný prohlížeč, doporučujeme Firefox!
|
||||
notSupportedLink = Proč není můj prohlížeč podporovaný?
|
||||
notSupportedOutdatedDetail = Tato verze Firefoxu bohužel nepodporuje webovou technologii, která pohání Firefox Send. Musíte aktualizovat svůj prohlížeč.
|
||||
updateFirefox = Aktualizovat Firefox
|
||||
downloadFirefoxButtonSub = Stáhnout zdarma
|
||||
uploadedFile = Soubor
|
||||
copyFileList = Kopírovat URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Platnost vyprší za
|
||||
deleteFileList = Smazat
|
||||
nevermindButton = Nevadí
|
||||
legalHeader = Podmínky a ochrana soukromí
|
||||
legalNoticeTestPilot = Firefox Send je ve fázi experimentu projektu Test Pilot a platí tak pro něj stejné <a>Podmínky používání</a> a <a>Zásady ochrany soukromí</a>. Více o tomto experimentu a sbíraných datech se dozvíte <a>zde</a>.
|
||||
legalNoticeMozilla = Používání webové služby Firefox Send se řídí <a>Zásadami ochrany soukromí</a> a <a>Podmínkami používání</a> webových stránek Mozilly.
|
||||
deletePopupText = Smazat tento soubor?
|
||||
deletePopupYes = Ano
|
||||
deletePopupCancel = Zrušit
|
||||
deleteButtonHover = Smazat
|
||||
copyUrlHover = Kopírovat URL
|
||||
footerLinkLegal = Právní informace
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = O programu Test Pilot
|
||||
footerLinkPrivacy = Soukromí
|
||||
footerLinkTerms = Podmínky
|
||||
footerLinkCookies = Cookies
|
||||
82
public/locales/cy/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = arbrawf gwe
|
||||
siteFeedback = Adborth
|
||||
uploadPageHeader = Rhannu Ffeiliau wedi eu Hamgryptio Preifat
|
||||
uploadPageExplainer = Anfon ffeiliau drwy ddolen diogel, breifat ac wedi ei amgryptio sy'n dod i ben yn awtomatig er mwyn sicrhau nad yw eich pethau'n bodoli ar lein am byth.
|
||||
uploadPageLearnMore = Dysgu rhagor
|
||||
uploadPageDropMessage = Gollyngwch eich ffeiliau yma i gychwyn llwytho i fyny
|
||||
uploadPageSizeMessage = Mae'n well cadw maint y ffeiliau o dan 1GB er mwyn iddo weithio ar ei orau.
|
||||
uploadPageBrowseButton = Dewiswch ffeil ar eich cyfrifiadur
|
||||
uploadPageBrowseButton1 = Dewiswch ffeil i'w llwytho i fyny
|
||||
uploadPageMultipleFilesAlert = Nid yw llwytho nifer lluosog o ffeilia neu ffolder yn cael ei gynnal ar hyn o bryd.
|
||||
uploadPageBrowseButtonTitle = Llwytho ffeil i fyny
|
||||
uploadingPageProgress = Llwytho $filename} i fyny ({ $size })
|
||||
importingFile = Mewnforio…
|
||||
verifyingFile = Wrthi'n gwirio…
|
||||
encryptingFile = Wrthi'n amgryptio…
|
||||
decryptingFile = Wrthi'n dadgryptio…
|
||||
notifyUploadDone = Mae eich llwytho wedi gorffen.
|
||||
uploadingPageMessage = Unwaith y bydd eich ffeil wedi llwytho bydd modd gosod manylion dod i ben.
|
||||
uploadingPageCancel = Diddymu'r llwytho
|
||||
uploadCancelNotification = Cafodd eich llwytho ei ddiddymu.
|
||||
uploadingPageLargeFileMessage = Mae'r ffeil yn fawr a gall gymryd peth amser i'w llwytho. Arhoswch!
|
||||
uploadingFileNotification = Dweud wrtha i pan fydd y llwytho wedi gorffen.
|
||||
uploadSuccessConfirmHeader = Yn Barod i Anfon
|
||||
uploadSvgAlt = LLwytho i Fyny
|
||||
uploadSuccessTimingHeader = Bydd y ddolen i'ch ffeil y dod i ben ar ôl 1 llwytho neu o fewn 24 awr.
|
||||
copyUrlFormLabelWithName = Copïo a rhannu'r ddolen i anfon eich ffeil: { $filename }
|
||||
copyUrlFormButton = Copïo i'r clipfwrdd
|
||||
copiedUrl = Wedi eu copïo!
|
||||
deleteFileButton = Dileu ffeil
|
||||
sendAnotherFileLink = Anfon ffeil arall
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Llwytho i lawr
|
||||
downloadFileName = Llwytho i lawr { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Mae ffrind i chi yn anfon ffeil atoch drwy Firefox Send, gwasanaeth sy'n caniatáu i chi rannu ffeiliau drwy ddolen ddiogel, breifat ac wedi ei amgryptio sy'n dod i ben yn awtomatig er mwyn sicrhau nad yw eich deunydd yn aros ar-lein am byth.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Llwytho i Lawr
|
||||
downloadNotification = Mae eich llwytho wedi gorffen
|
||||
downloadFinish = Llwytho wedi Gorffen
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } o { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Profwch Firefox Send
|
||||
downloadingPageProgress = Llwytho i lawr { $filename } ({ $size })
|
||||
downloadingPageMessage = Gadewch y tab yma ar agor tra fyddwn yn estyn eich ffeil a'i dad-amgryptio.
|
||||
errorAltText = Gwall llwytho
|
||||
errorPageHeader = Aeth rhywbeth o'i le!
|
||||
errorPageMessage = Bu gwall wrth lwytho'r ffeil.
|
||||
errorPageLink = Anfon ffeil arall
|
||||
fileTooBig = Mae'r ffeil yn rhy fawr i'w llwytho. Dylai fod yn llai na { $size }.
|
||||
linkExpiredAlt = Mae'r ddolen wedi dod i ben
|
||||
expiredPageHeader = Mae'r ddolen wedi dod i ben neu nad yw wedi bodoli erioed!
|
||||
notSupportedHeader = Nid yw eich porwr yn cael ei gynnal.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Yn anffodus nid yw'r porwr hwn yn cynnal y technoleg gwe sy'n cynnal Firefox Send. Bydd angen i chi ddefnyddio porwr arall. Rydym ni'n argymell Firefox!
|
||||
notSupportedLink = Pam nad yw fy mhorwr yn cael ei gynnal?
|
||||
notSupportedOutdatedDetail = Yn anffodus nid yw'r fersiwn yma o Firefox yn cynnal y technoleg gwe sy'n gyrru Firefox Send. Bydd angen i chi ddiweddaru eich porwr.
|
||||
updateFirefox = Diweddaru Firefox
|
||||
downloadFirefoxButtonSub = Llwytho i Lawr am Ddim
|
||||
uploadedFile = Ffeil
|
||||
copyFileList = Copïo URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Daw i ben ymhen
|
||||
deleteFileList = Dileu
|
||||
nevermindButton = Dim ots
|
||||
legalHeader = Amodau a Phreifatrwydd
|
||||
legalNoticeTestPilot = Ar hyn o mae Firefox Send yn arbrawf o fewn rhaglen Test Pilot ac yn destun <a>Amodau Gwasanaeth</a> a <a>Hysbysiad Preifatrwydd</a> Test Pilot . Gallwch ddysgu rhagor am yr arbrawf a'i gasglu data <a>yma</a>.
|
||||
legalNoticeMozilla = Mae'r defnydd o wefan Firefox Send hefyd yn destun <a>Hysbysiad Preifatrwydd Gwefannau</a> ac <a>Amodau Defnydd Gwefannau</a> Mozilla.
|
||||
deletePopupText = Dileu'r ffeil?
|
||||
deletePopupYes = Iawn
|
||||
deletePopupCancel = Diddymu
|
||||
deleteButtonHover = Dileu
|
||||
copyUrlHover = Copïo'r URL
|
||||
footerLinkLegal = Cyfreithiol
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Ynghylch Test Pilot
|
||||
footerLinkPrivacy = Preifatrwydd
|
||||
footerLinkTerms = Amodau
|
||||
footerLinkCookies = Cwcis
|
||||
82
public/locales/de/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = Web-Experiment
|
||||
siteFeedback = Feedback
|
||||
uploadPageHeader = Privates, verschlüsseltes Austauschen von Dateien
|
||||
uploadPageExplainer = Senden Sie Dateien über einen sicheren, privaten und verschlüsselten Link, der automatisch abläuft, damit Ihre Daten nicht für immer im Internet bleiben.
|
||||
uploadPageLearnMore = Mehr erfahren
|
||||
uploadPageDropMessage = Ziehen Sie eine Datei zum Hochladen hierher
|
||||
uploadPageSizeMessage = Dateien unter 1 GB sorgen für erhöhte Zuverlässigkeit des Betriebs
|
||||
uploadPageBrowseButton = Wählen Sie eine Datei auf Ihrem Computer aus
|
||||
uploadPageBrowseButton1 = Datei zum Hochladen auswählen
|
||||
uploadPageMultipleFilesAlert = Hochladen mehrerer Dateien oder eines Ordners wird derzeit nicht unterstützt.
|
||||
uploadPageBrowseButtonTitle = Datei hochladen
|
||||
uploadingPageProgress = { $filename } ({ $size }) wird hochgeladen
|
||||
importingFile = Wird importiert…
|
||||
verifyingFile = Wird überprüft…
|
||||
encryptingFile = Wird verschlüsselt…
|
||||
decryptingFile = Wird entschlüsselt…
|
||||
notifyUploadDone = Ihr Upload ist abgeschlossen.
|
||||
uploadingPageMessage = Sobald Ihre Datei hochgeladen wird, können Sie die Optionen zum Ablaufdatum auswählen.
|
||||
uploadingPageCancel = Hochladen abbrechen
|
||||
uploadCancelNotification = Ihr Upload wurde abgebrochen.
|
||||
uploadingPageLargeFileMessage = Diese Datei ist groß, sodass das hochladen einige Zeit dauern könnte. Haben Sie Geduld!
|
||||
uploadingFileNotification = Mich benachrichtigen, wenn der Upload abgeschlossen ist.
|
||||
uploadSuccessConfirmHeader = Bereit zum Senden
|
||||
uploadSvgAlt = Hochladen
|
||||
uploadSuccessTimingHeader = Der Link zu Ihrer Datei läuft nach einem Download oder in 24 Stunden ab.
|
||||
copyUrlFormLabelWithName = Kopieren und teilen Sie den Link, um Ihre Datei zu senden: { $filename }
|
||||
copyUrlFormButton = In Zwischenablage kopieren
|
||||
copiedUrl = Kopiert!
|
||||
deleteFileButton = Datei löschen
|
||||
sendAnotherFileLink = Eine weitere Datei senden
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Herunterladen
|
||||
downloadFileName = { $filename } herunterladen
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Ihr Freund schickt Ihnen eine Datei mit Firefox Send, einem Dienst, mit dem Sie Dateien über einen sicheren, privaten und verschlüsselten Link teilen können, der automatisch abläuft, damit Ihre Daten nicht für immer im Internet bleiben.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Herunterladen
|
||||
downloadNotification = Der Download wurde abgeschlossen.
|
||||
downloadFinish = Download abgeschlossen
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } von { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Firefox Send ausprobieren
|
||||
downloadingPageProgress = { $filename } ({ $size }) wird heruntergeladen
|
||||
downloadingPageMessage = Bitte lassen Sie diesen Tab geöffnet, während Ihre Datei heruntergeladen und entschlüsselt wird.
|
||||
errorAltText = Fehler beim Hochladen
|
||||
errorPageHeader = Ein Fehler ist aufgetreten!
|
||||
errorPageMessage = Beim Hochladen der Datei ist ein Fehler aufgetreten.
|
||||
errorPageLink = Eine weitere Datei senden
|
||||
fileTooBig = Die Datei ist zu groß zum Hochladen. Sie sollte maximal { $size } groß sein.
|
||||
linkExpiredAlt = Link abgelaufen
|
||||
expiredPageHeader = Dieser Link ist abgelaufen oder hat nie existiert!
|
||||
notSupportedHeader = Ihr Browser wird nicht unterstützt.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Leider unterstützt dieser Browser die Web-Technologie nicht, auf der Firefox Send basiert. Sie benötigen einen anderen Browser. Wir empfehlen Firefox!
|
||||
notSupportedLink = Warum wird mein Browser nicht unterstützt?
|
||||
notSupportedOutdatedDetail = Leider unterstützt diese Firefox-Version die Web-Technologie nicht, auf der Firefox Send basiert. Sie müssen Ihren Browser aktualisieren.
|
||||
updateFirefox = Firefox aktualisieren
|
||||
downloadFirefoxButtonSub = Kostenloser Download
|
||||
uploadedFile = Datei
|
||||
copyFileList = Adresse kopieren
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Läuft ab in
|
||||
deleteFileList = Löschen
|
||||
nevermindButton = Egal
|
||||
legalHeader = Nutzungsbedingungen und Datenschutz
|
||||
legalNoticeTestPilot = Firefox Send ist aktuell ein Test-Pilot-Experiment und unterliegt den <a>Nutzungsbedingungen</a> und dem <a>Datenschutzhinweis</a> von Test Pilot. Mehr über diese Experiment und die Daten, die es sammelt, erfahren Sie <a>hier</a>.
|
||||
legalNoticeMozilla = Die Nutzung der Website von Firefox Send unterliegt außerdem Mozillas <a>Datenschutzhinweis für Websites</a> und <a>Nutzungsbedingungen für Websites</a>.
|
||||
deletePopupText = Diese Datei löschen?
|
||||
deletePopupYes = Ja
|
||||
deletePopupCancel = Abbrechen
|
||||
deleteButtonHover = Löschen
|
||||
copyUrlHover = Adresse kopieren
|
||||
footerLinkLegal = Rechtliches
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Über Test Pilot
|
||||
footerLinkPrivacy = Datenschutz
|
||||
footerLinkTerms = Nutzungsbedingungen
|
||||
footerLinkCookies = Cookies
|
||||
82
public/locales/dsb/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = webeksperiment
|
||||
siteFeedback = Komentar
|
||||
uploadPageHeader = Priwatne, skoděrowane źělenje datajow
|
||||
uploadPageExplainer = Pósćelśo dataje pśez wěsty, priwatny a skoděrowany wótkaz, kótaryž awtomatiski spadnjo, až njeby waše daty na pśecej online wóstawali.
|
||||
uploadPageLearnMore = Dalšne informacije
|
||||
uploadPageDropMessage = Śěgniśo swóju dataju sem, aby ju nagrał
|
||||
uploadPageSizeMessage = Wužywajśo nejlěpje dataje, kótarež su mjeńše ako 1 GB za lěpšu spušćobnosć.
|
||||
uploadPageBrowseButton = Wubjeŕśo dataju na swójom licadle
|
||||
uploadPageBrowseButton1 = Wubjeŕśo dataju za nagraśe
|
||||
uploadPageMultipleFilesAlert = Nagrawanje někotarych datajow abo zarědnika se tuchylu njepódpěra.
|
||||
uploadPageBrowseButtonTitle = Dataju nagraś
|
||||
uploadingPageProgress = { $filename } ({ $size }) se nagrawa
|
||||
importingFile = Importěrujo se...
|
||||
verifyingFile = Pśespytujo se...
|
||||
encryptingFile = Koděrujo se...
|
||||
decryptingFile = Dešifrěrujo se...
|
||||
notifyUploadDone = Wašo nagraśe jo dokóńcone.
|
||||
uploadingPageMessage = Gaž se waša dataja nagrawa, móžośo nastajenja spadnjenja póstajiś.
|
||||
uploadingPageCancel = Nagraśe pśetergnus
|
||||
uploadCancelNotification = Wašo nagraśe jo se pśetergnuło.
|
||||
uploadingPageLargeFileMessage = Toś ta dataja jo wjelika a nagrawanje mógło chylku traś. Buźćo sćerpliwy!
|
||||
uploadingFileNotification = K wěsći daś, gaž nagraśe jo dokóńcone.
|
||||
uploadSuccessConfirmHeader = Gótowy za słanje
|
||||
uploadSvgAlt = Nagraś
|
||||
uploadSuccessTimingHeader = Wótkaz k wašej dataji pó 1 ześěgnjenju abo 24 góźinach spadnjo.
|
||||
copyUrlFormLabelWithName = Kopěrujśo a źělśo wótkaz, aby swóju dataju pósłał: { $filename }
|
||||
copyUrlFormButton = Do mjazywótkłada kopěrowaś
|
||||
copiedUrl = Kopěrowany!
|
||||
deleteFileButton = Dataju wulašowaś
|
||||
sendAnotherFileLink = Drugu dataju pósłaś
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Ześěgnuś
|
||||
downloadFileName = { $filename } ześěgnuś
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Waš pśijaśel wam dataju z Firefox Send sćelo, słužba, kótaraž wam zmóžnja, dataje pśez wěsty, priwatny a skoděrowany wótkaz źěliś, kótaryž awtomatiski spadnjo, až njeby waše daty na pśecej online wóstawali.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Ześěgnuś
|
||||
downloadNotification = Wašo ześěgnjenje jo dokóńcone.
|
||||
downloadFinish = Ześěgnjenje dokóńcone
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } z { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Firefox Send wopytaś
|
||||
downloadingPageProgress = { $filename } ({ $size }) se ześěgujo
|
||||
downloadingPageMessage = Pšosym wóstajśo toś ten rejtark wócynjony, mjaztym až wašu dataju ześěgujomy a dešifrěrujomy.
|
||||
errorAltText = Nagrawańska zmólka
|
||||
errorPageHeader = Něco njejo se raźiło!
|
||||
errorPageMessage = Pśi nagrawanju dataje jo zmólka nastała.
|
||||
errorPageLink = Drugu dataju pósłaś
|
||||
fileTooBig = Toś ta dataja jo pśewjelika za nagraśe. Měła mjeńša ako { $size } byś.
|
||||
linkExpiredAlt = Wótkaz spadnjony
|
||||
expiredPageHeader = Toś ten wótkaz jo spadnjony abo njejo nigda eksistěrował!
|
||||
notSupportedHeader = Waš wobglědowak se njepódpěra.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Bóžko toś ten wobglědowak webtechnologiju njepódpěra, na kótarejž Firefox Send bazěrujo. Musyśo drugi wobglědowak wužywaś. My Firefox dopórucujomy!
|
||||
notSupportedLink = Cogodla se mój wobglědowak njepódpěra?
|
||||
notSupportedOutdatedDetail = Bóžko toś ta wersija Firefox webtechnologiju njepódpěra, na kótarejž Firefox Send bazěrujo. Musyśo swój wobglědowak aktualizěrowaś.
|
||||
updateFirefox = Firefox aktualizěrowaś
|
||||
downloadFirefoxButtonSub = Dermotne ześěgnjenje
|
||||
uploadedFile = Dataja
|
||||
copyFileList = URL kopěrowaś
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Spadnjo za
|
||||
deleteFileList = Wulašowaś
|
||||
nevermindButton = Wšojadno
|
||||
legalHeader = Wuměnjenja a priwatnosć
|
||||
legalNoticeTestPilot = Firefox jo tuchylu eksperiment Test Pilot, a pódlažy <a>wužywańskim wuměnjenjam</a> a <a>pokazce priwatnosći</a> Test Pilot. Wěcej wó toś tom eksperimenśe a daty, kótarež gromaźi, <a>how</a> zgónijośo.
|
||||
legalNoticeMozilla = Teke wužywanje websedła Firefox Send <a>pokazce priwatnosći za websedła</a> a <a>wužywańskim wuměnjenjam za websedła</a> Mozilla pódlažy.
|
||||
deletePopupText = Toś tu dataju lašowaś?
|
||||
deletePopupYes = Jo
|
||||
deletePopupCancel = Pśetergnuś
|
||||
deleteButtonHover = Wulašowaś
|
||||
copyUrlHover = URL kopěrowaś
|
||||
footerLinkLegal = Pšawniske
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Wó Test Pilot
|
||||
footerLinkPrivacy = Priwatnosć
|
||||
footerLinkTerms = Wuměnjenja
|
||||
footerLinkCookies = Cookieje
|
||||
82
public/locales/el/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = πείραμα διαδικτύου
|
||||
siteFeedback = Σχόλια
|
||||
uploadPageHeader = Ιδιωτική, κρυπτογραφημένη κοινή χρήση αρχείων
|
||||
uploadPageExplainer = Στείλτε αρχεία μέσω ασφαλούς, ιδιωτικού και κρυπτογραφημένου συνδέσμου που λήγει αυτόματα ώστε να διασφαλίσετε ότι τα περιεχόμενά σας δεν θα παραμείνουν στο διαδίκτυο για πάντα.
|
||||
uploadPageLearnMore = Μάθετε περισσότερα
|
||||
uploadPageDropMessage = Εναποθέστε το αρχείο σας εδώ για έναρξη μεταφόρτωσης
|
||||
uploadPageSizeMessage = Για περισσότερο αξιόπιστη λειτουργία, προτείνεται να διατηρήσετε το αρχείο κάτω από 1GB
|
||||
uploadPageBrowseButton = Επιλέξτε αρχείο από τον υπολογιστή σας
|
||||
uploadPageBrowseButton1 = Επιλέξτε ένα αρχείο για μεταφόρτωση
|
||||
uploadPageMultipleFilesAlert = Η μεταφόρτωση πολλαπλών αρχείων ή φακέλου δεν υποστηρίζεται αυτή τη στιγμή.
|
||||
uploadPageBrowseButtonTitle = Μεταφόρτωση αρχείου
|
||||
uploadingPageProgress = Μεταφόρτωση του { $filename } ({ $size })
|
||||
importingFile = Εισαγωγή…
|
||||
verifyingFile = Επαλήθευση...
|
||||
encryptingFile = Κρυπτογράφηση…
|
||||
decryptingFile = Αποκρυπτογράφηση…
|
||||
notifyUploadDone = Η μεταφόρτωσή σας ολοκληρώθηκε.
|
||||
uploadingPageMessage = Αφού μεταφορτωθούν τα αρχεία σας, θα μπορείτε να ορίσετε επιλογές λήξης.
|
||||
uploadingPageCancel = Ακύρωση μεταφόρτωσης
|
||||
uploadCancelNotification = Η μεταφόρτωσή σας ακυρώθηκε.
|
||||
uploadingPageLargeFileMessage = Αυτό το αρχείο είναι μεγάλο και ίσως χρειαστεί λίγος αρκετός χρόνος για μεταφόρτωση. Χαλαρώστε!
|
||||
uploadingFileNotification = Ειδοποίηση όταν ολοκληρωθεί η μεταφόρτωση.
|
||||
uploadSuccessConfirmHeader = Έτοιμο για αποστολή
|
||||
uploadSvgAlt = Μεταφόρτωση
|
||||
uploadSuccessTimingHeader = Ο σύνδεσμος του αρχείου σας θα λήξει έπειτα από 1 λήψη ή 24 ώρες.
|
||||
copyUrlFormLabelWithName = Αντιγράψτε και μοιραστείτε τον σύνδεσμο για αποστολή του αρχείου σας : { $filename }
|
||||
copyUrlFormButton = Αντιγραφή στο πρόχειρο
|
||||
copiedUrl = Αντιγράφτηκε!
|
||||
deleteFileButton = Διαγραφή αρχείου
|
||||
sendAnotherFileLink = Αποστολή άλλου αρχείου
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Λήψη
|
||||
downloadFileName = Λήψη του { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Ο/Η φίλος/-η σας, σάς στέλνει ένα αρχείο με τη βοήθεια του Firefox Send, μιας υπηρεσίας που επιτρέπει τον διαμοιρασμό αρχείων μέσω ενός ασφαλούς, ιδιωτικού και κρυπτογραφημένου συνδέσμου που λήγει αυτόματα, ώστε να είστε σίγουροι ότι τα αρχεία σας δεν θα παραμείνουν στο διαδίκτυο για πάντα.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Λήψη
|
||||
downloadNotification = Η λήψη σας ολοκληρώθηκε.
|
||||
downloadFinish = Η λήψη ολοκληρώθηκε
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } από { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Δοκιμάστε το Firefox Send
|
||||
downloadingPageProgress = Γίνεται λήψη του { $filename } ({ $size })
|
||||
downloadingPageMessage = Παρακαλώ αφήστε ανοικτή αυτή την καρτέλα όσο λαμβάνουμε και αποκρυπτογραφούμε το αρχείο σας.
|
||||
errorAltText = Σφάλμα μεταφόρτωσης
|
||||
errorPageHeader = Κάτι πήγε στραβά!
|
||||
errorPageMessage = Παρουσιάστηκε σφάλμα κατά τη μεταφόρτωση του αρχείου.
|
||||
errorPageLink = Αποστολή άλλου αρχείου
|
||||
fileTooBig = Αυτό το αρχείο είναι πολύ μεγάλο για μεταφόρτωση. Πρέπει να είναι μικρότερο από { $size }.
|
||||
linkExpiredAlt = Ο σύνδεσμος έληξε
|
||||
expiredPageHeader = Αυτός ο σύνδεσμος έχει λήξει ή δεν υπήρξε ποτέ!
|
||||
notSupportedHeader = Το πρόγραμμα περιήγησής σας δεν υποστηρίζεται.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Δυστυχώς, αυτό το πρόγραμμα περιήγησης δεν υποστηρίζει την τεχνολογία ιστού στην οποία βασίζεται το Firefox Send. Θα πρέπει να δοκιμάσετε ένα άλλο πρόγραμμα περιήγησης. Προτείνουμε το Firefox!
|
||||
notSupportedLink = Γιατί δεν υποστηρίζεται το πρόγραμμα περιήγησής μου;
|
||||
notSupportedOutdatedDetail = Δυστυχώς, αυτή η έκδοση του Firefox δεν υποστηρίζει την τεχνολογία ιστού στην οποία βασίζεται το Firefox Send. Πρέπει να ενημερώσετε το πρόγραμμα περιήγησής σας.
|
||||
updateFirefox = Ενημέρωση Firefox
|
||||
downloadFirefoxButtonSub = Δωρεάν λήψη
|
||||
uploadedFile = Αρχείο
|
||||
copyFileList = Αντιγραφή URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Λήγει σε
|
||||
deleteFileList = Διαγραφή
|
||||
nevermindButton = Μην ανησυχείτε
|
||||
legalHeader = Όροι & απόρρητο
|
||||
legalNoticeTestPilot = Το Firefox Send αποτελεί προς το παρόν ένα πείραμα Test Pilot και υπόκειται στους <a>όρους υπηρεσίας</a> και την <a>πολιτική απορρήτου</a> του Test Pilot. Μπορείτε να μάθετε περισσότερα γι' αυτό το πείραμα και τη συλλογή δεδομένων <a>εδώ</a>.
|
||||
legalNoticeMozilla = Η χρήση της ιστοσελίδας Firefox Send υπόκειται επίσης στην <a>πολιτική απορρήτου ιστοσελίδων</a> και τους <a>όρους χρήσης ιστοσελίδων</a> της Mozilla.
|
||||
deletePopupText = Διαγραφή αρχείου;
|
||||
deletePopupYes = Ναι
|
||||
deletePopupCancel = Ακύρωση
|
||||
deleteButtonHover = Διαγραφή
|
||||
copyUrlHover = Αντιγραφή URL
|
||||
footerLinkLegal = Νομικά
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Σχετικά με το Test Pilot
|
||||
footerLinkPrivacy = Απόρρητο
|
||||
footerLinkTerms = Όροι
|
||||
footerLinkCookies = Cookies
|
||||
82
public/locales/en-US/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = web experiment
|
||||
siteFeedback = Feedback
|
||||
uploadPageHeader = Private, Encrypted File Sharing
|
||||
uploadPageExplainer = Send files through a safe, private, and encrypted link that automatically expires to ensure your stuff does not remain online forever.
|
||||
uploadPageLearnMore = Learn more
|
||||
uploadPageDropMessage = Drop your file here to start uploading
|
||||
uploadPageSizeMessage = For the most reliable operation, it’s best to keep your file under 1GB
|
||||
uploadPageBrowseButton = Select a file on your computer
|
||||
uploadPageBrowseButton1 = Select a file to upload
|
||||
uploadPageMultipleFilesAlert = Uploading multiple files or a folder is currently not supported.
|
||||
uploadPageBrowseButtonTitle = Upload file
|
||||
uploadingPageProgress = Uploading { $filename } ({ $size })
|
||||
importingFile = Importing…
|
||||
verifyingFile = Verifying…
|
||||
encryptingFile = Encrypting…
|
||||
decryptingFile = Decrypting…
|
||||
notifyUploadDone = Your upload has finished.
|
||||
uploadingPageMessage = Once your file uploads you will be able to set expiry options.
|
||||
uploadingPageCancel = Cancel upload
|
||||
uploadCancelNotification = Your upload was cancelled.
|
||||
uploadingPageLargeFileMessage = This file is large and may take a while to upload. Sit tight!
|
||||
uploadingFileNotification = Notify me when the upload is complete.
|
||||
uploadSuccessConfirmHeader = Ready to Send
|
||||
uploadSvgAlt = Upload
|
||||
uploadSuccessTimingHeader = The link to your file will expire after 1 download or in 24 hours.
|
||||
copyUrlFormLabelWithName = Copy and share the link to send your file: { $filename }
|
||||
copyUrlFormButton = Copy to clipboard
|
||||
copiedUrl = Copied!
|
||||
deleteFileButton = Delete file
|
||||
sendAnotherFileLink = Send another file
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Download
|
||||
downloadFileName = Download { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Your friend is sending you a file with Firefox Send, a service that allows you to share files with a safe, private, and encrypted link that automatically expires to ensure your stuff does not remain online forever.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Download
|
||||
downloadNotification = Your download has completed.
|
||||
downloadFinish = Download Complete
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } of { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Try Firefox Send
|
||||
downloadingPageProgress = Downloading { $filename } ({ $size })
|
||||
downloadingPageMessage = Please leave this tab open while we fetch your file and decrypt it.
|
||||
errorAltText = Upload error
|
||||
errorPageHeader = Something went wrong!
|
||||
errorPageMessage = There has been an error uploading the file.
|
||||
errorPageLink = Send another file
|
||||
fileTooBig = That file is too big to upload. It should be less than { $size }.
|
||||
linkExpiredAlt = Link expired
|
||||
expiredPageHeader = This link has expired or never existed in the first place!
|
||||
notSupportedHeader = Your browser is not supported.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Unfortunately this browser does not support the web technology that powers Firefox Send. You’ll need to try another browser. We recommend Firefox!
|
||||
notSupportedLink = Why is my browser not supported?
|
||||
notSupportedOutdatedDetail = Unfortunately this version of Firefox does not support the web technology that powers Firefox Send. You’ll need to update your browser.
|
||||
updateFirefox = Update Firefox
|
||||
downloadFirefoxButtonSub = Free Download
|
||||
uploadedFile = File
|
||||
copyFileList = Copy URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Expires In
|
||||
deleteFileList = Delete
|
||||
nevermindButton = Never mind
|
||||
legalHeader = Terms & Privacy
|
||||
legalNoticeTestPilot = Firefox Send is currently a Test Pilot experiment, and subject to the Test Pilot <a>Terms of Service</a> and <a>Privacy Notice</a>. You can learn more about this experiment and its data collection <a>here</a>.
|
||||
legalNoticeMozilla = Use of the Firefox Send website is also subject to Mozilla’s <a>Websites Privacy Notice</a> and <a>Websites Terms of Use</a>.
|
||||
deletePopupText = Delete this file?
|
||||
deletePopupYes = Yes
|
||||
deletePopupCancel = Cancel
|
||||
deleteButtonHover = Delete
|
||||
copyUrlHover = Copy URL
|
||||
footerLinkLegal = Legal
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = About Test Pilot
|
||||
footerLinkPrivacy = Privacy
|
||||
footerLinkTerms = Terms
|
||||
footerLinkCookies = Cookies
|
||||
82
public/locales/es-AR/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = experimento web
|
||||
siteFeedback = Opinión
|
||||
uploadPageHeader = Compartir archivos cifrados y privados
|
||||
uploadPageExplainer = Enviá archivos a través de un enlace cifrado, privado y seguro que expirará automáticamente para que tus datos no queden en línea para siempre.
|
||||
uploadPageLearnMore = Conocer más
|
||||
uploadPageDropMessage = Arrastrá el archivo hasta acá para empezar a subir
|
||||
uploadPageSizeMessage = Para una operación más confiable, es mejor que el archivo tenga menos de 1GB
|
||||
uploadPageBrowseButton = Seleccioná un archivo en tu computadora
|
||||
uploadPageBrowseButton1 = Seleccioná un archivo para subir
|
||||
uploadPageMultipleFilesAlert = Cargar múltiples archivos o una carpeta todavía no está soportado.
|
||||
uploadPageBrowseButtonTitle = Subir archivo
|
||||
uploadingPageProgress = Subiendo { $filename } ({ $size })
|
||||
importingFile = Importando…
|
||||
verifyingFile = Verificando…
|
||||
encryptingFile = Cifrando…
|
||||
decryptingFile = Descifrando…
|
||||
notifyUploadDone = La carga ha terminado.
|
||||
uploadingPageMessage = Una vez que se cargue el archivo podrás modificar las opciones de expiración.
|
||||
uploadingPageCancel = Cancelar subida
|
||||
uploadCancelNotification = La subida fue cancelada.
|
||||
uploadingPageLargeFileMessage = El archivo es grande y puede tardar un rato en subir. ¡Quedate quieto!
|
||||
uploadingFileNotification = Notificarme cuando la subida se complete.
|
||||
uploadSuccessConfirmHeader = Listo para enviar
|
||||
uploadSvgAlt = Subir
|
||||
uploadSuccessTimingHeader = El enlace al archivo expirará después de 1 descarga o en 24 horas.
|
||||
copyUrlFormLabelWithName = Copiá y compartí el enlace para enviar tu archivo: { $filename }
|
||||
copyUrlFormButton = Copiar al portapapeles
|
||||
copiedUrl = ¡Copiado!
|
||||
deleteFileButton = Borrar archivo
|
||||
sendAnotherFileLink = Enviar otro archivo
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Descargar
|
||||
downloadFileName = Descargar { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Tu amigo te está enviando un archivo con Firefox Send, un servicio que permite compartir archivos con un enlace cifrado, seguro y privado que expira automáticamente para asegurar que tus datos no quedan en línea para siempre.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Descargar
|
||||
downloadNotification = La descarga se completó.
|
||||
downloadFinish = Descarga completa
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } de { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Probá Firefox Send
|
||||
downloadingPageProgress = Descargando { $filename } ({ $size })
|
||||
downloadingPageMessage = Dejá esta pestaña abierta mientras descargamos el archivo y lo desciframos.
|
||||
errorAltText = Error de subida
|
||||
errorPageHeader = ¡Algo falló!
|
||||
errorPageMessage = Hubo un error al subir el archivo.
|
||||
errorPageLink = Enviar otro archivo
|
||||
fileTooBig = El archivo es demasiado grande para subir. Debería tener menos de { $size }.
|
||||
linkExpiredAlt = Enlace explirado
|
||||
expiredPageHeader = ¡Este enlace ha expirado o nunca existió en primer lugar!
|
||||
notSupportedHeader = El navegador no está soportado.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Desafortunadamente este navegador no soporta la tecnología web que necesita Firefox Send. Deberías probar otro navegador. ¡Te recomendamos Firefox!
|
||||
notSupportedLink = ¿Por qué mi navegador no está soportado?
|
||||
notSupportedOutdatedDetail = Desafortunadamente esta versión de Firefox no soporta la tecnología web que necesita Firefox Send. Necesitás actualizar el navegador.
|
||||
updateFirefox = Actualizar Firefox
|
||||
downloadFirefoxButtonSub = Descarga gratuita
|
||||
uploadedFile = Archivo
|
||||
copyFileList = Copiar URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Expira en
|
||||
deleteFileList = Borrar
|
||||
nevermindButton = No importa
|
||||
legalHeader = Términos y privacidad
|
||||
legalNoticeTestPilot = Firefox Send es actualmente un experimento de Test Pilot y está sujeto a los <a>términos de servicio</a> y la <a>nota de privacidad</a> de Test Pilot. Podés conocer más sobre este experimento y su recolección de datos <a>aquí</a>.
|
||||
legalNoticeMozilla = El uso del sitio web de Firefox Send también está sujeto a la <a>nota de privacidad de sitios web</a> y los <a>términos de uso de sitios web</a> de Mozilla.
|
||||
deletePopupText = ¿Borrar este archivo?
|
||||
deletePopupYes = Si
|
||||
deletePopupCancel = Cancelar
|
||||
deleteButtonHover = Borrar
|
||||
copyUrlHover = Copiar URL
|
||||
footerLinkLegal = Legales
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Acerca de Test Pilot
|
||||
footerLinkPrivacy = Privacidad
|
||||
footerLinkTerms = Términos
|
||||
footerLinkCookies = Cookies
|
||||
82
public/locales/es-CL/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = experimento web
|
||||
siteFeedback = Comentarios
|
||||
uploadPageHeader = Compartir archivos de forma privada y cifrada
|
||||
uploadPageExplainer = Enviar archivos a través de un enlace seguro, privado y cifrado que automáticamente expira para asegurar que tus cosas no permanecerán en línea por la eternidad.
|
||||
uploadPageLearnMore = Aprender más
|
||||
uploadPageDropMessage = Suelta tu archivo aquí para empezar a subirlo
|
||||
uploadPageSizeMessage = Para una operación más confiable, es mejor mantener el tamaño del archivo bajo 1 GB
|
||||
uploadPageBrowseButton = Selecciona un archivo en tu computador
|
||||
uploadPageBrowseButton1 = Selecciona un archivo a subir
|
||||
uploadPageMultipleFilesAlert = Subir múltiples archivos o una carpeta actualmente no es posible.
|
||||
uploadPageBrowseButtonTitle = Subir archivo
|
||||
uploadingPageProgress = Subiendo { $filename } ({ $size })
|
||||
importingFile = Importando…
|
||||
verifyingFile = Verificando…
|
||||
encryptingFile = Cifrando…
|
||||
decryptingFile = Descifrando…
|
||||
notifyUploadDone = Tu subida ha terminado.
|
||||
uploadingPageMessage = Una vez que tu archivo sea subido podrás ajustar las opciones de expiración.
|
||||
uploadingPageCancel = Cancelar subida
|
||||
uploadCancelNotification = Tu subida fue cancelada.
|
||||
uploadingPageLargeFileMessage = Este archivo es grande y puede tardar un rato en subir. ¡Aprovecha de hacer algo mientras!
|
||||
uploadingFileNotification = Notificarme cuando la subida sea completada.
|
||||
uploadSuccessConfirmHeader = Listo para enviar
|
||||
uploadSvgAlt = Subir
|
||||
uploadSuccessTimingHeader = El enlace a tu archivo expirará tras 1 descarga o en 24 horas.
|
||||
copyUrlFormLabelWithName = Copia y comparte el enlace para enviar tu archivo: { $filename }
|
||||
copyUrlFormButton = Copiar al portapapeles
|
||||
copiedUrl = ¡Copiado!
|
||||
deleteFileButton = Eliminar archivo
|
||||
sendAnotherFileLink = Enviar otro archivo
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Descargar
|
||||
downloadFileName = Descargar { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Tu amigo te está enviando un archivo con Firefox Send, un servicio que te permite compartir archivos con un enlace seguro, privado y cifrado que expira automáticamente para asegurar que tus cosas no queden en línea de por vida.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Descargar
|
||||
downloadNotification = Tu descarga se completó.
|
||||
downloadFinish = Descarga completa
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } de { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Probar Firefox Send
|
||||
downloadingPageProgress = Descargando { $filename } ({ $size })
|
||||
downloadingPageMessage = Por favor, deja esta pestaña abierta mientras recibimos tu archivo y lo desciframos.
|
||||
errorAltText = Error de subida
|
||||
errorPageHeader = ¡Algo se fue a las pailas!
|
||||
errorPageMessage = Hubo un error al subir el archivo.
|
||||
errorPageLink = Enviar otro archivo
|
||||
fileTooBig = Ese archivo es muy grande para ser subido. Debiera tener un tamaño menor a { $size }.
|
||||
linkExpiredAlt = Enlace expirado
|
||||
expiredPageHeader = ¡Este enlace ha expirado o quizá jamás existió!
|
||||
notSupportedHeader = Tu navegador no está soportado.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Lamentablemente este navegador no soporta la tecnología web que potencia a Firefox Send. Deberás probar en otro navegador. ¡Recomendamos Firefox!
|
||||
notSupportedLink = ¿Por qué mi navegador no es soportado?
|
||||
notSupportedOutdatedDetail = Lamentablemente esta versión de Firefox no soporta la tecnología web que potencia a Firefox Send. Deberás actualizar tu navegador.
|
||||
updateFirefox = Actualizar Firefox
|
||||
downloadFirefoxButtonSub = Descarga gratuita
|
||||
uploadedFile = Archivo
|
||||
copyFileList = Copiar URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Expira en
|
||||
deleteFileList = Eliminar
|
||||
nevermindButton = Da lo mismo
|
||||
legalHeader = Términos y privacidad
|
||||
legalNoticeTestPilot = Firefox Send es actualmente un experimento de Test Pilot, y está sujeto a los <a>Términos del servicio</a> y la <a>Política de privacidad</a> de Test Pilot. Puedes aprender más sobre este experimento y su recolección de datos <a>aquí</a>.
|
||||
legalNoticeMozilla = El uso del sitio web de Firefox Send también está sujeto a la <a>Política de privacidad de sitios web</a> y los <a>Términos de uso de sitios web</a> de Mozilla.
|
||||
deletePopupText = ¿Eliminar este archivo?
|
||||
deletePopupYes = Sí
|
||||
deletePopupCancel = Cancelar
|
||||
deleteButtonHover = Eliminar
|
||||
copyUrlHover = Copiar URL
|
||||
footerLinkLegal = Legal
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Acerca de Test Pilot
|
||||
footerLinkPrivacy = Privacidad
|
||||
footerLinkTerms = Términos
|
||||
footerLinkCookies = Cookies
|
||||
82
public/locales/es-ES/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = experimento web
|
||||
siteFeedback = Comentario
|
||||
uploadPageHeader = Compartir archivos cifrados y privados
|
||||
uploadPageExplainer = Envía archivos a través de un enlace cifrado, privado y seguro que caducará automáticamente para que tus datos no sean accesibles en línea de por vida.
|
||||
uploadPageLearnMore = Descubre más
|
||||
uploadPageDropMessage = Suelta aquí tu archivo para empezar a subirlo
|
||||
uploadPageSizeMessage = Para que la operación sea más segura, el archivo debería ocupar menos de 1GB
|
||||
uploadPageBrowseButton = Seleccionar un archivo en el equipo
|
||||
uploadPageBrowseButton1 = Seleccionar un archivo para subir
|
||||
uploadPageMultipleFilesAlert = Aún no se pueden subir varios archivos o una carpeta.
|
||||
uploadPageBrowseButtonTitle = Subir archivo
|
||||
uploadingPageProgress = Subiendo { $filename } ({ $size })
|
||||
importingFile = Imporando...
|
||||
verifyingFile = Comprobando...
|
||||
encryptingFile = Encriptando...
|
||||
decryptingFile = Desencriptando...
|
||||
notifyUploadDone = La subida ha finalizado.
|
||||
uploadingPageMessage = Cuando se suba tu archivo podrás condigurar las opciones de caducidad.
|
||||
uploadingPageCancel = Cancelar subida
|
||||
uploadCancelNotification = Se canceló la subida.
|
||||
uploadingPageLargeFileMessage = El archivo es grande y puede tardar unos minutos en subirse. ¡Tómatelo con calma!
|
||||
uploadingFileNotification = Notificarme cuando se complete la subida.
|
||||
uploadSuccessConfirmHeader = Listo para enviar
|
||||
uploadSvgAlt = Subir
|
||||
uploadSuccessTimingHeader = El enlace al archivo caducará tras descargarlo una vez o en 24 horas.
|
||||
copyUrlFormLabelWithName = Copiar y compartir el enlace para enviar tu archivo: { $filename }
|
||||
copyUrlFormButton = Copiar en el portapapeles
|
||||
copiedUrl = ¡Copiado!
|
||||
deleteFileButton = Eliminar archivo
|
||||
sendAnotherFileLink = Enviar otro archivo
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Descargar
|
||||
downloadFileName = Descargar { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Tu amigo te está enviando un archivo a través de Firefox Send, un servicio que te permite compartir archivos con un enlace seguro, privado y cifrado que caduca automáticamente para que tus cosas no sean accesibles en línea de por vida.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Descargar
|
||||
downloadNotification = Se completó la descarga.
|
||||
downloadFinish = Descarga completa
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } de { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Prueba Firefox Send
|
||||
downloadingPageProgress = Descargando { $filename } ({ $size })
|
||||
downloadingPageMessage = Deja esta pestaña abierta mientras buscamos tu archivo y lo desencriptamos.
|
||||
errorAltText = Error en la subida
|
||||
errorPageHeader = ¡Se produjo un error!
|
||||
errorPageMessage = Se produjo un error al subir el archivo.
|
||||
errorPageLink = Enviar otro archivo
|
||||
fileTooBig = Ese archivo es muy grande. Debería ocupar menos de { $size }.
|
||||
linkExpiredAlt = Enlace caducado
|
||||
expiredPageHeader = ¡El enlace ha caducado o nunca existió!
|
||||
notSupportedHeader = Tu navegador no está admitido.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Lamentablemente, este navegador no admite la tecnología web que necesita Firefox Send. Tendrás que probar otro navegador. ¡Te recomendamos Firefox!
|
||||
notSupportedLink = ¿Por qué no se admite mi navegador?
|
||||
notSupportedOutdatedDetail = Lamentablemente, esta versión de Firefox no admite la tecnología web que impulsa Firefox Send. Tendrás que actualizar tu navegador.
|
||||
updateFirefox = Actualizar Firefox
|
||||
downloadFirefoxButtonSub = Descarga gratuita
|
||||
uploadedFile = Archivo
|
||||
copyFileList = Copiar URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Caduca en
|
||||
deleteFileList = Eliminar
|
||||
nevermindButton = Da igual
|
||||
legalHeader = Términos y privacidad
|
||||
legalNoticeTestPilot = Firefox Send sigue siendo un experimento de Test Pilot y está sujero a las <a>Condiciones del servicio</a> y al <a>Aviso de privacidad</a> de Test Pilot.
|
||||
legalNoticeMozilla = El uso de la página de Firefox Send también está sujeto al <a>Aviso de privacidad sobre sitios web</a> y a los <a>Términos de uso sobre sitios web</a>.
|
||||
deletePopupText = ¿Eliminar el archivo?
|
||||
deletePopupYes = Sí
|
||||
deletePopupCancel = Cancelar
|
||||
deleteButtonHover = Eliminar
|
||||
copyUrlHover = Copiar URL
|
||||
footerLinkLegal = Legal
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Sobre Test Pilot
|
||||
footerLinkPrivacy = Privacidad
|
||||
footerLinkTerms = Términos
|
||||
footerLinkCookies = Cookies
|
||||
82
public/locales/es-MX/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = experimento web
|
||||
siteFeedback = Comentario
|
||||
uploadPageHeader = Compartir archivos encriptados y privados
|
||||
uploadPageExplainer = Enviar archivos a través de un enlace encriptado, privado y seguro que caducará automáticamente para que tus datos no sean accesibles en línea de por vida.
|
||||
uploadPageLearnMore = Saber más
|
||||
uploadPageDropMessage = Suelta aquí tu archivo para empezar a subirlo
|
||||
uploadPageSizeMessage = Para que la operación sea más segura, el archivo debería ocupar menos de 1GB
|
||||
uploadPageBrowseButton = Selecciona un archivo de tu computadora
|
||||
uploadPageBrowseButton1 = Seleccionar un archivo para subir
|
||||
uploadPageMultipleFilesAlert = Aún no se pueden subir varios archivos o una carpeta.
|
||||
uploadPageBrowseButtonTitle = Subir archivo
|
||||
uploadingPageProgress = Subiendo { $filename } ({ $size })
|
||||
importingFile = Importando...
|
||||
verifyingFile = Verificando...
|
||||
encryptingFile = Encriptando...
|
||||
decryptingFile = Desencriptando...
|
||||
notifyUploadDone = La subida ha terminado.
|
||||
uploadingPageMessage = Una vez que tu archivo haya subido podrás configurar las opciones de caducidad.
|
||||
uploadingPageCancel = Cancelar subida
|
||||
uploadCancelNotification = Se canceló la subida.
|
||||
uploadingPageLargeFileMessage = Este archivo es grande y puede tomar un rato para que suba. ¡Mantente tranquilo!
|
||||
uploadingFileNotification = Avísame cuando la subida del archivo esté completa.
|
||||
uploadSuccessConfirmHeader = Listo para enviar
|
||||
uploadSvgAlt = Subir
|
||||
uploadSuccessTimingHeader = El enlace a tu archivo expirará después de una descarga o en 24 horas.
|
||||
copyUrlFormLabelWithName = Copiar y compartir el enlace para enviar tu archivo: ($filename)
|
||||
copyUrlFormButton = Copiar a portapapeles
|
||||
copiedUrl = ¡Copiado!
|
||||
deleteFileButton = Eliminar archivo
|
||||
sendAnotherFileLink = Enviar otro archivo
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Descargar
|
||||
downloadFileName = Descargar ($filename)
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Tu amigo te está enviando un archivo a través de Firefox Send, un servicio que te permite compartir archivos con un enlace seguro, privado y encriptado que caduca automáticamente para que tus cosas no sean accesibles en línea de por vida.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Descargar
|
||||
downloadNotification = Tu descarga se ha completado
|
||||
downloadFinish = Descarga completa
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } de { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Prueba Firefox Send
|
||||
downloadingPageProgress = Descargando { $filename } ({ $size })
|
||||
downloadingPageMessage = Deja esta pestaña abierta mientras buscamos tu archivo y lo desencriptamos.
|
||||
errorAltText = Error en la subida
|
||||
errorPageHeader = ¡Algo salió mal!
|
||||
errorPageMessage = Ha ocurrido un error mientras subiamos tu archivo.
|
||||
errorPageLink = Enviar otro archivo
|
||||
fileTooBig = Ese archivo es muy grande. Debería ocupar menos de { $size }.
|
||||
linkExpiredAlt = Enlace caducado
|
||||
expiredPageHeader = ¡Este enlace ha caducado o nunca existió en primer lugar!
|
||||
notSupportedHeader = Tu navegador no está soportado.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Lamentablemente, este navegador no admite la tecnología web que necesita Firefox Send. Tendrás que probar otro navegador. ¡Te recomendamos Firefox!
|
||||
notSupportedLink = ¿Por qué mi navegador no tiene soporte?
|
||||
notSupportedOutdatedDetail = Lamentablemente esta versión de Firefox no soporta la tecnología web que potencia a Firefox Send. Deberás actualizar tu navegador.
|
||||
updateFirefox = Actualizar Firefox
|
||||
downloadFirefoxButtonSub = Descarga gratuita
|
||||
uploadedFile = Archivo
|
||||
copyFileList = Copiar URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Caduca en
|
||||
deleteFileList = Eliminar
|
||||
nevermindButton = Da igual
|
||||
legalHeader = Términos y privacidad
|
||||
legalNoticeTestPilot = Firefox Send sigue siendo un experimento de Test Pilot y está sujeto a las <a>Condiciones del servicio</a> y al <a>Aviso de privacidad</a> de Test Pilot. Puedes saber más acerca de este experimento y si recolección de datos <a>aquí</a>.
|
||||
legalNoticeMozilla = El uso de la página de Firefox Send también está sujeto al <a>Aviso de privacidad sobre sitios web</a> y a los <a>Términos de uso sobre sitios web</a>.
|
||||
deletePopupText = ¿Eliminar este archivo?
|
||||
deletePopupYes = Sí
|
||||
deletePopupCancel = Cancelar
|
||||
deleteButtonHover = Eliminar
|
||||
copyUrlHover = Copiar URL
|
||||
footerLinkLegal = Legal
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Acerca de Test Pilot
|
||||
footerLinkPrivacy = Privacidad
|
||||
footerLinkTerms = Términos
|
||||
footerLinkCookies = Cookies
|
||||
80
public/locales/et/send.ftl
Normal file
@@ -0,0 +1,80 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = veebieksperiment
|
||||
siteFeedback = Tagasiside
|
||||
uploadPageHeader = Privaatne ja krüpteeritud failiedastus
|
||||
uploadPageExplainer = Firefox Send võimaldab saata faile üle ohutu, privaatse ja krüpteeritud kanali. Failid kustutatakse automaatselt, et need ei jääks internetti igaveseks.
|
||||
uploadPageLearnMore = Rohkem teavet
|
||||
uploadPageDropMessage = Faili üleslaadimiseks lohista see siia
|
||||
uploadPageSizeMessage = Parima kogemuse saamiseks tasub faili suurus hoida alla 1GB
|
||||
uploadPageBrowseButton = Vali fail arvutist
|
||||
uploadPageBrowseButton1 = Vali fail üleslaadimiseks
|
||||
uploadPageMultipleFilesAlert = Mitme faili või kausta üleslaadimine pole praegu toetatud.
|
||||
uploadPageBrowseButtonTitle = Laadi fail üles
|
||||
uploadingPageProgress = Faili { $filename } ({ $size }) üleslaadimine
|
||||
importingFile = Importimine...
|
||||
verifyingFile = Kontrollimine…
|
||||
encryptingFile = Krüptimine…
|
||||
decryptingFile = Dekrüptimine...
|
||||
notifyUploadDone = Üleslaadimine on lõpetatud.
|
||||
uploadingPageMessage = Aegumise sätteid saab muuta siis, kui faili üles laaditakse.
|
||||
uploadingPageCancel = Katkesta üleslaadimine
|
||||
uploadCancelNotification = Üleslaadimine katkestati
|
||||
uploadingPageLargeFileMessage = Fail on suur ja selle üleslaadimine võib aega võtta.
|
||||
uploadSuccessConfirmHeader = Saatmiseks valmis
|
||||
uploadSvgAlt = Laadi üles
|
||||
uploadSuccessTimingHeader = Link failile aegub pärast 1. allalaadimist või 24 tunni möödumisel.
|
||||
copyUrlFormLabelWithName = Kopeeri ja jaga linki faili allalaadimiseks: { $filename }
|
||||
copyUrlFormButton = Kopeeri vahemällu
|
||||
copiedUrl = Kopeeritud!
|
||||
deleteFileButton = Kustuta fail
|
||||
sendAnotherFileLink = Saada järgmine fail
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = Laadi alla
|
||||
downloadFileName = Laadi fail { $filename } alla
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = Sulle on saadetud fail Firefox Sendiga - teenusega, mis lubab faile ohutult, privaatselt ja krüpteeritult jagada. Failid kustutatakse automaatselt, et need ei jääks internetti igaveseks.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = Laadi alla
|
||||
downloadNotification = Allalaadimine on lõpetatud.
|
||||
downloadFinish = Allalaadimine lõpetati
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize }/{ $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Proovi Firefox Sendi
|
||||
downloadingPageProgress = Faili { $filename } ({ $size }) allalaadimine
|
||||
downloadingPageMessage = Palun jäta see kaart lahti, kuni fail on alla laaditud ja dekrüptitud.
|
||||
errorAltText = Viga üleslaadimisel
|
||||
errorPageHeader = Midagi läks valesti!
|
||||
errorPageMessage = Faili üleslaadimisel esines viga.
|
||||
errorPageLink = Saada järgmine fail
|
||||
fileTooBig = Fail on üleslaadimiseks liiga suur. See peaks olema väiksem kui { $size }.
|
||||
linkExpiredAlt = Link on aegunud
|
||||
expiredPageHeader = See link on aegunud või seda pole kunagi olnudki!
|
||||
notSupportedHeader = Sinu brauser pole toetatud.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = Kahjuks ei toeta see brauser veebitehnoloogiaid, mis teevad Firefox Sendi toimimise võimalikuks. Sa pead proovima teise brauseriga. Me soovitame Firefoxi!
|
||||
notSupportedLink = Miks mu brauser toetatud pole?
|
||||
notSupportedOutdatedDetail = Kahjuks ei toeta see Firefoxi versioon veebitehnoloogiaid, mis teevad Firefox Sendi toimimise võimalikuks. Sa pead oma brauserit uuendama.
|
||||
updateFirefox = Uuenda Firefox
|
||||
downloadFirefoxButtonSub = Laadi alla tasuta
|
||||
uploadedFile = Fail
|
||||
copyFileList = Kopeeri URL
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = Aegub
|
||||
deleteFileList = Kustuta
|
||||
legalHeader = Tingimused ja privaatsusreeglid
|
||||
legalNoticeTestPilot = Firefox Send on praegu Test Piloti eksperiment ja sellele rakenduvad Test Piloti <a>teenusetingimused</a> ning <a>privaatsusreeglid</a>. Rohkem teavet selle eksperimendi ja kogutavate andmete kohta leiab <a>siit</a>.
|
||||
legalNoticeMozilla = Firefox Sendi veebilehe kasutamisele rakenduvad ka Mozilla <a>veebilehtede privaatsusreeglid</a> ja <a>veebilehtede teenusetingimused</a>.
|
||||
deletePopupText = Kas kustutada see fail?
|
||||
deletePopupYes = Jah
|
||||
deletePopupCancel = Loobu
|
||||
deleteButtonHover = Kustuta
|
||||
copyUrlHover = Kopeeri URL
|
||||
footerLinkLegal = Õiguslik teave
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = Test Pilotist
|
||||
footerLinkPrivacy = Privaatsusest
|
||||
footerLinkTerms = Teenusetingimused
|
||||
footerLinkCookies = Küpsistest
|
||||
82
public/locales/fa/send.ftl
Normal file
@@ -0,0 +1,82 @@
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
title = Firefox Send
|
||||
siteSubtitle = آزمایش وب
|
||||
siteFeedback = بازخورد
|
||||
uploadPageHeader = اشتراکگذاری پروندهها، رمزنگاری شده و خصوصی
|
||||
uploadPageExplainer = پرونده های خود را به صورت ایمن، خصوصی و رمزنگاری شده با تعیین تاریخ انقضا خودکار ارسال کنید تا اطمینان پیدا کنید چیزهای شما همیشه آنلاین باقی نماند.
|
||||
uploadPageLearnMore = بیشتر بدانید
|
||||
uploadPageDropMessage = برای شروع بارگذاری پروندههای خود را اینجا بیاندازید
|
||||
uploadPageSizeMessage = برای بیشترین قابلیت اطمینان، بهتر است که پروندهتان کمتر از ۱ گیگابایت باشد
|
||||
uploadPageBrowseButton = یک پرونده را از روی کامپیوتر خود انتخاب کنید
|
||||
uploadPageBrowseButton1 = یک پرونده را برای بارگذاری انتخاب کنید
|
||||
uploadPageMultipleFilesAlert = بارگذاری چندین پرونده یا یک پوشه در حال حاضر پشتیبانی نمیشود.
|
||||
uploadPageBrowseButtonTitle = بارگذاری پرونده
|
||||
uploadingPageProgress = در حال بارگذاری پرونده { $filename } ({ $size })
|
||||
importingFile = در حال وارد کردن…
|
||||
verifyingFile = در حال تایید…
|
||||
encryptingFile = در حال رمزنگاری…
|
||||
decryptingFile = در حال رمزگشایی…
|
||||
notifyUploadDone = بارگذاری شما پایان یافت.
|
||||
uploadingPageMessage = به محض بارگذاری پرونده شما قادر خواهید بود برای آن گزینه انقضا تعیین کنید.
|
||||
uploadingPageCancel = لغو بارگذاری
|
||||
uploadCancelNotification = بارگذاری شما لغو شد
|
||||
uploadingPageLargeFileMessage = پرونده بزرگ است و ممکن است بارگذاری آن مدتی طول بکشد. محکم بشینید!
|
||||
uploadingFileNotification = هر وقت بارگذاری تمام شد به من اطلاع بده.
|
||||
uploadSuccessConfirmHeader = آماده برای ارسال
|
||||
uploadSvgAlt = بارگذاری
|
||||
uploadSuccessTimingHeader = پیوند به پرونده شما بعد از ۱ بار دانلود یا ۲۴ ساعت حذف خواهد شد.
|
||||
copyUrlFormLabelWithName = برای ارسال پرونده پیوند آن را رونوشت و به اشتراک بگذارید: { $filename }
|
||||
copyUrlFormButton = رونوشت به کلیپبورد
|
||||
copiedUrl = رونوشت شد!
|
||||
deleteFileButton = حذف پرونده
|
||||
sendAnotherFileLink = ارسال پرونده دیگر
|
||||
// Alternative text used on the download link/button (indicates an action).
|
||||
downloadAltText = دریافت
|
||||
downloadFileName = بارگیری { $filename }
|
||||
downloadFileSize = ({ $size })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
downloadMessage = دوست شما درحال ارسال پرونده ای به وسیله Firefox Send است، این سرویس این امکان را به شما میدهد تا پروندههای خود را به صورت ایمن،خصوصی و رمزنگاری شده به همراه پیوند انقضا خودکار همرسانی کنید تا اطمینان حاصل کنید چیزهای شما برای همیشه آنلاین باقی نخواهد ماند.
|
||||
// Text and title used on the download link/button (indicates an action).
|
||||
downloadButtonLabel = بارگیری
|
||||
downloadNotification = بارگیری شما کامل شد.
|
||||
downloadFinish = بارگیری کامل شد
|
||||
// This message is displayed when uploading or downloading a file, e.g. "(1,3 MB of 10 MB)".
|
||||
fileSizeProgress = ({ $partialSize } از { $totalSize })
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
sendYourFilesLink = Firefox Send را امتحان کنید
|
||||
downloadingPageProgress = دریافت { $filename } ({ $size })
|
||||
downloadingPageMessage = لطفا این زبانه را باز بگذارید در حالی که ما فایل شما را دریافت میکنیم و کدگذاری میکنیم.
|
||||
errorAltText = خطا در بارگذاری
|
||||
errorPageHeader = چیزی دچار اشکال شده است!
|
||||
errorPageMessage = خطایی در هنگام بارگذاری پرونده شما رخ داده است.
|
||||
errorPageLink = پرونده دیگری ارسال کنید.
|
||||
fileTooBig = این پرونده بسیار حجیم است. حجم آن میبایستی کم تر { $size } باشد.
|
||||
linkExpiredAlt = پیوند منقضی شده است
|
||||
expiredPageHeader = پیوند منقضی شده است یا در از همان ابتدا وجود نداشته است!
|
||||
notSupportedHeader = مرورگر شما پشتیبانی نمیکند.
|
||||
// Firefox Send is a brand name and should not be localized.
|
||||
notSupportedDetail = متاسفانه این مرورگر این تکنولوژی وب را که به Firefox Send قدرت میبخشد را پشتیبانی نمیکند. شما بایستی مرورگری دیگری را امتحان کنید. پیشنهاد ما به شما فایرفاکس است !
|
||||
notSupportedLink = چرا مرورگر من پشتیبانی نمیکند؟
|
||||
notSupportedOutdatedDetail = متاسفانه این نسخه از فایرفاکس این تکنولوژی وب که به Firefox Send قدرت میبخشد را پشتیبانی نمیکند. شما نیاز دارید تا مرورگر خود را بروز کنید.
|
||||
updateFirefox = بروزرسانی فایرفاکس
|
||||
downloadFirefoxButtonSub = دریافت رایگان
|
||||
uploadedFile = پرونده
|
||||
copyFileList = رونوشت از نشانی
|
||||
// expiryFileList is used as a column header
|
||||
expiryFileList = زمان انقضا
|
||||
deleteFileList = حذف
|
||||
nevermindButton = بیخیال
|
||||
legalHeader = شرایط و حریمخصوصی
|
||||
legalNoticeTestPilot = Firefox Send در حال حاضر در نسخه آزمایشی خود به صورت میدهد و تحت عنوان خلبان آموزشی <a>شرایط و خدمات</a> و <a>موارد حریم خصوصی </a> کار میکند. شما میتوانید اطلاعات بیشتر در مورد این آزمایش و اطلاعات که ذخیره میکنید را از <a> اینجا </a> کسب کنید.
|
||||
legalNoticeMozilla = استفاده از Firefox Send همچنین منصوب به موزیلا است. <a>پایگاه اینترنتی نکات حریم شخصی </a> و <a> پایگاه اطلاع رسانی شرایط خدمات و استفاده </a>.
|
||||
deletePopupText = حذف این پرونده؟
|
||||
deletePopupYes = بله
|
||||
deletePopupCancel = انصراف
|
||||
deleteButtonHover = حذف
|
||||
copyUrlHover = رونوشت از نشانی
|
||||
footerLinkLegal = ملاحظات حقوقی
|
||||
// Test Pilot is a proper name and should not be localized.
|
||||
footerLinkAbout = درباره Test Pilot
|
||||
footerLinkPrivacy = حریمخصوصی
|
||||
footerLinkTerms = شرایط
|
||||
footerLinkCookies = کوکیها
|
||||