diff --git a/bower.json b/bower.json index 0cabd2b5f..2b9c05687 100644 --- a/bower.json +++ b/bower.json @@ -43,7 +43,8 @@ "nthen": "^0.1.5", "open-sans-fontface": "^1.4.2", "bootstrap-tokenfield": "^0.12.1", - "localforage": "^1.5.2" + "localforage": "^1.5.2", + "html2canvas": "^0.4.1" }, "resolutions": { "bootstrap": "v4.0.0-alpha.6" diff --git a/customize.dist/application_config.js b/customize.dist/application_config.js index 9cf29d565..079c36eab 100644 --- a/customize.dist/application_config.js +++ b/customize.dist/application_config.js @@ -12,6 +12,7 @@ define(function() { * You can change their duration here (measured in milliseconds) */ config.notificationTimeout = 5000; + config.disableUserlistNotifications = false; config.enablePinning = true; diff --git a/customize.dist/pages.js b/customize.dist/pages.js index 793f2133e..cc11f1be2 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -76,7 +76,7 @@ define([ ]) ]) ]), - h('div.cp-version-footer', "CryptPad v1.18.0 (Snallygaster)") + h('div.cp-version-footer', "CryptPad v1.19.0 (Tarasque)") ]); }; @@ -728,7 +728,7 @@ define([ Pages['/profile/'] = Pages['/profile/index.html'] = function () { return [ - h('div#toolbar'), + h('div#cp-toolbar'), h('div#container'), loadingScreen() ]; diff --git a/customize.dist/src/less/variables.less b/customize.dist/src/less/variables.less index 4d804abea..1d3415d89 100644 --- a/customize.dist/src/less/variables.less +++ b/customize.dist/src/less/variables.less @@ -102,9 +102,9 @@ @category-bg: #f4f4f4; -@button-bg: #3066e5; -@button-alt-bg: #fff; -@button-red-bg: #e54e4e; +@button-bg: @colortheme_sidebar-button-bg; +@button-alt-bg: @colortheme_sidebar-button-alt-bg; +@button-red-bg: @colortheme_sidebar-button-red-bg; .unselectable () { -webkit-touch-callout: none; diff --git a/customize.dist/src/less2/include/colortheme.less b/customize.dist/src/less2/include/colortheme.less index e5e57cc74..4893f5fa2 100644 --- a/customize.dist/src/less2/include/colortheme.less +++ b/customize.dist/src/less2/include/colortheme.less @@ -41,6 +41,7 @@ @colortheme_pad-bg: #1c4fa0; @colortheme_pad-color: #fff; +@colortheme_pad-toolbar-bg: #c1e7ff; @colortheme_slide-bg: #e57614; @colortheme_slide-color: #fff; @@ -50,6 +51,9 @@ @colortheme_poll-bg: #006304; @colortheme_poll-color: #fff; +@colortheme_poll-help-bg: #bbffbb; +@colortheme_poll-th-bg: #005bef; +@colortheme_poll-th-fg: #fff; @colortheme_whiteboard-bg: #800080; @colortheme_whiteboard-color: #fff; @@ -60,7 +64,7 @@ @colortheme_file-bg: #cd2532; @colortheme_file-color: #fff; -@colortheme_friends-bg: #607B8D; +@colortheme_friends-bg: #607b8d; @colortheme_friends-color: #fff; @colortheme_default-bg: #ddd; @@ -75,7 +79,7 @@ @colortheme_todo-bg: #7bccd1; @colortheme_todo-color: #000; -// Sidebar layout +// Sidebar layout (profile / settings) @colortheme_sidebar-active: #fff; @colortheme_sidebar-left-bg: #eee; @colortheme_sidebar-left-fg: #000; @@ -83,7 +87,9 @@ @colortheme_sidebar-right-bg: #fff; @colortheme_sidebar-right-fg: #000; @colortheme_sidebar-description: #777; - +@colortheme_sidebar-button-bg: #3066e5; +@colortheme_sidebar-button-red-bg: #e54e4e; +@colortheme_sidebar-button-alt-bg: #fff; @cryptpad_color_blue: #4591C4; @cryptpad_color_grey: #999999; diff --git a/customize.dist/src/less2/include/icon-colors.less b/customize.dist/src/less2/include/icon-colors.less index 345a48a9a..db9de2a14 100644 --- a/customize.dist/src/less2/include/icon-colors.less +++ b/customize.dist/src/less2/include/icon-colors.less @@ -13,5 +13,18 @@ .cp-icon-color-profile { color: @colortheme_settings-bg; } .cp-icon-color-default { color: @colortheme_default-bg; } .cp-icon-color-todo { color:@colortheme_todo-bg; } + + .cp-border-color-pad { border-color: @colortheme_pad-bg !important; } + .cp-border-color-code { border-color: @colortheme_code-bg !important; } + .cp-border-color-slide { border-color: @colortheme_slide-bg !important; } + .cp-border-color-poll { border-color: @colortheme_poll-bg !important; } + .cp-border-color-file { border-color: @colortheme_file-bg !important; } + .cp-border-color-contacts { border-color: @colortheme_friends-bg !important; } + .cp-border-color-whiteboard { border-color: @colortheme_whiteboard-bg !important; } + .cp-border-color-drive { border-color: @colortheme_drive-bg !important; } + .cp-border-color-settings { border-color: @colortheme_settings-bg !important; } + .cp-border-color-profile { border-color: @colortheme_settings-bg !important; } + .cp-border-color-default { border-color: @colortheme_default-bg !important; } + .cp-border-color-todo { border-color:@colortheme_todo-bg !important; } } diff --git a/customize.dist/src/less2/include/sidebar-layout.less b/customize.dist/src/less2/include/sidebar-layout.less new file mode 100644 index 000000000..e0bec9dcf --- /dev/null +++ b/customize.dist/src/less2/include/sidebar-layout.less @@ -0,0 +1,99 @@ +@import (once) "/customize/src/less2/include/colortheme.less"; +@import (once) "/customize/src/less2/include/leftside-menu.less"; + +@leftside-bg: @colortheme_sidebar-left-bg; +@leftside-color: @colortheme_sidebar-left-fg; +@rightside-color: @colortheme_sidebar-right-fg; +@description-color: @colortheme_sidebar-description; + +@button-width: 400px; + + +.sidebar-layout_main() { + input[type="text"] { + padding-left: 10px; + } + #cp-sidebarlayout-container { + font-size: 16px; + display: flex; + flex: 1; + min-height: 0; + #cp-sidebarlayout-leftside { + color: @leftside-color; + width: 250px; + background: @leftside-bg; + display: flex; + flex-flow: column; + .cp-sidebarlayout-categories { + flex: 1; + .cp-sidebarlayout-category { + .leftside-menu-category_main(); + } + } + } + #cp-sidebarlayout-rightside { + flex: 1; + padding: 5px 20px; + color: @rightside-color; + overflow: auto; + + // Following rules are only in settings + .element { + label:not(.noTitle), .label { + display: block; + font-weight: bold; + margin-bottom: 0; + } + .description { + display: block; + color: @description-color; + margin-bottom: 5px; + } + margin-bottom: 20px; + } + [type="text"], button { + vertical-align: middle; + height: 40px; + box-sizing: border-box; + } + .inputBlock { + display: inline-flex; + width: @button-width; + input { + flex: 1; + border-radius: 0.25em 0 0 0.25em; + border: 1px solid #adadad; + border-right: 0px; + } + button { + border-radius: 0 0.25em 0.25em 0; + //border: 1px solid #adadad; + border-left: 0px; + } + } + &>div { + margin: 10px 0; + } + button.btn { + @button-bg: @colortheme_sidebar-button-bg; + @button-red-bg: @colortheme_sidebar-button-red-bg; + background-color: @button-bg; + border-color: darken(@button-bg, 10%); + color: white; + &:hover { + background-color: darken(@button-bg, 10%); + } + &.btn-danger { + background-color: @button-red-bg; + border-color: darken(@button-red-bg, 10%); + color: white; + &:hover { + background-color: darken(@button-red-bg, 10%); + } + } + } + } + } +} + + diff --git a/customize.dist/src/less2/main.less b/customize.dist/src/less2/main.less index 85a906902..38c242b10 100644 --- a/customize.dist/src/less2/main.less +++ b/customize.dist/src/less2/main.less @@ -33,4 +33,6 @@ body.cp-app-filepicker { @import "../../../filepicker/app-filepicker.less"; } body.cp-app-contacts { @import "../../../contacts/app-contacts.less"; } body.cp-app-poll { @import "../../../poll/app-poll.less"; } body.cp-app-whiteboard { @import "../../../whiteboard/app-whiteboard.less"; } +body.cp-app-todo { @import "../../../todo/app-todo.less"; } +body.cp-app-profile { @import "../../../profile/app-profile.less"; } diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index 06fb7f13b..a94907da8 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -44,6 +44,7 @@ define(function () { out.typing = "Édition"; out.initializing = "Initialisation..."; out.forgotten = 'Déplacé vers la corbeille'; + out.errorState = 'Erreur critique : {0}'; out.lag = 'Latence'; out.readonly = 'Lecture seule'; out.anonymous = "Anonyme"; @@ -56,6 +57,7 @@ define(function () { out.viewers = "lecteurs"; out.editor = "éditeur"; out.editors = "éditeurs"; + out.userlist_offline = "Vous êtes actuellement hors-ligne, la liste des utilisateurs n'est pas disponible."; out.language = "Langue"; @@ -359,8 +361,8 @@ define(function () { out.fm_openParent = "Montrer dans le dossier"; out.fm_noname = "Document sans titre"; out.fm_emptyTrashDialog = "Êtes-vous sûr de vouloir vider la corbeille ?"; - out.fm_removeSeveralPermanentlyDialog = "Êtes-vous sûr de vouloir supprimer ces {0} éléments de manière permanente ?"; - out.fm_removePermanentlyDialog = "Êtes-vous sûr de vouloir supprimer cet élément de manière permanente ?"; + out.fm_removeSeveralPermanentlyDialog = "Êtes-vous sûr de vouloir supprimer ces {0} éléments de votre CryptDrive de manière permanente ?"; + out.fm_removePermanentlyDialog = "Êtes-vous sûr de vouloir supprimer cet élément de votre CryptDrive de manière permanente ?"; out.fm_restoreDialog = "Êtes-vous sûr de vouloir restaurer {0} à son emplacement précédent ?"; out.fm_removeSeveralDialog = "Êtes-vous sûr de vouloir déplacer ces {0} éléments vers la corbeille ?"; out.fm_removeDialog = "Êtes-vous sûr de vouloir déplacer {0} vers la corbeille ?"; @@ -397,9 +399,9 @@ define(function () { out.fc_rename = "Renommer"; out.fc_open = "Ouvrir"; out.fc_open_ro = "Ouvrir (lecture seule)"; - out.fc_delete = "Supprimer"; + out.fc_delete = "Déplacer vers la corbeille"; out.fc_restore = "Restaurer"; - out.fc_remove = "Supprimer définitivement"; + out.fc_remove = "Supprimer de votre CryptDrive"; out.fc_empty = "Vider la corbeille"; out.fc_prop = "Propriétés"; out.fc_hashtag = "Mots-clés"; @@ -486,6 +488,13 @@ define(function () { out.settings_resetTipsButton = "Réinitialiser les astuces visibles dans CryptDrive"; out.settings_resetTipsDone = "Toutes les astuces sont de nouveau visibles."; + out.settings_thumbnails = "Vignettes"; + out.settings_disableThumbnailsAction = "Désactiver la création de vignettes dans CryptDrive"; + out.settings_disableThumbnailsDescription = "Des vignettes de vos pads sont automatiquement créées et stockées dans votre navigateur. Vous pouvez désactiver cette fonctionnalité."; + out.settings_resetThumbnailsAction = "Nettoyer"; + out.settings_resetThumbnailsDescription = "Nettoyer toutes les vignettes stockées dans votre navigateur."; + out.settings_resetThumbnailsDone = "Toutes les vignettes ont été effacées."; + out.settings_importTitle = "Importer les pads récents de ce navigateur dans votre CryptDrive"; out.settings_import = "Importer"; out.settings_importConfirm = "Êtes-vous sûr de vouloir importer les pads récents de ce navigateur dans le CryptDrive de votre compte utilisateur ?"; diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index 9e9531627..29735e18f 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -43,9 +43,10 @@ define(function () { out.disconnected = 'Disconnected'; out.synchronizing = 'Synchronizing'; out.reconnecting = 'Reconnecting...'; - out.typing = "Typing"; + out.typing = "Editing"; out.initializing = "Initializing..."; out.forgotten = 'Moved to the trash'; + out.errorState = 'Critical error: {0}'; out.lag = 'Lag'; out.readonly = 'Read only'; out.anonymous = "Anonymous"; @@ -58,6 +59,7 @@ define(function () { out.viewers = "viewers"; out.editor = "editor"; out.editors = "editors"; + out.userlist_offline = "You're currently offline, the user list is not available."; out.language = "Language"; @@ -361,8 +363,8 @@ define(function () { out.fm_openParent = "Show in folder"; out.fm_noname = "Untitled Document"; out.fm_emptyTrashDialog = "Are you sure you want to empty the trash?"; - out.fm_removeSeveralPermanentlyDialog = "Are you sure you want to remove these {0} elements from the trash permanently?"; - out.fm_removePermanentlyDialog = "Are you sure you want to remove that element permanently?"; + out.fm_removeSeveralPermanentlyDialog = "Are you sure you want to remove these {0} elements from your CryptDrive permanently?"; + out.fm_removePermanentlyDialog = "Are you sure you want to remove that element from your CryptDrive permanently?"; out.fm_removeSeveralDialog = "Are you sure you want to move these {0} elements to the trash?"; out.fm_removeDialog = "Are you sure you want to move {0} to the trash?"; out.fm_restoreDialog = "Are you sure you want to restore {0} to its previous location?"; @@ -399,9 +401,9 @@ define(function () { out.fc_rename = "Rename"; out.fc_open = "Open"; out.fc_open_ro = "Open (read-only)"; - out.fc_delete = "Delete"; + out.fc_delete = "Move to trash"; out.fc_restore = "Restore"; - out.fc_remove = "Delete permanently"; + out.fc_remove = "Remove from your CryptDrive"; out.fc_empty = "Empty the trash"; out.fc_prop = "Properties"; out.fc_hashtag = "Tags"; @@ -491,6 +493,13 @@ define(function () { out.settings_resetTipsButton = "Reset the available tips in CryptDrive"; out.settings_resetTipsDone = "All the tips are now visible again."; + out.settings_thumbnails = "Thumbnails"; + out.settings_disableThumbnailsAction = "Disable thumbnails creation in your CryptDrive"; + out.settings_disableThumbnailsDescription = "Thumbnails are automatically created and stored in your browser when you visit a new pad. You can disable this feature here."; + out.settings_resetThumbnailsAction = "Clean"; + out.settings_resetThumbnailsDescription = "Clean all the pads thumbnails stored in your browser."; + out.settings_resetThumbnailsDone = "All the thumbnails have been erased."; + out.settings_importTitle = "Import this browser's recent pads in your CryptDrive"; out.settings_import = "Import"; out.settings_importConfirm = "Are you sure you want to import recent pads from this browser to your user account's CryptDrive?"; diff --git a/package.json b/package.json index 3cc3a4873..14bb2c321 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cryptpad", "description": "realtime collaborative visual editor with zero knowlege server", - "version": "1.18.0", + "version": "1.19.0", "dependencies": { "chainpad-server": "^1.0.1", "express": "~4.10.1", diff --git a/www/assert/main.js b/www/assert/main.js index 0913674ae..3eb9e5892 100644 --- a/www/assert/main.js +++ b/www/assert/main.js @@ -7,7 +7,8 @@ define([ '/drive/tests.js', '/common/test.js', '/common/common-thumbnail.js', -], function ($, Hyperjson, TextPatcher, Sortify, Cryptpad, Drive, Test, Thumb) { + '/common/flat-dom.js', +], function ($, Hyperjson, TextPatcher, Sortify, Cryptpad, Drive, Test, Thumb, Flat) { window.Hyperjson = Hyperjson; window.TextPatcher = TextPatcher; window.Sortify = Sortify; @@ -236,11 +237,20 @@ define([ !secret.hashData.present); }, "test support for trailing slashes in version 1 hash failed to parse"); + assert(function (cb) { + var secret = Cryptpad.parsePadUrl('/invite/#/1/ilrOtygzDVoUSRpOOJrUuQ/e8jvf36S3chzkkcaMrLSW7PPrz7VDp85lIFNI26dTmr=/'); + var hd = secret.hashData; + cb(hd.channel === "ilrOtygzDVoUSRpOOJrUuQ" && + hd.pubkey === "e8jvf36S3chzkkcaMrLSW7PPrz7VDp85lIFNI26dTmr=" && + hd.type === 'invite'); + }, "test support for invite urls"); + assert(function (cb) { // TODO return cb(true); }, "version 2 hash failed to parse correctly"); +/* assert(function (cb) { var getBlob = function (url, cb) { var xhr = new XMLHttpRequest(); @@ -266,9 +276,21 @@ define([ }); }); }); +*/ Drive.test(assert); + assert(function (cb) { + // extract dom elements into a flattened JSON representation + var flat = Flat.fromDOM(document.body); + // recreate a _mostly_ equivalent DOM + var dom = Flat.toDOM(flat); + // assume we don't care about comments + var bodyText = document.body.outerHTML.replace(//g, ''); + // check for equality + cb(dom.outerHTML === bodyText); + }); + var swap = function (str, dict) { return str.replace(/\{\{(.*?)\}\}/g, function (all, key) { return typeof dict[key] !== 'undefined'? dict[key] : all; diff --git a/www/code/inner.html b/www/code/inner.html index 5d914b6c8..327363fd0 100644 --- a/www/code/inner.html +++ b/www/code/inner.html @@ -6,6 +6,7 @@
diff --git a/www/code/inner.js b/www/code/inner.js index d5d7edfdd..5f2cf3df1 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -145,6 +145,10 @@ define([ $codeMirror.addClass('cp-app-code-fullpage'); }; + var isVisible = function () { + return $previewContainer.is(':visible'); + }; + framework.onReady(function () { // add the splitter var splitter = $('