Browse Source

Implemented pictures for session.

pull/67/head
Simon Eisenmann 11 years ago
parent
commit
f38fd982aa
  1. 25
      src/styles/components/_buddylist.scss
  2. 2
      static/css/main.min.css
  3. 64
      static/js/filters/buddyimagesrc.js
  4. 74
      static/js/services/buddylist.js
  5. 69
      static/js/services/buddypicture.js
  6. 3
      static/js/services/services.js
  7. 2
      static/partials/buddy.html
  8. 13
      static/partials/buddyactions.html

25
src/styles/components/_buddylist.scss

@ -154,6 +154,7 @@ @@ -154,6 +154,7 @@
.#{$fa-css-prefix} {
color: $actioncolor2;
line-height: 46px;
font-size: 3em;
}
img {
bottom: 0;
@ -172,6 +173,7 @@ @@ -172,6 +173,7 @@
margin-right:4px;
.#{$fa-css-prefix} {
line-height: 30px;
font-size: 2em;
}
}
.buddy1 {
@ -201,9 +203,10 @@ @@ -201,9 +203,10 @@
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
display: inline-block;
width:174px;
text-align:left;
vertical-align:middle;
display: inline-block;
width: 132px;
}
}
@ -220,28 +223,32 @@ @@ -220,28 +223,32 @@
transition-duration: .3s;
white-space: nowrap;
z-index: 5;
.#{$fa-css-prefix} {
font-size: 1.5em;
pointer-events: none;
> .btn {
width: 42px;
height: 40px;
padding: 0px;
text-align: center;
font-size: 2em;
}
}
.buddy .buddysessions {
margin-top: 56px;
max-height:0px;
margin-bottom: 10px;
transition-property: max-height;
transition-duration: 1s;
transition-delay: .1s;
ul {
padding-top: 10px;
margin-left: 14px;
margin: 0 10px 0 14px;
padding-left: 0px;
border-left: 1px dotted $bordercolor;
}
ul li {
margin-bottom: 1px;
margin-top: 1px;
margin-left: -4px;
margin-bottom: 4px;
margin-top: 2px;
margin-left: 0px;
list-style-type: none;
}
.currentsession .buddy3 {

2
static/css/main.min.css vendored

File diff suppressed because one or more lines are too long

64
static/js/filters/buddyimagesrc.js

@ -20,33 +20,6 @@ @@ -20,33 +20,6 @@
*/
define(["underscore"], function(_) {
// Simple function which converts data urls to blobs, both base64 or not.
var dataURLToBlob = (function() {
var is_base64 = ";base64,";
return function(dataURL) {
var parts, ct;
if (dataURL.indexOf(is_base64) === -1) {
// No base64.
parts = dataURL.split(",");
ct = parts[0].split(":")[1];
return new Blob([parts[1]], {
type: ct
});
}
parts = dataURL.split(is_base64);
ct = parts[0].split(":")[1];
var data = window.atob(parts[1]);
var length = data.length;
var buffer = new Uint8Array(length);
for (var i = 0; i < length; i++) {
buffer[i] = data.charCodeAt(i);
}
return new Blob([buffer], {
type: ct
});
};
}());
// Create URLs for blobs.
var blobToObjectURL = function(blob) {
return URL.createObjectURL(blob);
@ -57,7 +30,7 @@ define(["underscore"], function(_) { @@ -57,7 +30,7 @@ define(["underscore"], function(_) {
};
// buddyImageSrc
return ["buddyData", "appData", function(buddyData, appData) {
return ["buddyData", "buddyPicture", "appData", function(buddyData, buddyPicture, appData) {
// Cache created blob urls.
var urls = {};
@ -75,24 +48,35 @@ define(["underscore"], function(_) { @@ -75,24 +48,35 @@ define(["underscore"], function(_) {
});
}, 5000);
return function(id) {
return function(id, display) {
var scope = buddyData.lookup(id, false, true);
if (scope) {
var display = scope.display;
if (display) {
if (typeof(display) === "undefined") {
var scope = buddyData.lookup(id, false, true);
if (scope) {
display = scope.display;
}
}
if (display) {
if (display.buddyPictureLocalUrl) {
return display.buddyPictureLocalUrl;
} else if (display.buddyPicture) {
var url = urls[id];
if (url) {
revokeURL(id, url);
}
// No existing data. Check if service does find something.
buddyPicture.update(display);
if (display.buddyPictureLocalUrl) {
return display.buddyPictureLocalUrl;
} else if (display.buddyPicture) {
var url = urls[id];
if (url) {
revokeURL(id, url);
}
// New data -> new url.
var blob = dataURLToBlob(display.buddyPicture);
}
// Check if we should handle it as blob.
url = display.buddyPicture;
if (url.indexOf("data:") === 0) {
var blob = buddyPicture.toBlob(null, url);
url = display.buddyPictureLocalUrl = urls[id] = blobToObjectURL(blob);
return url;
}
return null;
}
} else {
var data = appData.get();

74
static/js/services/buddylist.js

@ -129,7 +129,7 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text! @@ -129,7 +129,7 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
};
// buddyList
return ["$window", "$compile", "playSound", "buddyData", "buddySession", "fastScroll", "mediaStream", "animationFrame", "$q", function($window, $compile, playSound, buddyData, buddySession, fastScroll, mediaStream, animationFrame, $q) {
return ["$window", "$compile", "playSound", "buddyData", "buddySession", "buddyPicture", "fastScroll", "mediaStream", "animationFrame", "$q", function($window, $compile, playSound, buddyData, buddySession, buddyPicture, fastScroll, mediaStream, animationFrame, $q) {
var buddyTemplate = $compile(templateBuddy);
var buddyActions = $compile(templateBuddyActions);
@ -378,55 +378,6 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text! @@ -378,55 +378,6 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
};
Buddylist.prototype.updateBuddyPicture = function(status) {
url = status.buddyPicture;
if (!url) {
return;
}
if (url.indexOf("img:") === 0) {
status.buddyPicture = status.buddyPictureLocalUrl = mediaStream.url.buddy(url.substr(4));
}
};
Buddylist.prototype.dumpBuddyPictureToBlob = function(scope, data) {
if (!data) {
data = this.dumpBuddyPictureToString(scope);
if (!data) {
return null;
}
}
// NOTE(longsleep): toBlob is not widely supported narf ..
// see: https://code.google.com/p/chromium/issues/detail?id=67587
var parts = data.match(/data:([^;]*)(;base64)?,([0-9A-Za-z+\/]+)/);
var binStr = atob(parts[3]);
var buf = new ArrayBuffer(binStr.length);
var view = new Uint8Array(buf);
for (var i = 0; i < view.length; i++) {
view[i] = binStr.charCodeAt(i);
}
return new Blob([view], {'type': parts[1]});
};
Buddylist.prototype.dumpBuddyPictureToString = function(scope) {
var img = scope.element.find(".buddyPicture img").get(0);
if (img) {
var canvas = $window.document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
return canvas.toDataURL("image/jpeg");
}
return null;
};
Buddylist.prototype.setDisplay = function(id, scope, data, queueName) {
var status = data.Status;
@ -434,8 +385,7 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text! @@ -434,8 +385,7 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
// Set display.name.
display.displayName = status.displayName;
// Set display.picture.
display.buddyPicture = status.buddyPicture;
this.updateBuddyPicture(display);
buddyPicture.update(display, status.buddyPicture);
// Set display subline.
this.updateSubline(display, status.message);
// Add to render queue when no element exists.
@ -473,11 +423,9 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text! @@ -473,11 +423,9 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
}
// Update display picture.
if (contact) {
display.buddyPicture = contact.buddyPicture || status.buddyPicture || null;
this.updateBuddyPicture(display);
buddyPicture.update(display, contact.buddyPicture || status.buddyPicture || null);
} else if (status.buddyPicture) {
display.buddyPicture = status.buddyPicture || null;
this.updateBuddyPicture(display);
buddyPicture.update(display, status.buddyPicture || null);
}
};
@ -640,7 +588,7 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text! @@ -640,7 +588,7 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
delete status.message;
// Convert buddy image.
if (status.buddyPicture) {
var img = this.dumpBuddyPictureToString(scope);
var img = buddyPicture.toString(scope.element.find(".buddyPicture img").get(0));
if (img) {
status.buddyPicture = img;
} else {
@ -684,10 +632,16 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text! @@ -684,10 +632,16 @@ define(['underscore', 'modernizr', 'avltree', 'text!partials/buddy.html', 'text!
Buddylist.prototype.click = function(buddyElement, target) {
//console.log("click handler", buddyElement, target);
var action = $(target).data("action");
var be = buddyElement.get(0);
// Traverse up to find click action.
var action;
do {
action = $(target).data("action");
target = $(target).parent().get(0);
} while (!action && target && target !== be);
// Make call the default action.
if (!action) {
// Make call the default action.
action = "chat";
}

69
static/js/services/buddypicture.js

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
/*
* Spreed WebRTC.
* Copyright (C) 2013-2014 struktur AG
*
* This file is part of Spreed WebRTC.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
define(['underscore'], function(underscore) {
// buddyPicture
return ["mediaStream", "$window", function(mediaStream, $window) {
var buddyPicture = {
update: function(data, url) {
if (typeof(url) !== "undefined") {
data.buddyPicture = url;
} else {
url = data.buddyPicture;
}
if (!url) {
return;
}
if (url.indexOf("img:") === 0) {
data.buddyPicture = data.buddyPictureLocalUrl = mediaStream.url.buddy(url.substr(4));
}
},
toString: function(img, mime_type) {
if (img) {
if (typeof(mime_type) === "undefined") {
mime_type = "image/jpeg";
}
var canvas = $window.document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
return canvas.toDataURL(mime_type);
}
return null;
}
};
return buddyPicture;
}];
});

3
static/js/services/services.js

@ -28,6 +28,7 @@ define([ @@ -28,6 +28,7 @@ define([
'services/appdata',
'services/buddydata',
'services/buddylist',
'services/buddypicture',
'services/enrichmessage',
'services/safemessage',
'services/alertify',
@ -56,6 +57,7 @@ mediaStream, @@ -56,6 +57,7 @@ mediaStream,
appData,
buddyData,
buddyList,
buddyPicture,
enrichMessage,
safeMessage,
alertify,
@ -86,6 +88,7 @@ animationFrame) { @@ -86,6 +88,7 @@ animationFrame) {
appData: appData,
buddyData: buddyData,
buddyList: buddyList,
buddyPicture: buddyPicture,
enrichMessage: enrichMessage,
safeMessage: safeMessage,
alertify: alertify,

2
static/partials/buddy.html

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<div class="buddy" ng-class="{'contact': contact, 'withSubline': display.subline || session.Userid}">
<div class="buddyPicture"><i class="fa fa-user fa-3x"/><img ng-show="display.buddyPicture" alt ng-src="{{display.buddyPicture}}" width="46" height="46"/></div>
<div class="buddyPicture"><i class="fa fa-user"/><img ng-show="display.buddyPicture" alt ng-src="{{display.buddyPicture}}"/></div>
<div class="buddy1">{{session.Id|displayName}}</div>
<div class="buddy2"><span ng-show="session.Userid"><i class="fa contact" data-action="contact"></i><span ng-show="session.count"> ({{session.count}})</span></span> <span title="{{display.sublineFull}}">{{display.subline}}</span></div>
</div>

13
static/partials/buddyactions.html

@ -1,11 +1,18 @@ @@ -1,11 +1,18 @@
<div class="buddyhover">
<div class="buddyactions active">
<a class="btn btn-info" data-action="call" title="{{_('Start video call')}}"><i class="fa fa-phone fa-fw"></i></a>
<a class="btn btn-info" data-action="chat" title="{{_('Start chat')}}"><i class="fa fa-comments-o fa-fw"></i></a>
<a class="btn btn-info" data-action="call" title="{{_('Start video call')}}"><i class="fa fa-phone"></i></a>
<a class="btn btn-info" data-action="chat" title="{{_('Start chat')}}"><i class="fa fa-comments-o"></i></a>
</div>
<div class="buddysessions" ng-if="session.count>1">
<ul>
<li ng-repeat="(id, s) in session.sessions" ng-class="{currentsession: s.Id === session.Id}"><span class="btn-group"><a class="btn btn-sm btn-default buddy3" ng-click="$event.stopPropagation()"><span>{{s.Status.displayName}}<span ng-show="s.Status.message">, {{s.Status.message}}</span></span></a><a class="btn btn-sm btn-default" title="{{_('Start video call')}}" ng-click="doCall(s.Id); $event.stopPropagation()"><i class="fa fa-eye"></i></a><a class="btn btn-sm btn-default" title="{{_('Start chat')}}" ng-click="doChat(s.Id); $event.stopPropagation()"><i class="fa fa-comments-o"></i></a></span></li>
<li ng-repeat="(id, s) in session.sessions" ng-class="{currentsession: s.Id === session.Id}">
<span>
<div class="buddyPicture buddyPictureSmall"><i class="fa fa-user"/><img ng-show="s.Status.buddyPicture" alt ng-src="{{s.Id|buddyImageSrc:s.Status}}"/></div>
<div class="buddy3" title="{{s.Status.message}}">{{s.Status.displayName}}<span ng-show="s.Status.message">, {{s.Status.message}}</span></div>
<a class="btn btn-sm btn-default" title="{{_('Start video call')}}" ng-click="doCall(s.Id); $event.stopPropagation()"><i class="fa fa-phone"></i></a>
<a class="btn btn-sm btn-default" title="{{_('Start chat')}}" ng-click="doChat(s.Id); $event.stopPropagation()"><i class="fa fa-comments-o"></i></a>
</span>
</li>
</ul>
</div>
</div>

Loading…
Cancel
Save