Compare commits
109 Commits
b1281fb4ab
...
24a1d1b622
Author | SHA1 | Date |
---|---|---|
ansuz | 24a1d1b622 | |
dependabot[bot] | 589a09e721 | |
ansuz | 58eb65e35d | |
ansuz | 8887d8fc1e | |
ansuz | 554ce65346 | |
ansuz | 09bdcb2013 | |
ansuz | 47067b020b | |
ansuz | 09f0b8f61e | |
Weblate | 89b52b6110 | |
ansuz | c1f9d11333 | |
ansuz | 3976bfae84 | |
ansuz | cad514cc17 | |
ansuz | 1e12b85b7c | |
ansuz | b0539fe613 | |
ansuz | 1485c62746 | |
ansuz | 11bcdbd7e3 | |
ansuz | c1a19ea65c | |
ansuz | add234a8f7 | |
ansuz | ad0d2ab3b7 | |
ansuz | 69a393f374 | |
ansuz | 9b3cd7dae3 | |
ansuz | b7f627d896 | |
ansuz | 04234aa1f4 | |
ansuz | f701e30364 | |
ansuz | f12a276c78 | |
ansuz | a779d043ca | |
ansuz | 4810d6b5ba | |
ansuz | 25a3359671 | |
ansuz | 375bf7a62e | |
ansuz | e4879b5117 | |
ansuz | 036248a659 | |
ansuz | 8d17ae64f3 | |
ansuz | 6413be24f3 | |
ansuz | 7f41f8765e | |
ansuz | 975259f935 | |
ansuz | 7e80b90bca | |
Weblate | afdfc273e8 | |
ansuz | 72bf3696ee | |
ansuz | 384d4be864 | |
David Benqué | ddee1e9b40 | |
David Benqué | d05f03c8c6 | |
David Benqué | fc4178df7e | |
ansuz | 44f5aee4ac | |
ansuz | 44688026d6 | |
ansuz | 59aefef2ad | |
ansuz | 2a8c70598b | |
ansuz | 2dc4ec1b24 | |
ansuz | 7647a60219 | |
ansuz | d8af3a16ab | |
ansuz | b9eced7bfd | |
ansuz | 1c08a27f60 | |
ansuz | d960c10a31 | |
ansuz | a33774aa6f | |
Weblate | 17ea1611e7 | |
Weblate | 61df9214ff | |
ansuz | b0fcaf8e51 | |
Weblate | 6a4f02831e | |
Weblate | 55a8c94eb4 | |
ansuz | b5c051a27f | |
ansuz | 30c2bfbdfa | |
ansuz | d6886fb4c0 | |
ansuz | 900db1fcb0 | |
ansuz | e4d5431f29 | |
ansuz | 34aa959a10 | |
ansuz | acd7148967 | |
ansuz | ed8c2f4319 | |
aemi-dev | 9910c97d5e | |
ansuz | ded834b2c7 | |
ansuz | 4a80007fea | |
aemi-dev | 085736e4b7 | |
aemi-dev | 3ba0f4d0b8 | |
aemi-dev | b365c411ea | |
aemi-dev | 11dc7d12d5 | |
ansuz | 53ba25b5b0 | |
ansuz | 73acfd9b42 | |
ansuz | 2d405b5a32 | |
ansuz | d9b6d94580 | |
ansuz | 4800ac724e | |
ansuz | 93f73add9f | |
ansuz | 9ecb9e4cd6 | |
ansuz | 98df612eb4 | |
Weblate | 0a216e4c96 | |
Weblate | d2ff6d4eee | |
ansuz | c2ad600ef9 | |
ansuz | 18c439986c | |
ansuz | 4e02c309bb | |
ansuz | 51b57f0341 | |
ansuz | f141fdef3b | |
ansuz | 0497d663b6 | |
ansuz | 97646fdb89 | |
ansuz | d8a7e4aa2a | |
ansuz | 298d69e914 | |
ansuz | 22357f882b | |
ansuz | a20bfbf6c1 | |
ansuz | 053224a825 | |
Weblate | d67d6069d4 | |
ansuz | 48ad82c4fb | |
ansuz | 7885a3ff5b | |
ansuz | ceab8fe2df | |
ansuz | dd53b6fa72 | |
ansuz | 613868bbde | |
ansuz | 7ed41aa8e6 | |
ansuz | f4e2e505fe | |
ansuz | b6cc4ef8cf | |
ansuz | c6fefd73d8 | |
Weblate | 1247ed0b6b | |
ansuz | d926930b4c | |
ansuz | f0eef49522 | |
ansuz | 8bdccbdcb0 |
|
@ -22,4 +22,4 @@ block/
|
|||
logs/
|
||||
privileged.conf
|
||||
config/config.js
|
||||
*yolo.sh
|
||||
*.sh
|
||||
|
|
|
@ -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
|
||||
|
|
57
CHANGELOG.md
57
CHANGELOG.md
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: {},
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;",
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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(){
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
});
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()));
|
|
@ -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") {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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('');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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)}});
|
|
@ -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'
|
||||
], {});
|
||||
|
|
|
@ -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ó",
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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}"
|
||||
}
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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": "折りたたむ"
|
||||
}
|
||||
|
|
|
@ -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}"
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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?",
|
||||
|
|
|
@ -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ą"
|
||||
|
|
|
@ -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 URL’s 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",
|
||||
|
|
|
@ -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.",
|
||||
|
|
|
@ -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": "Владельцы",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -208,7 +208,7 @@
|
|||
"upload_pending": "待處理",
|
||||
"upload_cancelled": "已取消的",
|
||||
"upload_size": "大小",
|
||||
"footer_aboutUs": "關於 Cryptpad",
|
||||
"footer_aboutUs": "關於 CryptPad",
|
||||
"about": "關於",
|
||||
"privacy": "隱私",
|
||||
"contact": "聯繫",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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'];
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
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
Loading…
Reference in New Issue