Avatar upload in the profile app

pull/1/head
yflory 8 years ago
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 $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; } if (APP.readOnly) { return; }
//var $button = $('<button>', {'class': 'btn btn-success'}).text('TODO: change avatar');
//$block.append($button);
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…
Cancel
Save