Compare commits

...

109 Commits

Author SHA1 Message Date
ansuz 24a1d1b622
Merge pull request #782 from xwiki-labs/dependabot/npm_and_yarn/jszip-3.7.1
Bump jszip from 3.6.0 to 3.7.1
2021-08-17 05:55:28 -04:00
dependabot[bot] 589a09e721
Bump jszip from 3.6.0 to 3.7.1
Bumps [jszip](https://github.com/Stuk/jszip) from 3.6.0 to 3.7.1.
- [Release notes](https://github.com/Stuk/jszip/releases)
- [Changelog](https://github.com/Stuk/jszip/blob/master/CHANGES.md)
- [Commits](https://github.com/Stuk/jszip/compare/v3.6.0...v3.7.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-17 09:42:43 +00:00
ansuz 58eb65e35d report screen width and height in support tickets 2021-08-17 12:15:55 +05:30
ansuz 8887d8fc1e remove dead code 2021-08-17 12:15:29 +05:30
ansuz 554ce65346 check for HTML tags across multiple lines 2021-08-17 12:15:07 +05:30
ansuz 09bdcb2013 update changelog for 4.10.0 2021-08-17 10:51:20 +05:30
ansuz 47067b020b defer some more minor issues till 4.11.0 2021-08-16 18:38:33 +05:30
ansuz 09f0b8f61e Merge branch 'soon' into staging 2021-08-16 18:36:02 +05:30
Weblate 89b52b6110 Translated using Weblate (French)
Currently translated at 100.0% (1382 of 1382 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/fr/
2021-08-16 15:05:22 +02:00
ansuz c1f9d11333 delay working on some flagged issues till next release 2021-08-16 18:32:34 +05:30
ansuz 3976bfae84 remove unnecessary notes 2021-08-16 18:24:57 +05:30
ansuz cad514cc17 remove hacky experiments with charts.css
...and finalize forms changes
2021-08-16 17:24:37 +05:30
ansuz 1e12b85b7c use updated translation key and add a comment 2021-08-13 18:36:44 +05:30
ansuz b0539fe613 Merge branch 'staging' into hackathon-2021 2021-08-13 17:55:24 +05:30
ansuz 1485c62746 Merge branch 'main' into soon 2021-08-13 17:54:46 +05:30
ansuz 11bcdbd7e3 hotfix for forms
avoid browser fights when multiple authors view a form
with a sortable list at the same time
2021-08-13 17:28:40 +05:30
ansuz c1a19ea65c remove some invalid notes 2021-08-13 17:26:29 +05:30
ansuz add234a8f7 Merge branch 'staging' into hackathon-2021 2021-08-13 16:06:14 +05:30
ansuz ad0d2ab3b7 style for kanban 'tools toggle' and notes for later 2021-08-13 16:05:32 +05:30
ansuz 69a393f374 add support for alternate icons and text in 'toggle' buttons 2021-08-13 15:54:53 +05:30
ansuz 9b3cd7dae3 WIP changelog for 4.10.0 2021-08-13 15:54:10 +05:30
ansuz b7f627d896 update version string for 4.10.0
and commit some new 'npm run' commands while we're at it
2021-08-13 15:53:42 +05:30
ansuz 04234aa1f4 fix a typo in a class 2021-08-13 15:52:14 +05:30
ansuz f701e30364 correct invalid use of ':' in french translations 2021-08-13 15:45:54 +05:30
ansuz f12a276c78 correct inconsistent capitalization of 'CryptPad' in markdown files.
Add a rule to the translation linter to detect future inconsistencies.
2021-08-13 15:44:11 +05:30
ansuz a779d043ca standardize capitalization of CryptPad in translated strings and fix some typos 2021-08-13 15:10:43 +05:30
ansuz 4810d6b5ba use custom styles for the form timeline, move away from charts.css 2021-08-13 12:20:26 +05:30
ansuz 25a3359671 Merge branch 'staging' into hackathon-2021 2021-08-12 20:07:09 +05:30
ansuz 375bf7a62e correct an inaccurate comment 2021-08-12 19:21:33 +05:30
ansuz e4879b5117 guard against possibly undefined team data in 'setPadMetadata' 2021-08-12 19:15:52 +05:30
ansuz 036248a659 handle warnings from history trim, not just errors 2021-08-12 19:14:30 +05:30
ansuz 8d17ae64f3 log an error with a channel if we try to pin an invalid channel 2021-08-12 19:08:18 +05:30
ansuz 6413be24f3 apply a click handler with vanilla js instead of jquery
the jquery method only worked ~50% of the time in Firefox 90
for a completely unknown reason
2021-08-12 19:04:09 +05:30
ansuz 7f41f8765e avoid bypassing guards against raw HTML in some dialogs 2021-08-12 19:02:25 +05:30
ansuz 975259f935 Merge branch 'soon' into staging 2021-08-12 16:10:32 +05:30
ansuz 7e80b90bca standardize usage of BR tag in translations 2021-08-12 16:07:43 +05:30
Weblate afdfc273e8 Translated using Weblate (Spanish)
Currently translated at 43.5% (602 of 1382 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/es/
2021-08-12 12:05:11 +02:00
ansuz 72bf3696ee correct some unncessary instances of raw HTML injection 2021-08-11 19:51:44 +05:30
ansuz 384d4be864 suppress browsers' password autocomplete for document passwords 2021-08-11 19:21:19 +05:30
David Benqué ddee1e9b40 Fix toolbar collapse button 2021-08-11 13:21:34 +01:00
David Benqué d05f03c8c6 Use icon only for toolbar collapse/expand button 2021-08-11 13:01:45 +01:00
David Benqué fc4178df7e Refactor form control buttons 2021-08-11 10:42:59 +01:00
ansuz 44f5aee4ac Dependency management:
move (most) third-party dependencies from www/common/ => www/lib/

* unify less.js files by standardizing on our slightly modified version
* update textFit.js to the latest version
* describe exact versions of files where known, otherwise link to their project sites
2021-08-11 15:07:38 +05:30
ansuz 44688026d6 exclude ids with invalid lengths from our list of owned documents 2021-08-10 19:53:56 +05:30
ansuz 59aefef2ad update changelog 2021-08-10 19:51:43 +05:30
ansuz 2a8c70598b Merge branch 'soon' into staging 2021-08-10 19:51:28 +05:30
ansuz 2dc4ec1b24 include vendor and appVersion in support ticket data 2021-08-10 19:49:22 +05:30
ansuz 7647a60219 guess OS version on checkup page 2021-08-10 19:48:15 +05:30
ansuz d8af3a16ab exclude invalid channel and blob ids when fetching your channel list
for all variations of the same API
2021-08-10 18:51:00 +05:30
ansuz b9eced7bfd remove unused 'noscriptfix' hack 2021-08-10 18:49:29 +05:30
ansuz 1c08a27f60 fix a newly introduced reference error 2021-08-10 18:48:34 +05:30
ansuz d960c10a31 clear login token when deleting your account and before logging in 2021-08-10 18:46:10 +05:30
ansuz a33774aa6f properly abort from channel archival if no metadata is returned
and add some logging when trimming history
2021-08-10 15:24:23 +05:30
Weblate 17ea1611e7 Translated using Weblate (German)
Currently translated at 100.0% (1382 of 1382 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/de/

Translated using Weblate (German)

Currently translated at 99.8% (1380 of 1382 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/de/
2021-08-10 11:50:32 +02:00
Weblate 61df9214ff Translated using Weblate (Japanese)
Currently translated at 100.0% (1382 of 1382 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/ja/
2021-08-10 11:50:32 +02:00
ansuz b0fcaf8e51 Merge branch 'soon' into staging 2021-08-09 20:21:11 +05:30
Weblate 6a4f02831e Translated using Weblate (English)
Currently translated at 100.0% (1382 of 1382 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/

Translated using Weblate (English)

Currently translated at 100.0% (1381 of 1381 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/

Translated using Weblate (English)

Currently translated at 100.0% (1380 of 1380 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/
2021-08-09 16:50:34 +02:00
Weblate 55a8c94eb4 Translated using Weblate (French)
Currently translated at 99.8% (1380 of 1382 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/fr/
2021-08-09 16:50:34 +02:00
ansuz b5c051a27f label hardcoded form translations 2021-08-09 15:59:23 +05:30
ansuz 30c2bfbdfa more small tweaks 2021-08-09 15:47:27 +05:30
ansuz d6886fb4c0 style and text fixes for form timeline 2021-08-09 15:37:31 +05:30
ansuz 900db1fcb0 disable usage of charts.css except for the timeline 2021-08-06 18:51:51 +05:30
ansuz e4d5431f29 display form answer timeline oldest => newest 2021-08-05 17:15:56 +05:30
ansuz 34aa959a10 Merge branch 'staging' into hackathon-2021 2021-08-05 17:04:08 +05:30
ansuz acd7148967 change collapse/expand icons from 'caret' to 'chevron' 2021-08-05 17:01:11 +05:30
ansuz ed8c2f4319
Merge pull request #781 from aemi-dev/hackathon-2021
Hackathon 2021 - Timeline - Minor Edits & Comments
2021-08-05 06:56:27 -04:00
aemi-dev 9910c97d5e Hackathon 2021 - Timeline - Minor Edits & Comments 2021-08-05 11:58:41 +02:00
ansuz ded834b2c7 lint compliance 2021-08-05 11:53:35 +05:30
ansuz 4a80007fea
Merge pull request #780 from aemi-dev/hackathon-2021
Hackathon 2021
2021-08-05 02:13:14 -04:00
aemi-dev 085736e4b7 Hackathon 2021 - Timeline 2021-08-05 02:10:29 +02:00
aemi-dev 3ba0f4d0b8 Merge branch 'hackathon-2021' of https://github.com/aemi-dev/cryptpad into hackathon-2021
Merge hackathon works
2021-08-05 02:00:58 +02:00
aemi-dev b365c411ea Hackathon 2021 - Timeline 2021-08-05 01:58:22 +02:00
aemi-dev 11dc7d12d5 Hackathon 2021 - Timeline 2021-08-05 01:57:48 +02:00
ansuz 53ba25b5b0 more chart visualizations, brand colors 2021-08-04 20:27:45 +05:30
ansuz 73acfd9b42 start integrating some basic charts in form answers 2021-08-04 17:08:29 +05:30
ansuz 2d405b5a32 add more annotations indicating what type of chart should be used 2021-08-04 15:31:57 +05:30
ansuz d9b6d94580 use consistent capitalization for CryptPad
run docs/ARCHITECTURE.md:[XWiki-Labs](https://labs.xwiki.com/) has published an open source suite (called [Cryptpad](https://github.com/xwiki-labs/cryptpad)) of collaborative editors  which employ end to end encryption.
docs/ARCHITECTURE.md:Cryptpad is capable of using a variety of data stores.
docs/ARCHITECTURE.md:Cryptpad was initially written to use [websockets](https://en.wikipedia.org/wiki/WebSocket) for transportation of messages.
docs/ARCHITECTURE.md:The encryption scheme employed by Cryptpad is a [symmetric encryption](https://en.wikipedia.org/wiki/Symmetric-key_algorithm) which utilizes a single [pre-shared-key](https://en.wikipedia.org/wiki/Pre-shared_key) known by all participants.
readme.md:See [Cryptpad-Docker](https://github.com/xwiki-labs/cryptpad-docker) repository for details on how to get up-and-running with Cryptpad in Docker. This repository is maintained by the community and not officially supported.
readme.md:If you have any questions or comments, or if you're interested in contributing to Cryptpad, come say hi in our [Matrix channel](https://app.element.io/#/room/#cryptpad:matrix.xwiki.com).
www/common/translations/README.md:To illustrate the process of translating, this guide will make an english-pirate translation of Cryptpad.
www/common/translations/README.md:We'll assume that you have a work locally-installed, properly functioning installation of Cryptpad.
www/common/translations/README.md:If you don't have Cryptpad installed locally, start by following the steps in the main readme.
www/common/translations/README.md:    out.main_title = "Cryptpad: Zero Knowledge, Collaborative Real Time Editing";
www/common/translations/README.md:    out.main_title = "Cryptpad: Knowledge lost at sea while ye scribble with yer mateys";
www/common/translations/README.md:It's advisable to save your translation file frequently, and reload Cryptpad in your browser to check that there are no errors in your translation file.
www/common/translations/README.md:When you're happy with your translation file, you can visit http://localhost:3000/assert/translations/ to view Cryptpad's tests.
www/common/translations/messages.ca.json:    "topbar_whatIsCryptpad": "Què és CryptPad",
www/common/translations/messages.de.json:    "topbar_whatIsCryptpad": "Was ist CryptPad",
www/common/translations/messages.el.json:    "topbar_whatIsCryptpad": "Τι είναι το CryptPad",
www/common/translations/messages.es.json:    "main_title": "Cryptpad: Zero Knowledge, Editor Colaborativo en Tiempo Real",
www/common/translations/messages.es.json:    "tos_title": "Condiciones de servicio Cryptpad",
www/common/translations/messages.es.json:    "tos_e2ee": "Los documentos Cryptpad pueden ser leídos o modificados por cualquiera que pueda adivinar o que pueda tener el enlace. Recomendamos que utilices mensajes cifrados de punto a punto (e2ee) para compartir URLs, no asumimos ninguna responsabilidad en el evento de alguna fuga.",
www/common/translations/messages.es.json:    "topbar_whatIsCryptpad": "Qué es CryptPad",
www/common/translations/messages.es.json:    "settings_autostoreHint": "<b> Automático </b> Todos los pads que visita se almacenan en su CryptDrive. <br> <b> Manual (siempre pregunte) </b> Si aún no ha guardado un pad, se le preguntará si desea para almacenarlos en su CryptDrive. <br> <b> Manual (nunca preguntar) </b> Los Pads no se almacenan automáticamente en su Cryptpad. La opción para almacenarlos estará oculta.",
www/common/translations/messages.fi.json:    "home_host": "Tämä on itsenäinen yhteisön ylläpitämä Cryptpad-instanssi.",
www/common/translations/messages.fi.json:    "topbar_whatIsCryptpad": "Mikä on CryptPad",
www/common/translations/messages.fr.json:    "topbar_whatIsCryptpad": "Qu'est-ce que CryptPad",
www/common/translations/messages.fr.json:    "admin_updateAvailableHint": "Une nouvelle version de Cryptpad est disponible",
www/common/translations/messages.id.json:    "main_title": "Cryptpad: Informasi Aman, Kolaborasi Waktu Nyata"
www/common/translations/messages.it.json:    "topbar_whatIsCryptpad": "Cos'è CryptPad",
www/common/translations/messages.it.json:    "settings_autostoreHint": "<b>Automatico</b> Tutti i pad che visiti sono conservati nel tuo CryptDrive.<br><b>Manuale (chiedi sempre)</b> Se non hai ancora conservato alcun pad ti verrà chiesto se vuoi conservarli nel tuo CryptDrive.<br><b>Manuale (non chiedere mai)</b> I pads non sono conservati automaticamente nel tuo Cryptpad. L'opzione di conservarli sarà nascosta.",
www/common/translations/messages.it.json:    "survey": "Sondaggio Cryptpad",
www/common/translations/messages.it.json:    "crowdfunding_button": "Supporta Cryptpad",
www/common/translations/messages.ja.json:    "topbar_whatIsCryptpad": "CryptPadとは何か",
www/common/translations/messages.json:    "settings_autostoreHint": "<b>Automatic</b> All the pads you visit are stored in your CryptDrive.<br><b>Manual (always ask)</b> If you have not stored a pad yet, you will be asked if you want to store them in your CryptDrive.<br><b>Manual (never ask)</b> Pads are not stored automatically in your Cryptpad. The option to store them will be hidden.",
www/common/translations/messages.json:    "topbar_whatIsCryptpad": "What is CryptPad",
www/common/translations/messages.nb.json:    "topbar_whatIsCryptpad": "Hva er CryptPad",
www/common/translations/messages.nl.json:    "settings_autostoreHint": "<b>Automatisch</b> Alle geopende werkomgevingen worden automatisch opgeslagen in uw CryptDrive.<br><b>Handmatig (altijd vragen)</b> Als u een werkomgeving nog niet hebt opgeslagen, zult u gevraagd worden of u het in uw CryptDrive wilt opslaan.<br><b>Handmatig (nooit vragen)</b> Werkomgevingen worden niet automatisch opgeslagen in uw Cryptpad. The optie om op te slaan wordt verborgen.",
www/common/translations/messages.pl.json:    "main_title": "Cryptpad: Wspólne edytowanie w czasie rzeczywistym, bez wiedzy specjalistycznej",
www/common/translations/messages.pl.json:    "tos_title": "Warunki korzystania z usług Cryptpad",
www/common/translations/messages.pl.json:    "tos_e2ee": "Dokumenty Cryptpad mogą być odczytywane i modyfikowane przez każdego kto może zgadnąć lub w inny sposób uzyskać identyfikator dokumentu. Polecamy korzystania z oprogramowania szyfrującego end-to-end (e2ee) do udostępniania linków URL. Nie będziesz rościł sobie żadnych wierzytelności w wypadku gdy taki URL dostanie się w niepowołane ręce.",
www/common/translations/messages.pt-br.json:    "main_title": "Cryptpad: Zero Knowledge, Edição Colaborativa em Tempo Real",
www/common/translations/messages.pt-br.json:    "tos_title": "Termos de serviço doCryptpad",
www/common/translations/messages.pt-br.json:    "topbar_whatIsCryptpad": "O que é CryptPad",
www/common/translations/messages.ro.json:    "settings_autostoreHint": "<b>Automat</b> Toate documentele accesate sunt stocate în CryptDrive-ul dumneavoastră.<br><b>Manual (întreabă întotdeauna)</b> Dacă nu ai stocat încă un document, vei fi întrebat dacă dorești să îl stochezi în Cryptdrive-ul tău.<br><b>Manual (nu mai întreba)</b> Documentele nu sunt stocate automat în Cryptpad-ul tău. Opțiunea de a le stoca ulterior va fi ascunsă.",
www/common/translations/messages.ru.json:    "topbar_whatIsCryptpad": "Что такое CryptPad",
www/common/translations/messages.zh.json:    "footer_aboutUs": "關於 Cryptpad", for many more examples
2021-08-04 14:18:07 +05:30
ansuz 4800ac724e highlight some relevant sections of the form app 2021-08-04 13:51:02 +05:30
ansuz 93f73add9f the charts library should only be used in the inner scope 2021-08-04 13:50:38 +05:30
ansuz 9ecb9e4cd6 chart experiments 2021-08-04 13:26:40 +05:30
ansuz 98df612eb4 ignore shell scripts in the project root 2021-08-04 13:25:48 +05:30
Weblate 0a216e4c96 Translated using Weblate (Japanese)
Currently translated at 100.0% (1379 of 1379 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/ja/
2021-08-04 09:29:08 +02:00
Weblate d2ff6d4eee Translated using Weblate (German)
Currently translated at 100.0% (1379 of 1379 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/de/
2021-08-04 09:29:08 +02:00
ansuz c2ad600ef9 update changelog 2021-08-04 11:37:45 +05:30
ansuz 18c439986c implement main toolbar collapse button 2021-08-03 16:19:50 +05:30
ansuz 4e02c309bb Merge branch 'staging' into collapse-toolbar 2021-08-03 14:30:37 +05:30
ansuz 51b57f0341 update changelog with kanban improvements 2021-08-03 13:55:39 +05:30
ansuz f141fdef3b set a smaller width on the kanban's 'addboard' button 2021-08-03 13:51:16 +05:30
ansuz 0497d663b6 Merge branch 'staging' into hide-kanban-controls 2021-08-03 13:39:43 +05:30
ansuz 97646fdb89 Merge branch 'soon' into staging 2021-08-03 13:36:50 +05:30
ansuz d8a7e4aa2a update changelog 2021-08-03 12:35:02 +05:30
ansuz 298d69e914 guard against another possible type error
(in the user object)
2021-08-03 12:23:18 +05:30
ansuz 22357f882b guard against a type error in user-object when FILES_DATA doesn't exist 2021-08-03 12:17:42 +05:30
ansuz a20bfbf6c1 lint compliance 2021-08-03 12:15:30 +05:30
ansuz 053224a825 Merge branch 'soon' into staging 2021-08-03 12:07:15 +05:30
Weblate d67d6069d4 Translated using Weblate (English)
Currently translated at 100.0% (1379 of 1379 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/
2021-08-03 08:33:26 +02:00
ansuz 48ad82c4fb Merge branch 'soon' into staging 2021-08-02 19:55:46 +05:30
ansuz 7885a3ff5b update changelog with latest hotfixes 2021-08-02 19:55:19 +05:30
ansuz ceab8fe2df disable broken CSV export 2021-08-02 18:16:22 +05:30
ansuz dd53b6fa72 constrain table width in checkup summaries 2021-08-02 18:05:46 +05:30
ansuz 613868bbde fix safari-specific warnings in checkup 2021-08-02 17:59:53 +05:30
ansuz 7ed41aa8e6 make a note to update a translation key 2021-08-02 17:38:13 +05:30
ansuz f4e2e505fe lint compliance 2021-08-02 17:37:06 +05:30
ansuz b6cc4ef8cf test browser-dependent SharedArrayBuffer support in checkup
include debugging information in final report
for when browser vendors inevitably break APIs again
2021-08-02 17:36:51 +05:30
ansuz c6fefd73d8 fix sheet conversion in Chrome
by instantiating SharedArrayBuffers in a more portable way
2021-07-30 19:23:48 +05:30
Weblate 1247ed0b6b Translated using Weblate (Japanese)
Currently translated at 100.0% (1379 of 1379 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/ja/

Translated using Weblate (Japanese)

Currently translated at 99.9% (1378 of 1379 strings)

Translation: CryptPad/App
Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/ja/
2021-07-29 09:53:49 +02:00
ansuz d926930b4c prototype toolbar collapse 2021-07-16 14:59:27 +05:30
ansuz f0eef49522 Merge branch 'staging' into hide-kanban-controls 2021-05-07 18:18:57 +05:30
ansuz 8bdccbdcb0 hide kanban controls 2021-03-19 16:34:20 +05:30
207 changed files with 1008 additions and 338 deletions

2
.gitignore vendored
View File

@ -22,4 +22,4 @@ block/
logs/
privileged.conf
config/config.js
*yolo.sh
*.sh

View File

@ -1,11 +1,5 @@
node_modules/
www/bower_components/
www/common/less.min.js
www/common/pdfjs/
www/common/tippy/
www/common/textFit.min.js
www/common/highlight/
www/common/jquery-ui/
www/common/onlyoffice/sdkjs
www/common/onlyoffice/web-apps
www/common/onlyoffice/x2t
@ -14,7 +8,6 @@ www/common/onlyoffice/v2*
www/common/onlyoffice/v4
server.js
www/common/old-media-tag.js
www/scratch
www/accounts
www/lib

View File

@ -1,3 +1,60 @@
# 4.10.0
## Goals
August is typically a quiet month for CryptPad's development team, as members of our team and many of our users take their (northern hemisphere) summer holidays. We took the opportunity to catch up on some regular maintentance and to review and some prototype branches of our code that had been ready for integration for some time.
It seems that some browser developers thought to do the same thing, because we noticed some significant regressions in some APIs that we rely on. Some of our time went towards addressing the resulting bugs and restructuring some code to avoid future regressions for browser behaviour that seem likely to be changed again in the near future.
## Update notes
4.10.0 includes some minor changes to [the checkup page](https://docs.cryptpad.fr/fr/admin_guide/installation.html#diagnostics). Some admins have included screenshots of this page in bug reports or requests for support along with details of problems they suspect of being related. Because we've observed that the root of many issues is the browser (sometimes in addition to the server) we have decided to include details about the browser in this page's summary.
Up until now the checkup page only tested observable behaviour of the server such as HTTP headers on particular resources, configuration parameters distributed to the client, and the availability of essential resources. This practice meant that a report for an instance should have been the same regardless of the device that was used to generate the report. In light of a serious regression in Chrome (and all its derivatives) we decided that objectiveness was less important than utility and introduced some tests which check whether the client running the diagnostics interprets the provided server configuration. Terrible browsers (ie. every browser that is available on iOS) will fail these tests every time because they don't implement the expected APIs, but we've tried to detect these cases and warn that they are expected.
For the most part you (as an admin) will not need to do anything special for this release as a result. If you notice weird issues on particular browsers in the future, however, it might be helpful to view this page from the affected browser/device and include any information that is provided in bug reports.
To update from 4.9.0 to 4.10.0:
1. Stop your server
2. Get the latest code with git
3. Install the latest dependencies with `bower update` and `npm i`
4. Restart your server
5. Confirm that your instance is passing all the tests included on the `/checkup/` page (on whatever devices you intend to support)
## Features
As noted above, web standards and the browsers that implement them are constantly changing. Web applications like CryptPad which use new and advanced browser features are particularly prone to regressions even when we use browser features exactly as intended and advertized. The "Features" section of each release's notes typically highlights visible things, like clickable buttons or improvements to the interface. This point is included as a reminder that _regular maintenance is at least as important to an open-source software project_, even though it gets little attention and far less funding. The funding bodies that have generously supported our work typically award grants for research and the development of novel features, but we are sorely in need of increased support to allow us the flexibility to deal with unanticipated problems as they arise. If you are fortunate enough to have some disposable income and value the work that keeps CryptPad functional we would greatly appreciate a one-time or recurring donation to [our OpenCollative campaign](https://opencollective.com/cryptpad/contribute).
* This release coincided the yearly seminar of [XWiki (our parent organization)](https://www.xwiki.com) which always features a day-long hackathon. This year our team was joined by [@aemi-dev](https://github.com/aemi-dev) who has been working as an intern within XWiki's product team. Together we worked on adding some data visualization to our recently introduced _Form_ app. The improvements include a timeline to visualize how many responses were submitted to the form during each day and bar charts for a variety of question types to complement the existing tally of results. There's still more work to be done in this direction, but we established some useful foundations during our relatively short session.
* Frequent users of small screens will be pleased to hear that CryptPad's app toolbar now includes a button to collapse the upper segment of the toolbar which includes CryptPad's logo, the current document's title, status indicator (saved, editing, disconnected, etc.), and the user administration menu.
* Likewise, Kanban users may note that the app's toolbar also features a "Tools" menu (like that in the markdown editor) which toggles display of the controls which filter board items by tag and select view state (detailed or brief).
* Password fields that are specific to files and documents now have the `autocomplete="new-password"` attribute applied to prevent browsers and integrated password managers from suggesting that users enter their account password. This lowers the risk that users will inadvertently reveal their account password in the future. Additionally, Firefox will now prompt users to use a high-entropy password instead.
* Our integrated support ticket functionality automatically includes some commonly needed information about the user's account and browser. As of this release this data will also include the browser's `vendor` and `appVersion`, which are useful hints about the host browser and OS (which we almost always have to ask about when the ticket is for a bug report). This data will also include the browser's current width and height, as some issues only occur at particular resolutions and can otherwise be difficult to reproduce.
* We reviewed a range of third-party dependencies that are included in our repository and updated `cryptpad/www/lib/changelog.md` to better indicate their exact version, source, and any CryptPad-specific modifications we've made to them.
* We found `less.js` had been duplicated, with one version (provided by bower) being used for custom styles in our slide editor while the rest of the platform used a custom version that fixed an apparent bug in the _reference import_ syntax. We've standardized on our custom version and removed the alternative from our `bower.json` file.
* We also identified a few files that were no longer in use and removed them. There's still more work to be done to document the exact versions and source of some dependencies, so we've made this process a part of our regular release checklist.
* During a manual review we noticed some inconsistencies between different translations of CryptPad and have automated these checks by adding them to a script which we use to review translations before each release. These have helped us standardize things like the capitalization of "CryptPad", the syntax for some basic markup like `<br>` tags, and the consistent use of both dialect-specific suffixes in English and punctuation rules in French. We have only added tests for languages in which members of our team are fluent, so if you maintain a translation in another language and can suggest additional qualities we could test we would welcome your suggestions.
* The improved consistency of our translations has also enabled us to construct some translated UI components programmatically without directly using their inline HTML. This provides an extra layer of security in the event that
1. malicious code was included in a translation file
2. our tests failed to identify the code before it was included in a release
3. the release was deployed by an admin that had failed to take advantage of the sandboxing system that prevents the injection of scripts into the UI
## Bug fixes
* The Chrome development team made some changes related to the availability of the `SharedArrayBuffer` API in cross-site-isolated contexts such as that of our sandboxing system which resulted in it being disabled despite the fact that our usage conformed to a specification that should have been supported. We use this modern browser feature (where available) to convert spreadsheets between different formats in the browser itself, whereas other services (even those advertizing their use of encryption for documents) send users' content to their server for conversion. Since Chrome's engine is used as the basis for a wide variety of other browsers, this broke sheet export everywhere except Firefox (which correctly implements the specification). Luckily, we found a simple workaround to use the same underlying feature using an alternate syntax that they had failed to disable. This is only a short-term solution as we have no expectation that it will continue to work, so we are actively investigating making this conversion a trusted process that will be run outside of our sandboxing system.
* On the topic of spreadsheet conversion, we updated our translations of the warning that is displayed in our conversion UI when the required browser features are not available. Rather than referring to "Microsoft Office formats" we now refer to _"Office formats"_ since we offer support for ODS in addition to XLSX.
* We found that CSV export mysteriously stopped working as well (seemingly everywhere, not just Chrome and derivatives). We're still not sure why this is the case, but the option is disabled in the UI until we can find and fix the problem.
* The _drive_ app includes a button that lets guest users wipe their personal data from their browser's session. We noticed that this button did nothing after approximately 50% of page loads in Firefox, suggesting there was an unpredictable quality related to either how the button was being created or how "click handlers" were declared. We traced it back to the jQuery library and rewrote the handler to use "VanillaJS". We don't have the time or budget to dig into why it stopped working, so unless someone else can figure it out for us then you, dear reader, may never learn the answer to this mystery.
* While investigating the drive we also added some guards against some possible type errors.
* We noticed that the `loginToken` attribute was not correctly removed from clients' localStorage when they deleted their account. The value of this token is random and is of no use to attackers (especially when the token belongs to a deleted account), but it was a cause of some inconvenience to us when testing account deletion, as the mismatch between the token stored locally and in accounts (after login) required us to login in a second time before. We've updated the related code to:
1. correctly delete the token when you delete an account from the settings page
2. ensure that no such token is present when logging in
* Document ids with invalid lengths are excluded from accounts' lists of "pinned documents" (those which should not be deleted from the server). We recently implemented a similar fix, but found that this list could be constructed in more than one way depending on the context.
* We identified and fixed two problems with our "history trim" functionality (accessible via documents' "Properties" menu):
1. In the extremely unlikely event that a user requested that the server trim the history of a document and its metadata failed to load, the server would respond to the user with an error but did not correctly abort from the subsequent process to trim the document's history. In theory this could have been used by non-owners to archive parts of the documents history, however, we have no reason to believe that this was possible in practice. In any case, the flaw has been corrected.
2. Complex documents like spreadsheets that use more than one channel to store different types of content would trim their respective histories in parallel, however, in such cases any errors were returned to the calling function as a list of warnings rather than a singular error. This format was not handled by the UI, resulting in an apparent success in cases of a partial or complete failure for such document types.
# 4.9.0
## Goals and announcements

View File

@ -36,7 +36,6 @@
"alertifyjs": "1.0.11",
"scrypt-async": "1.2.0",
"require-css": "0.1.10",
"less": "3.7.1",
"bootstrap": "^v4.0.0",
"diff-dom": "2.1.1",
"nthen": "0.1.7",

View File

@ -463,6 +463,7 @@ define([
var proceed = function (result) {
hashing = false;
if (test && typeof test === "function" && test()) { return; }
LocalStore.clearLoginToken();
Realtime.whenRealtimeSyncs(result.realtime, function () {
Exports.redirect();
});

View File

@ -105,7 +105,7 @@ define([
var imprintUrl = AppConfig.imprint && (typeof(AppConfig.imprint) === "boolean" ?
'/imprint.html' : AppConfig.imprint);
Pages.versionString = "v4.9.0";
Pages.versionString = "v4.10.0";
// used for the about menu

View File

@ -5,7 +5,7 @@ define([
'/common/common-feedback.js',
'/common/common-interface.js',
'/common/common-hash.js',
'/common/textFit.min.js',
'/lib/textFit.min.js',
'/customize/messages.js',
'/customize/application_config.js',
'/common/outer/local-store.js',
@ -67,6 +67,7 @@ define([
icons.forEach(function (a) {
setTimeout(function () {
// ensure that text in our app icons doesn't overflow
TextFit($(a).find('.pad-button-text')[0], {minFontSize: 13, maxFontSize: 18});
});
});

View File

@ -0,0 +1,53 @@
.charts_main() {
// basic functional things
table.cp-charts.column {
box-sizing: border-box;
display: flex;
height: 100%;
overflow-x: auto;
tbody {
height: 100%;
display: flex;
align-items: stretch;
min-width: 100%;
tr {
position: relative;
display: flex;
justify-content: flex-start;
flex-direction: row;
flex-shrink: 1;
flex-grow: 1;
justify-content: flex-start;
align-items: flex-end;
td {
display: flex;
height: calc(100% * var(--size));
align-items: flex-start;
flex-grow: 1;
}
}
}
}
// styles
table.cp-charts.column {
//border: 1px solid white;
tbody {
tr {
max-width: 30px;
td {
min-width: 3px;
border: 1px solid @cryptpad_color_brand;
background: @cryptpad_color_brand;
margin: 1px;
}
}
}
}
}

View File

@ -431,6 +431,10 @@
}
}
.cp-toolbar-top {
&.toolbar-hidden {
display: none !important;
}
@media screen and (max-width: @browser_media-medium-screen),
screen and (max-height: 500px) {
flex-wrap: wrap;
@ -966,6 +970,19 @@
margin-right: 5px;
}
}
button.cp-toolbar-collapse {
/*
XXX this button toggles between two states and uses two titles for either state.
tippy doesn't work well with this, so the titles are applied to two icons
and we display the relevant one. Unfortunately, the hoverable area for the inner icon
is very small, which makes it unlikely that you'll see the title unless
you hover perfectly. The same is true of the drive's grid/list view toggle.
*/
.fa {
margin-right: 0px;
}
}
&.cp-toolbar-small {
button {

View File

@ -2,7 +2,7 @@ So you want to write a realtime collaborative application?
This guide will focus on applications which require **multiple clients** to **collaboratively construct a single authoratative document**.
[XWiki-Labs](https://labs.xwiki.com/) has published an open source suite (called [Cryptpad](https://github.com/xwiki-labs/cryptpad)) of collaborative editors which employ end to end encryption.
[XWiki-Labs](https://labs.xwiki.com/) has published an open source suite (called [CryptPad](https://github.com/xwiki-labs/cryptpad)) of collaborative editors which employ end to end encryption.
This guide will refer to the techniques used in the prototypes developed therein.
Let's start with an overview of the components involved.
@ -75,7 +75,7 @@ Chainpad can handle out of order messages, but it performs best when its message
By architecting your system such that all clients send to a server which then relays to other clients, you guarantee that a particular chain of patches is consistent between the participants of your session.
Cryptpad is capable of using a variety of data stores.
CryptPad is capable of using a variety of data stores.
Which data store your instance employs can be [easily configured](https://github.com/xwiki-labs/cryptpad/blob/master/config.example.js).
You simply need to write an adaptor which conforms to a simple API.
@ -85,7 +85,7 @@ Whether you decide to use a single server, or distribute messages across a netwo
## Transport
Cryptpad was initially written to use [websockets](https://en.wikipedia.org/wiki/WebSocket) for transportation of messages.
CryptPad was initially written to use [websockets](https://en.wikipedia.org/wiki/WebSocket) for transportation of messages.
Since a relay server is indispensable in this model, that server doubles as the **History Keeper**, and implements a datastore.
@ -202,7 +202,7 @@ That isn't to say that there are no tradeoffs when keeping that information from
### Our Encryption Scheme
The encryption scheme employed by Cryptpad is a [symmetric encryption](https://en.wikipedia.org/wiki/Symmetric-key_algorithm) which utilizes a single [pre-shared-key](https://en.wikipedia.org/wiki/Pre-shared_key) known by all participants.
The encryption scheme employed by CryptPad is a [symmetric encryption](https://en.wikipedia.org/wiki/Symmetric-key_algorithm) which utilizes a single [pre-shared-key](https://en.wikipedia.org/wiki/Pre-shared_key) known by all participants.
Encryption is complex, and poorly understood by the majority of those who use it on a daily basis.
Pre-shared-keys are among the weakest possible cryptographic tools available today, however, few if any other encryption schemes scale to any number of users.

View File

@ -54,7 +54,8 @@ Channel.clearOwnedChannel = function (Env, safeKey, channelId, cb, Server) {
});
};
var archiveOwnedChannel = function (Env, safeKey, channelId, _cb, Server) {
var archiveOwnedChannel = function (Env, safeKey, channelId, __cb, Server) {
var _cb = Util.once(Util.mkAsync(__cb));
var unsafeKey = Util.unescapeKeyCharacters(safeKey);
nThen(function (w) {
// confirm that the channel exists before worrying about whether
@ -160,7 +161,10 @@ Channel.trimHistory = function (Env, safeKey, data, cb) {
nThen(function (w) {
Metadata.getMetadataRaw(Env, channelId, w(function (err, metadata) {
if (err) { return void cb(err); }
if (err) {
w.abort();
return void cb(err);
}
if (!Core.hasOwners(metadata)) {
w.abort();
return void cb('E_NO_OWNERS');
@ -173,6 +177,11 @@ Channel.trimHistory = function (Env, safeKey, data, cb) {
}));
}).nThen(function () {
Env.msgStore.trimChannel(channelId, hash, function (err) {
Env.Log.info('HK_TRIM_HISTORY', {
unsafeKey: unsafeKey,
channelId: channelId,
status: err? String(err): 'SUCCESS',
});
if (err) { return void cb(err); }
// clear historyKeeper's cache for this channel
Env.historyKeeper.channelClose(channelId);

View File

@ -123,7 +123,7 @@ module.exports.create = function (config) {
maxWorkers: config.maxWorkers,
disableIntegratedTasks: config.disableIntegratedTasks || false,
disableIntegratedEviction: typeof(config.disableIntegratedEviction) === 'undefined'? true: config.disableIntegratedEviction, // XXX 4.10.0 false,
disableIntegratedEviction: typeof(config.disableIntegratedEviction) === 'undefined'? true: config.disableIntegratedEviction, // XXX 4.11.0 false,
lastEviction: +new Date(),
evictionReport: {},
commandTimers: {},

8
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "cryptpad",
"version": "4.9.0",
"version": "4.10.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -1591,9 +1591,9 @@
}
},
"jszip": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.6.0.tgz",
"integrity": "sha512-jgnQoG9LKnWO3mnVNBnfhkh0QknICd1FGSrXcgrl67zioyJ4wgx25o9ZqwNtrROSflGBCGYnJfjrIyRIby1OoQ==",
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz",
"integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==",
"dev": true,
"requires": {
"lie": "~3.3.0",

View File

@ -1,7 +1,7 @@
{
"name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowlege server",
"version": "4.9.0",
"version": "4.10.0",
"license": "AGPL-3.0+",
"repository": {
"type": "git",
@ -45,7 +45,8 @@
"lint:js": "jshint --config .jshintrc --exclude-path .jshintignore .",
"lint:server": "jshint --config .jshintrc lib",
"lint:less": "./node_modules/lesshint/bin/lesshint -c ./.lesshintrc ./customize.dist/src/less2/",
"lint:translations": "node ./scripts/unused-translations.js",
"lint:translations": "node ./scripts/lint-translations.js",
"unused-translations": "node ./scripts/unused-translations.js",
"test": "node scripts/TestSelenium.js",
"test-rpc": "cd scripts/tests && node test-rpc",
"template": "cd customize.dist/src && for page in ../index.html ../privacy.html ../terms.html ../contact.html ../what-is-cryptpad.html ../features.html ../../www/login/index.html ../../www/register/index.html ../../www/user/index.html;do echo $page; cp template.html $page; done;",

View File

@ -20,7 +20,7 @@ The most recent version and all past release notes can be found [here](https://g
## Setup using Docker
See [Cryptpad-Docker](https://github.com/xwiki-labs/cryptpad-docker) repository for details on how to get up-and-running with Cryptpad in Docker. This repository is maintained by the community and not officially supported.
See [CryptPad-Docker](https://github.com/xwiki-labs/cryptpad-docker) repository for details on how to get up-and-running with CryptPad in Docker. This repository is maintained by the community and not officially supported.
# Security
@ -72,7 +72,7 @@ CryptPad is actively developed by a team at [XWiki SAS](https://www.xwiki.com),
We love Open Source and we love contribution. Learn more about [contributing](https://docs.cryptpad.fr/en/how_to_contribute.html).
If you have any questions or comments, or if you're interested in contributing to Cryptpad, come say hi in our [Matrix channel](https://app.element.io/#/room/#cryptpad:matrix.xwiki.com).
If you have any questions or comments, or if you're interested in contributing to CryptPad, come say hi in our [Matrix channel](https://app.element.io/#/room/#cryptpad:matrix.xwiki.com).
# License

View File

@ -1,101 +0,0 @@
var EN = require("../www/common/translations/messages.json");
var simpleTags = [
'<br>',
'<br />',
'<br/>',
'<a href="/login/">',
'<a href="/register/">',
// FIXME
"<a href='#'>",
'<a href="#docs">',
'<h3>',
'</h3>',
// FIXME register_notes
'<ul class="cp-notes-list">',
'</ul>',
'<li>',
'</li>',
'<span class="red">',
'</span>',
];
['a', 'b', 'em', 'p', 'i'].forEach(function (tag) {
simpleTags.push('<' + tag + '>');
simpleTags.push('</' + tag + '>');
});
// these keys are known to be problematic
var KNOWN_ISSUES = [ // FIXME
//'newVersion',
//'fm_info_anonymous',
//'register_notes',
];
var processLang = function (map, lang, primary) {
var announced = false;
var announce = function () {
if (announced) { return; }
announced = true;
console.log("NEXT LANGUAGE: ", lang);
};
Object.keys(map).forEach(function (k) {
if (!EN[k]) { return; }
if (KNOWN_ISSUES.indexOf(k) !== -1) { return; }
var s = map[k];
if (typeof(s) !== 'string') { return; }
var usesHTML;
s.replace(/<.*?>/g, function (html) {
if (simpleTags.indexOf(html) !== -1) { return; }
announce();
usesHTML = true;
if (!primary) {
console.log("{%s}", html);
}
});
if (usesHTML) {
announce();
console.log("%s", s);
console.log("[%s]\n", k);
}
});
};
processLang(EN, 'en', true);
[
'ar',
//'bn_BD',
'ca',
'de',
'es',
'fi',
'fr',
'hi',
'it',
'ja',
'nb',
'nl',
'pl',
'pt-br',
'ro',
'ru',
'sv',
//'te',
'tr',
'zh',
].forEach(function (lang) {
try {
var map = require("../www/common/translations/messages." + lang + ".json");
if (!Object.keys(map).length) { return; }
processLang(map, lang);
} catch (err) {
console.error(err);
}
});

View File

@ -1,8 +1,127 @@
// TODO unify the following scripts
// unused-translations.js
// find-html-translations
var EN = require("../www/common/translations/messages.json");
// more linting
// Search for 'Cryptpad' string (should be 'CryptPad')
// Search English for -ise\s
var simpleTags = [
'<br>',
'<a href="/login/">',
'<a href="/register/">',
// FIXME
"<a href='#'>",
'<a href="#docs">',
'<h3>',
'</h3>',
// FIXME register_notes
'<ul class="cp-notes-list">',
'</ul>',
'<li>',
'</li>',
'<span class="red">',
'</span>',
];
['a', 'b', 'em', 'p', 'i'].forEach(function (tag) {
simpleTags.push('<' + tag + '>');
simpleTags.push('</' + tag + '>');
});
// these keys are known to be problematic
var KNOWN_ISSUES = [ // FIXME
//'newVersion',
//'fm_info_anonymous',
//'register_notes',
];
var special_rules = {};
special_rules.en = function (s) {
// Prefer the american -ize suffix for verbs rather than -ise
return /[^w]ise/.test(s);
};
special_rules.fr = function (s) {
/*
hacky regexp to check whether there are any instances of ':'
which do not have the preceding space as is expected.
ignore instances where the following character is a '/'
because this is probably a URL (http(s)://)
*/
return /\S[:;\?\!][^\/]{1,}/.test(s);
};
var noop = function () {};
var processLang = function (map, lang, primary) {
var announced = false;
var announce = function () {
if (announced) { return; }
announced = true;
console.log("NEXT LANGUAGE: ", lang);
};
var special = special_rules[lang] || noop;
Object.keys(map).forEach(function (k) {
if (!EN[k]) { return; }
if (KNOWN_ISSUES.indexOf(k) !== -1) { return; }
var s = map[k];
if (typeof(s) !== 'string') { return; }
var usesHTML;
s.replace(/<[\s\S]*?>/g, function (html) {
if (simpleTags.indexOf(html) !== -1) { return; }
announce();
usesHTML = true;
if (!primary) {
console.log("{%s}", html);
}
});
var weirdCapitalization;
s.replace(/cryptpad(\.fr)*/gi, function (brand) {
if (['CryptPad', 'cryptpad.fr'].includes(brand)) { return; }
weirdCapitalization = true;
});
var specialViolation = special(s);
if (usesHTML || weirdCapitalization || specialViolation) {
announce();
console.log("%s", s);
console.log("[%s]\n", k);
}
});
};
processLang(EN, 'en', true);
[
'ar',
//'bn_BD',
'ca',
'de',
'es',
'fi',
'fr',
'hi',
'it',
'ja',
'nb',
'nl',
'pl',
'pt-br',
'ro',
'ru',
'sv',
//'te',
'tr',
'zh',
].forEach(function (lang) {
try {
var map = require("../www/common/translations/messages." + lang + ".json");
if (!Object.keys(map).length) { return; }
processLang(map, lang);
} catch (err) {
console.error(err);
}
});

View File

@ -311,7 +311,7 @@ var httpServer = Env.httpServer = Http.createServer(app);
nThen(function (w) {
Fs.exists(__dirname + "/customize", w(function (e) {
if (e) { return; }
console.log("Cryptpad is customizable, see customize.dist/readme.md for details");
console.log("CryptPad is customizable, see customize.dist/readme.md for details");
}));
}).nThen(function (w) {
httpServer.listen(config.httpPort,config.httpAddress,function(){

View File

@ -14,11 +14,15 @@ html, body {
.report {
font-size: 30px;
max-width: 50%;
max-width: 26em;
margin: auto;
padding-top: 15px;
}
.summary, .failure, .error, .success {
margin-bottom: 1em;
}
.pending {
border: 1px solid @cryptpad_text_col;
.fa {
@ -42,10 +46,18 @@ html, body {
padding: 15px;
}
table {
td {
padding: 5px;
border: 1px solid @cryptpad_text_col;
.table-container {
overflow-x: auto;
width: 100%;
table {
td {
padding: 5px;
border: 1px solid @cryptpad_text_col;
font-size: 60%;
}
td:nth-child(2) {
word-break: break-word;
}
}
}
@ -72,10 +84,14 @@ html, body {
color: @cryptpad_color_link;
}
}
.cp-app-checkup-version {
text-decoration: underline;
}
.cp-notice-browser, .cp-notice-details, .cp-notice-other {
font-size: 70%;
}
.underline { text-decoration: underline; }
.cp-app-checkup-version, .cp-app-checkup-browser {
.underline;
}
iframe {
display: none;
}

View File

@ -0,0 +1,55 @@
define([
], function () {
var Tools = {};
Tools.supportsSharedArrayBuffers = function () {
try {
return Object.prototype.toString.call(new window.WebAssembly.Memory({
shared: true,
initial: 0,
maximum: 0,
}).buffer) === '[object SharedArrayBuffer]';
} catch (err) {
console.error(err);
}
return false;
};
var OS_HINTS = {
"Win": "Windows",
"Mac": "MacOS",
"X11": "UNIX",
"Linux": "Linux",
};
Tools.guessOS = function () {
var result = "UNKNOWN";
if (!window.navigator || !window.navigator.appVersion) { return result; }
result = window.navigator.appVersion;
console.log(result);
Object.keys(OS_HINTS).some(function (key) {
if (result.indexOf(key) === -1) { return; }
result = OS_HINTS[key]; // else
return true;
});
return result;
};
Tools.isSafari = function () {
return navigator.vendor.match(/apple/i);
};
Tools.isChrome = function () {
return navigator.vendor.match(/google/i);
};
Tools.guessBrowser = function () {
if (Tools.isChrome()) { return 'chrome/blink'; }
if (Tools.isSafari()) { return 'safari/webkit'; }
if (navigator.userAgent.match(/firefox\//i)) { return 'firefox/gecko'; }
if (navigator.userAgent.match(/edge\//i)) { return 'edge/edgehtml'; }
if (navigator.userAgent.match(/trident\//i)) { return 'ie/trident'; }
return navigator.userAgent + "\n" + navigator.vendor;
};
return Tools;
});

View File

@ -13,13 +13,14 @@ define([
'/common/pinpad.js',
'/common/outer/network-config.js',
'/customize/pages.js',
'/checkup/checkup-tools.js',
'/bower_components/tweetnacl/nacl-fast.min.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/checkup/app-checkup.less',
], function ($, ApiConfig, Assertions, h, Messages, DomReady,
nThen, SFCommonO, Login, Hash, Util, Pinpad,
NetConfig, Pages) {
NetConfig, Pages, Tools) {
var Assert = Assertions();
var trimSlashes = function (s) {
if (typeof(s) !== 'string') { return s; }
@ -703,6 +704,69 @@ define([
});
});
var safariGripe = function () {
return h('p.cp-notice-other', 'This is expected because Safari and platforms that use its engine lack commonly supported functionality.');
};
var browserIssue = function () {
return h('p.cp-notice-other', 'This test checks for the presence of features in your browser and is not necessarily caused by server misconfiguration.');
};
assert(function (cb, msg) {
cb = Util.once(cb);
setWarningClass(msg);
var notice = h('span', [
h('p', 'It appears that some features required for Office file format conversion are not present.'),
Tools.isSafari()? safariGripe(): undefined,
browserIssue(),
]);
msg.appendChild(notice);
var expected = [
'Atomics',
'SharedArrayBuffer',
'WebAssembly',
['WebAssembly', 'Memory'],
['WebAssembly', 'instantiate'],
['WebAssembly', 'instantiateStreaming'],
['Buffer', 'from'],
'SharedWorker',
'worker',
'crossOriginIsolated',
];
var responses = {};
nThen(function (w) {
deferredPostMessage({
command: 'CHECK_JS_APIS',
content: {
globals: expected,
},
}, w(function (response) {
Util.extend(responses, response);
}));
deferredPostMessage({
command: 'FANCY_API_CHECKS',
content: {
},
}, w(function (response) {
Util.extend(responses, response);
}));
}).nThen(function () {
if (!responses.Atomics || !responses.WebAssembly) {
return void cb(responses);
}
if (responses.SharedArrayBuffer || responses.SharedArrayBufferFallback) {
return cb(true);
}
return void cb(response);
});
});
var isHTTPS = function (host) {
return /^https:\/\//.test(host);
};
@ -831,17 +895,19 @@ define([
var failureReport = function (obj) {
var printableValue = obj.output;
try {
printableValue = JSON.stringify(obj.output);
printableValue = JSON.stringify(obj.output, null, ' ');
} catch (err) {
console.error(err);
}
return h('div.error', [
h('h5', obj.message),
h('table', [
row(["Failed test number", obj.test + 1]),
row(["Returned value", code(printableValue)]),
]),
h('div.table-container',
h('table', [
row(["Failed test number", obj.test + 1]),
row(["Returned value", h('pre', code(printableValue))]),
])
),
]);
};
@ -849,7 +915,7 @@ define([
var $progress = $('#cp-progress');
var versionStatement = function () {
return h('p', [
return h('p.cp-notice-version', [
"This instance is running ",
h('span.cp-app-checkup-version',[
"CryptPad",
@ -860,6 +926,18 @@ define([
]);
};
var browserStatement = function () {
var name = Tools.guessBrowser();
if (!name) { return; }
return h('p.cp-notice-browser', [
"You appear to be using a ",
h('span.cp-app-checkup-browser', name),
' browser on ',
h('span.underline', Tools.guessOS()),
' to view this page.',
]);
};
Assert.run(function (state) {
var errors = state.errors;
var failed = errors.length;
@ -870,10 +948,11 @@ define([
var failedDetails = "Details found below";
var successDetails = "This checkup only tests the most common configuration issues. You may still experience errors or incorrect behaviour.";
var details = h('p', failed? failedDetails: successDetails);
var details = h('p.cp-notice-details', failed? failedDetails: successDetails);
var summary = h('div.summary.' + statusClass, [
versionStatement(),
browserStatement(),
h('p', Messages._getKey('assert_numberOfTestsPassed', [
state.passed,
state.total

View File

@ -1,10 +1,12 @@
define([
'jquery',
'/common/common-util.js',
'/checkup/checkup-tools.js',
'/bower_components/tweetnacl/nacl-fast.min.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/checkup/app-checkup.less',
], function ($) {
], function ($, Util, Tools) {
var postMessage = function (content) {
window.parent.postMessage(JSON.stringify(content), '*');
};
@ -26,6 +28,26 @@ define([
});
};
COMMANDS.CHECK_JS_APIS = function (content, cb) {
var globalAPIs = content['globals'] || [];
var response = {};
globalAPIs.forEach(function (key) {
if (Array.isArray(key)) {
response[key.join('.')] = Boolean(Util.find(window, key));
return;
}
response[key] = Boolean(window[key]);
});
cb(response);
};
COMMANDS.FANCY_API_CHECKS = function (content, cb) {
cb({
SharedArrayBufferFallback: Tools.supportsSharedArrayBuffers(),
});
};
window.addEventListener("message", function (event) {
var txid, command;
if (event && event.data) {

View File

@ -110,7 +110,7 @@ define([
if (lessEngine) {
cb(lessEngine);
} else {
require(['/common/less.min.js'], function (Less) {
require(['/lib/less.min.js'], function (Less) {
if (lessEngine) { return void cb(lessEngine); }
lessEngine = Less;
Less.functions.functionRegistry.add('LessLoader_currentFile', function () {

View File

@ -15,15 +15,15 @@ define([
'/common/common-notifier.js',
'/customize/application_config.js',
'/bower_components/alertifyjs/dist/js/alertify.js',
'/common/tippy/tippy.min.js',
'/lib/tippy/tippy.min.js',
'/common/hyperscript.js',
'/customize/loading.js',
'/common/test.js',
'/common/jquery-ui/jquery-ui.min.js',
'/lib/jquery-ui/jquery-ui.min.js', // autocomplete widget
'/bower_components/bootstrap-tokenfield/dist/bootstrap-tokenfield.js',
'css!/common/tippy/tippy.css',
'css!/common/jquery-ui/jquery-ui.min.css'
'css!/lib/tippy/tippy.css',
'css!/lib/jquery-ui/jquery-ui.min.css'
], function ($, Messages, Util, Hash, Notifier, AppConfig,
Alertify, Tippy, h, Loading, Test) {
var UI = {};
@ -867,7 +867,8 @@ define([
UI.passwordInput = function (opts, displayEye) {
opts = opts || {};
var attributes = merge({
type: 'password'
type: 'password',
autocomplete: 'new-password', // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#values
}, opts);
var input = h('input.cp-password-input', attributes);

View File

@ -145,7 +145,7 @@ define([
video.src = url;
};
Thumb.fromPdfBlob = function (blob, cb) {
require.config({paths: {'pdfjs-dist': '/common/pdfjs'}});
require.config({paths: {'pdfjs-dist': '/lib/pdfjs'}});
require(['pdfjs-dist/build/pdf'], function (PDFJS) {
var url = URL.createObjectURL(blob);
var makeThumb = function (page) {

View File

@ -526,6 +526,7 @@ define([
var button;
var sframeChan = common.getSframeChannel();
var appType = (common.getMetadataMgr().getMetadata().type || 'pad').toUpperCase();
data = data || {};
switch (type) {
case 'export':
button = $('<button>', {
@ -835,8 +836,8 @@ define([
button = $(h('button.cp-toolbar-tools', {
//title: data.title || '', // TODO display if the label text is collapsed
}, [
h('i.fa.fa-wrench'),
h('span.cp-toolbar-name', Messages.toolbar_tools)
h('i.fa.' + (data.icon || 'fa-wrench')),
h('span.cp-toolbar-name', data.text || Messages.toolbar_tools)
])).click(common.prepareFeedback(type));
/*
window.setTimeout(function () {
@ -902,7 +903,6 @@ define([
button
.click(common.prepareFeedback(type))
.click(function () {
data = data || {};
if (typeof(data.load) !== "function" || typeof(data.make) !== "function") {
return;
}
@ -910,7 +910,6 @@ define([
});
break;
default:
data = data || {};
var drawerCls = data.drawer === false ? '' : '.cp-toolbar-drawer-element';
var icon = data.icon || "fa-question";
button = $(h('button', {
@ -919,10 +918,13 @@ define([
}, [
h('i.fa.' + icon),
h('span.cp-toolbar-name'+drawerCls, data.text)
])).click(common.prepareFeedback(data.name || 'DEFAULT'));
if (callback) {
button.click(callback);
}
]));
var feedbackHandler = common.prepareFeedback(data.name || 'DEFAULT');
button[0].addEventListener('click', function () {
feedbackHandler();
if (typeof(callback) !== 'function') { return; }
callback();
});
if (data.style) { button.attr('style', data.style); }
if (data.id) { button.attr('id', data.id); }
if (data.hiddenReadOnly) { button.addClass('cp-hidden-if-readonly'); }
@ -3039,12 +3041,12 @@ define([
// fc_open ("Open")
// share_linkOpen ("Preview")
// resources_openInNewTab ("Open it in a new tab")
Messages.link_open = Messages.fc_open; // XXX 4.10.0
Messages.link_open = Messages.fc_open; // XXX 4.11.0
//Messages.link_store = "Store link in drive";
// toolbar_storeInDrive ? ("Store in CryptDrive")
// autostore_store ? ("Store")
Messages.link_store = Messages.toolbar_storeInDrive; // XXX 4.10.0
Messages.link_store = Messages.toolbar_storeInDrive; // XXX 4.11.0
var content = h('div', [
@ -3703,6 +3705,21 @@ define([
return false;
};
UIElements.fixInlineBRs = function (htmlString) {
if (!htmlString && typeof(htmlString) === 'string') { return; }
var lines = htmlString.split('<br>');
if (lines.length === 1) { return lines; }
var len = lines.length - 1;
var result = [];
for (var i = 0; i <= len; i++) {
result.push(lines[i]);
if (i < len) {
result.push(h('br'));
}
}
return result;
};
UIElements.openSnapshotsModal = function (common, load, make, remove) {
var modal;
var readOnly = common.getMetadataMgr().getPrivateData().readOnly;

View File

@ -165,6 +165,12 @@
map[key] = (map[key] || 0) + (typeof(val) === 'number'? val: 1);
};
Util.values = function (obj) {
return Object.keys(obj).map(function (k) {
return obj[k];
});
};
Util.find = function (map, path) {
var l = path.length;
for (var i = 0; i < l; i++) {

View File

@ -8,13 +8,13 @@ define([
'/common/inner/common-mediatag.js',
'/common/media-tag.js',
'/customize/messages.js',
'/common/less.min.js',
'/lib/less.min.js',
'/customize/pages.js',
'/common/highlight/highlight.pack.js',
'/lib/highlight/highlight.pack.js',
'/lib/diff-dom/diffDOM.js',
'/bower_components/tweetnacl/nacl-fast.min.js',
'css!/common/highlight/styles/'+ (window.CryptPad_theme === 'dark' ? 'dark.css' : 'github.css')
'css!/lib/highlight/styles/'+ (window.CryptPad_theme === 'dark' ? 'dark.css' : 'github.css')
],function ($, ApiConfig, Marked, Hash, Util, h, MT, MediaTag, Messages, Less, Pages) {
var DiffMd = {};
@ -424,7 +424,7 @@ define([
// Only allow iframe, video and audio with local source
var checkSrc = function (root) {
if (restrictedTags.indexOf(root.nodeName.toUpperCase()) === -1) { return true; }
return root.getAttribute && /^(blob\:|\/common\/pdfjs)/.test(root.getAttribute('src'));
return root.getAttribute && /^(blob\:|\/lib\/pdfjs)/.test(root.getAttribute('src'));
};
var removeForbiddenTags = function (root) {

View File

@ -1733,7 +1733,7 @@ define([
removeSelected();
refresh();
});
}, null, true);
});
};
@ -2783,7 +2783,7 @@ define([
var u = $url.val().trim();
if (!n || !u) { return true; }
if (!Util.isValidURL(u)) {
// XXX 4.10.0 add style for invalid input? input:invalid
// XXX 4.11.0 add style for invalid input? input:invalid
UI.warn(Messages.fm_link_invalid);
return true;
}

View File

@ -981,11 +981,11 @@ define([
common.gotoURL(_href);
}, {force: true});
}
return void UI.alert(Messages.properties_passwordSuccess, function () {
return void UI.alert(UIElements.fixInlineBRs(Messages.properties_passwordSuccess), function () {
if (!isSharedFolder) {
common.gotoURL(_href);
}
}, {force: true});
});
});
});
});

View File

@ -20,7 +20,7 @@ define([
// This file is loaded by sframe-common so the following config is used in all the inner apps
if (MediaTag) {
MediaTag.setDefaultConfig('pdf', {
viewer: '/common/pdfjs/web/viewer.html'
viewer: '/lib/pdfjs/web/viewer.html'
});
MediaTag.setDefaultConfig('download', {
text: Messages.mediatag_saveButton,

View File

@ -170,7 +170,8 @@ define([
teamId: typeof(owned) === "number" && owned
}, function (obj) {
spinner.hide();
if (obj && obj.error) {
if (obj && obj.error || obj.warning) {
console.error(obj.warning);
$(size).append(h('div.alert.alert-danger', Messages.trimHistory_error));
return;
}

View File

@ -1,3 +0,0 @@
// Fix for noscript bugs when caching iframe content.
// Caution, this file will get cached, you must change the name if you change it.
document.getElementById('pad-iframe').setAttribute('src', 'inner.html?cb=' + (+new Date()));

View File

@ -72,8 +72,31 @@ define([
return JSONSortify(obj);
};
/* Chrome 92 dropped support for SharedArrayBuffer in cross-origin contexts
where window.crossOriginIsolated is false.
Their blog (https://blog.chromium.org/2021/02/restriction-on-sharedarraybuffers.html)
isn't clear about why they're doing this, but since it's related to site-isolation
it seems they're trying to do vague security things.
In any case, there seems to be a workaround where you can still create them
by using `new WebAssembly.Memory({shared: true, ...})` instead of `new SharedArrayBuffer`.
This seems unreliable, but it's better than not being able to export, since
we actively rely on postMessage between iframes and therefore can't afford
to opt for full isolation.
*/
var supportsSharedArrayBuffers = function () {
try {
return Object.prototype.toString.call(new window.WebAssembly.Memory({shared: true, initial: 0, maximum: 0}).buffer) === '[object SharedArrayBuffer]';
} catch (err) {
console.error(err);
}
return false;
};
var supportsXLSX = function () {
return !(typeof(Atomics) === "undefined" || typeof (SharedArrayBuffer) === "undefined" || typeof(WebAssembly) === 'undefined');
return !(typeof(Atomics) === "undefined" || !supportsSharedArrayBuffers() /* || typeof (SharedArrayBuffer) === "undefined" */ || typeof(WebAssembly) === 'undefined');
};
@ -1915,7 +1938,9 @@ define([
var exportXLSXFile = function() {
var text = getContent();
var suggestion = Title.suggestTitle(Title.defaultTitle);
var ext = ['.xlsx', '.ods', '.bin', '.csv', '.pdf'];
var ext = ['.xlsx', '.ods', '.bin',
//'.csv', // XXX 4.11.0
'.pdf'];
var type = common.getMetadataMgr().getPrivateData().ooType;
var warning = '';
if (type==="presentation") {

View File

@ -1,3 +1,8 @@
function SUPPORTS_SHARED_MEMORY() {
return typeof(SharedArrayBuffer) !== 'undefined';
}
// Support for growable heap + pthreads, where the buffer may change, so JS views
// must be updated.
function GROWABLE_HEAP_STORE_I8(ptr, value) {
@ -1030,7 +1035,7 @@ if (ENVIRONMENT_IS_PTHREAD) {
"maximum": 1073741824 / WASM_PAGE_SIZE,
"shared": true
});
if (!(wasmMemory.buffer instanceof SharedArrayBuffer)) {
if (Object.prototype.toString.call(wasmMemory.buffer) !== '[object SharedArrayBuffer]') {
err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");
if (ENVIRONMENT_HAS_NODE) {
console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");
@ -2161,7 +2166,7 @@ var PThread = {
}),
receiveObjectTransfer: (function(data) {}),
allocateUnusedWorkers: (function(numWorkers, onFinishedLoading) {
if (typeof SharedArrayBuffer === "undefined") return;
if (!SUPPORTS_SHARED_MEMORY()) return;
var workers = [];
var numWorkersToCreate = numWorkers;
if (PThread.preallocatedWorkers.length > 0) {
@ -2276,7 +2281,7 @@ var PThread = {
}
}),
createNewWorkers: (function(numWorkers) {
if (typeof SharedArrayBuffer === "undefined") return [];
if (!SUPPORTS_SHARED_MEMORY()) return [];
var pthreadMainJs = "x2t.worker.js";
pthreadMainJs = locateFile(pthreadMainJs);
var newWorkers = [];
@ -5683,7 +5688,7 @@ function _emscripten_get_sbrk_ptr() {
}
Module["_emscripten_get_sbrk_ptr"] = _emscripten_get_sbrk_ptr;
function _emscripten_has_threading_support() {
return typeof SharedArrayBuffer !== "undefined";
return SUPPORTS_SHARED_MEMORY();
}
Module["_emscripten_has_threading_support"] = _emscripten_has_threading_support;
function _emscripten_is_main_browser_thread() {
@ -6761,7 +6766,7 @@ function _pthread_self() {
}
Module["_pthread_self"] = _pthread_self;
function _pthread_create(pthread_ptr, attr, start_routine, arg) {
if (typeof SharedArrayBuffer === "undefined") {
if (!SUPPORTS_SHARED_MEMORY()) {
err("Current environment does not support SharedArrayBuffer, pthreads are not available!");
return 6;
}

View File

@ -775,7 +775,10 @@ define([
}
});
}
return list;
return list.filter(function (channel) {
if (typeof(channel) !== 'string') { return; }
return [32, 48].indexOf(channel.length) !== -1;
});
};
var removeOwnedPads = function (waitFor) {
// Delete owned pads
@ -2156,6 +2159,8 @@ define([
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
if (!data.command) { return void cb({ error: 'EINVAL' }); }
var s = getStore(data.teamId);
if (!s) { return void cb({ error: 'ENOTFOUND' }); }
var otherChannels = data.channels;
delete data.channels;
s.rpc.setMetadata(data, function (err, res) {

View File

@ -97,7 +97,7 @@ define([
var checkCheckpoints = function (array) {
if (!Array.isArray(array)) { return; }
// Keep the last 100 messages
if (array.length > 100) { // XXX 4.10.0
if (array.length > 100) { // XXX 4.11.0
array.splice(0, array.length - 100);
}
// Remove every message before the first checkpoint

View File

@ -82,6 +82,10 @@ define([
} catch (err) { return; }
};
LocalStore.clearLoginToken = function () {
localStorage.removeItem(Constants.loginToken);
};
LocalStore.setDriveRedirectPreference = function (bool) {
localStorage.setItem(Constants.redirectToDriveKey, Boolean(bool));
};

View File

@ -133,7 +133,7 @@ var factory = function (Util, Rpc) {
exp.removeOwnedChannel = function (channel, cb) {
if (typeof(channel) !== 'string' || [32,48].indexOf(channel.length) === -1) {
// can't use this on files because files can't be owned...
console.error('invalid channel to remove', channel);
return void cb('INVALID_ARGUMENTS');
}
rpc.send('REMOVE_OWNED_CHANNEL', channel, function (e, response) {

View File

@ -1167,6 +1167,13 @@ define([
Store
*/
var excludeInvalidIdentifiers = function (result) {
return result.filter(function (channel) {
if (typeof(channel) !== 'string') { return; }
return [32, 48].indexOf(channel.length) !== -1;
});
};
// Get the list of channels filtered by a type (expirable channels, owned channels, pin list)
var getChannelsList = function (Env, type) {
var result = [];
@ -1228,8 +1235,8 @@ define([
}
};
if (type === 'owned' && !Env.edPublic) { return result; }
if (type === 'pin' && !Env.edPublic) { return result; }
if (type === 'owned' && !Env.edPublic) { return excludeInvalidIdentifiers(result); }
if (type === 'pin' && !Env.edPublic) { return excludeInvalidIdentifiers(result); }
// Get the list of user objects
var userObjects = _getUserObjects(Env);
@ -1256,10 +1263,7 @@ define([
Array.prototype.push.apply(result, sfChannels);
}
return result.filter(function (channel) {
if (typeof(channel) !== 'string') { return; }
return [32, 48].indexOf(channel.length) !== -1;
});
return excludeInvalidIdentifiers(result);
};
var addPad = function (Env, path, pad, cb) {

View File

@ -13,8 +13,6 @@ define([
"mermaid": "/code/mermaid.min",
// json.sortify same
"json.sortify": "/bower_components/json.sortify/dist/JSON.sortify",
//"pdfjs-dist/build/pdf": "/bower_components/pdfjs-dist/build/pdf",
//"pdfjs-dist/build/pdf.worker": "/bower_components/pdfjs-dist/build/pdf.worker"
cm: '/bower_components/codemirror',
'tui-code-snippet': '/lib/calendar/tui-code-snippet.min',
'tui-date-picker': '/lib/calendar/date-picker',

View File

@ -921,7 +921,7 @@ define([
});
ctx.sframeChan.on('EV_WORKER_TIMEOUT', function () {
UI.errorLoadingScreen(Messages.timeoutError, false, function () {
UI.errorLoadingScreen(Messages.timeoutError, false, function () { // XXX 4.11.0 mobile users can't necessarily hit 'ESC' as this message suggests. provice a click option
funcs.gotoURL('');
});
});

View File

@ -1 +0,0 @@
(function(root,factory){"use strict";if(typeof define==="function"&&define.amd){define([],factory)}else if(typeof exports==="object"){module.exports=factory()}else{root.textFit=factory()}})(typeof global==="object"?global:this,function(){"use strict";var defaultSettings={alignVert:false,alignHoriz:false,multiLine:false,detectMultiLine:true,minFontSize:6,maxFontSize:80,reProcess:true,widthOnly:false,alignVertWithFlexbox:false};return function textFit(els,options){if(!options)options={};var settings={};for(var key in defaultSettings){if(options.hasOwnProperty(key)){settings[key]=options[key]}else{settings[key]=defaultSettings[key]}}if(typeof els.toArray==="function"){els=els.toArray()}var elType=Object.prototype.toString.call(els);if(elType!=="[object Array]"&&elType!=="[object NodeList]"&&elType!=="[object HTMLCollection]"){els=[els]}for(var i=0;i<els.length;i++){processItem(els[i],settings)}};function processItem(el,settings){if(!isElement(el)||!settings.reProcess&&el.getAttribute("textFitted")){return false}if(!settings.reProcess){el.setAttribute("textFitted",1)}var innerSpan,originalHeight,originalHTML,originalWidth;var low,mid,high;originalHTML=el.innerHTML;originalWidth=innerWidth(el);originalHeight=innerHeight(el);if(!originalWidth||!settings.widthOnly&&!originalHeight){if(!settings.widthOnly)throw new Error("Set a static height and width on the target element "+el.outerHTML+" before using textFit!");else throw new Error("Set a static width on the target element "+el.outerHTML+" before using textFit!")}if(originalHTML.indexOf("textFitted")===-1){innerSpan=document.createElement("span");innerSpan.className="textFitted";innerSpan.style["display"]="inline-block";innerSpan.innerHTML=originalHTML;el.innerHTML="";el.appendChild(innerSpan)}else{innerSpan=el.querySelector("span.textFitted");if(hasClass(innerSpan,"textFitAlignVert")){innerSpan.className=innerSpan.className.replace("textFitAlignVert","");innerSpan.style["height"]="";el.className.replace("textFitAlignVertFlex","")}}if(settings.alignHoriz){el.style["text-align"]="center";innerSpan.style["text-align"]="center"}var multiLine=settings.multiLine;if(settings.detectMultiLine&&!multiLine&&innerSpan.scrollHeight>=parseInt(window.getComputedStyle(innerSpan)["font-size"],10)*2){multiLine=true}if(!multiLine){el.style["white-space"]="nowrap"}low=settings.minFontSize+1;high=settings.maxFontSize+1;while(low<=high){mid=parseInt((low+high)/2,10);innerSpan.style.fontSize=mid+"px";if(innerSpan.scrollWidth<=originalWidth&&(settings.widthOnly||innerSpan.scrollHeight<=originalHeight)){low=mid+1}else{high=mid-1}}innerSpan.style.fontSize=mid-1+"px";if(settings.alignVert){addStyleSheet();var height=innerSpan.scrollHeight;if(window.getComputedStyle(el)["position"]==="static"){el.style["position"]="relative"}if(!hasClass(innerSpan,"textFitAlignVert")){innerSpan.className=innerSpan.className+" textFitAlignVert"}innerSpan.style["height"]=height+"px";if(settings.alignVertWithFlexbox&&!hasClass(el,"textFitAlignVertFlex")){el.className=el.className+" textFitAlignVertFlex"}}}function innerHeight(el){var style=window.getComputedStyle(el,null);return el.clientHeight-parseInt(style.getPropertyValue("padding-top"),10)-parseInt(style.getPropertyValue("padding-bottom"),10)}function innerWidth(el){var style=window.getComputedStyle(el,null);return el.clientWidth-parseInt(style.getPropertyValue("padding-left"),10)-parseInt(style.getPropertyValue("padding-right"),10)}function isElement(o){return typeof HTMLElement==="object"?o instanceof HTMLElement:o&&typeof o==="object"&&o!==null&&o.nodeType===1&&typeof o.nodeName==="string"}function hasClass(element,cls){return(" "+element.className+" ").indexOf(" "+cls+" ")>-1}function addStyleSheet(){if(document.getElementById("textFitStyleSheet"))return;var style=[".textFitAlignVert{","position: absolute;","top: 0; right: 0; bottom: 0; left: 0;","margin: auto;","display: flex;","justify-content: center;","flex-direction: column;","}",".textFitAlignVertFlex{","display: flex;","}",".textFitAlignVertFlex .textFitAlignVert{","position: static;","}"].join("");var css=document.createElement("style");css.type="text/css";css.id="textFitStyleSheet";css.innerHTML=style;document.body.appendChild(css)}});

View File

@ -455,6 +455,32 @@ MessengerUI, Messages, Pages) {
return $container;
};
createCollapse = function (toolbar) {
var up = h('i.fa.fa-chevron-up', {title: Messages.ui_collapse});
var down = h('i.fa.fa-chevron-down', {title: Messages.ui_expand});
var $button = $(h('button.cp-toolbar-collapse',[
up,
down
]));
var $up = $(up);
var $down = $(down);
toolbar.$bottomR.prepend($button);
$down.hide();
$button.click(function () {
toolbar.$top.toggleClass('toolbar-hidden');
var hidden = toolbar.$top.hasClass('toolbar-hidden');
$button.toggleClass('cp-toolbar-button-active');
if (hidden) {
$up.hide();
$down.show();
} else {
$up.show();
$down.hide();
}
});
};
var initChat = function (toolbar) {
var $container = $('<div>', {
id: 'cp-app-contacts-container',
@ -1330,6 +1356,7 @@ MessengerUI, Messages, Pages) {
// Create the subelements
var tb = {};
tb['userlist'] = createUserList;
tb['collapse'] = createCollapse;
tb['chat'] = createChat;
tb['share'] = createShare;
tb['access'] = createAccess;
@ -1351,7 +1378,9 @@ MessengerUI, Messages, Pages) {
tb['pad'] = function () {
toolbar.$file.show();
addElement([
'chat', 'userlist', 'title', 'useradmin', 'spinner',
'chat',
'collapse',
'userlist', 'title', 'useradmin', 'spinner',
'newpad', 'share', 'access', 'limit', 'unpinnedWarning',
'notifications'
], {});

View File

@ -418,7 +418,7 @@
"settings_deleteButton": "Suprimir el vostre compte",
"settings_deleteModal": "Envieu la següent informació a qui administri el vostre CryptPad per tal que les vostres dades siguin esborrades del servidor.",
"settings_deleted": "El vostre compte ha estat suprimit. Premeu D'acord per tornar a la pàgina inicial.",
"storageStatus": "Emmagatzematge:<br /><b>{0}</b> utilitzats de <b>{1}</b>",
"storageStatus": "Emmagatzematge:<br><b>{0}</b> utilitzats de <b>{1}</b>",
"settings_anonymous": "No heu iniciat la sessió. Els paràmetres només s'aplicaran al navegador actual.",
"settings_publicSigningKey": "Clau pública de signatura",
"settings_logoutEverywhereButton": "Tanca la sessió",

View File

@ -677,7 +677,7 @@
"share_linkFriends": "Mit Kontakten teilen",
"share_withFriends": "Teilen",
"notifications_dismiss": "Verbergen",
"fm_info_sharedFolderHistory": "Dies ist nur der Verlauf deines geteilten Ordners: <b>{0}</b><br/>Dein CryptDrive bleibt beim Navigieren im Nur-Lesen-Modus.",
"fm_info_sharedFolderHistory": "Dies ist nur der Verlauf deines geteilten Ordners: <b>{0}</b><br>Dein CryptDrive bleibt beim Navigieren im Nur-Lesen-Modus.",
"fc_expandAll": "Alle ausklappen",
"fc_collapseAll": "Alle einklappen",
"fc_color": "Farbe ändern",
@ -822,7 +822,7 @@
"properties_passwordWarningFile": "Das Passwort wurde erfolgreich geändert. Allerdings konnten die Daten in deinem CryptDrive nicht aktualisiert werden. Möglicherweise musst du die alte Version der Datei manuell entfernen.",
"properties_passwordSuccessFile": "Das Passwort wurde geändert.",
"driveOfflineError": "Die Verbindung zu CryptPad ist verloren gegangen. Änderungen an diesem Pad werden nicht in deinem CryptDrive gespeichert. Bitte schließe alle CryptPad-Tabs und versuche es in einem neuen Fenster erneut. ",
"storageStatus": "Speicher:<br /><b>{0}</b> von <b>{1}</b> belegt",
"storageStatus": "Speicher:<br><b>{0}</b> von <b>{1}</b> belegt",
"teams_table": "Rollen",
"teams_table_generic": "Rollen und Berechtigungen",
"teams_table_generic_view": "Ansehen: Zugriff auf Ordner und Pads (nur Lesen)",
@ -1231,7 +1231,7 @@
"register_registrationIsClosed": "Die Registrierung ist geschlossen.",
"mediatag_defaultImageName": "Bild",
"oo_importBin": "Klicke auf OK, um CryptPads interne Format .bin zu importieren.",
"oo_conversionSupport": "Dein Browser unterstützt die Konvertierung von und in Microsoft-Office-Formaten nicht. Wir empfehlen die Verwendung einer aktuellen Version von Firefox oder Chrome.",
"oo_conversionSupport": "Dein Browser unterstützt die Konvertierung von und in Office-Dateiformaten nicht. Wir empfehlen die Verwendung einer aktuellen Version von Firefox oder Chrome.",
"admin_emailTitle": "E-Mail-Adresse der Administratoren",
"admin_emailHint": "Lege hier die Kontaktadresse für deine Instanz fest",
"admin_supportPrivHint": "Lasse dir den privaten Schlüssel anzeigen, den andere Administratoren zum Zugriff auf die Support-Tickets benötigen. Ein Formular zur Eingabe dieses Schlüssels wird in ihrem Administrationsbereich angezeigt.",
@ -1379,5 +1379,8 @@
"fm_link_name_placeholder": "Mein Link",
"fm_link_url": "URL",
"fm_link_type": "Link",
"fm_link_new": "Neuer Link"
"fm_link_new": "Neuer Link",
"form_totalResponses": "Antworten insgesamt: {0}",
"ui_expand": "Ausklappen",
"ui_collapse": "Einklappen"
}

View File

@ -1,5 +1,5 @@
{
"main_title": "Cryptpad: Zero Knowledge, Editor Colaborativo en Tiempo Real",
"main_title": "CryptPad: Zero Knowledge, Editor Colaborativo en Tiempo Real",
"type": {
"pad": "Texto enriquecido",
"code": "Código",
@ -13,7 +13,8 @@
"file": "Archivo",
"media": "Media",
"sheet": "Hoja de Cálculo",
"teams": "Equipos"
"teams": "Equipos",
"form": "Formulario"
},
"disconnected": "Desconectado",
"synchronizing": "Sincronizando",
@ -51,10 +52,10 @@
"button_newcode": "Crear nuevo pad de código",
"button_newpoll": "Crear nueva encuesta",
"button_newslide": "Crear nueva presentación",
"tos_title": "Condiciones de servicio Cryptpad",
"tos_title": "Condiciones de servicio CryptPad",
"tos_legal": "Por favor, no seas malicioso, abusivo o hagas algo ilegal.",
"tos_availability": "Esperamos que este servicio te parezca útil, pero nuestra disponibilidad o rendimiento no pueden ser garantizados. Por favor, exporta tus datos regularmente.",
"tos_e2ee": "Los documentos Cryptpad pueden ser leídos o modificados por cualquiera que pueda adivinar o que pueda tener el enlace. Recomendamos que utilices mensajes cifrados de punto a punto (e2ee) para compartir URLs, no asumimos ninguna responsabilidad en el evento de alguna fuga.",
"tos_e2ee": "Los documentos CryptPad pueden ser leídos o modificados por cualquiera que pueda adivinar o que pueda tener el enlace. Recomendamos que utilices mensajes cifrados de punto a punto (e2ee) para compartir URLs, no asumimos ninguna responsabilidad en el evento de alguna fuga.",
"tos_logs": "Los metadatos entregados por el navegador al servidor pueden ser almacenados para la mantenencia del servicio.",
"tos_3rdparties": "No proveemos datos individualizados a terceros a menos de ser obligados por la ley.",
"header_logoTitle": "Volver a tu CryptDrive",
@ -467,7 +468,7 @@
"register_emailWarning1": "Puedes hacerlo si usted quiere, pero no se enviara a nuestros servidores.",
"register_emailWarning2": "No podrá restablecer su contraseña utilizando su correo electrónico como puede hacerlo con muchos otros servicios.",
"register_emailWarning3": "Si de todos modos entiende y desea utilizar su correo electrónico para su nombre de usuario, haga clic en Aceptar.",
"settings_autostoreHint": "<b> Automático </b> Todos los pads que visita se almacenan en su CryptDrive. <br> <b> Manual (siempre pregunte) </b> Si aún no ha guardado un pad, se le preguntará si desea para almacenarlos en su CryptDrive. <br> <b> Manual (nunca preguntar) </b> Los Pads no se almacenan automáticamente en su Cryptpad. La opción para almacenarlos estará oculta.",
"settings_autostoreHint": "<b> Automático </b> Todos los pads que visita se almacenan en su CryptDrive. <br> <b> Manual (siempre pregunte) </b> Si aún no ha guardado un pad, se le preguntará si desea para almacenarlos en su CryptDrive. <br> <b> Manual (nunca preguntar) </b> Los Pads no se almacenan automáticamente en su CryptDrive. La opción para almacenarlos estará oculta.",
"settings_driveDuplicateTitle": "Pads de propiedad duplicadas",
"settings_driveDuplicateHint": "Cuando mueve sus propias Pads a una carpeta compartida, se guarda una copia en su CryptDrive para asegurarse de que conserva su control sobre ella. Puedes ocultar archivos duplicados. Solo la versión compartida será visible, a menos que se elimine, en cuyo caso el original se mostrará en su ubicación anterior.",
"settings_padWidthHint": "Cambia entre el modo de página (por defecto) que limita el ancho del editor de texto, y el uso del ancho total de la pantalla.",
@ -563,7 +564,7 @@
"features_f_subscribe_note": "Se necesita una cuenta registrada para suscribirse",
"four04_pageNotFound": "No pudimos encontrar la página que estabas buscando.",
"help_genericMore": "Obtenga más información sobre cómo CryptPad puede funcionar para usted leyendo nuestras <a> Preguntas frecuentes </a>",
"storageStatus": "Almacenamiento:<br /><b>{0}</b> usado de <b>{1}</b>",
"storageStatus": "Almacenamiento:<br><b>{0}</b> usado de <b>{1}</b>",
"settings_cursorColorTitle": "Color de puntero",
"mdToolbar_button": "Mostrar u ocultar la barra de herramientas de Markdown",
"creation_404": "Este pad ya no existe. Utilice el siguiente formulario para crear un nuevo pad.",

View File

@ -62,7 +62,7 @@
"language": "Kieli",
"upgrade": "Päivitä",
"upgradeAccount": "Päivitä tili",
"storageStatus": "Tallennustila:<br /><b>{0}</b> käytetty <b>{1}</b>",
"storageStatus": "Tallennustila:<br><b>{0}</b> käytetty <b>{1}</b>",
"MB": "Mt",
"GB": "Gt",
"KB": "Kt",
@ -503,7 +503,7 @@
"mdToolbar_check": "Tehtävälista",
"mdToolbar_code": "Koodi",
"mdToolbar_toc": "Sisällysluettelo",
"home_host": "Tämä on itsenäinen yhteisön ylläpitämä Cryptpad-instanssi.",
"home_host": "Tämä on itsenäinen yhteisön ylläpitämä CryptPad-instanssi.",
"main_catch_phrase": "Kollaboraatioalusta<br>päästä päähän -salattu ja avoin lähdekoodi",
"footer_aboutUs": "Tietoa meistä",
"about": "Tietoa meistä",
@ -863,7 +863,7 @@
"admin_supportInitHelp": "Palvelimellesi ei ole asetettu ylläpitopostilaatikkoa. Jos haluat ottaa käyttöön ylläpitopostilaatikon käyttäjiltä tulevia viestejä varten, pyydä palvelimen ylläpitäjää ajamaan skripti \"./scripts/generate-admin-keys.js\", laittamaan skriptin generoima julkinen avain \"config.js\"-tiedostoon ja lähettämään sinulle yksityinen avain.",
"admin_cat_support": "Tuki",
"supportPage": "Tuki",
"fm_info_sharedFolderHistory": "Tämä on jaetun kansiosi historia: <b>{0}</b><br/>CryptDrivesi pysyy vain luku-tilassa selatessasi sitä.",
"fm_info_sharedFolderHistory": "Tämä on jaetun kansiosi historia: <b>{0}</b><br>CryptDrivesi pysyy vain luku-tilassa selatessasi sitä.",
"notifications_dismiss": "Hylkää",
"share_withFriends": "Jaa",
"share_linkFriends": "Jaa yhteystietojen kanssa",

View File

@ -121,7 +121,7 @@
"printTransition": "Activer les animations de transition",
"printBackground": "Utiliser une image d'arrière-plan",
"printBackgroundButton": "Choisir une image",
"printBackgroundValue": "<b>Arrière-plan actuel:</b> <em>{0}</em>",
"printBackgroundValue": "<b>Arrière-plan actuel :</b> <em>{0}</em>",
"printBackgroundNoValue": "<em>Aucun arrière-plan affiché</em>",
"printBackgroundRemove": "Supprimer cet arrière-plan",
"filePickerButton": "Intégrer un fichier stocké dans CryptDrive",
@ -289,14 +289,14 @@
"fm_error_cantPin": "Erreur interne du serveur. Veuillez recharger la page et essayer de nouveau.",
"fm_viewListButton": "Liste",
"fm_viewGridButton": "Grille",
"fm_renamedPad": "Vous avez renommé ce pad dans votre Drive. Son titre est:<br><b>{0}</b>",
"fm_renamedPad": "Vous avez renommé ce pad dans votre Drive. Son titre est :<br><b>{0}</b>",
"fm_canBeShared": "Ce dossier peut être partagé",
"fm_prop_tagsList": "Mots-clés",
"fm_burnThisDriveButton": "Effacer toutes les informations stockées par CryptPad dans votre navigateur",
"fm_burnThisDrive": "Êtes-vous sûr de vouloir supprimer tout ce qui est stocké par CryptPad dans votre navigateur ?<br>Cette action supprimera votre CryptDrive et son historique de votre navigateur, mais les pads existeront toujours (de manière chiffrée) sur notre serveur.",
"fm_padIsOwned": "Vous êtes le propriétaire de ce pad",
"fm_padIsOwnedOther": "Ce pad est la propriété d'un autre utilisateur",
"fm_deletedPads": "Ces pads n'existent plus sur le serveur, ils ont été supprimés de votre CryptDrive: {0}",
"fm_deletedPads": "Ces pads n'existent plus sur le serveur, ils ont été supprimés de votre CryptDrive : {0}",
"fm_tags_name": "Mot-clé",
"fm_tags_used": "Nombre d'utilisations",
"fm_restoreDrive": "Restauration de votre CryptDrive à une version antérieure. Pour de meilleurs résultats, veuillez éviter de modifier votre CryptDrive avant que cette restauration ne soit terminée.",
@ -679,7 +679,7 @@
"share_linkFriends": "Partager avec des contacts",
"share_withFriends": "Partager",
"notifications_dismiss": "Cacher",
"fm_info_sharedFolderHistory": "Vous regardez l'historique de votre dossier partagé <b>{0}</b><br/>Votre CryptDrive restera en lecture seule pendant la navigation.",
"fm_info_sharedFolderHistory": "Vous regardez l'historique de votre dossier partagé <b>{0}</b><br>Votre CryptDrive restera en lecture seule pendant la navigation.",
"fc_color": "Changer la couleur",
"supportPage": "Support",
"admin_cat_support": "Support",
@ -819,7 +819,7 @@
"properties_passwordWarningFile": "Le mot de passe a été modifié avec succès mais nous n'avons pas réussi à mettre à jour votre CryptDrive avec les nouvelles informations. Vous devrez peut-être supprimer manuellement l'ancienne version de ce fichier.",
"properties_passwordSuccessFile": "Le mot de passe a été modifié avec succès.",
"driveOfflineError": "Votre connexion à CryptPad a été perdue. Les modifications dans ce pad ne seront pas stockées dans votre CryptDrive. Veuillez fermer tous vos onglets CryptPad et ré-essayer dans une nouvelle fenêtre. ",
"storageStatus": "Stockage : <br /><b>{0}</b> utilisés sur <b>{1}</b>",
"storageStatus": "Stockage : <br><b>{0}</b> utilisés sur <b>{1}</b>",
"teams_table": "Rôles",
"teams_table_generic": "Rôles et permissions",
"teams_table_generic_view": "Voir : accéder aux dossiers et pads (lecture seule).",
@ -1230,7 +1230,7 @@
"genericCopySuccess": "Copié dans le presse-papiers",
"mediatag_defaultImageName": "image",
"register_registrationIsClosed": "Les inscriptions sont fermées.",
"oo_conversionSupport": "Votre navigateur ne gère pas la conversion vers et depuis les formats Microsoft Office. Il est recommandé d'utiliser une version récente de Firefox ou Chrome.",
"oo_conversionSupport": "Votre navigateur ne gère pas la conversion vers et depuis les formats office. Il est recommandé d'utiliser une version récente de Firefox ou Chrome.",
"oo_importBin": "Cliquez sur OK pour importer au format .bin interne à CryptPad.",
"admin_emailButton": "Valider",
"admin_supportPrivButton": "Afficher la clé",
@ -1258,7 +1258,7 @@
"admin_consentToContactTitle": "Consentement à la prise de contact",
"admin_checkupButton": "Exécuter le diagnostic",
"admin_updateAvailableTitle": "Nouvelles versions",
"admin_updateAvailableHint": "Une nouvelle version de Cryptpad est disponible",
"admin_updateAvailableHint": "Une nouvelle version de CryptPad est disponible",
"admin_checkupHint": "CryptPad est doté d'une page qui diagnostique automatiquement les problèmes de configuration courants et suggère comment les corriger si nécessaire.",
"admin_checkupTitle": "Valider la configuration de l'instance",
"admin_updateAvailableButton": "Lire les notes de mise à jour",
@ -1379,5 +1379,8 @@
"fm_link_name": "Titre du lien",
"fm_link_type": "Lien",
"fm_link_new": "Nouveau Lien",
"notification_openLink": "Vous avez reçu un lien <b>{0}</b> de {1} :"
"notification_openLink": "Vous avez reçu un lien <b>{0}</b> de {1} :",
"ui_expand": "Développer",
"ui_collapse": "Réduire",
"form_totalResponses": "Nombre de réponses : {0}"
}

View File

@ -397,7 +397,7 @@
"settings_deleteHint": "La cancellazione dell'account è permanente. Il tuo CryptDrive e il tuo elenco di pad saranno cancellati dal server. Il resto dei tuoi pad sarà eliminato in 90 giorni se nessun altro li ha salvati nel suo CryptDrive.",
"settings_deleteButton": "Cancella il tuo account",
"padNotPinnedVariable": "Questo pad scadrà dopo {4} giorni di inattività, {0}accedi{1} o {2}registrati{3} per conservarlo.",
"storageStatus": "Spazio:<br /><b>{0}</b> utilizzato su <b>{1}</b>",
"storageStatus": "Spazio:<br><b>{0}</b> utilizzato su <b>{1}</b>",
"uploadFolderButton": "Carica cartella",
"fm_morePads": "Altro",
"fc_color": "Cambia colore",
@ -550,7 +550,7 @@
"settings_anonymous": "Non sei connesso. Queste impostazioni sono specifiche per questo browser.",
"settings_deleted": "Il tuo account utente è stato cancellato. Premi OK per tornare alla home page.",
"settings_deleteModal": "Condividi le seguenti informazioni con il tuo amministratore CryptPad per far rimuovere i tuoi dati dal server.",
"settings_autostoreHint": "<b>Automatico</b> Tutti i pad che visiti sono conservati nel tuo CryptDrive.<br><b>Manuale (chiedi sempre)</b> Se non hai ancora conservato alcun pad ti verrà chiesto se vuoi conservarli nel tuo CryptDrive.<br><b>Manuale (non chiedere mai)</b> I pads non sono conservati automaticamente nel tuo Cryptpad. L'opzione di conservarli sarà nascosta.",
"settings_autostoreHint": "<b>Automatico</b> Tutti i pad che visiti sono conservati nel tuo CryptDrive.<br><b>Manuale (chiedi sempre)</b> Se non hai ancora conservato alcun pad ti verrà chiesto se vuoi conservarli nel tuo CryptDrive.<br><b>Manuale (non chiedere mai)</b> I pads non sono conservati automaticamente nel tuo CryptDrive. L'opzione di conservarli sarà nascosta.",
"settings_autostoreNo": "Manuale (non chiedere mai)",
"settings_autostoreYes": "Automatico",
"settings_autostoreTitle": "Conservazione pad nel CryptDrive",
@ -669,9 +669,9 @@
"adminPage": "Amministrazione",
"admin_cat_stats": "Statistiche",
"admin_cat_general": "Generale",
"survey": "Sondaggio Cryptpad",
"survey": "Sondaggio CryptPad",
"crowdfunding_popup_no": "Non ora",
"crowdfunding_button": "Supporta Cryptpad",
"crowdfunding_button": "Supporta CryptPad",
"autostore_pad": "pad",
"autostore_sf": "cartella",
"autostore_file": "file",
@ -910,7 +910,7 @@
"admin_flushCacheButton": "Svuota la cache",
"admin_diskUsageHint": "Lo spazio di memoria disponibile è stato esaurito da varie risorse CryptPad",
"profile_info": "Altri utenti possono trovare il tuo profilo tramite il tuo avatar nella lista degli utenti dei documenti.",
"fm_info_sharedFolderHistory": "questa è solo la cronologia delle tue cartelle condivise: <b>{0}</b><br/>Il tuo CryptDrive rimarrà in sola lettura durante la navigazione.",
"fm_info_sharedFolderHistory": "questa è solo la cronologia delle tue cartelle condivise: <b>{0}</b><br>Il tuo CryptDrive rimarrà in sola lettura durante la navigazione.",
"admin_supportInitHelp": "Il tuo server non è ancora configurato per avere una mailbox di supporto. Se vuoi una mailbox di supporto per ricevere messaggi dai tuoi utenti, chiedi all'amministratore del server di avviare lo script posizionato in \"./scripts/generate-admin-keys.js\", quindi salvare la chiave pubblica nel file \"config.js\" ed inviarti la chiave privata.",
"admin_supportInitPrivate": "La tua installazione CryptPad è configurata per usare una mailbox di supporto ma il tuo account non ha la chiave privata corretta per accedervi. Usa il modulo che segue per aggiungere o aggiornare la chiave privata del tuo account.",
"admin_supportInitHint": "Puoi configurare una mailbox di supporto per dare agli utenti del tuo CryptPad un modo per contattarti in maniera sicura se hanno problemi con i loro account.",

View File

@ -86,7 +86,7 @@
"settings_trimHistoryTitle": "履歴の削除",
"trimHistory_success": "履歴を削除しました",
"trimHistory_button": "履歴を削除",
"storageStatus": "ストレージ使用量:<br /><b>{1}</b> の内 <b>{0}</b>",
"storageStatus": "ストレージ使用量:<br><b>{1}</b> の内 <b>{0}</b>",
"formattedKB": "{0} KB",
"formattedGB": "{0} GB",
"formattedMB": "{0} MB",
@ -560,7 +560,7 @@
"form_form": "フォーム",
"form_editor": "エディタ",
"form_delete": "削除",
"form_sent": "送信しました",
"form_sent": "回答を送信しました",
"form_reset": "リセット",
"form_update": "更新",
"form_submit": "送信",
@ -807,7 +807,7 @@
"settings_resetThumbnailsDescription": "ブラウザに保存したサムネイルを削除します。",
"settings_disableThumbnailsDescription": "新しいパッドを開くと、サムネイルが自動で作成され、ブラウザに保存されます。ここでサムネイルの作成を無効にできます。",
"fm_info_root": "フォルダを作成してファイルを整理できます。",
"oo_conversionSupport": "お使いのブラウザはMicrosoft Officeのフォーマットの変換に対応していません。FirefoxもしくはChromeの最新バージョンの使用を推奨します。",
"oo_conversionSupport": "お使いのブラウザは、オフィスソフトウェアのフォーマットの変換に対応していません。FirefoxもしくはChromeの最新バージョンの使用を推奨します。",
"register_registrationIsClosed": "登録は締め切りました。",
"settings_notifCalendarHint": "今後のカレンダーのイベントの全ての通知を有効もしくは無効にします。",
"reminder_inProgressAllDay": "今日: <b>{0}</b>",
@ -1149,7 +1149,7 @@
"support_disabledTitle": "サポートは有効になっていません",
"admin_supportListHint": "ユーザーからサポートのメールボックスに送信されたチケットの一覧です。管理者はメッセージと回答を閲覧できます。終了したチケットは再開することができます。終了したチケットについては削除する(隠す)ことができますが、他の管理者には引き続き表示されます。",
"drive_sfPassword": "共有フォルダ「 {0} 」は利用できません。オーナーにより削除されたか、新しいパスワードで保護されています。CryptDriveから削除するか、新しいパスワードを使ってアクセスを回復できます。",
"fm_info_sharedFolderHistory": "これは共有フォルダの履歴です: <b>{0}</b><br/>CryptDriveは閲覧モードを継続します。",
"fm_info_sharedFolderHistory": "これは共有フォルダの履歴です: <b>{0}</b><br>CryptDriveは閲覧モードを継続します。",
"notification_folderShared": "{0}があなたとフォルダを共有しました: <b>{1}</b>",
"convertFolderToSF_SFChildren": "このフォルダは共有フォルダを含んでいるため、共有フォルダに変更できません。続けるには、このフォルダを共有フォルダの外に移動してください。",
"sharedFolders_share": "このリンクを登録ユーザーと共有すると、共有フォルダへのアクセスが可能になります。相手がリンクを開くと、CryptDriveに共有フォルダが追加されます。",
@ -1378,5 +1378,9 @@
"notification_linkShared": "{0}があなたとリンクを共有しました: <b>{1}</b>",
"fm_link_name_placeholder": "あなたのリンク",
"fm_link_warning": "注意URLが200字を超えています",
"fm_link_invalid": "URLが無効です"
"fm_link_invalid": "URLが無効です",
"form_answerAs": "名前を記入してください",
"form_totalResponses": "回答数:{0}",
"ui_expand": "広げる",
"ui_collapse": "折りたたむ"
}

View File

@ -62,7 +62,7 @@
"language": "Language",
"upgrade": "Upgrade",
"upgradeAccount": "Upgrade account",
"storageStatus": "Storage:<br /><b>{0}</b> used out of <b>{1}</b>",
"storageStatus": "Storage:<br><b>{0}</b> used out of <b>{1}</b>",
"MB": "MB",
"GB": "GB",
"KB": "KB",
@ -404,7 +404,7 @@
"settings_importConfirm": "Are you sure you want to import recent pads from this browser to your user account's CryptDrive?",
"settings_importDone": "Import completed",
"settings_autostoreTitle": "Pad storage in CryptDrive",
"settings_autostoreHint": "<b>Automatic</b> All the pads you visit are stored in your CryptDrive.<br><b>Manual (always ask)</b> If you have not stored a pad yet, you will be asked if you want to store them in your CryptDrive.<br><b>Manual (never ask)</b> Pads are not stored automatically in your Cryptpad. The option to store them will be hidden.",
"settings_autostoreHint": "<b>Automatic</b> All the pads you visit are stored in your CryptDrive.<br><b>Manual (always ask)</b> If you have not stored a pad yet, you will be asked if you want to store them in your CryptDrive.<br><b>Manual (never ask)</b> Pads are not stored automatically in your CryptDrive. The option to store them will be hidden.",
"settings_autostoreYes": "Automatic",
"settings_autostoreNo": "Manual (never ask)",
"settings_autostoreMaybe": "Manual (always ask)",
@ -701,7 +701,7 @@
"share_linkFriends": "Share with contacts",
"share_withFriends": "Share",
"notifications_dismiss": "Dismiss",
"fm_info_sharedFolderHistory": "This is only the history of your shared folder: <b>{0}</b><br/>Your CryptDrive will stay in read-only mode while you navigate.",
"fm_info_sharedFolderHistory": "This is only the history of your shared folder: <b>{0}</b><br>Your CryptDrive will stay in read-only mode while you navigate.",
"supportPage": "Support",
"admin_cat_support": "Support",
"admin_supportInitHelp": "Your server is not yet configured to have a support mailbox. If you want a support mailbox to receive messages from your users, you should ask your server administrator to run the script located in \"./scripts/generate-admin-keys.js\", then store the public key in the \"config.js\" file and send you the private key.",
@ -1230,7 +1230,7 @@
"genericCopySuccess": "Copied to clipboard",
"mediatag_defaultImageName": "image",
"register_registrationIsClosed": "Registration is closed.",
"oo_conversionSupport": "Your browser cannot handle conversion to and from Microsoft Office formats. We suggest using a recent version of Firefox or Chrome.",
"oo_conversionSupport": "Your browser cannot handle conversion to and from office formats. We suggest using a recent version of Firefox or Chrome.",
"oo_importBin": "Click OK to import CryptPad's internal .bin format.",
"admin_emailTitle": "Admin contact email",
"admin_emailHint": "Set the contact email for your instance here",
@ -1379,5 +1379,8 @@
"form_anonName": "Your name",
"form_answerAs": "Answer as",
"fm_link_warning": "Warning: the URL exceeds 200 characters",
"fm_link_invalid": "Invalid URL"
"fm_link_invalid": "Invalid URL",
"ui_collapse": "Collapse",
"ui_expand": "Expand",
"form_totalResponses": "Total responses: {0}"
}

View File

@ -46,7 +46,7 @@
"KB": "KB",
"GB": "GB",
"MB": "MB",
"storageStatus": "Saugykla: <br /> <b> {0} </b> sunaudota iš <b> {1} </b>",
"storageStatus": "Saugykla: <br> <b> {0} </b> sunaudota iš <b> {1} </b>",
"upgrade": "Atnaujinti",
"upgradeAccount": "Atnaujinti paskyrą",
"language": "Kalba",

View File

@ -265,7 +265,7 @@
"formattedKB": "{0} KB",
"formattedGB": "{0} GB",
"formattedMB": "{0} MB",
"storageStatus": "Lagringsplass:<br /><b>{0}</b> brukt, av <b>{1}</b>",
"storageStatus": "Lagringsplass:<br><b>{0}</b> brukt, av <b>{1}</b>",
"padNotPinnedVariable": "Denne dokumentet utløper etter {4] dager med inaktivitet, {0}logg inn{1} eller {2}registrer deg{3} for å bevare det.",
"history_restoreTitle": "Gjenopprett den valgte dokumentversjonen",
"history_closeTitle": "Lukk historikken",

View File

@ -131,7 +131,7 @@
"KB": "KB",
"GB": "GB",
"MB": "MB",
"storageStatus": "Opslag:<br /><b>{0}</b> verbruikt van <b>{1}</b>",
"storageStatus": "Opslag:<br><b>{0}</b> verbruikt van <b>{1}</b>",
"upgradeAccount": "Account opwaarderen",
"upgrade": "Opwaarderen",
"language": "Taal",
@ -324,7 +324,7 @@
"settings_autostoreMaybe": "Handmatig (altijd vragen)",
"settings_autostoreNo": "Handmatig (nooit vragen)",
"settings_autostoreYes": "Automatisch",
"settings_autostoreHint": "<b>Automatisch</b> Alle geopende werkomgevingen worden automatisch opgeslagen in uw CryptDrive.<br><b>Handmatig (altijd vragen)</b> Als u een werkomgeving nog niet hebt opgeslagen, zult u gevraagd worden of u het in uw CryptDrive wilt opslaan.<br><b>Handmatig (nooit vragen)</b> Werkomgevingen worden niet automatisch opgeslagen in uw Cryptpad. The optie om op te slaan wordt verborgen.",
"settings_autostoreHint": "<b>Automatisch</b> Alle geopende werkomgevingen worden automatisch opgeslagen in uw CryptDrive.<br><b>Handmatig (altijd vragen)</b> Als u een werkomgeving nog niet hebt opgeslagen, zult u gevraagd worden of u het in uw CryptDrive wilt opslaan.<br><b>Handmatig (nooit vragen)</b> Werkomgevingen worden niet automatisch opgeslagen in uw CryptDrive. The optie om op te slaan wordt verborgen.",
"settings_autostoreTitle": "Opslag van werkomgevingen in CryptDrive",
"settings_importDone": "Importeren voltooid",
"settings_importConfirm": "Weet u zeker dat u de recente pads van uw browser in uw geregistreerde CryptDrive wilt importeren?",

View File

@ -1,5 +1,5 @@
{
"main_title": "Cryptpad: Wspólne edytowanie w czasie rzeczywistym, bez wiedzy specjalistycznej",
"main_title": "CryptPad: Wspólne edytowanie w czasie rzeczywistym, bez wiedzy specjalistycznej",
"type": {
"pad": "Pad",
"code": "Kod",
@ -46,10 +46,10 @@
"button_newcode": "STWÓRZ PAD DO KODU",
"button_newpoll": "STWÓRZ GŁOSOWANIE",
"button_newslide": "STWÓRZ PREZENTACJĘ",
"tos_title": "Warunki korzystania z usług Cryptpad",
"tos_title": "Warunki korzystania z usług CryptPad",
"tos_legal": "Prosimy abyś nie był złośliwy, obelżywy i nie wykorzystywał tego oprogramowania do celow niezgodnych z prawem.",
"tos_availability": "Mamy nadzieję iż uznasz tę usługę za przydatną, lecz dostępność i wydajność nie mogą być przez nas gwarantowane. Prosimy, abyś eksportował swoje dane regularnie.",
"tos_e2ee": "Dokumenty Cryptpad mogą być odczytywane i modyfikowane przez każdego kto może zgadnąć lub w inny sposób uzyskać identyfikator dokumentu. Polecamy korzystania z oprogramowania szyfrującego end-to-end (e2ee) do udostępniania linków URL. Nie będziesz rościł sobie żadnych wierzytelności w wypadku gdy taki URL dostanie się w niepowołane ręce.",
"tos_e2ee": "Dokumenty CryptPad mogą być odczytywane i modyfikowane przez każdego kto może zgadnąć lub w inny sposób uzyskać identyfikator dokumentu. Polecamy korzystania z oprogramowania szyfrującego end-to-end (e2ee) do udostępniania linków URL. Nie będziesz rościł sobie żadnych wierzytelności w wypadku gdy taki URL dostanie się w niepowołane ręce.",
"tos_logs": "Metadane dostarczane przez twoją przeglądarkę do serwera mogą być zapisywane i przechowywane w celu utrzymywania serwisu.",
"tos_3rdparties": "Nie dostarczamy indywidualizowanych danych do osób trzecich, poza sytuacjami dyktowanymi prawnie.",
"header_logoTitle": "Przejdź na stronę główną"

View File

@ -1,5 +1,5 @@
{
"main_title": "Cryptpad: Zero Knowledge, Edição Colaborativa em Tempo Real",
"main_title": "CryptPad: Zero Knowledge, Edição Colaborativa em Tempo Real",
"type": {
"pad": "Notas",
"code": "Código",
@ -212,7 +212,7 @@
"contact": "Contact",
"terms": "ToS",
"blog": "Blog",
"tos_title": "Termos de serviço doCryptpad",
"tos_title": "Termos de serviço do CryptPad",
"tos_legal": "Pedimos encarecidamente que, como usuário desta plataforma, você evite a prática de quaisquer atos ilegais e que evite a utilização maliciosa e/ou abusiva desta plataforma.",
"tos_availability": "Nós esperamos que você ache este serviço útil, porém nós não podemos garantir a disponibilidade constante ou a alta performance do mesmo. Por favor, mantenha um backup dos seus dados como forma de segurança adicional.",
"tos_e2ee": "Os documentos do CryptPad podem ser modificados por qualquer um que conseguir adivinhar ou obter de qualquer forma o seu identificador único. Nós recomendamos que você utilize criptografia ponto a ponto de mensagens (e2ee) sempre que possível para compartilhar suas URL's. Nós não assumimos qualquer responsabilidade sobre chaves e/ou URLs e seus respectivos conteúdos vazadas para o público.",
@ -322,7 +322,7 @@
"oo_uploaded": "Seu envio foi completado. Clique OK para recarregar a página ou cancele para continuar no modo somente leitura.",
"canvas_opacityLabel": "Opacidade: {0}",
"canvas_widthLabel": "Largura: {0}",
"storageStatus": "Armazenamento:<br /><b>{0}</b> usados do total <b>{1}</b>",
"storageStatus": "Armazenamento:<br><b>{0}</b> usados do total <b>{1}</b>",
"upgradeAccount": "Atualizar conta",
"padNotPinnedVariable": "Este pad vai expirar em {4} dias de inatividade, {0} faça login{1} ou {2}registre-se{3} para preserva-lo.",
"settings_cursorColorTitle": "Cor do cursor",
@ -363,7 +363,7 @@
"settings_autostoreNo": "Manual (nunca perguntar)",
"settings_autostoreMaybe": "Manual (sempre perguntar)",
"settings_autostoreYes": "Automático",
"settings_autostoreHint": "<b>Automatico</b> Todos os blocos que visitou estão armazenados no seu CryptDrive.<br><b>Manual (sempre pergunta)<b> Se você não armazenou um bloco ainda, você será questionado se quer armazenar no seu CryptDrive.<br><b>Manual (nunca pergunta)</b> Blocos não são armazenados automaticamente no seu CryptPad. A opção para armazena-los estará escondida.",
"settings_autostoreHint": "<b>Automatico</b> Todos os blocos que visitou estão armazenados no seu CryptDrive.<br><b>Manual (sempre pergunta)<b> Se você não armazenou um bloco ainda, você será questionado se quer armazenar no seu CryptDrive.<br><b>Manual (nunca pergunta)</b> Blocos não são armazenados automaticamente no seu CryptDrive. A opção para armazena-los estará escondida.",
"settings_autostoreTitle": "Bloco armazenado no CryptDrive",
"settings_resetThumbnailsDone": "Todas as miniaturas foram apagadas.",
"settings_resetThumbnailsDescription": "Limpar todos as miniaturas de blocos armazenadas no seu navegador.",
@ -791,7 +791,7 @@
"admin_supportInitHelp": "Seu servidor ainda não está configurado para ter uma caixa de correio de suporte. Se você deseja que uma caixa de correio de suporte receba mensagens de seus usuários, peça ao administrador do servidor para executar o script localizado em \"./scripts/generate-admin-keys.js\" e, em seguida, armazene a chave pública em \"config.js \"arquivo e enviar a chave privada.",
"admin_cat_support": "Suporte",
"supportPage": "Suporte",
"fm_info_sharedFolderHistory": "Este é apenas o histórico da sua pasta compartilhada: <b> {0} </b> <br/> Seu CryptDrive permanecerá no modo somente leitura enquanto você navega.",
"fm_info_sharedFolderHistory": "Este é apenas o histórico da sua pasta compartilhada: <b> {0} </b> <br> Seu CryptDrive permanecerá no modo somente leitura enquanto você navega.",
"notifications_dismiss": "Recusar",
"share_withFriends": "Compartilhar",
"share_linkFriends": "Compartilhar com contatos",

View File

@ -433,7 +433,7 @@
"settings_autostoreMaybe": "Manual (întreabă întotdeauna)",
"settings_autostoreNo": "Manual (nu mai întreba)",
"settings_autostoreYes": "Automat",
"settings_autostoreHint": "<b>Automat</b> Toate documentele accesate sunt stocate în CryptDrive-ul dumneavoastră.<br><b>Manual (întreabă întotdeauna)</b> Dacă nu ai stocat încă un document, vei fi întrebat dacă dorești să îl stochezi în Cryptdrive-ul tău.<br><b>Manual (nu mai întreba)</b> Documentele nu sunt stocate automat în Cryptpad-ul tău. Opțiunea de a le stoca ulterior va fi ascunsă.",
"settings_autostoreHint": "<b>Automat</b> Toate documentele accesate sunt stocate în CryptDrive-ul dumneavoastră.<br><b>Manual (întreabă întotdeauna)</b> Dacă nu ai stocat încă un document, vei fi întrebat dacă dorești să îl stochezi în Cryptdrive-ul tău.<br><b>Manual (nu mai întreba)</b> Documentele nu sunt stocate automat în CryptDrive-ul tău. Opțiunea de a le stoca ulterior va fi ascunsă.",
"settings_autostoreTitle": "Capacitatea de stocare a documentelor în CryptDrive",
"register_emailWarning2": "Nu veți putea să vă resetați parola folosind adresa de e-mail, așa cum puteți cu multe alte servicii.",
"register_emailWarning1": "Poți proceda astfel dacă doreşti, însă nici o notificare nu va fi transmisă server-ului nostru.",
@ -443,7 +443,7 @@
"fc_color": "Schimbă culoarea",
"fm_morePads": "Mai mult",
"uploadFolderButton": "Încarcă dosar",
"storageStatus": "Capacitate de stocare:<br /><b>{0}</b> utilizat din <b>{1}</b>",
"storageStatus": "Capacitate de stocare:<br><b>{0}</b> utilizat din <b>{1}</b>",
"fc_collapseAll": "Restrânge",
"settings_padSpellcheckLabel": "Activați verificarea ortografică",
"settings_padSpellcheckHint": "Această opțiune vă permite să activați verificarea ortografică în editorul de text. Erorile de ortografie vor fi subliniate cu roșu și va trebui să țineți apăsată tasta Ctrl sau tasta Meta în timp ce faceți clic dreapta pentru a vedea opțiunile corecte.",

View File

@ -442,7 +442,7 @@
"fc_openInCode": "Открыть в редакторе кода",
"fm_morePads": "Ещё",
"uploadFolderButton": "Загрузить папку",
"storageStatus": "Хранилище:<br /><b>{0}</b> использовано из <b>{1}</b>",
"storageStatus": "Хранилище:<br><b>{0}</b> использовано из <b>{1}</b>",
"padNotPinnedVariable": "Этот документ исчезнет через {4} дней неактивности, {0}войдите{1} или {2}зарегистируйтесь{3} чтобы сохранить его.",
"creation_passwordValue": "Пароль",
"creation_owners": "Владельцы",

View File

@ -102,7 +102,7 @@
"KB": "KB",
"GB": "GB",
"MB": "MB",
"storageStatus": "Lagring:<br /><b>{0}</b> använd av <b>{1}</b>",
"storageStatus": "Lagring:<br><b>{0}</b> använd av <b>{1}</b>",
"upgradeAccount": "Uppgradera konto",
"upgrade": "Uppgradera",
"language": "Språk",

View File

@ -208,7 +208,7 @@
"upload_pending": "待處理",
"upload_cancelled": "已取消的",
"upload_size": "大小",
"footer_aboutUs": "關於 Cryptpad",
"footer_aboutUs": "關於 CryptPad",
"about": "關於",
"privacy": "隱私",
"contact": "聯繫",

View File

@ -316,13 +316,24 @@ define([
// Get data from AllFiles (Cryptpad_RECENTPADS)
var getFileData = exp.getFileData = function (file, editable) {
if (!file) { return; }
var link = (files[STATIC_DATA] || {})[file];
var link;
try {
link = (files[STATIC_DATA] || {})[file];
} catch (err) {
console.error(err);
}
if (link) {
var _link = editable ? link : Util.clone(link);
if (!editable) { _link.static = true; }
return _link;
}
var data = files[FILES_DATA][file] || {};
var data;
try {
data = files[FILES_DATA][file] || {};
} catch (err) {
console.error(err);
data = {};
}
if (!editable) {
data = JSON.parse(JSON.stringify(data));
if (data.href && data.href.indexOf('#') === -1) {
@ -356,8 +367,13 @@ define([
return '??';
}
var data = getFileData(file);
if (!data) {
error("unable to retrieve data about the requested file: ", file, data);
return;
}
// handle links
if (data.static) { return data.name; }
if (!file || !data || !(data.href || data.roHref)) {
if (!file || !(data.href || data.roHref)) {
error("getTitle called with a non-existing file id: ", file, data);
return;
}

View File

@ -192,8 +192,8 @@ define([
},
};
Messages.convertPage = "Convert"; // XXX 4.10.0
Messages.convert_hint = "Pick the file you want to convert. The list of output format will be visible afterward."; // XXX 4.10.0
Messages.convertPage = "Convert"; // XXX 4.11.0
Messages.convert_hint = "Pick the file you want to convert. The list of output format will be visible afterward."; // XXX 4.11.0
var createToolbar = function () {
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle', 'notifications'];

View File

@ -279,10 +279,11 @@ define([
tippy: Messages.fm_burnThisDriveButton,
drawer: false
}, function () {
UI.confirm(Messages.fm_burnThisDrive, function (yes) {
var confirmContent = UIElements.fixInlineBRs(Messages.fm_burnThisDrive);
UI.confirm(confirmContent, function (yes) {
if (!yes) { return; }
common.getSframeChannel().event('EV_BURN_ANON_DRIVE');
}, null, true);
});
});
}

View File

@ -1,6 +1,7 @@
@import (reference) '../../customize/src/less2/include/framework.less';
@import (reference) '../../customize/src/less2/include/tools.less';
@import (reference) '../../customize/src/less2/include/avatar.less';
@import (reference) '../../customize/src/less2/include/charts.less';
&.cp-app-form {
@form_input-width: 400px;
@ -68,6 +69,11 @@
justify-content: center;
min-width: 300px;
div.timeline-container {
width: 100%;
height: 200px;
}
.cp-form-input-block {
display: flex;
}
@ -485,13 +491,14 @@
.cp-form-creator-results-controls {
margin-bottom: 20px;
margin-top: 20px;
//background: @cp_form-bg1;
//padding: 10px;
button {
margin-right: 10px;
}
}
}
.cp-form-creator-results-export {
margin-bottom: 20px;
}
.cp-form-creator-results-content {
padding-bottom: 100px;
.cp-form-block {
@ -542,6 +549,16 @@
&.cp-value {
min-width: 200px;
}
&.cp-bar-container {
width: 99%;
padding: 0px;
position: relative;
.cp-bar {
position: absolute;
background: @cryptpad_color_brand;
height: 100%;
}
}
}
}
}
@ -797,5 +814,6 @@
}
}
.charts_main();
}

View File

@ -803,7 +803,7 @@ define([
return total;
};
var getEmpty = function (empty) {
var getEmpty = function (empty) { // TODO don't include this in the scrollable area
if (empty) {
return UI.setHTML(h('div.cp-form-results-type-text-empty'), Messages._getKey('form_notAnswered', [empty]));
}
@ -953,6 +953,34 @@ define([
},
};
var arrayMax = function (A) {
return Array.isArray(A)? Math.max.apply(null, A): NaN;
};
var barGraphic = function (itemScale) {
return h('span.cp-bar-container', h('div.cp-bar', {
style: 'width: ' + (itemScale * 100) + '%',
}, ' '));
};
var renderTally = function (tally, empty, showBar) {
var rows = [];
var counts = Util.values(tally);
var max = arrayMax(counts);
Object.keys(tally).forEach(function (value) {
var itemCount = tally[value];
var itemScale = (itemCount / max);
rows.push(h('div.cp-form-results-type-radio-data', [
h('span.cp-value', value),
h('span.cp-count', itemCount),
showBar? barGraphic(itemScale): undefined,
]));
});
if (empty) { rows.push(getEmpty(empty)); }
return rows;
};
var TYPES = {
input: {
defaultOpts: {
@ -990,15 +1018,31 @@ define([
printResults: function (answers, uid) {
var results = [];
var empty = 0;
Object.keys(answers).forEach(function (author) { // TODO deduplicate these?
var tally = {};
Object.keys(answers).forEach(function (author) {
var obj = answers[author];
var answer = obj.msg[uid];
if (!answer || !answer.trim()) { return empty++; }
results.push(h('div.cp-form-results-type-text-data', answer));
Util.inc(tally, answer);
});
results.push(getEmpty(empty));
//var counts = Util.values(tally);
//var max = arrayMax(counts);
return h('div.cp-form-results-type-text', results);
//if (max < 2) { // there are no duplicates, so just return text
Object.keys(answers).forEach(function (author) {
var obj = answers[author];
var answer = obj.msg[uid];
if (!answer || !answer.trim()) { return empty++; }
results.push(h('div.cp-form-results-type-text-data', answer));
});
results.push(getEmpty(empty));
return h('div.cp-form-results-type-text', results);
//}
/*
var rendered = renderTally(tally, empty);
return h('div.cp-form-results-type-text', rendered);
*/
},
icon: h('i.cptools.cptools-form-text')
},
@ -1053,7 +1097,7 @@ define([
reset: function () { $text.val(''); }
};
},
printResults: function (answers, uid) {
printResults: function (answers, uid) { // results textarea
var results = [];
var empty = 0;
Object.keys(answers).forEach(function (author) { // TODO deduplicate these
@ -1122,25 +1166,20 @@ define([
};
},
printResults: function (answers, uid) {
var results = [];
printResults: function (answers, uid, form, content) {
// results radio
var empty = 0;
var count = {};
var showBars = Boolean(content);
Object.keys(answers).forEach(function (author) {
var obj = answers[author];
var answer = obj.msg[uid];
if (!answer || !answer.trim()) { return empty++; }
Util.inc(count, answer);
});
Object.keys(count).forEach(function (value) {
results.push(h('div.cp-form-results-type-radio-data', [
h('span.cp-value', value),
h('span.cp-count', count[value])
]));
});
results.push(getEmpty(empty));
return h('div.cp-form-results-type-radio', results);
var rendered = renderTally(count, empty, showBars);
return h('div.cp-form-results-type-radio', rendered);
},
icon: h('i.cptools.cptools-form-list-radio')
},
@ -1217,6 +1256,7 @@ define([
},
printResults: function (answers, uid, form) {
// results multiradio
var structure = form[uid];
if (!structure) { return; }
var opts = structure.opts || TYPES.multiradio.defaultOpts;
@ -1235,19 +1275,52 @@ define([
Util.inc(c, res);
});
});
Object.keys(count).forEach(function (q_uid) {
var max = 0;
var count_keys = Object.keys(count);
count_keys.forEach(function (q_uid) {
var counts = Object.values(count[q_uid]);
counts.push(max);
max = arrayMax(counts);
});
count_keys.forEach(function (q_uid) {
var q = findItem(opts.items, q_uid);
var c = count[q_uid];
var values = Object.keys(c).map(function (res) {
var itemCount = c[res];
return h('div.cp-form-results-type-radio-data', [
h('span.cp-value', res),
h('span.cp-count', c[res])
h('span.cp-count', itemCount),
//barGraphic((itemCount / max) * 100)
]);
});
results.push(h('div.cp-form-results-type-multiradio-data', [
h('span.cp-mr-q', q),
h('span.cp-mr-value', values)
]));
return;
/*
var table = Charts.table([
h('caption', {
style: 'color: var(--msg-color)',
}, q),
h('tbody', Object.keys(c).map(function (res) {
return Charts.row(res, c[res] / max, c[res]);
})),
], [
'charts-css',
'bar',
'show-heading',
'show-data-on-hover',
'show-labels',
]);
results.push(h('div.cp-form-results-type-multiradio-data', {
style: 'width: 100%',
}, table));
*/
});
results.push(getEmpty(empty));
@ -1333,10 +1406,11 @@ define([
};
},
printResults: function (answers, uid) {
var results = [];
printResults: function (answers, uid, form, content) {
// results checkbox
var empty = 0;
var count = {};
var showBars = Boolean(content);
Object.keys(answers).forEach(function (author) {
var obj = answers[author];
var answer = obj.msg[uid];
@ -1345,15 +1419,9 @@ define([
Util.inc(count, val);
});
});
Object.keys(count).forEach(function (value) {
results.push(h('div.cp-form-results-type-radio-data', [
h('span.cp-value', value),
h('span.cp-count', count[value])
]));
});
results.push(getEmpty(empty));
return h('div.cp-form-results-type-radio', results);
var rendered = renderTally(count, empty, showBars);
return h('div.cp-form-results-type-radio', rendered);
},
icon: h('i.cptools.cptools-form-list-check')
},
@ -1442,6 +1510,7 @@ define([
},
printResults: function (answers, uid, form) {
// results multicheckbox
var structure = form[uid];
if (!structure) { return; }
var opts = structure.opts || TYPES.multicheck.defaultOpts;
@ -1461,9 +1530,19 @@ define([
});
});
});
Object.keys(count).forEach(function (q_uid) {
var max = 0;
var count_keys = Object.keys(count);
count_keys.forEach(function (q_uid) {
var counts = Object.values(count[q_uid]);
counts.push(max);
max = arrayMax(counts);
});
count_keys.forEach(function (q_uid) {
var q = findItem(opts.items, q_uid);
var c = count[q_uid];
var values = Object.keys(c).map(function (res) {
return h('div.cp-form-results-type-radio-data', [
h('span.cp-value', res),
@ -1474,6 +1553,26 @@ define([
h('span.cp-mr-q', q),
h('span.cp-mr-value', values)
]));
/*
var table = Charts.table([
h('caption', {
style: 'color: var(--msg-color)',
}, q),
h('tbody', Object.keys(c).map(function (res) {
return Charts.row(res, c[res] / max, c[res]);
})),
], [
'charts-css',
'bar',
'show-heading',
'show-data-on-hover',
'show-labels',
]);
results.push(h('div.cp-form-results-type-multiradio-data', {
style: 'width: 100%',
}, table));
*/
});
results.push(getEmpty(empty));
@ -1507,7 +1606,16 @@ define([
var map = {};
var invMap = {};
var sorted = false;
Util.shuffleArray(opts.values);
if (!APP.isEditor) {
/* There is probably a more reliable check for this, but if we always
shuffle the values then authors reorder the results in the data structure
every time they reload. If multiple authors are present then this leads
to fights over what the content should be, which tends to trick chainpad
into concatenating strings, which quickly turns the sortable list
into complete nonsense.
*/
Util.shuffleArray(opts.values);
}
var els = opts.values.map(function (data) {
var uid = Util.uid();
map[uid] = data;
@ -1583,12 +1691,14 @@ define([
};
},
printResults: function (answers, uid, form) {
printResults: function (answers, uid, form, content) {
// results sort
var opts = form[uid].opts || TYPES.sort.defaultOpts;
var l = (opts.values || []).length;
var results = [];
//var results = [];
var empty = 0;
var count = {};
var showBars = Boolean(content);
Object.keys(answers).forEach(function (author) {
var obj = answers[author];
var answer = obj.msg[uid];
@ -1598,18 +1708,9 @@ define([
Util.inc(count, el, score);
});
});
var sorted = Object.keys(count).sort(function (a, b) {
return count[b] - count[a];
});
sorted.forEach(function (value) {
results.push(h('div.cp-form-results-type-radio-data', [
h('span.cp-value', value),
h('span.cp-count', count[value])
]));
});
results.push(getEmpty(empty));
return h('div.cp-form-results-type-radio', results);
var rendered = renderTally(count, empty, showBars);
return h('div.cp-form-results-type-radio', rendered);
},
icon: h('i.cptools.cptools-form-list-ordered')
},
@ -1754,10 +1855,77 @@ define([
},
};
var getDay = function (d) {
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
};
var ONE_DAY = 1000 * 60 * 60 * 24;
var getDayArray = function (a, b) {
// coerce inputs to numbers
var r_a = +getDay(new Date(a));
var r_b = +getDay(new Date(b));
var A = [ r_a ];
var next = r_a + ONE_DAY;
while (next <= r_b) {
A.push(next);
next += ONE_DAY;
}
return A;
};
Messages.form_timelineLabel = "{0} ({1})"; // TODO investigate whether this needs translation
var makeTimeline = APP.makeTimeline = function (answers) {
// Randomly changing date of answers to get a more realistic example of timeline
var tally = {};
//var answersByTime = {};
Object.keys(answers).forEach(function (curve) {
var obj = answers[curve];
var day = getDay(new Date(obj.time));
Util.inc(tally, +day);
});
var times = Object.keys(tally).map(Number).filter(Boolean);
var max_count = arrayMax(Util.values(tally));
var min_day = Math.min.apply(null, times);
var max_day = arrayMax(times);
var days = getDayArray(new Date(min_day), new Date(max_day));
if (days.length < 2) { return; }
return h('div.timeline-container', {
//style: 'width: 100%; height: 200px;',
}, h('table.cp-charts.column.cp-chart-timeline.cp-chart-table',
h('tbody', days.map(function (time) {
var count = tally[time] || 0;
var percent = count / max_count;
var date = new Date(time).toLocaleDateString();
var bar = h('td', {
style: '--size: ' + Number(percent).toFixed(2),
//"data-tippy-placement": "top",
title: Messages._getKey('form_timelineLabel', [date, count])
});
//var dateEl = h('th', { scope: "row" }, date);
return h('tr', bar/* dateEl*/ );
}))
)
);
};
var renderResults = APP.renderResults = function (content, answers, showUser) {
var $container = $('div.cp-form-creator-results').empty();
if (!Object.keys(answers || {}).length) {
var answerCount = Object.keys(answers || {}).length;
if (!answerCount) {
$container.append(h('div.alert.alert-info', Messages.form_results_empty));
return;
}
@ -1768,11 +1936,18 @@ define([
DiffMd.apply(DiffMd.render(content.answers.msg), $desc, APP.common);
}
var heading = h('h2#cp-title', Messages._getKey('form_totalResponses', [answerCount]));
$(heading).appendTo($container);
var timeline = h('div.cp-form-creator-results-timeline');
var $timeline = $(timeline).appendTo($container);
$timeline.append(makeTimeline(answers));
var controls = h('div.cp-form-creator-results-controls');
var $controls = $(controls).appendTo($container);
var exportButton = h('button.btn.btn-secondary', Messages.form_exportCSV);
var exportCSV = h('div.cp-form-creator-results-export', exportButton);
$(exportCSV).appendTo($container);
var exportButton = h('button.btn.btn-primary', [
h('i.fa.fa-download'),
Messages.form_exportCSV
]);
$(exportButton).appendTo($controls);
var results = h('div.cp-form-creator-results-content');
var $results = $(results).appendTo($container);
@ -1789,7 +1964,7 @@ define([
var summary = true;
var form = content.form;
var switchMode = h('button.btn.btn-primary', Messages.form_showIndividual);
var switchMode = h('button.btn.btn-secondary', Messages.form_showIndividual);
$controls.hide().append(switchMode);
var show = function (answers, header) {
@ -2564,11 +2739,11 @@ define([
var responseMsg = h('div.cp-form-response-msg-container');
var $responseMsg = $(responseMsg);
var refreshResponse = function () {
if (true) { return; } // XXX 4.10.0
if (true) { return; } // XXX 4.11.0
$responseMsg.empty();
Messages.form_updateMsg = "Update response message"; // XXX 4.10.0
Messages.form_addMsg = "Add response message"; // XXX 4.10.0
Messages.form_responseMsg = "Add a message that will be displayed in the response page."; // XXX 4.10.0
Messages.form_updateMsg = "Update response message"; // XXX 4.11.0
Messages.form_addMsg = "Add response message"; // XXX 4.11.0
Messages.form_responseMsg = "Add a message that will be displayed in the response page."; // XXX 4.11.0
var text = content.answers.msg ? Messages.form_updateMsg : Messages.form_addMsg;
var btn = h('button.btn.btn-secondary', text);
$(btn).click(function () {
@ -2597,7 +2772,7 @@ define([
name: Messages.settings_save,
onClick: function () {
var v = editor.getValue();
content.answers.msg = v.trim(0, 2000); // XXX 4.10.0 max length?
content.answers.msg = v.trim(0, 2000); // XXX 4.11.0 max length?
framework.localChange();
framework._.cpNfInner.chainpad.onSettle(function () {
UI.log(Messages.saved);
@ -2623,7 +2798,7 @@ define([
}
UI.openCustomModal(APP.responseModal);
});
// $responseMsg.append(btn); // XXX 4.10.0
// $responseMsg.append(btn); // XXX 4.11.0
};
//refreshResponse();

View File

@ -176,7 +176,7 @@ define([
validateKey: keys.secondaryValidateKey,
owners: [myKeys.edPublic],
crypto: crypto,
//Cache: Utils.Cache // XXX 4.10.0
//Cache: Utils.Cache // XXX 4.11.0
};
var results = {};
config.onError = function (info) {

View File

@ -353,6 +353,8 @@
}
#cp-kanban-controls {
//background-color: fade(@toolbar-bg-color-active, 50%); // FIXME ?
//color: @cp_toolbar-fg;
padding: 10px;
display: flex;
position: relative;
@ -545,7 +547,7 @@
#kanban-addboard {
order: 2;
width: 300px;
width: 50px;
margin: 10px 5px;
border: 1px solid @cp_kanban-fg;
color: @cp_kanban-fg;

View File

@ -1006,6 +1006,18 @@ define([
]);
$container.before(container);
var common = framework._.sfCommon;
var $button = common.createButton('toggle', true, {
element: $(container),
//icon: 'fa-tags', // FIXME
//text: Messages.fm_tagsName, // FIXME
}, function () {
$button.toggleClass('cp-toolbar-button-active');
});
$button.addClass('cp-toolbar-button-active');
framework._.toolbar.$bottomL.append($button);
onRedraw.reg(function () {
// Redraw if new tags have been added to items
var old = Sortify(existing);

View File

@ -1,4 +1,11 @@
This file is intended to be used as a log of what third-party source we have vendored, where we got it, and what modifications we have made to it (if any).
* [turndown v7.1.1](https://github.com/mixmark-io/turndown/releases/tag/v7.1.1) built from unmodified source as per its build scripts.
* [less.min.js v3.11.1](https://github.com/less/less.js/releases/tag/v3.11.1) with a minor modification to produce slightly more compact CSS
* [textFit.min.js v2.4.0 ](https://github.com/STRML/textFit/releases/tag/v2.4.0) to ensure that app names fit inside their icon containers on the home page
* [highlightjs](https://github.com/highlightjs/highlight.js/) for syntax highlighting in our code editor
* [our fork of tippy.js](https://github.com/xwiki-labs/tippyjs) for adding tooltips.
* [jscolor v2.0.5](https://jscolor.com/) for providing a consistent color picker across all browsers
* [jquery.ui 1.12.1](https://jqueryui.com/) for its 'autocomplete' extension which is used for our tag picker
* [pdfjs](https://mozilla.github.io/pdf.js/) with some minor modifications to prevent CSP errors

View File

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Some files were not shown because too many files have changed in this diff Show More