From a5e8f6ae81ca9804089bb3be263aebcefc69113e Mon Sep 17 00:00:00 2001
From: yflory <yann.flory@xwiki.com>
Date: Thu, 6 Jul 2017 18:00:03 +0200
Subject: [PATCH] Add friend app and fix avatar size

---
 customize.dist/pages.js                |  4 +++
 customize.dist/src/less/toolbar.less   |  7 +++-
 customize.dist/src/less/variables.less |  2 ++
 customize.dist/template.js             |  5 ++-
 www/common/common-messaging.js         | 44 ++++++++++++++++++++---
 www/common/cryptpad-common.js          | 33 +++++++++--------
 www/common/toolbar2.js                 |  2 +-
 www/friends/index.html                 | 30 ++++++++++++++++
 www/friends/inner.html                 | 17 +++++++++
 www/friends/inner.js                   | 13 +++++++
 www/friends/main.js                    | 50 ++++++++++++++++++++++++++
 www/friends/main.less                  | 47 ++++++++++++++++++++++++
 www/profile/main.less                  |  2 +-
 13 files changed, 234 insertions(+), 22 deletions(-)
 create mode 100644 www/friends/index.html
 create mode 100644 www/friends/inner.html
 create mode 100644 www/friends/inner.js
 create mode 100644 www/friends/main.js
 create mode 100644 www/friends/main.less

diff --git a/customize.dist/pages.js b/customize.dist/pages.js
index 5cd8a3a5f..86117677f 100644
--- a/customize.dist/pages.js
+++ b/customize.dist/pages.js
@@ -489,6 +489,10 @@ define([
         return loadingScreen();
     };
 
+    Pages['/friends/'] = Pages['/friends/index.html'] = function () {
+        return loadingScreen();
+    };
+
     Pages['/pad/'] = Pages['/pad/index.html'] = function () {
         return loadingScreen();
     };
diff --git a/customize.dist/src/less/toolbar.less b/customize.dist/src/less/toolbar.less
index 22b4183ad..c8d0488e0 100644
--- a/customize.dist/src/less/toolbar.less
+++ b/customize.dist/src/less/toolbar.less
@@ -21,6 +21,7 @@
 .slideColor { color: @toolbar-slide-bg; }
 .pollColor { color: @toolbar-poll-bg; }
 .fileColor { color: @toolbar-file-bg; }
+.friendsColor { color: @toolbar-friends-bg; }
 .whiteboardColor { color: @toolbar-whiteboard-bg; }
 .driveColor { color: @toolbar-drive-bg; }
 .defaultColor { color: @toolbar-default-bg; }
@@ -165,7 +166,6 @@ body .userlist-drawer {
                     min-height: 100%;
                     max-width: none;
                     max-height: none; // To override 'media-tag img' in slide.less
-                    flex-shrink: 0;
                 }
             }
         }
@@ -310,6 +310,11 @@ body {
         @color: @toolbar-file-color;
         .addToolbarColors(@color, @bgcolor);
     }
+    &.app-friends {
+        @bgcolor: @toolbar-friends-bg;
+        @color: @toolbar-friends-color;
+        .addToolbarColors(@color, @bgcolor);
+    }
 
 }
 
diff --git a/customize.dist/src/less/variables.less b/customize.dist/src/less/variables.less
index 2ccebf170..63c737266 100644
--- a/customize.dist/src/less/variables.less
+++ b/customize.dist/src/less/variables.less
@@ -97,6 +97,8 @@
 @toolbar-drive-color: #fff;
 @toolbar-file-bg: #cd2532;
 @toolbar-file-color: #fff;
+@toolbar-friends-bg: #607B8D;
+@toolbar-friends-color: #fff;
 @toolbar-default-bg: #ddd;
 @toolbar-default-color: #000;
 
diff --git a/customize.dist/template.js b/customize.dist/template.js
index d187e9685..f6bc7cd9c 100644
--- a/customize.dist/template.js
+++ b/customize.dist/template.js
@@ -12,7 +12,7 @@ $(function () {
     var Messages = Cryptpad.Messages;
     var $body = $('body');
     var isMainApp = function () {
-        return /^\/(pad|code|slide|poll|whiteboard|file|media|drive)\/$/.test(location.pathname);
+        return /^\/(pad|code|slide|poll|whiteboard|file|media|friends|drive)\/$/.test(location.pathname);
     };
 
     var rightLink = function (ref, loc, txt) {
@@ -148,6 +148,9 @@ $(function () {
                 } else if (/file/.test(pathname)) {
                     $('body').append(h('body', Pages[pathname]()).innerHTML);
                     require([ '/file/main.js' ], ready);
+                } else if (/friends/.test(pathname)) {
+                    $('body').append(h('body', Pages[pathname]()).innerHTML);
+                    require([ '/friends/main.js' ], ready);
                 } else if (/pad/.test(pathname)) {
                     $('body').append(h('body', Pages[pathname]()).innerHTML);
                     require([ '/pad/main.js' ], ready);
diff --git a/www/common/common-messaging.js b/www/common/common-messaging.js
index 4b086b970..3af6b9d8a 100644
--- a/www/common/common-messaging.js
+++ b/www/common/common-messaging.js
@@ -1,10 +1,47 @@
 define([
+    'jquery',
     '/bower_components/chainpad-crypto/crypto.js',
-], function (Crypto) {
+], function ($, Crypto) {
     var Msg = {};
 
     var pending = {};
 
+    Msg.getFriendList = function (common) {
+        var proxy = common.getProxy();
+        return proxy.friends || {};
+    };
+
+    var avatars = {};
+    Msg.getFriendListUI = function (common) {
+        var proxy = common.getProxy();
+        var $block = $('<div>');
+        var friends = proxy.friends || {};
+        Object.keys(friends).forEach(function (f) {
+            var data = friends[f];
+            var $friend = $('<div>', {'class': 'friend'}).appendTo($block);
+            $friend.data('key', f);
+            var $rightCol = $('<span>', {'class': 'right-col'});
+            $('<span>', {'class': 'name'}).text(data.displayName).appendTo($rightCol);
+            $friend.dblclick(function () {
+                window.open('/profile/#' + data.profile);
+            });
+            $friend.click(function () {
+                // TODO
+            });
+            if (data.avatar && avatars[data.avatar]) {
+                $friend.append(avatars[data.avatar]);
+                $friend.append($rightCol);
+            } else {
+                common.displayAvatar($friend, data.avatar, data.displayName, function ($img) {
+                    if (data.avatar && $img) {
+                        avatars[data.avatar] = $img[0].outerHTML;
+                    }
+                    $friend.append($rightCol);
+                });
+            }
+        });
+    };
+
     Msg.createOwnedChannel = function (common, channelId, validateKey, owners, cb) {
         var network = common.getNetwork();
         network.join(channelId).then(function (wc) {
@@ -56,7 +93,8 @@ define([
             displayName: proxy[common.displayNameKey],
             profile: proxy.profile.view,
             edPublic: proxy.edPublic,
-            curvePublic: proxy.curvePublic
+            curvePublic: proxy.curvePublic,
+            avatar: proxy.profile.avatar
         };
     };
 
@@ -68,7 +106,6 @@ define([
     Msg.addDirectMessageHandler = function (common) {
         var network = common.getNetwork();
         if (!network) { return void console.error('Network not ready'); }
-        var proxy = common.getProxy();
         network.on('message', function (message, sender) {
             var msg;
             if (sender === network.historyKeeper) { return; }
@@ -85,7 +122,6 @@ define([
                 msg = JSON.parse(decryptMsg);
                 if (msg[1] !== parsed.hashData.channel) { return; }
                 var msgData = msg[2];
-                var msg;
                 var msgStr;
                 if (msg[0] === "FRIEND_REQ") {
                     msg = ["FRIEND_REQ_NOK", chan];
diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js
index 8d162d15e..1c0809915 100644
--- a/www/common/cryptpad-common.js
+++ b/www/common/cryptpad-common.js
@@ -1307,27 +1307,32 @@ define([
                             }
                             var $image = $img.find('img');
                             var onLoad = function () {
-                                var w = $image.width();
-                                var h = $image.height();
-                                if (w>h) {
-                                    $image.css('max-height', '100%');
+                                var img = new Image();
+                                img.src = $image.attr('src');
+                                img.onload = function () {
+                                    var w = img.width;
+                                    var h = img.height;
+                                    console.log(w,h);
+                                    if (w>h) {
+                                        $image.css('max-height', '100%');
+                                        $img.css('flex-direction', 'column');
+                                        if (cb) { cb($img); }
+                                        return;
+                                    }
+                                    $image.css('max-width', '100%');
                                     $img.css('flex-direction', 'row');
                                     if (cb) { cb($img); }
-                                    return;
-                                }
-                                $image.css('max-width', '100%');
-                                $img.css('flex-direction', 'column');
-                                if (cb) { cb($img); }
+                                };
                             };
                             if ($image[0].complete) { onLoad(); }
                             $image.on('load', onLoad);
                         }
                     });
-                    observer.observe($img[0], {
-                        attributes: false,
-                        childList: true,
-                        characterData: false
-                    });
+                });
+                observer.observe($img[0], {
+                    attributes: false,
+                    childList: true,
+                    characterData: false
                 });
             });
         }
diff --git a/www/common/toolbar2.js b/www/common/toolbar2.js
index 340a74af1..1cbc625fe 100644
--- a/www/common/toolbar2.js
+++ b/www/common/toolbar2.js
@@ -676,7 +676,7 @@ define([
         $('<span>', {'class': 'bar3'}).appendTo($container);
         $('<span>', {'class': 'bar4'}).appendTo($container);
         $('<span>', {'class': 'disconnected fa fa-exclamation-circle'}).appendTo($a);
-        if (config.realtime) {
+        if (config.network) {
             checkLag(toolbar, config, $a);
             setInterval(function () {
                 if (!toolbar.connected) { return; }
diff --git a/www/friends/index.html b/www/friends/index.html
new file mode 100644
index 000000000..a76879a6d
--- /dev/null
+++ b/www/friends/index.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class="cp pad">
+<head>
+    <title>CryptPad</title>
+    <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <script async data-bootload="/customize/template.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.1.15"></script>
+    <style>
+        html, body {
+            margin: 0px;
+            padding: 0px;
+        }
+        #pad-iframe {
+            position:fixed;
+            top:0px;
+            left:0px;
+            bottom:0px;
+            right:0px;
+            width:100%;
+            height:100%;
+            border:none;
+            margin:0;
+            padding:0;
+            overflow:hidden;
+        }
+    </style>
+</head>
+<body>
+    <iframe id="pad-iframe"></iframe><script src="/common/noscriptfix.js"></script>
+
diff --git a/www/friends/inner.html b/www/friends/inner.html
new file mode 100644
index 000000000..3809c9ac6
--- /dev/null
+++ b/www/friends/inner.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta content="text/html; charset=utf-8" http-equiv="content-type"/>
+    <script src="/bower_components/jquery/dist/jquery.min.js"></script>
+    <script async data-bootload="/friends/inner.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.1.15"></script>
+    <style>.loading-hidden, .loading-hidden * {display: none !important;}</style>
+</head>
+<body class="loading-hidden">
+    <div id="toolbar" class="toolbar-container"></div>
+    <div id="app">
+        <div id="friendList"></div>
+        <div id="messaging"></div>
+    </div>
+</body>
+</html>
+
diff --git a/www/friends/inner.js b/www/friends/inner.js
new file mode 100644
index 000000000..5ea8cf63e
--- /dev/null
+++ b/www/friends/inner.js
@@ -0,0 +1,13 @@
+define([
+    'jquery',
+    'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
+    'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
+    'less!/friends/main.less',
+    'less!/customize/src/less/toolbar.less',
+], function ($) {
+    $('.loading-hidden').removeClass('loading-hidden');
+    // dirty hack to get rid the flash of the lock background
+    setTimeout(function () {
+        $('#app').addClass('ready');
+    }, 100);
+});
diff --git a/www/friends/main.js b/www/friends/main.js
new file mode 100644
index 000000000..ce883807c
--- /dev/null
+++ b/www/friends/main.js
@@ -0,0 +1,50 @@
+define([
+    'jquery',
+    '/bower_components/chainpad-crypto/crypto.js',
+    '/common/toolbar2.js',
+    '/common/cryptpad-common.js',
+
+    'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
+    'less!/customize/src/less/cryptpad.less',
+], function ($, Crypto, Toolbar, Cryptpad) {
+    var Messages = Cryptpad.Messages;
+
+    var APP = {
+        Cryptpad: Cryptpad
+    };
+
+    $(function () {
+
+    var andThen = function () {
+        Cryptpad.addLoadingScreen();
+
+        var ifrw = $('#pad-iframe')[0].contentWindow;
+        var $iframe = $('#pad-iframe').contents();
+        var $appContainer = $iframe.find('#app');
+        var $list = $iframe.find('#friendList');
+        var $messages = $iframe.find('#messaging');
+        var $bar = $iframe.find('.toolbar-container');
+
+        var displayed = ['useradmin', 'newpad', 'limit', 'lag', 'spinner'];
+
+        var configTb = {
+            displayed: displayed,
+            ifrw: ifrw,
+            common: Cryptpad,
+            $container: $bar,
+            network: Cryptpad.getNetwork()
+        };
+        var toolbar = APP.toolbar = Toolbar.create(configTb);
+        toolbar.$rightside.html(''); // Remove the drawer if we don't use it to hide the toolbar
+        
+
+        Cryptpad.removeLoadingScreen();
+    };
+
+    Cryptpad.ready(function () {
+        andThen();
+        Cryptpad.reportAppUsage();
+    });
+
+    });
+});
diff --git a/www/friends/main.less b/www/friends/main.less
new file mode 100644
index 000000000..b6dbaf9dc
--- /dev/null
+++ b/www/friends/main.less
@@ -0,0 +1,47 @@
+@import "/customize/src/less/variables.less";
+@import "/customize/src/less/mixins.less";
+
+@button-border: 2px;
+@bg-color: @toolbar-friends-bg;
+
+html, body {
+    margin: 0px;
+    height: 100%;
+}
+
+#toolbar {
+    display: flex; // We need this to remove a 3px border at the bottom of the toolbar
+}
+
+body {
+    display: flex;
+    flex-flow: column;
+}
+#app {
+    flex: 1;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+#app.ready {
+    //background: url('/customize/bg3.jpg') no-repeat center center;
+    background-size: cover;
+    background-position: center;
+}
+.cryptpad-toolbar {
+    padding: 0px;
+    display: inline-block;
+}
+
+#friendList {
+    width: 350px;
+    height: 100%;
+    background-color: lighten(@bg-color, 10%);
+}
+
+#messaging {
+    flex: 1;
+    height: 100%;
+    background-color: lighten(@bg-color, 20%);
+}
diff --git a/www/profile/main.less b/www/profile/main.less
index d3d3f2e07..3cb7e33f9 100644
--- a/www/profile/main.less
+++ b/www/profile/main.less
@@ -57,7 +57,7 @@
                 min-height: 100%;
                 max-width: none;
                 max-height: none;
-                flex-shrink: 0;
+                flex: 1;
             }
         }
         button {