diff --git a/customize.dist/src/less2/include/drive.less b/customize.dist/src/less2/include/drive.less index 7c428a3de..0eb400587 100644 --- a/customize.dist/src/less2/include/drive.less +++ b/customize.dist/src/less2/include/drive.less @@ -716,6 +716,9 @@ } } } + .cp-app-drive-element-state { + display: none !important; + } } } .cp-app-drive-element { @@ -729,6 +732,9 @@ .cp-app-drive-element-type, .cp-app-drive-element-filler { display: none !important; } + .cp-app-drive-element-sort { + display: block !important; + } } @media screen and (max-width: 740px) { @@ -744,9 +750,6 @@ .cp-app-drive-element-header .cp-app-drive-element-state { display: none !important; } - .cp-app-drive-element-sort { - display: block !important; - } } } @@ -902,126 +905,6 @@ } } - /* Toolbar */ - - // XXX remove, preserve drive path? - #cp-app-drive-toolbar { - background: @colortheme_drive-bg-light; - color: @colortheme_drive-color; - //height: 30px; - //display: flex; - //flex-flow: row; - z-index: 100; - box-sizing: border-box; - height: @variables_bar-height; - padding: 0; - display: flex; - flex-flow: row; - - * { - outline-width: 0; - &:focus { - outline-width: 0; - } - } - - .cp-toolbar-icon-history { - float: right; - &.active { - background-color: rgba(0, 0, 255, 0.2); - } - .cp-toolbar-drawer-element { - display: none; - } - } - - .cp-app-drive-toolbar-rightside, .cp-app-drive-toolbar-leftside { - display: inline-block; - margin: 0; - padding: 0; - .fa, .cptools { - margin: 0; - vertical-align: top; - } - button { - height: @variables_bar-height !important; - padding: 0 10px; - border: none; - border-radius: 0; - box-sizing: border-box; - background: transparent; - font-size: @colortheme_app-font-size; - color: @colortheme_drive-color; - transition: all 0.15s; - display: inline-flex; - align-items: center; - .drawer { - display: none; - } - .fa, .cptools, span { - font-size: @colortheme_app-font-size; - } - &:hover { - background: @colortheme_drive-bg-active; - } - &.cp-app-drive-toolbar-active { - display: none; - } - } - } - .cp-app-drive-toolbar-rightside { - float: right; - flex-shrink: 0; - & > * { - float: right; - } - #cp-app-drive-toolbar-contextbuttons { - display: inline-block; - height: 100%; - } - padding-left: 10px; - } - .cp-app-drive-toolbar-leftside { - flex-shrink: 0; - & > span { - height: 100%; - margin: 0; - } - button { - padding: 0 10px; - .fa, .cptools { - margin-right: 5px; - } - .cp-dropdown-button-title { - display: inline-flex; - height: @variables_bar-height; - align-items: center; - span:not(.fa):not(.cptools) { - line-height: 23px; - } - } - } - } - - button { - font: @colortheme_app-font; - span { - font: @colortheme_app-font; - } - .fa, &.fa { - font-family: FontAwesome; - } - .cptools, &.cptools { - font-family: cptools; - } - } - - - .cp-app-drive-toolbar-filler { - flex: 1; - } - } - #cp-app-drive-edition-state { height: @variables_bar-height; display: flex; diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 0c26c0e3b..985f6bd83 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -949,10 +949,6 @@ } } - .cp-dropdown-content { - margin-top: -1px; - } - & > span { height: @toolbar_line-height; } diff --git a/www/code/markers.js b/www/code/markers.js index fb67736a6..b070e68fc 100644 --- a/www/code/markers.js +++ b/www/code/markers.js @@ -622,30 +622,9 @@ define([ }); }; - var authorUid = function (existing) { - if (!Array.isArray(existing)) { existing = []; } - var n; - var i = 0; - while (!n || existing.indexOf(n) !== -1 && i++ < 1000) { - n = Math.floor(Math.random() * 1000000); - } - // If we can't find a valid number in 1000 iterations, use 0... - if (existing.indexOf(n) !== -1) { n = 0; } - return n; - }; var getAuthorId = function (Env) { - var existing = Object.keys(Env.authormarks.authors || {}).map(Number); - if (!Env.common.isLoggedIn()) { return authorUid(existing); } - var userData = Env.common.getMetadataMgr().getUserData(); - var uid; - existing.some(function (id) { - var author = Env.authormarks.authors[id] || {}; - if (author.curvePublic !== userData.curvePublic) { return; } - uid = Number(id); - return true; - }); - return uid || authorUid(existing); + return Env.common.getAuthorId(Env.authormarks.authors, userData.curvePublic); }; var ready = function (Env) { Env.ready = true; diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 5d9f38077..ef1f13ca2 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -2141,8 +2141,17 @@ define([ var show = function () { var wh = $(window).height(); - var topPos = $container[0].getBoundingClientRect().bottom; - $innerblock.css('max-height', Math.floor(wh - topPos - 1)+'px'); + var button = $button[0].getBoundingClientRect(); + var topPos = button.bottom; + $innerblock.css('bottom', ''); + if (config.noscroll) { + var h = $innerblock.outerHeight(); + if ((topPos + h) > wh) { + $innerblock.css('bottom', button.height+'px'); + } + } else { + $innerblock.css('max-height', Math.floor(wh - topPos - 1)+'px'); + } $innerblock.show(); $innerblock.find('.cp-dropdown-element-active').removeClass('cp-dropdown-element-active'); if (config.isSelect && value) { @@ -2157,6 +2166,11 @@ define([ e.stopPropagation(); var state = $innerblock.is(':visible'); $('.cp-dropdown-content').hide(); + + var $c = $container.closest('.cp-toolbar-drawer-content'); + $c.removeClass('cp-dropdown-visible'); + if (!state) { $c.addClass('cp-dropdown-visible'); } + try { $('iframe').each(function (idx, ifrw) { $(ifrw).contents().find('.cp-dropdown-content').hide(); diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 991fe5cc4..a92e383d1 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -1207,9 +1207,6 @@ define([ if ($element.is('.cp-app-drive-element-notrash')) { // We can't delete elements in virtual categories hide.push('delete'); - } else { - // We can only open parent in virtual categories - hide.push('openparent'); } if (!$element.is('.cp-border-color-file')) { //hide.push('download'); @@ -1310,6 +1307,10 @@ define([ hide.push('open'); } + if (!APP.loggedIn) { + hide.push('openparent'); + } + filter = function ($el, className) { if (hide.indexOf(className) !== -1) { return true; } }; @@ -1325,7 +1326,7 @@ define([ 'deleteowned', 'removesf', 'access', 'properties', 'hashtag']; break; case 'default': - show = ['open', 'openro', 'preview', 'share', 'openparent', 'delete', 'deleteowned', 'properties', 'access', 'hashtag', 'makeacopy']; + show = ['open', 'openro', 'preview', 'openincode', 'share', 'download', 'openparent', 'delete', 'deleteowned', 'properties', 'access', 'hashtag', 'makeacopy', 'savelocal', 'rename']; break; case 'trashtree': { show = ['empty']; @@ -2117,7 +2118,7 @@ define([ onElementClick(e, $element); }); if (!isTrash) { - $element.contextmenu(openContextMenu('tree')); + $element.on('contextmenu', openContextMenu('tree')); $element.data('context', 'tree'); } else { $element.contextmenu(openContextMenu('trash')); @@ -2747,21 +2748,22 @@ define([ var options = [{ tag: 'a', attributes: {'class': 'cp-app-drive-element-type'}, - content: Messages.fm_type + content: '' + Messages.fm_type },{ tag: 'a', attributes: {'class': 'cp-app-drive-element-atime'}, - content: Messages.fm_lastAccess + content: '' + Messages.fm_lastAccess },{ tag: 'a', attributes: {'class': 'cp-app-drive-element-ctime'}, - content: Messages.fm_creation + content: '' + Messages.fm_creation }]; var dropdownConfig = { text: '', // Button initial text options: options, // Entries displayed in the menu container: $fhSort, left: true, + noscroll: true, common: common }; var $sortBlock = UIElements.createDropdown(dropdownConfig); @@ -2804,7 +2806,7 @@ define([ if (APP.store[SORT_FILE_BY] === '') { classSorted = 'cp-app-drive-sort-filename'; } else if (APP.store[SORT_FILE_BY]) { classSorted = 'cp-app-drive-element-' + APP.store[SORT_FILE_BY]; } if (classSorted) { - $list.find('.' + classSorted).addClass('cp-app-drive-sort-active').prepend($icon); + $list.find('.' + classSorted).addClass('cp-app-drive-sort-active').prepend($icon).find('i').hide(); } }; var getFileListHeader = function (clickable) { @@ -3312,6 +3314,7 @@ define([ } // Display the pad + /* var $icon = getFileIcon(id); var ro = manager.isReadOnlyFile(id); // ro undefined means it's an old hash which doesn't support read-only @@ -3319,21 +3322,13 @@ define([ ro ? ' cp-app-drive-element-readonly' : ''; var $element = $('
  • ', { 'class': 'cp-app-drive-element cp-app-drive-element-notrash cp-app-drive-element-file cp-app-drive-element-row' + roClass, - }); - $element.prepend($icon).dblclick(function () { - openFile(id); - }); - addFileData(id, $element); - $element.data('path', path); - $element.click(function(e) { - e.stopPropagation(); - onElementClick(e, $element); - }); - $element.contextmenu(openContextMenu('default')); + });*/ + var parentPath = path.slice(); + var key = parentPath.pop(); + var root = manager.find(parentPath); + var $element = createElement(parentPath, key, root); + $element.off('contextmenu').contextmenu(openContextMenu('default')); $element.data('context', 'default'); - /*if (draggable) { - addDragAndDropHandlers($element, path, false, false); - }*/ $list.append($element); i++; }); diff --git a/www/common/sframe-app-framework.js b/www/common/sframe-app-framework.js index e690bfb08..6e10b0a77 100644 --- a/www/common/sframe-app-framework.js +++ b/www/common/sframe-app-framework.js @@ -433,21 +433,37 @@ define([ var ext = (typeof(extension) === 'function') ? extension() : extension; var suggestion = title.suggestTitle('cryptpad-document'); ext = ext || '.txt'; - var types = [{ - tag: 'a', - attributes: { - 'data-value': ext, - 'href': '#' - }, - content: ext - }, { + var types = []; + if (Array.isArray(ext) && ext.length) { + ext.forEach(function (_ext) { + types.push({ + tag: 'a', + attributes: { + 'data-value': _ext, + 'href': '#' + }, + content: _ext + }); + }); + ext = ext[0]; + } else { + types.push({ + tag: 'a', + attributes: { + 'data-value': ext, + 'href': '#' + }, + content: ext + }); + } + types.push({ tag: 'a', attributes: { 'data-value': '', 'href': '#' }, content: ' ' - }]; + }); var dropdownConfig = { text: ext, // Button initial text caretDown: true, @@ -461,14 +477,15 @@ define([ Util.fixFileName(suggestion), function (filename) { if (!(typeof(filename) === 'string' && filename)) { return; } - filename = filename + $select.getValue(); + var ext = $select.getValue(); + filename = filename + ext; if (async) { fe(function (blob) { SaveAs(blob, filename); - }); + }, ext); return; } - var blob = fe(); + var blob = fe(null, ext); SaveAs(blob, filename); }, { typeInput: $select[0] diff --git a/www/common/sframe-common-codemirror.js b/www/common/sframe-common-codemirror.js index fe251e696..02e3867ec 100644 --- a/www/common/sframe-common-codemirror.js +++ b/www/common/sframe-common-codemirror.js @@ -311,14 +311,7 @@ define([ common: Common }; var $block = exp.$language = UIElements.createDropdown(dropdownConfig); - $block.find('button').attr('title', Messages.languageButtonTitle).click(function () { - var state = $block.find('.cp-dropdown-content').is(':visible'); - var $c = $block.closest('.cp-toolbar-drawer-content'); - $c.removeClass('cp-dropdown-visible'); - if (!state) { - $c.addClass('cp-dropdown-visible'); - } - }); + $block.find('button').attr('title', Messages.languageButtonTitle); var isHovering = false; var $aLanguages = $block.find('a'); diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js index 4fe715cf9..3d5df4f03 100644 --- a/www/common/sframe-common.js +++ b/www/common/sframe-common.js @@ -202,6 +202,33 @@ define([ }; }; + funcs.getAuthorId = function () { + }; + + var authorUid = function(existing) { + if (!Array.isArray(existing)) { existing = []; } + var n; + var i = 0; + while (!n || existing.indexOf(n) !== -1 && i++ < 1000) { + n = Math.floor(Math.random() * 1000000); + } + // If we can't find a valid number in 1000 iterations, use 0... + if (existing.indexOf(n) !== -1) { n = 0; } + return n; + }; + funcs.getAuthorId = function(authors, curve) { + var existing = Object.keys(authors || {}).map(Number); + if (!funcs.isLoggedIn()) { return authorUid(existing); } + + var uid; + existing.some(function(id) { + var author = authors[id] || {}; + if (author.curvePublic !== curve) { return; } + uid = Number(id); + return true; + }); + return uid || authorUid(existing); + }; // Chat var padChatChannel; diff --git a/www/pad/comments.js b/www/pad/comments.js index 128784671..da98ceeb2 100644 --- a/www/pad/comments.js +++ b/www/pad/comments.js @@ -42,30 +42,8 @@ define([ var canonicalize = function(t) { return t.replace(/\r\n/g, '\n'); }; - // XXX function duplicated from www/code/markers.js - var authorUid = function(existing) { - if (!Array.isArray(existing)) { existing = []; } - var n; - var i = 0; - while (!n || existing.indexOf(n) !== -1 && i++ < 1000) { - n = Math.floor(Math.random() * 1000000); - } - // If we can't find a valid number in 1000 iterations, use 0... - if (existing.indexOf(n) !== -1) { n = 0; } - return n; - }; var getAuthorId = function(Env, curve) { - var existing = Object.keys(Env.comments.authors || {}).map(Number); - if (!Env.common.isLoggedIn()) { return authorUid(existing); } - - var uid; - existing.some(function(id) { - var author = Env.comments.authors[id] || {}; - if (author.curvePublic !== curve) { return; } - uid = Number(id); - return true; - }); - return uid || authorUid(existing); + return Env.common.getAuthorId(Env.comments.authors, curve); }; // Return the author ID and add/update the data for registered users diff --git a/www/pad/export.js b/www/pad/export.js index d1deef146..f1e3497c9 100644 --- a/www/pad/export.js +++ b/www/pad/export.js @@ -5,15 +5,17 @@ define([ '/bower_components/nthen/index.js', ], function ($, Util, Hyperjson, nThen) { var module = { - ext: '.html' + ext: '.html', // default + exts: ['.html', '.doc'] }; var exportMediaTags = function (inner, cb) { var $clone = $(inner).clone(); nThen(function (waitFor) { $(inner).find('media-tag').each(function (i, el) { - if (!$(el).data('blob') || !el.blob) { return; } - Util.blobToImage(el.blob || $(el).data('blob'), waitFor(function (imgSrc) { + var blob = Util.find(el, ['_mediaObject','_blob', 'content']); + if (!blob) { return; } + Util.blobToImage(blob, waitFor(function (imgSrc) { $clone.find('media-tag[src="' + $(el).attr('src') + '"] img') .attr('src', imgSrc); $clone.find('media-tag').parent() @@ -25,18 +27,31 @@ define([ }); }; + var cleanHtml = function (inner) { + return inner.innerHTML.replace(/]*class="cke_anchor"[^>]*data-cke-realelement="([^"]*)"[^>]*>/g, + function(match,realElt){ + //console.log("returning realElt \"" + unescape(realElt)+ "\"."); + return decodeURIComponent(realElt); + }); + }; module.getHTML = function (inner) { return ('\n' + '\n' + ' \n ' + - inner.innerHTML.replace(/]*class="cke_anchor"[^>]*data-cke-realelement="([^"]*)"[^>]*>/g, - function(match,realElt){ - //console.log("returning realElt \"" + unescape(realElt)+ "\"."); - return decodeURIComponent(realElt); }) + + cleanHtml(inner) + ' \n' ); }; - module.main = function (userDoc, cb) { + var exportDoc = function (inner) { + var preHtml = "Export HTML To Doc"; + var postHtml = ""; + var _html = preHtml+cleanHtml(inner)+postHtml; + return _html; + }; + + module.main = function (userDoc, cb, ext) { + if (!ext || module.exts.indexOf(ext) === -1) { ext = module.ext; } + var inner; if (userDoc && userDoc.tagName) { inner = userDoc; @@ -56,7 +71,14 @@ define([ } } exportMediaTags(inner, function (toExport) { - cb(new Blob([ module.getHTML(toExport) ], { type: "text/html;charset=utf-8" })); + if (ext === ".doc") { + var blob = new Blob(['\ufeff', exportDoc(toExport)], { + type: 'application/msword' + }); + return void cb(blob); + } + var html = module.getHTML(toExport); + cb(new Blob([ html ], { type: "text/html;charset=utf-8" })); }); }; diff --git a/www/pad/inner.js b/www/pad/inner.js index b7f309c35..05cf2c788 100644 --- a/www/pad/inner.js +++ b/www/pad/inner.js @@ -793,8 +793,8 @@ define([ }); }, true); - framework.setFileExporter(Exporter.ext, function(cb) { - Exporter.main(inner, cb); + framework.setFileExporter(Exporter.exts, function(cb, ext) { + Exporter.main(inner, cb, ext); }, true); framework.setNormalizer(function(hjson) {