Avatar upload in the profile app
This commit is contained in:
parent
6c94605b9b
commit
19ff8a345d
@ -12,12 +12,13 @@ define([
|
|||||||
'/common/common-metadata.js',
|
'/common/common-metadata.js',
|
||||||
'/common/common-codemirror.js',
|
'/common/common-codemirror.js',
|
||||||
'/common/common-file.js',
|
'/common/common-file.js',
|
||||||
|
'/file/file-crypto.js',
|
||||||
|
|
||||||
'/common/clipboard.js',
|
'/common/clipboard.js',
|
||||||
'/common/pinpad.js',
|
'/common/pinpad.js',
|
||||||
'/customize/application_config.js'
|
'/customize/application_config.js'
|
||||||
], function ($, Config, Messages, Store, Util, Hash, UI, History, UserList, Title, Metadata,
|
], function ($, Config, Messages, Store, Util, Hash, UI, History, UserList, Title, Metadata,
|
||||||
CodeMirror, Files, Clipboard, Pinpad, AppConfig) {
|
CodeMirror, Files, FileCrypto, Clipboard, Pinpad, AppConfig) {
|
||||||
|
|
||||||
/* This file exposes functionality which is specific to Cryptpad, but not to
|
/* This file exposes functionality which is specific to Cryptpad, but not to
|
||||||
any particular pad type. This includes functions for committing metadata
|
any particular pad type. This includes functions for committing metadata
|
||||||
@ -974,9 +975,14 @@ define([
|
|||||||
var ev = {
|
var ev = {
|
||||||
target: data.target
|
target: data.target
|
||||||
};
|
};
|
||||||
|
if (data.filter && !data.filter(file)) {
|
||||||
|
common.log('TODO: invalid avatar (type or size)');
|
||||||
|
return;
|
||||||
|
}
|
||||||
data.FM.handleFile(file, ev);
|
data.FM.handleFile(file, ev);
|
||||||
if (callback) { callback(); }
|
if (callback) { callback(); }
|
||||||
});
|
});
|
||||||
|
if (data.accept) { $input.attr('accept', data.accept); }
|
||||||
button.click(function () { $input.click(); });
|
button.click(function () { $input.click(); });
|
||||||
break;
|
break;
|
||||||
case 'template':
|
case 'template':
|
||||||
@ -1129,6 +1135,70 @@ define([
|
|||||||
return button;
|
return button;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
common.avatarAllowedTypes = [
|
||||||
|
'image/png',
|
||||||
|
'image/jpeg',
|
||||||
|
'image/jpg',
|
||||||
|
'image/gif',
|
||||||
|
];
|
||||||
|
common.displayAvatar = function ($container, href) {
|
||||||
|
var MutationObserver = window.MutationObserver;
|
||||||
|
$container.html('');
|
||||||
|
if (href) {
|
||||||
|
var parsed = common.parsePadUrl(href);
|
||||||
|
var secret = common.getSecrets('file', parsed.hash);
|
||||||
|
if (secret.keys && secret.channel) {
|
||||||
|
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
||||||
|
var hexFileName = common.base64ToHex(secret.channel);
|
||||||
|
var src = common.getBlobPathFromHex(hexFileName);
|
||||||
|
common.getFileSize(href, function (e, data) {
|
||||||
|
if (e) { return void console.error(e); }
|
||||||
|
if (typeof data !== "number") { return; }
|
||||||
|
if (common.bytesToMegabytes(data) > 0.5) { return; }
|
||||||
|
var $img = $('<media-tag>').appendTo($container);
|
||||||
|
$img.attr('src', src);
|
||||||
|
$img.attr('data-crypto-key', 'cryptpad:' + cryptKey);
|
||||||
|
require(['/common/media-tag.js'], function (MediaTag) {
|
||||||
|
MediaTag.CryptoFilter.setAllowedMediaTypes(common.avatarAllowedTypes);
|
||||||
|
MediaTag($img[0]);
|
||||||
|
var observer = new MutationObserver(function(mutations) {
|
||||||
|
mutations.forEach(function(mutation) {
|
||||||
|
if (mutation.type === 'childList' && mutation.addedNodes.length) {
|
||||||
|
console.log(mutation);
|
||||||
|
if (mutation.addedNodes.length > 1 ||
|
||||||
|
mutation.addedNodes[0].nodeName !== 'IMG') {
|
||||||
|
$img.remove();
|
||||||
|
return;
|
||||||
|
//TODO display default avatar
|
||||||
|
}
|
||||||
|
var $image = $img.find('img');
|
||||||
|
var onLoad = function () {
|
||||||
|
var w = $image.width();
|
||||||
|
var h = $image.height();
|
||||||
|
if (w>h) {
|
||||||
|
$image.css('max-height', '100%');
|
||||||
|
$img.css('flex-direction', 'row');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$image.css('max-width', '100%');
|
||||||
|
$img.css('flex-direction', 'column');
|
||||||
|
};
|
||||||
|
if ($image[0].complete) { onLoad(); }
|
||||||
|
$image.on('load', onLoad);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
observer.observe($img[0], {
|
||||||
|
attributes: false,
|
||||||
|
childList: true,
|
||||||
|
characterData: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Create a button with a dropdown menu
|
// Create a button with a dropdown menu
|
||||||
// input is a config object with parameters:
|
// input is a config object with parameters:
|
||||||
// - container (optional): the dropdown container (span)
|
// - container (optional): the dropdown container (span)
|
||||||
|
|||||||
@ -156,7 +156,6 @@ define([
|
|||||||
MediaTag(el);
|
MediaTag(el);
|
||||||
var observer = new MutationObserver(function(mutations) {
|
var observer = new MutationObserver(function(mutations) {
|
||||||
mutations.forEach(function(mutation) {
|
mutations.forEach(function(mutation) {
|
||||||
console.log(mutation);
|
|
||||||
if (mutation.type === 'childList') {
|
if (mutation.type === 'childList') {
|
||||||
var list_values = [].slice.call(el.children);
|
var list_values = [].slice.call(el.children);
|
||||||
mediaMap[el.getAttribute('src')] = list_values;
|
mediaMap[el.getAttribute('src')] = list_values;
|
||||||
|
|||||||
@ -196,51 +196,105 @@ define([
|
|||||||
cb();
|
cb();
|
||||||
};
|
};
|
||||||
var rt = APP.lm.realtime;
|
var rt = APP.lm.realtime;
|
||||||
var placeholder = "URL"; //TODO
|
var placeholder = "URL"; //XXX
|
||||||
createEditableInput($block, LINK_ID, placeholder, getValue, setValue, rt);
|
createEditableInput($block, LINK_ID, placeholder, getValue, setValue, rt);
|
||||||
};
|
};
|
||||||
|
|
||||||
var addAvatar = function ($container) {
|
var addAvatar = function ($container) {
|
||||||
var $block = $('<div>', {id: AVATAR_ID}).appendTo($container);
|
var $block = $('<div>', {id: AVATAR_ID}).appendTo($container);
|
||||||
var $span = $('<span>').appendTo($block);
|
var $span = $('<span>').appendTo($block);
|
||||||
if (APP.lm.proxy.avatar) {
|
var allowedMediaTypes = Cryptpad.avatarAllowedTypes;
|
||||||
//var file = APP.lm.proxy.avatar;
|
var displayAvatar = function () {
|
||||||
var $img = $('<media-tag>').appendTo($span);
|
$span.html('');
|
||||||
$img.attr('src', '/blob/45/45170bcd64aae1726b0b0e06c4360181a08bad9596640863');
|
if (!APP.lm.proxy.avatar) {
|
||||||
$img.attr('data-crypto-key', 'cryptpad:5vs/ciPzSAyHeP6XRwxpFZt/cjkRC+EE2CRw+/xfcVI=');
|
$('<img>', {
|
||||||
require(['/common/media-tag.js'], function (MediaTag) {
|
src: '/customize/images/avatar.png',
|
||||||
var allowedMediaTypes = [
|
title: 'Avatar', // XXX
|
||||||
'image/png',
|
alt: 'Avatar'
|
||||||
'image/jpeg',
|
}).appendTo($span);
|
||||||
'image/jpg',
|
return;
|
||||||
'image/gif',
|
}
|
||||||
];
|
Cryptpad.displayAvatar($span, APP.lm.proxy.avatar);
|
||||||
MediaTag.CryptoFilter.setAllowedMediaTypes(allowedMediaTypes);
|
|
||||||
MediaTag($img[0]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (APP.readOnly) { return; }
|
|
||||||
|
|
||||||
//var $button = $('<button>', {'class': 'btn btn-success'}).text('TODO: change avatar');
|
if (APP.readOnly) { return; }
|
||||||
//$block.append($button);
|
|
||||||
|
var $delButton = $('<button>', {'class': 'delete btn btn-danger fa fa-times'}); //XXX
|
||||||
|
$span.append($delButton);
|
||||||
|
$delButton.click(function () {
|
||||||
|
console.log('clicked');
|
||||||
|
var oldChanId = Cryptpad.hrefToHexChannelId(APP.lm.proxy.avatar);
|
||||||
|
Cryptpad.unpinPads([oldChanId], function (e) {
|
||||||
|
if (e) { Cryptpad.log(e); }
|
||||||
|
console.log('unpinned');
|
||||||
|
delete APP.lm.proxy.avatar;
|
||||||
|
delete Cryptpad.getProxy().profile.avatar;
|
||||||
|
Cryptpad.whenRealtimeSyncs(APP.lm.realtime, function () {
|
||||||
|
console.log('synced1');
|
||||||
|
var driveRt = Cryptpad.getStore().getProxy().info.realtime;
|
||||||
|
Cryptpad.whenRealtimeSyncs(driveRt, function () {
|
||||||
|
console.log('synced2');
|
||||||
|
displayAvatar();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
displayAvatar();
|
||||||
|
if (APP.readOnly) { return; }
|
||||||
|
|
||||||
var fmConfig = {
|
var fmConfig = {
|
||||||
noHandlers: true,
|
noHandlers: true,
|
||||||
noStore: true,
|
noStore: true,
|
||||||
body: $('body'),
|
body: $('body'),
|
||||||
onUploaded: function (ev, data) {
|
onUploaded: function (ev, data) {
|
||||||
console.log(data);
|
var chanId = Cryptpad.hrefToHexChannelId(data.url);
|
||||||
|
var profile = Cryptpad.getProxy().profile;
|
||||||
|
var old = profile.avatar;
|
||||||
|
var todo = function () {
|
||||||
|
Cryptpad.pinPads([chanId], function (e) {
|
||||||
|
if (e) { return void Cryptpad.log(e); }
|
||||||
|
APP.lm.proxy.avatar = data.url;
|
||||||
|
Cryptpad.getProxy().profile.avatar = data.url;
|
||||||
|
Cryptpad.whenRealtimeSyncs(APP.lm.realtime, function () {
|
||||||
|
var driveRt = Cryptpad.getStore().getProxy().info.realtime;
|
||||||
|
Cryptpad.whenRealtimeSyncs(driveRt, function () {
|
||||||
|
displayAvatar();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if (old) {
|
||||||
|
var oldChanId = Cryptpad.hrefToHexChannelId(old);
|
||||||
|
Cryptpad.unpinPads([oldChanId], function (e) {
|
||||||
|
if (e) { Cryptpad.log(e); }
|
||||||
|
todo();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
todo();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
APP.FM = Cryptpad.createFileManager(fmConfig);
|
APP.FM = Cryptpad.createFileManager(fmConfig);
|
||||||
var data = {FM: APP.FM};
|
var data = {
|
||||||
$block.append(Cryptpad.createButton('upload', false, data));
|
FM: APP.FM,
|
||||||
|
filter: function (file) {
|
||||||
|
var sizeMB = Cryptpad.bytesToMegabytes(file.size);
|
||||||
|
var type = file.type;
|
||||||
|
return sizeMB <= 0.5 && allowedMediaTypes.indexOf(type) !== -1;
|
||||||
|
},
|
||||||
|
accept: ".gif,.jpg,.jpeg,.png"
|
||||||
|
};
|
||||||
|
var $upButton = Cryptpad.createButton('upload', false, data);
|
||||||
|
$upButton.text(" Upload a new avatar");
|
||||||
|
$upButton.prepend($('<span>', {'class': 'fa fa-upload'}));
|
||||||
|
$block.append($upButton);
|
||||||
};
|
};
|
||||||
|
|
||||||
var addDescription = function ($container) {
|
var addDescription = function ($container) {
|
||||||
var $block = $('<div>', {id: DESCRIPTION_ID}).appendTo($container);
|
var $block = $('<div>', {id: DESCRIPTION_ID}).appendTo($container);
|
||||||
|
|
||||||
if (APP.readOnly) {
|
if (APP.readOnly) {
|
||||||
|
if (!APP.lm.proxy.description.trim()) { return void $block.hide(); }
|
||||||
var $div = $('<div>', {'class': 'rendered'}).appendTo($block);
|
var $div = $('<div>', {'class': 'rendered'}).appendTo($block);
|
||||||
var val = Marked(APP.lm.proxy.description);
|
var val = Marked(APP.lm.proxy.description);
|
||||||
$div.html(val);
|
$div.html(val);
|
||||||
@ -274,13 +328,10 @@ define([
|
|||||||
|
|
||||||
var addPublicKey = function ($container) {
|
var addPublicKey = function ($container) {
|
||||||
var $block = $('<div>', {id: PUBKEY_ID});
|
var $block = $('<div>', {id: PUBKEY_ID});
|
||||||
var pubKey = Cryptpad.getProxy().edPublic;
|
|
||||||
$block.text(pubKey);
|
|
||||||
$container.append($block);
|
$container.append($block);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onReady = function () {
|
var onReady = function () {
|
||||||
// TODO: on reconnect, this is called multiple times...
|
|
||||||
APP.$container.find('#'+CREATE_ID).remove();
|
APP.$container.find('#'+CREATE_ID).remove();
|
||||||
|
|
||||||
if (!APP.initialized) {
|
if (!APP.initialized) {
|
||||||
@ -332,13 +383,32 @@ define([
|
|||||||
var secret = Cryptpad.getSecrets();
|
var secret = Cryptpad.getSecrets();
|
||||||
obj.profile = {};
|
obj.profile = {};
|
||||||
var channel = Cryptpad.createChannelId();
|
var channel = Cryptpad.createChannelId();
|
||||||
obj.profile.edit = Cryptpad.getEditHashFromKeys(channel, secret.keys);
|
Cryptpad.pinPads([channel], function (e) {
|
||||||
obj.profile.view = Cryptpad.getViewHashFromKeys(channel, secret.keys);
|
if (e) {
|
||||||
obj.profile.name = APP.rt.proxy[Cryptpad.displayNameKey] || '';
|
if (e === 'E_OVER_LIMIT') {
|
||||||
andThen(obj.profile.edit);
|
Cryptpad.alert(Messages.pinLimitNotPinned, null, true);
|
||||||
|
}
|
||||||
|
return void Cryptpad.log('Error while creating your profile: ' + e); // XXX
|
||||||
|
}
|
||||||
|
obj.profile.edit = Cryptpad.getEditHashFromKeys(channel, secret.keys);
|
||||||
|
obj.profile.view = Cryptpad.getViewHashFromKeys(channel, secret.keys);
|
||||||
|
obj.profile.name = APP.rt.proxy[Cryptpad.displayNameKey] || '';
|
||||||
|
andThen(obj.profile.edit);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: if not logged in, display a register button here?
|
if (!Cryptpad.isLoggedIn()) { // XXX
|
||||||
|
var $p = $('<p>').text('TODO: You have to register to create a profile');
|
||||||
|
var $a = $('<a>', {
|
||||||
|
href: '/register/'
|
||||||
|
});
|
||||||
|
$('<button>', {
|
||||||
|
'class': 'btn btn-success',
|
||||||
|
}).text(Messages.login_register).appendTo($a);
|
||||||
|
$p.append($('<br>')).append($a);
|
||||||
|
APP.$container.append($p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
var $create = $('<div>', {id: CREATE_ID});
|
var $create = $('<div>', {id: CREATE_ID});
|
||||||
var $button = $('<button>', {'class': 'btn btn-success'});
|
var $button = $('<button>', {'class': 'btn btn-success'});
|
||||||
$button.text('TODO: create a profile?').click(todo).appendTo($create); // XXX
|
$button.text('TODO: create a profile?').click(todo).appendTo($create); // XXX
|
||||||
|
|||||||
@ -23,25 +23,43 @@
|
|||||||
width: 300px;
|
width: 300px;
|
||||||
//height: 350px;
|
//height: 350px;
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
|
margin-right: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
&> span {
|
&> span {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
line-height: 300px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 300px;
|
height: 300px;
|
||||||
|
width: 300px;
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
.delete {
|
||||||
|
right: 0;
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0.7;
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
max-width: 300px;
|
max-width: 100%;
|
||||||
max-height: 300px;
|
max-height: 100%;
|
||||||
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
media-tag {
|
media-tag {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: inline-block;
|
width: 100%;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
img {
|
img {
|
||||||
vertical-align: top;
|
min-width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
max-width: none;
|
||||||
|
max-height: none;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
@ -83,6 +101,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
border: 1px solid #DDD;
|
border: 1px solid #DDD;
|
||||||
|
margin-bottom: 20px;
|
||||||
.rendered {
|
.rendered {
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user