Browse Source

First bunch of dom and js changes to make chat switching and events more sane.

pull/16/head
Simon Eisenmann 11 years ago
parent
commit
c93fd57c50
  1. 81
      src/styles/components/_chat.scss
  2. 3
      static/js/controllers/chatroomcontroller.js
  3. 66
      static/js/directives/chat.js
  4. 30
      static/partials/chatroom.html

81
src/styles/components/_chat.scss

@ -27,6 +27,10 @@ top:0px;
pointer-events: none; pointer-events: none;
z-index:45; z-index:45;
overflow:hidden; overflow:hidden;
-webkit-perspective: 1000;
-moz-perspective: 1000;
-o-perspective: 1000;
perspective: 1000;
} }
.withChat #chat .chatpane { .withChat #chat .chatpane {
left:0px; left:0px;
@ -39,43 +43,71 @@ width:auto;
} }
} }
.chatpane { .chatpane {
height:100%;
position:absolute; position:absolute;
top:0px; top:0px;
left:260px; left:260px;
bottom:0px; bottom:0px;
right:0px; right:0px;
width:260px; width:260px;
-webkit-transition: left 200ms ease-in-out;
-moz-transition: left 200ms ease-in-out;
-ms-transition: left 200ms ease-in-out;
-o-transition: left 200ms ease-in-out;
transition: left 200ms ease-in-out; transition: left 200ms ease-in-out;
-webkit-transition: 0.2s;
-webkit-transform-style: preserve-3d;
-moz-transition: 0.2s;
-moz-transform-style: preserve-3d;
-o-transition: 0.2s;
-o-transform-style: preserve-3d;
transition: 0.2s;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
}
.withChat .chatpane.flip {
-webkit-transform: rotateY(360deg);
-moz-transform: rotateY(360deg);
-o-transform: rotateY(360deg);
transform: rotateY(360deg);
} }
.chat { .chat {
position:absolute;
pointer-events: auto; pointer-events: auto;
position:absolute;
top:0px; top:0px;
bottom:0px; bottom:0px;
right:0px; right:0px;
left:0px; left:0px;
background: #e7e7e7; background: #e7e7e7;
border-top: 1px solid $bordercolor;
border-right:1px solid $bordercolor; border-right:1px solid $bordercolor;
overflow:hidden; overflow:hidden;
display:none; display:none;
} }
.chat.visible { .chat.visible {
}
.chat.visible.active {
display:block; display:block;
} }
.chat .chatbody {
position:absolute;
bottom:0px;
left:0px;
right:0px;
top: 30px;
}
.chat.active .chatbody {
}
.chat .chatheader { .chat .chatheader {
position:relative;
background: $componentbg; background: $componentbg;
padding:8px 4px 0px 8px; padding:8px 4px 0px 8px;
border-top: 1px solid $bordercolor;
border-bottom: 1px solid $bordercolor; border-bottom: 1px solid $bordercolor;
border-left: 1px solid $bordercolor;
font-size:0.8em; font-size:0.8em;
font-weight:bold; font-weight:bold;
height:30px; height:30px;
} }
.chat.active .chatheader {
}
.chat .chatheader .ctrl { .chat .chatheader .ctrl {
position:absolute; position:absolute;
top:4px; top:4px;
@ -98,10 +130,8 @@ cursor: pointer;
position:absolute; position:absolute;
left:0px; left:0px;
right:0px; right:0px;
top:34px; top:0px;
bottom:74px; bottom:74px;
//max-width:600px;
margin:0 auto;
} }
.chat .output { .chat .output {
overflow-x: hidden; overflow-x: hidden;
@ -296,29 +326,32 @@ white-space:nowrap;
overflow:hidden; overflow:hidden;
text-overflow:ellipsis; text-overflow:ellipsis;
} }
.chat .chatbodybottom {
background: #e7e7e7;
position: absolute;
left:0px;
bottom:0px;
right:0px;
height:90px;
margin:0 auto;
}
.chat .typinghint { .chat .typinghint {
position:absolute; padding:6px;
left:6px; white-space: no-wrap;
right:6px; overflow: hidden;
bottom:60px;
font-size:.8em; font-size:.8em;
color: #aaa; color: #aaa;
max-width:500px; height:22px;
margin:0 auto;
} }
.chat .inputbox { .chat .inputbox {
position:absolute; position:relative;
left:0px;
bottom:0px;
right:0px;
height:60px;
//max-width:500px;
margin:0 auto;
} }
.chat .inputbox .btn { .chat .inputbox .btn {
position:absolute; position:absolute;
right:6px; right:6px;
top:4px; top:0px;
padding: 0.5em 1em; padding: 0.5em 1em;
} }
.chat .inputbox > div { .chat .inputbox > div {

3
static/js/controllers/chatroomcontroller.js

@ -25,6 +25,7 @@ define(['underscore', 'moment', 'text!partials/fileinfo.html'], function(_, mome
$scope.outputElement = $(".output", $element); $scope.outputElement = $(".output", $element);
$scope.inputElement = $(".input", $element); $scope.inputElement = $(".input", $element);
$scope.bodyElement = $(".chatbody", $element);
var lastSender = null; var lastSender = null;
var lastDate = null; var lastDate = null;
var lastMessageContainer = null; var lastMessageContainer = null;
@ -36,7 +37,7 @@ define(['underscore', 'moment', 'text!partials/fileinfo.html'], function(_, mome
var scrollAfterInput = false; var scrollAfterInput = false;
// Mark seen on several events. // Mark seen on several events.
$element.on("mouseover mouseenter touchstart", _.debounce(function(event) { $scope.bodyElement.on("mouseover mouseenter touchstart", _.debounce(function(event) {
$scope.$parent.seen(); $scope.$parent.seen();
$scope.$apply(); $scope.$apply();
}, 100)); }, 100));

66
static/js/directives/chat.js

@ -31,6 +31,7 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
$scope.layout.chatMaximized = false; $scope.layout.chatMaximized = false;
var rooms = {}; var rooms = {};
var visibleRooms = [];
mediaStream.api.e.on("received.chat", function(event, id, from, data, p2p) { mediaStream.api.e.on("received.chat", function(event, id, from, data, p2p) {
@ -91,14 +92,19 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
$scope.$parent.$on("startchat", function(event, id, options) { $scope.$parent.$on("startchat", function(event, id, options) {
//console.log("startchat requested", event, id); //console.log("startchat requested", event, id);
$scope.showRoom(id, {title: translation._("Chat with")}, options); if (id === group_chat_id) {
$scope.showGroupRoom(null, options);
} else {
$scope.showRoom(id, {title: translation._("Chat with")}, options);
}
}); });
// Shared data; // Shared data;
return { return {
rooms: rooms, rooms: rooms,
visibleRooms: [], visibleRooms: visibleRooms,
group: group_chat_id,
get: function(id) { get: function(id) {
return rooms[id]; return rooms[id];
} }
@ -111,6 +117,10 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
var chat = $compile(templateChatroom); var chat = $compile(templateChatroom);
return function(scope, iElement, iAttrs, controller) { return function(scope, iElement, iAttrs, controller) {
scope.showGroupRoom = function(settings, options) {
var stngs = $.extend({title: translation._("Room chat")}, settings);
return scope.showRoom(controller.group, stngs, options);
};
scope.currentRoom = null; scope.currentRoom = null;
scope.showRoom = function(id, settings, options) { scope.showRoom = function(id, settings, options) {
var options = $.extend({}, options); var options = $.extend({}, options);
@ -122,7 +132,7 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
subscope = controller.rooms[id] = scope.$new(); subscope = controller.rooms[id] = scope.$new();
translation.inject(subscope); translation.inject(subscope);
subscope.id = id; subscope.id = id;
subscope.isgroupchat = id === group_chat_id ? true : false; subscope.isgroupchat = id === controller.group ? true : false;
subscope.index = index; subscope.index = index;
subscope.settings = settings; subscope.settings = settings;
subscope.visible = false; subscope.visible = false;
@ -131,6 +141,7 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
subscope.peerIsTyping = "no"; subscope.peerIsTyping = "no";
subscope.firstmessage = true; subscope.firstmessage = true;
subscope.p2pstate = false; subscope.p2pstate = false;
subscope.active = false;
if (!subscope.isgroupchat) { if (!subscope.isgroupchat) {
buddyData.push(id); buddyData.push(id);
} }
@ -151,7 +162,7 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
subscope.$broadcast("seen"); subscope.$broadcast("seen");
} }
}; };
subscope.toggle = function() { subscope.toggleMax = function() {
scope.toggleMax(); scope.toggleMax();
}; };
subscope.sendChat = function(to, message, status, mid, noloop) { subscope.sendChat = function(to, message, status, mid, noloop) {
@ -273,9 +284,7 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
if (options.autofocus && subscope.visible) { if (options.autofocus && subscope.visible) {
subscope.$broadcast("focus"); subscope.$broadcast("focus");
} }
}
if (scope.currentRoom !== subscope && scope.currentRoom) {
scope.currentRoom.hide();
} }
if (options.restore && !options.noenable) { if (options.restore && !options.noenable) {
@ -284,7 +293,10 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
} }
} }
scope.currentRoom = subscope; if (!options.noactivate) {
scope.activateRoom(subscope.id, true);
}
safeApply(subscope); safeApply(subscope);
return subscope; return subscope;
}; };
@ -309,10 +321,9 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
scope.currentRoom = null; scope.currentRoom = null;
} }
if (!controller.visibleRooms.length) { if (!controller.visibleRooms.length) {
scope.showRoom(group_chat_id, {title: translation._("Room chat")}, {restore: true, noenable: true}); scope.showGroupRoom(null, {restore: true, noenable: true, activate: true});
if (id === group_chat_id) { // If last visible room was removed, hide chat.
scope.layout.chat = false; scope.layout.chat = false;
}
} }
}; };
scope.killRoom = function(id) { scope.killRoom = function(id) {
@ -329,17 +340,38 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
scope.toggleMax = function() { scope.toggleMax = function() {
scope.layout.chatMaximized = !scope.layout.chatMaximized; scope.layout.chatMaximized = !scope.layout.chatMaximized;
}; };
scope.activateRoom = function(id, active) {
var subscope = controller.rooms[id];
//console.log("toggleActive", active, id, scope.currentRoom, scope.currentRoom == subscope, subscope.active);
if (scope.currentRoom == subscope) {
subscope.active = active;
} else {
if (scope.currentRoom) {
scope.currentRoom.active = false;
scope.currentRoom.hide();
}
if (active) {
scope.currentRoom = subscope;
iElement.toggleClass("flip");
}
subscope.active = active;
}
};
scope.$on("room", function(event, room) { scope.$on("room", function(event, room) {
if (room == null) { if (room == null) {
scope.hideRoom(group_chat_id); scope.hideRoom(controller.group);
} else { } else {
var subscope;
if (!controller.visibleRooms.length) { if (!controller.visibleRooms.length) {
scope.showRoom(group_chat_id, {title: translation._("Room chat")}, {restore: true, noenable: true}); subscope = scope.showGroupRoom(null, {restore: true, noenable: true});
} else {
subscope = controller.get(controller.group);
}
if (room) {
var msg = translation._("You are now in room %s ...", room);
subscope.$broadcast("display", null, $("<i><span>"+msg+"</span></i>"));
} }
var subscope = controller.get(group_chat_id);
var msg = translation._("You are now in room %s ...", room);
subscope.$broadcast("display", null, $("<i><span>"+msg+"</span></i>"));
} }
}); });

30
static/partials/chatroom.html

@ -1,16 +1,20 @@
<div ng-controller="ChatroomController" class="chat room-{{index}}" ng-class="{'newmessage': newmessage, 'visible': visible, 'chat-p2p': 'p2pstate', 'with_pictures': isgroupchat}"> <div ng-controller="ChatroomController" class="chat room-{{index}}" ng-class="{'newmessage': newmessage, 'visible': visible, 'chat-p2p': 'p2pstate', 'with_pictures': isgroupchat, 'active': active}">
<div class="chatheader"><span ng-show="p2pstate" class="fa fa-exchange" title="{{_('Peer to peer')}}"/><span>{{settings.title}} {{id|displayName}}</span> <div class="ctrl"><i ng-hide="layout.chatMaximized" ng-click="toggle()" class="fa fa-expand"></i><i ng-show="layout.chatMaximized" ng-click="toggle()" class="fa fa-compress"></i><i title="{{_('Close chat')}}" ng-click="hide()" class="fa fa-times"></i></div></div> <div class="chatheader"><span ng-show="p2pstate" class="fa fa-exchange" title="{{_('Peer to peer')}}"/><span>{{settings.title}} {{id|displayName}}</span> <div class="ctrl"><i ng-hide="layout.chatMaximized" ng-click="toggleMax()" class="fa fa-expand"></i><i ng-show="layout.chatMaximized" ng-click="toggleMax()" class="fa fa-compress"></i><i title="{{_('Close chat')}}" ng-click="hide()" class="fa fa-times"></i></div></div>
<div class="outputbox"> <div class="chatbody">
<div class="output nicescroll"></div> <div class="outputbox">
</div> <div class="output nicescroll"></div>
<div class="typinghint" ng-switch on="peerIsTyping"> </div>
<span ng-switch-when="start"><i class="fa fa-pencil"></i> {{id|displayName}} {{_('is typing...')}}</span> <div class="chatbodybottom">
<span ng-switch-when="stop"><i class="fa fa-pencil"></i> {{id|displayName}} {{_('has stopped typing...')}}</span> <div class="typinghint" ng-switch on="peerIsTyping">
</div> <span ng-switch-when="start"><i class="fa fa-pencil"></i> {{id|displayName}} {{_('is typing...')}}</span>
<div class="inputbox"> <span ng-switch-when="stop"><i class="fa fa-pencil"></i> {{id|displayName}} {{_('has stopped typing...')}}</span>
<div> </div>
<textarea class="input nicescroll form-control" ng-disabled="!(enabled)" on-enter="submit()" ng-model="input" placeholder="{{_('Type here to chat...')}}"/> <div class="inputbox">
<div>
<textarea class="input nicescroll form-control" ng-disabled="!(enabled)" on-enter="submit()" ng-model="input" placeholder="{{_('Type here to chat...')}}"/>
</div>
<a ng-disabled="!(enabled)" ng-click="submit()" title="{{_('Send')}}" class="btn btn-small btn-info fa fa-play"></a>
</div>
</div> </div>
<a ng-disabled="!(enabled)" ng-click="submit()" title="{{_('Send')}}" class="btn btn-small btn-info fa fa-play"></a>
</div> </div>
</div> </div>

Loading…
Cancel
Save