From 7dc7d5d95081cc2101026a92570b0c10ab4f979c Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 9 Mar 2018 12:12:47 +0100 Subject: [PATCH 01/33] lint compliance --- customize.dist/src/less2/include/help.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/customize.dist/src/less2/include/help.less b/customize.dist/src/less2/include/help.less index 7e22b713a..90f23119b 100644 --- a/customize.dist/src/less2/include/help.less +++ b/customize.dist/src/less2/include/help.less @@ -18,7 +18,7 @@ margin: 0; padding: 15px; a { - color: darken(@colortheme_link-color, 30%); + //color: darken(@colortheme_link-color, 30%); @spin: spin(lighten(@bg-color, 15%), 180); color: contrast(lighten(@bg-color, 15%), lighten(@spin, 10%), darken(@spin, 10%)); //color: darken(spin(lighten(@bg-color, 15%), 180), 10%); From b2df2ba341ceffdd876679188c1e355fcb1c014a Mon Sep 17 00:00:00 2001 From: ansuz Date: Mon, 12 Mar 2018 17:50:47 +0100 Subject: [PATCH 02/33] prototype owned file upload --- package.json | 1 + rpc.js | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/package.json b/package.json index 3ab228851..e94c51a14 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "dependencies": { "chainpad-server": "^2.0.0", "express": "~4.16.0", + "mkdirp": "^0.5.1", "nthen": "~0.1.0", "pull-stream": "^3.6.1", "replify": "^1.2.0", diff --git a/rpc.js b/rpc.js index 465413fd1..3ad1a9a42 100644 --- a/rpc.js +++ b/rpc.js @@ -13,6 +13,7 @@ const Package = require('./package.json'); const Pinned = require('./pinned'); const Saferphore = require("saferphore"); const nThen = require("nthen"); +const Mkdirp = require("mkdirp"); var RPC = module.exports; @@ -980,6 +981,93 @@ var upload_complete = function (Env, publicKey, cb) { tryRandomLocation(handleMove); }; +var owned_upload_complete = function (Env, safeKey, cb) { + var session = getSession(Env.Sessions, safeKey); + + // the file has already been uploaded to the staging area + // close the pending writestream + if (session.blobstage && session.blobstage.close) { + session.blobstage.close(); + delete session.blobstage; + } + + var oldPath = makeFilePath(Env.paths.staging, safeKey); + + // construct relevant paths + var root = Env.paths.staging; + + //var safeKey = escapeKeyCharacters(safeKey); + var safeKeyPrefix = safeKey.slice(0, 2); + + var blobId = createFileId(); + var blobIdPrefix = blobId.slice(0, 2); + + var plannedPath = Path.join(root, safeKeyPrefix, safeKey, blobIdPrefix); + + var tries = 0; + + var chooseSafeId = function (cb) { + if (tries >= 3) { + // you've already failed three times in a row + // give up and return an error + cb('E_REPEATED_FAILURE'); + } + + var path = Path.join(plannedPath, blobId); + Fs.access(path, Fs.constants.R_OK | Fs.constants.W_OK, function (e) { + if (!e) { + // generate a new id (with the same prefix) and recurse + blobId = blobIdPrefix + createFileId().slice(2); + return void chooseSafeId(cb); + } else if (e.code === 'ENOENT') { + // no entry, so it's safe for us to proceed + return void cb(void 0, path); + } else { + // it failed in an unexpected way. log it + // try again, but no more than a fixed number of times... + tries++; + chooseSafeId(cb); + } + }); + }; + + // the user wants to move it into their own space + // /blob/safeKeyPrefix/safeKey/blobPrefix/blobID + + var finalPath; + nThen(function (w) { + // make the requisite directory structure using Mkdirp + Mkdirp(plannedPath, w(function (e /*, path */) { + if (e) { // does not throw error if the directory already existed + w.abort(); + return void cb(e); // XXX do we export Errors or strings? + } + })); + }).nThen(function (w) { + // produce an id which confirmably does not collide with another + chooseSafeId(w(function (e, path) { + if (e) { + w.abort(); + return void cb(e); + } + finalPath = path; // this is where you'll put the new file + })); + }).nThen(function (w) { + // move the existing file to its new path + Fs.rename(oldPath /* XXX */, finalPath, w(function (e) { + if (e) { + w.abort(); + return void cb(e.code); + } + // otherwise it worked... + })); + }).nThen(function () { + // clean up their session when you're done + // call back with the blob id... + cb(void 0, blobId); + }); +}; + var upload_status = function (Env, publicKey, filesize, cb) { var paths = Env.paths; @@ -1054,6 +1142,7 @@ var isAuthenticatedCall = function (call) { 'GET_LIMIT', 'UPLOAD_STATUS', 'UPLOAD_COMPLETE', + 'OWNED_UPLOAD_COMPLETE', 'UPLOAD_CANCEL', 'EXPIRE_SESSION', 'CLEAR_OWNED_CHANNEL', @@ -1128,6 +1217,7 @@ RPC.create = function ( var pinPath = paths.pin = keyOrDefaultString('pinPath', './pins'); var blobPath = paths.blob = keyOrDefaultString('blobPath', './blob'); var blobStagingPath = paths.staging = keyOrDefaultString('blobStagingPath', './blobstage'); + console.log(blobStagingPath); var isUnauthenticateMessage = function (msg) { return msg && msg.length === 2 && isUnauthenticatedCall(msg[0]); @@ -1375,6 +1465,12 @@ RPC.create = function ( WARN(e, hash); Respond(e, hash); }); + case 'OWNED_UPLOAD_COMPLETE': + if (!privileged) { return deny(); } + return void owned_upload_complete(Env, safeKey, function (e, blobId) { + WARN(e, blobId); + Respond(e, blobId); + }); case 'UPLOAD_CANCEL': if (!privileged) { return deny(); } return void upload_cancel(Env, safeKey, function (e) { From c9ed6d6bf8a602e56768e686dcf78dcd55ae6027 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 13 Mar 2018 11:31:08 +0100 Subject: [PATCH 03/33] New pad creation screen --- customize.dist/pages.js | 7 +- .../src/less2/include/checkmark.less | 67 ++++ .../src/less2/include/colortheme.less | 7 + .../src/less2/include/creation.less | 288 ++++++++++------ customize.dist/template.js | 2 + www/common/common-interface.js | 5 +- www/common/common-thumbnail.js | 3 + www/common/common-ui-elements.js | 319 ++++++++++-------- www/common/cryptpad-common.js | 18 +- www/common/outer/async-store.js | 7 + www/common/outer/store-rpc.js | 6 + www/common/sframe-common-outer.js | 69 +++- www/common/sframe-common.js | 4 +- www/common/sframe-protocol.js | 2 + 14 files changed, 535 insertions(+), 269 deletions(-) create mode 100644 customize.dist/src/less2/include/checkmark.less diff --git a/customize.dist/pages.js b/customize.dist/pages.js index a08e40d3c..5178cac17 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -384,7 +384,8 @@ define([ var item = faq[c][q]; if (typeof item !== "object") { return; } var answer = h('p.cp-faq-questions-a'); - var question = h('p.cp-faq-questions-q'); + var hash = c + '-' + q; + var question = h('p.cp-faq-questions-q#' + hash); $(question).click(function () { if ($(answer).is(':visible')) { return void $(answer).slideUp(); @@ -401,6 +402,10 @@ define([ h('div.cp-faq-category-questions', questions) ])); }); + var hash = window.location.hash; + if (hash) { + $(categories).find(hash).click(); + } return h('div#cp-main', [ infopageTopbar(), h('div.container.cp-container', [ diff --git a/customize.dist/src/less2/include/checkmark.less b/customize.dist/src/less2/include/checkmark.less new file mode 100644 index 000000000..30c6e7d4a --- /dev/null +++ b/customize.dist/src/less2/include/checkmark.less @@ -0,0 +1,67 @@ +@import (once) "./colortheme-all.less"; + +.checkmark_main(@size) { + + @width: round(@size / 8); + @dim1: round(@size / 3); + @dim2: round(2 * @size / 3); + @top: round(@size / 12); + // Text + .cp-checkmark { + margin: 0; + display: flex; + align-items: center; + position: relative; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + &.cp-checkmark-secondary { + .cp-checkmark-mark { + &:after { + border-color: @colortheme_checkmark-col2; + } + } + input { + &:checked ~ .cp-checkmark-mark { + background-color: @colortheme_checkmark-back2; + } + } + } + &:hover .cp-checkmark-mark { + background-color: @colortheme_checkmark-back0-active; + } + + input { + display: none; + &:checked ~ .cp-checkmark-mark { + background-color: @colortheme_checkmark-back1; + &:after { + display: block; + } + } + } + + .cp-checkmark-mark { + margin-right: 10px; + position: relative; + height: @size; + width: @size; + background-color: @colortheme_checkmark-back0; + display: flex; + justify-content: center; + &:after { + content: ""; + display: none; + margin-top: @top; + width: @dim1; + height: @dim2; + transform: rotate(45deg); + border: solid @colortheme_checkmark-col1; + border-width: 0 @width @width 0; + } + } + + } +} diff --git a/customize.dist/src/less2/include/colortheme.less b/customize.dist/src/less2/include/colortheme.less index 1a2b143e5..1bdb69291 100644 --- a/customize.dist/src/less2/include/colortheme.less +++ b/customize.dist/src/less2/include/colortheme.less @@ -109,3 +109,10 @@ @cryptpad_color_grey: #999999; @cryptpad_header_col: #1E1F1F; @cryptpad_text_col: #3F4141; + +@colortheme_checkmark-back0: #ffffff; +@colortheme_checkmark-back0-active: #bbbbbb; +@colortheme_checkmark-back1: #FF0073; +@colortheme_checkmark-col1: #ffffff; +@colortheme_checkmark-back2: #FFFFFF; +@colortheme_checkmark-col2: #000000; diff --git a/customize.dist/src/less2/include/creation.less b/customize.dist/src/less2/include/creation.less index 16bce0637..6d7e6462c 100644 --- a/customize.dist/src/less2/include/creation.less +++ b/customize.dist/src/less2/include/creation.less @@ -1,5 +1,7 @@ @import (once) "./colortheme-all.less"; @import (once) "./tools.less"; +@import (once) "./checkmark.less"; +@import (once) './icon-colors.less'; .creation_main() { .tippy-popper { @@ -31,149 +33,211 @@ max-width: 100%; margin: 40px auto; text-align: left; - display: flex; - flex-wrap: wrap; - justify-content: center; - align-items: center; - h2 { - width: 100%; - display: flex; - margin-bottom: 20px; - justify-content: space-between; - .cp-creation-help { - display: none; - } - } - .cp-creation-help-container { - width: 100%; - display: flex; - justify-content: space-between; - p { - padding: 0 20px; - flex-grow: 0; - flex-shrink: 0; - flex-basis: 50%; - text-align: justify; - } - } - @media screen and (max-width: 500px) { - width: ~"calc(100% - 30px)"; - } - @media screen and (max-height: 800px), screen and (max-width: 500px) { - h2 .cp-creation-help { - display: inline; - } - .cp-creation-help-container { - display: none; - } - } - @media screen and (min-height: 601px) { - @media screen and (min-width: 501px) { - p { - display: block !important; - } - } - } } .cp-creation-create, .cp-creation-settings { + @creation-button: #FF0073; button { .tools_unselectable(); padding: 15px; - background: darken(@colortheme_loading-bg, 10%); + //background: @creation-button; + background: spin(@colortheme_loading-bg, 180); + background: #60ff6b; + background: #30b239; color: @colortheme_loading-color; + color: spin(#60ff6b, 180); + color: #000; + color: #FFF; + font-weight: bold; margin: 3px 10px; border: none; cursor: pointer; outline: none; &:hover { - background: darken(@colortheme_loading-bg, 5%); - } - &.cp-creation-button-selected { - color: darken(@colortheme_loading-bg, 10%); - background: @colortheme_loading-color; + background: darken(@creation-button, 5%); } } } + .cp-creation-create { + text-align: center; + } - input[type="radio"] { - display: none; - &:checked { - & + label { - font-weight: bold; - background-color: lighten(@colortheme_loading-bg, 20%); - cursor: default; - border: 1px solid #c1158e; - &:hover { - background-color: lighten(@colortheme_loading-bg, 20%); + #cp-creation-form { + display: flex; + flex-flow: column; + align-items: center; + & > div { + width: 400px; + max-width: 100%; + display: flex; + align-items: center; + flex-wrap: wrap; + font-size: 16px; + margin: 10px 0; + label { + flex: 1; + } + input[type="checkbox"] { + &+ label { + margin-bottom: 0; + flex: 1; + padding: 0 10px; } } - } - } - input[type="radio"] + label { - .tools_unselectable(); - display: inline-flex; - align-items: center; - justify-content: center; - width: 200px; - height: 50px; - padding: 5px; - margin: 0 20px; - border: 1px solid @colortheme_loading-color; - cursor: pointer; - &:hover { - background-color: lighten(@colortheme_loading-bg, 10%); - } - } - .cp-creation-expire { - #cp-creation-expire-true { - display: none; - &:checked { - & + label { - height: 100px; - .cp-creation-expire-picker { - display: inline; - } + .cp-creation-help { + font-size: 18px; + color: white; + &:hover { + color: #AAA; + text-decoration: none; } } } - label[for="cp-creation-expire-true"] { - flex-wrap: wrap; + .cp-creation-expire { .cp-creation-expire-picker { - display: none; + display: block; + overflow: hidden; + max-height: 0px; + transition: max-height 0.5s ease-in-out; + width: 100%; + text-align: center; + margin-top: 10px; + input { + width: 100px; + } } - input { - width: 70px; + .cp-creation-expire-picker.active { + max-height: 40px; } - select { - width: 100px; + } + .cp-creation-settings { + button { + margin: 0; + padding: 0; } - input, select { - border: none; - height: 30px; - background: @colortheme_loading-bg; - color: @colortheme_loading-color; - border-radius: 3px; + .cp-filler { flex: 1; } + } + + div.cp-creation-template { + width: 100%; + background-color: darken(@colortheme_modal-bg, 3%); + padding: 20px; + margin: 30px 0; + } + .cp-creation-template-container { + width: 100%; + display: flex; + flex-wrap: wrap; + justify-content: center; + overflow-y: auto; + align-items: center; + .cp-creation-template-element { + @darker: darken(@colortheme_modal-fg, 30%); + + width: 125px; + padding: 10px; + margin: 5px; + display: inline-flex; + flex-flow: column; + + box-sizing: content-box; + + text-align: left; + line-height: 1em; + cursor: pointer; + + background-color: #111; + color: @darker; + border: 1px solid transparent; + + &.cp-creation-template-selected { + border: 1px solid white; + background-color: #222; + } + + transition: all 0.1s; + + &:hover { + color: @colortheme_modal-fg; + } + + align-items: center; + + img { + max-width: 100px; + max-height: 100px; + background: #fff; + } + + .cp-creation-template-element-name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + height: 20px; + line-height: 20px; + margin-top: 5px; + max-width: 100%; + } + .fa { + cursor: pointer; + width: 100px; + height: 100px; + font-size: 70px; + text-align: center; + line-height: 100px; + } } } } - .cp-creation-settings { - justify-content: left; - a { - color: #0275d8; - &:hover { - color: lighten(#0275d8, 10%); - } + + .cp-creation-deleted-container { + text-align: center; + .cp-creation-deleted { + background: #111; + padding: 10px; + text-align: center; + font-weight: bold; + display: inline-block; } - &> span.fa { - margin-left: 15px; + } + + .checkmark_main(30px); + + @media screen and (max-width: @browser_media-narrow-screen) { + & > div { + width: 95%; + margin: 10px auto; } } - .cp-creation-deleted { - background: #111; - padding: 10px; - text-align: justify; - font-weight: bold; + @media screen and (max-width: @browser_media-medium-screen) { + #cp-creation-form { + div.cp-creation-template { + margin: 0; + padding: 5px; + .cp-creation-template-container { + .cp-creation-template-element { + flex-flow: row; + margin: 1px; + padding: 5px; + img { + display: none; + } + .fa { + font-size: 18px; + width: 20px; + height: 20px; + line-height: 20px; + display: inline !important; + } + .cp-creation-template-element-name { + margin: 0; + margin-left: 5px; + } + } + } + } + } } + } } diff --git a/customize.dist/template.js b/customize.dist/template.js index 2aed683ce..9285567ca 100644 --- a/customize.dist/template.js +++ b/customize.dist/template.js @@ -108,6 +108,8 @@ $(function () { require([ '/customize/main.js', ], function () {}); } else if (/invite/.test(pathname)) { require([ '/invite/main.js'], function () {}); + } else if (/faq/.test(pathname)) { + window.location.hash = window.location.hash; } else { require([ '/customize/main.js', ], function () {}); } diff --git a/www/common/common-interface.js b/www/common/common-interface.js index d10b289cd..c486df7cc 100644 --- a/www/common/common-interface.js +++ b/www/common/common-interface.js @@ -638,9 +638,10 @@ define([ var $icon = UI.getIcon(); if (!data) { return $icon; } var href = data.href; - if (!href) { return $icon; } + var type = data.type; + if (!href && !type) { return $icon; } - var type = Hash.parsePadUrl(href).type; + if (!type) { type = Hash.parsePadUrl(href).type; } $icon = UI.getIcon(type); return $icon; diff --git a/www/common/common-thumbnail.js b/www/common/common-thumbnail.js index f3864e6a3..455b095c9 100644 --- a/www/common/common-thumbnail.js +++ b/www/common/common-thumbnail.js @@ -237,6 +237,9 @@ define([ $span.prepend(img); cb($(img)); }; + Thumb.addThumbnail = function(thumb, $span, cb) { + return addThumbnail(null, thumb, $span, cb); + }; var getKey = function (href) { var parsed = Hash.parsePadUrl(href); return 'thumbnail-' + parsed.type + '-' + parsed.hashData.channel; diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 3d6b33964..ce716640e 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1792,6 +1792,7 @@ define([ UIElements.setExpirationValue = function (val, $expire) { if (val && typeof (val) === "number") { + $expire.find('#cp-creation-expire').attr('checked', true).trigger('change'); $expire.find('#cp-creation-expire-true').attr('checked', true); if (val % (3600 * 24 * 30) === 0) { $expire.find('#cp-creation-expire-unit').val("month"); @@ -1828,16 +1829,21 @@ define([ }; // Title - $creation.append(h('h1.cp-creation-title', Messages['button_new'+type])); + $creation.append(h('h1.cp-creation-title', 'Create a new pad')); // XXX // Deleted pad warning - if (metadataMgr.getPrivateData().isDeleted) { - $creation.append(h('div.cp-creation-deleted', Messages.creation_404)); + if (metadataMgr.getPrivateData().isDeleted || true) { // XXX + $creation.append(h('div.cp-creation-deleted-container', + h('div.cp-creation-deleted', Messages.creation_404) + )); } - var createHelper = function (text) { - var q = h('span.cp-creation-help.fa.fa-question', { - title: text + var origin = common.getMetadataMgr().getPrivateData().origin; + var createHelper = function (href, text) { + var q = h('a.cp-creation-help.fa.fa-question', { + title: text, + href: origin + href, + target: "_blank" }); return q; }; @@ -1845,78 +1851,145 @@ define([ // Owned pads // Default is Owned pad var owned = h('div.cp-creation-owned', [ - h('h2', [ - Messages.creation_ownedTitle, - createHelper(Messages.creation_owned1 + '\n' + Messages.creation_owned2) - ]), - h('div.cp-creation-help-container', [ - setHTML(h('p'), Messages.creation_owned1), - setHTML(h('p'), Messages.creation_owned2) - ]), - h('input#cp-creation-owned-true.cp-creation-owned-value', { - type: 'radio', - name: 'cp-creation-owned', - value: 1, - checked: 'checked' - }), - h('label', { 'for': 'cp-creation-owned-true' }, Messages.creation_ownedTrue), - h('input#cp-creation-owned-false.cp-creation-owned-value', { - type: 'radio', - name: 'cp-creation-owned', - value: 0 - }), - h('label', { 'for': 'cp-creation-owned-false' }, Messages.creation_ownedFalse) + h('label.cp-checkmark', [ + h('input', { + type: 'checkbox', + id: 'cp-creation-owned', + checked: 'checked' + }), + h('span.cp-checkmark-mark'), + 'Owned pad' + ]), // XXX + createHelper('/faq.html#keywords-owned', Messages.creation_owned1) ]); - $creation.append(owned); - - // If set to "open pad", check "open pad" - if (!cfg.owned && typeof cfg.owned !== "undefined") { - $creation.find('#cp-creation-owned-false').attr('checked', true); - } // Life time var expire = h('div.cp-creation-expire', [ - h('h2', [ - Messages.creation_expireTitle, - createHelper(Messages.creation_expire1, Messages.creation_expire2) - ]), - h('div.cp-creation-help-container', [ - setHTML(h('p'), Messages.creation_expire1), - setHTML(h('p'), Messages.creation_expire2) - ]), - h('input#cp-creation-expire-false.cp-creation-expire-value', { - type: 'radio', - name: 'cp-creation-expire', - value: 0, - checked: 'checked' - }), - h('label', { 'for': 'cp-creation-expire-false' }, Messages.creation_expireFalse), - h('input#cp-creation-expire-true.cp-creation-expire-value', { - type: 'radio', - name: 'cp-creation-expire', - value: 1 - }), - h('label', { 'for': 'cp-creation-expire-true' }, [ - Messages.creation_expireTrue, - h('span.cp-creation-expire-picker', [ - h('input#cp-creation-expire-val', { - type: "number", - min: 1, - max: 100, - value: 3 - }), - h('select#cp-creation-expire-unit', [ - h('option', { value: 'hour' }, Messages.creation_expireHours), - h('option', { value: 'day' }, Messages.creation_expireDays), - h('option', { - value: 'month', - selected: 'selected' - }, Messages.creation_expireMonths) - ]) + //Messages.creation_ownedTitle, + h('label.cp-checkmark', [ + h('input', { + type: 'checkbox', + id: 'cp-creation-expire' + }), + h('span.cp-checkmark-mark'), + 'Expiring pad' + ]), // XXX + createHelper('faq.html#keywords-expiring', Messages.creation_expire1), + h('div.cp-creation-expire-picker', [ + h('input#cp-creation-expire-val', { + type: "number", + min: 1, + max: 100, + value: 3 + }), + h('select#cp-creation-expire-unit', [ + h('option', { value: 'hour' }, Messages.creation_expireHours), + h('option', { value: 'day' }, Messages.creation_expireDays), + h('option', { + value: 'month', + selected: 'selected' + }, Messages.creation_expireMonths) ]) ]) ]); - $creation.append(expire); + + var templates = h('div.cp-creation-template', [ + h('div.cp-creation-template-container', [ + h('span.fa.fa-circle-o-notch.fa-spin.fa-4x.fa-fw') + ]) + ]); + + var settings = h('div.cp-creation-remember', [ + h('label.cp-checkmark.cp-checkmark-secondary', [ + h('input', { + type: 'checkbox', + id: 'cp-creation-remember', + checked: 'checked' + }), + h('span.cp-checkmark-mark'), + 'Save settings' + ]), // XXX + createHelper('/settings/#creation', "View more settings") + ]); + + $(h('div#cp-creation-form', [ + owned, + expire, + templates, + settings + ])).appendTo($creation); + + // Display templates + var selected = 0; + sframeChan.query("Q_CREATE_TEMPLATES", type, function (err, res) { + if (!res.data || !Array.isArray(res.data)) { + return void console.error("Error: get the templates list"); + } + var data = res.data.slice().sort(function (a, b) { + if (a.name === b.name) { return 0; } + return a.name < b.name ? -1 : 1; + }); + data.unshift({ + name: "No template", + id: 0, + icon: h('span.fa.fa-times') + }); + data.push({ + name: "New template", + id: -1, + icon: h('span.fa.fa-plus') + }); + var $container = $(templates).find('.cp-creation-template-container').html(''); + data.forEach(function (obj, idx) { + var name = obj.name; + var $span = $('', { + 'class': 'cp-creation-template-element', + 'title': name, + }).appendTo($container); + console.log(obj.id); + $span.data('id', obj.id); + if (idx === 0) { $span.addClass('cp-creation-template-selected') } + $span.append(obj.icon || UI.getFileIcon({type: type})); + $('', {'class': 'cp-creation-template-element-name'}).text(name) + .appendTo($span); + $span.click(function () { + $container.find('.cp-creation-template-selected') + .removeClass('cp-creation-template-selected'); + $span.addClass('cp-creation-template-selected'); + selected = idx; + }); + + // Add thumbnail if it exists + if (obj.thumbnail) { + common.addThumbnail(obj.thumbnail, $span, function () {}); + } + }); + }); + // Change template selection when Tab is pressed + var next = function (revert) { + var max = $creation.find('.cp-creation-template-element').length; + selected = revert ? + (--selected < 0 ? max-1 : selected) : + ++selected % max; + $creation.find('.cp-creation-template-element') + .removeClass('cp-creation-template-selected'); + $($creation.find('.cp-creation-template-element').get(selected)) + .addClass('cp-creation-template-selected'); + }; + + + // Display expiration form when checkbox checked + $creation.find('#cp-creation-expire').on('change', function () { + if ($(this).is(':checked')) { + $creation.find('.cp-creation-expire-picker:not(.active)').addClass('active'); + $creation.find('#cp-creation-expire-val').focus(); + return; + } + $creation.find('.cp-creation-expire-picker').removeClass('active'); + $creation.focus(); + }); + + // Keyboard shortcuts $creation.find('#cp-creation-expire-val').keydown(function (e) { if (e.which === 9) { e.stopPropagation(); @@ -1928,15 +2001,20 @@ define([ } }); + + // Initial values + if (!cfg.owned && typeof cfg.owned !== "undefined") { + $creation.find('#cp-creation-owned').attr('checked', false); + } UIElements.setExpirationValue(cfg.expire, $creation); // Create the pad var getFormValues = function (template) { // Type of pad - var ownedVal = parseInt($('input[name="cp-creation-owned"]:checked').val()); + var ownedVal = $('#cp-creation-owned').is(':checked') ? 1 : 0; // Life time var expireVal = 0; - if(parseInt($('input[name="cp-creation-expire"]:checked').val())) { + if($('#cp-creation-expire').is(':checked')) { var unit = 0; switch ($('#cp-creation-expire-unit').val()) { case "hour" : unit = 3600; break; @@ -1947,62 +2025,45 @@ define([ expireVal = ($('#cp-creation-expire-val').val() || 0) * unit; } + var $template = $creation.find('.cp-creation-template-selected'); + var template = $template.data('id') || undefined; + return { owned: ownedVal, expire: expireVal, - template: template + templateId: template }; }; - var create = function (template) { - $creationContainer.remove(); + var create = function () { + var val = getFormValues(); - common.createPad(getFormValues(template), function () { + if ($('#cp-creation-remember').is(':checked')) { + common.setAttribute(['general', 'creation', 'owned'], + val.owned, function (e) { + if (e) { return void console.error(e); } + }); + common.setAttribute(['general', 'creation', 'expire'], + val.expire, function (e) { + if (e) { return void console.error(e); } + }); + } + + $creationContainer.remove(); + common.createPad(val, function () { cb(); }); }; - var $create = $(h('div.cp-creation-create', [ - h('h2', Messages.creation_createTitle) - ])).appendTo($creation); - // Pick a template? - sframeChan.query("Q_TEMPLATE_EXIST", type, function (err, data) { - if (!data) { return; } - var $templateButton = $('