Browse Source

Refactor web app room logic into separate service.

Contains the following major changes:
  * Export connector, api, and webrtc mediastream objects as angular services.
  * Export url formatter as a separate angular service.
  * Move `authorizing` flag to a function on the root scope.
  * Use directive to set the page title.
  * Move buddy list visibility toggling into the  buddy list directive.
  * Room information is no longer exposed on the root scope.
  * Use room.joined and room.left events instead of room.
  * Treat rooms as an object identified by name, rather than a string id.
  * Remove the following unused or semantically ambiguous events from the
    connector: opened, helloed, closed
  * Centralize all room state in an angular service.
  * Move call to hello from connector to api.
pull/112/head
Lance Cooper 11 years ago committed by Simon Eisenmann
parent
commit
9118194e89
  1. 3
      static/js/app.js
  2. 61
      static/js/controllers/mediastreamcontroller.js
  3. 69
      static/js/controllers/roomchangecontroller.js
  4. 63
      static/js/directives/buddylist.js
  5. 38
      static/js/directives/chat.js
  6. 8
      static/js/directives/directives.js
  7. 54
      static/js/directives/page.js
  8. 24
      static/js/directives/roombar.js
  9. 10
      static/js/directives/socialshare.js
  10. 48
      static/js/directives/title.js
  11. 40
      static/js/directives/usability.js
  12. 24
      static/js/mediastream/api.js
  13. 59
      static/js/mediastream/connector.js
  14. 27
      static/js/services/api.js
  15. 4
      static/js/services/buddypicture.js
  16. 27
      static/js/services/connector.js
  17. 141
      static/js/services/mediastream.js
  18. 38
      static/js/services/resturl.js
  19. 152
      static/js/services/rooms.js
  20. 23
      static/js/services/services.js
  21. 27
      static/js/services/webrtc.js
  22. 12
      static/partials/chat.html
  23. 8
      static/partials/page/welcome.html
  24. 4
      static/partials/roombar.html
  25. 1
      static/partials/usability.html

3
static/js/app.js

@ -184,6 +184,9 @@ define([ @@ -184,6 +184,9 @@ define([
var deferred = $.Deferred();
var globalContext = JSON.parse($("#globalcontext").text());
if (!globalContext.Cfg.Version) {
globalContext.Cfg.Version = "unknown";
}
app.constant("globalContext", globalContext);
// Configure language.

61
static/js/controllers/mediastreamcontroller.js

@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
*/
define(['underscore', 'bigscreen', 'moment', 'sjcl', 'modernizr', 'webrtc.adapter'], function(_, BigScreen, moment, sjcl, Modernizr) {
return ["$scope", "$rootScope", "$element", "$window", "$timeout", "safeDisplayName", "safeApply", "mediaStream", "appData", "playSound", "desktopNotify", "alertify", "toastr", "translation", "fileDownload", "localStorage", "screensharing", "userSettingsData", "localStatus", "dialogs", function($scope, $rootScope, $element, $window, $timeout, safeDisplayName, safeApply, mediaStream, appData, playSound, desktopNotify, alertify, toastr, translation, fileDownload, localStorage, screensharing, userSettingsData, localStatus, dialogs) {
return ["$scope", "$rootScope", "$element", "$window", "$timeout", "safeDisplayName", "safeApply", "mediaStream", "appData", "playSound", "desktopNotify", "alertify", "toastr", "translation", "fileDownload", "localStorage", "screensharing", "userSettingsData", "localStatus", "dialogs", "rooms", function($scope, $rootScope, $element, $window, $timeout, safeDisplayName, safeApply, mediaStream, appData, playSound, desktopNotify, alertify, toastr, translation, fileDownload, localStorage, screensharing, userSettingsData, localStatus, dialogs, rooms) {
/*console.log("route", $route, $routeParams, $location);*/
@ -544,20 +544,16 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'modernizr', 'webrtc.adapte @@ -544,20 +544,16 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'modernizr', 'webrtc.adapte
// Unmark authorization process.
if (data.Userid) {
mediaStream.users.authorizing(false);
} else if (!mediaStream.users.authorizing()) {
$rootScope.authorizing(false);
} else if (!$rootScope.authorizing()) {
// Trigger user data load when not in authorizing phase.
$scope.loadUserSettings();
}
if (!$rootScope.roomid && $scope.master.settings.defaultRoom) {
if (rooms.inDefaultRoom() && $scope.master.settings.defaultRoom) {
console.log("Selecting default room from settings:", [$scope.master.settings.defaultRoom]);
mediaStream.changeRoom($scope.master.settings.defaultRoom, true);
rooms.joinByName($scope.master.settings.defaultRoom, true);
}
// Always apply room after self received to avoid double stuff.
mediaStream.applyRoom();
});
mediaStream.webrtc.e.on("peercall", function(event, peercall) {
@ -660,36 +656,36 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'modernizr', 'webrtc.adapte @@ -660,36 +656,36 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'modernizr', 'webrtc.adapte
}
};
mediaStream.connector.e.on("open error close", function(event, options) {
var t = event.type;
var opts = $.extend({}, options);
$scope.$on("room.joined", function(ev) {
// TODO(lcooper): Is it really needful to do this stuff?
$timeout.cancel(ttlTimeout);
if (!opts.soft) {
// Reset login information for anything not soft.
$scope.userid = $scope.suserid = null;
}
switch (t) {
connected = true;
reconnecting = false;
$scope.updateStatus(true);
});
mediaStream.connector.e.on("open error close", function(event) {
$timeout.cancel(ttlTimeout);
$scope.userid = $scope.suserid = null;
switch (event.type) {
case "open":
t = "waiting";
connected = true;
reconnecting = false;
$scope.updateStatus(true);
if (opts.soft) {
return;
}
$scope.setStatus("waiting");
break;
case "error":
if (reconnecting || connected) {
reconnecting = false;
reconnect();
return;
} else {
$scope.setStatus(event.type);
}
break;
case "close":
reconnect();
return;
break;
}
$scope.setStatus(t);
});
mediaStream.webrtc.e.on("waitforusermedia connecting", function(event, currentcall) {
@ -797,23 +793,6 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'modernizr', 'webrtc.adapte @@ -797,23 +793,6 @@ define(['underscore', 'bigscreen', 'moment', 'sjcl', 'modernizr', 'webrtc.adapte
if (mediaStream.connector.connected) {
$scope.setStatus("waiting");
}
if ($scope.roomstatus) {
$scope.layout.buddylist = true;
$scope.layout.buddylistAutoHide = false;
} else {
$scope.layout.buddylist = false;
$scope.layout.buddylistAutoHide = true;
}
});
$scope.$watch("roomstatus", function(roomstatus) {
if (roomstatus && !$scope.peer) {
$scope.layout.buddylist = true;
$scope.layout.buddylistAutoHide = false;
} else if (!$scope.layout.buddylistAutoHide) {
$scope.layout.buddylist = false;
$scope.layout.buddylistAutoHide = true;
}
});
mediaStream.webrtc.e.on("busy", function(event, from) {

69
static/js/controllers/roomchangecontroller.js

@ -19,72 +19,7 @@ @@ -19,72 +19,7 @@
*
*/
define([], function() {
// RoomchangeController
return ["$scope", "$element", "$window", "mediaStream", "$http", "$timeout", function($scope, $element, $window, mediaStream, $http, $timeout) {
//console.log("Room change controller", $element, $scope.roomdata);
var url = mediaStream.url.api("rooms");
var ctrl = this;
ctrl.enabled = true;
ctrl.getRoom = function(cb) {
$http({
method: "POST",
url: url,
data: $.param({}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).
success(function(data, status) {
cb(data);
}).
error(function() {
console.error("Failed to retrieve room link.");
cb({});
});
};
$scope.changeRoomToId = function(id) {
return mediaStream.changeRoom(id);
};
$scope.refreshRoom = function() {
if (ctrl.enabled) {
ctrl.getRoom(function(roomdata) {
console.info("Retrieved room data", roomdata);
$scope.roomdata = roomdata;
$element.find(".btn-roomcreate").get(0).focus();
});
}
};
$scope.$on("$destroy", function() {
//console.log("Room change controller destroyed");
ctrl.enabled = false;
});
$scope.roomdata = {};
$scope.$watch("roomdata.name", function(n) {
//console.log("roomdata.name changed", n);
if (!n) {
n = "";
}
var u = encodeURIComponent(n);
$scope.roomdata.url = "/" + u;
$scope.roomdata.link = mediaStream.url.room(n);
});
var roomDataLinkInput = $element.find(".roomdata-link-input");
if (roomDataLinkInput.length) {
$timeout(function() {
$scope.refreshRoom();
}, 100);
}
return ["$scope", "rooms", function($scope, rooms) {
$scope.joinRoomByName = rooms.joinByName;
}];
});

63
static/js/directives/buddylist.js

@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
define(['underscore', 'text!partials/buddylist.html'], function(_, template) {
// buddyList
return ["$compile", "buddyList", "mediaStream", "contacts", function($compile, buddyList, mediaStream, contacts) {
return ["buddyList", "api", "webrtc", "contacts", function(buddyList, api, webrtc, contacts) {
//console.log("buddyList directive");
@ -30,10 +30,34 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) { @@ -30,10 +30,34 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) {
$scope.layout.buddylist = false;
$scope.layout.buddylistAutoHide = true;
$scope.doCall = function(id) {
var inRoom = false;
var updateBuddyListVisibility = function() {
if (inRoom && !$scope.peer) {
$scope.layout.buddylist = true;
$scope.layout.buddylistAutoHide = false;
} else if (!$scope.layout.buddylistAutoHide) {
$scope.layout.buddylist = false;
$scope.layout.buddylistAutoHide = true;
}
};
webrtc.e.on("done", function() {
updateBuddyListVisibility();
});
mediaStream.webrtc.doCall(id);
$scope.$on("room.joined", function(ev, room) {
inRoom = true;
updateBuddyListVisibility();
});
$scope.$on("room.left", function(ev) {
inRoom = false;
buddylist.onClosed();
updateBuddyListVisibility();
});
$scope.doCall = function(id) {
webrtc.doCall(id);
};
$scope.doChat = function(id) {
@ -61,23 +85,6 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) { @@ -61,23 +85,6 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) {
};
/*
$scope.doAudioConference = function(id) {
$scope.updateAutoAccept(id);
mediaStream.api.sendChat(id, null, {
AutoCall: {
Type: "conference",
Id: mediaStream.connector.roomid
}
})
};*/
$scope.setRoomStatus = function(status) {
$scope.$emit("roomStatus", status);
};
var buddylist = $scope.buddylist = buddyList.buddylist($element, $scope, {});
var onJoined = _.bind(buddylist.onJoined, buddylist);
var onLeft = _.bind(buddylist.onLeft, buddylist);
@ -85,15 +92,14 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) { @@ -85,15 +92,14 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) {
var onContactAdded = _.bind(buddylist.onContactAdded, buddylist);
var onContactRemoved = _.bind(buddylist.onContactRemoved, buddylist);
var onContactUpdated = _.bind(buddylist.onContactUpdated, buddylist);
mediaStream.api.e.on("received.userleftorjoined", function(event, dataType, data) {
api.e.on("received.userleftorjoined", function(event, dataType, data) {
if (dataType === "Left") {
onLeft(data);
} else {
onJoined(data);
}
});
mediaStream.api.e.on("received.users", function(event, data) {
$scope.setRoomStatus(true);
api.e.on("received.users", function(event, data) {
var selfId = $scope.id;
_.each(data, function(p) {
if (p.Id !== selfId) {
@ -102,17 +108,10 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) { @@ -102,17 +108,10 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) {
});
$scope.$apply();
});
mediaStream.api.e.on("received.status", function(event, data) {
api.e.on("received.status", function(event, data) {
onStatus(data);
});
mediaStream.connector.e.on("closed error", function() {
$scope.setRoomStatus(false);
buddylist.onClosed();
});
// Request user list whenever the connection comes ready.
mediaStream.connector.ready(function() {
mediaStream.api.requestUsers();
});
// Contacts.
contacts.e.on("contactadded", function(event, data) {
onContactAdded(data);

38
static/js/directives/chat.js

@ -44,16 +44,13 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'], @@ -44,16 +44,13 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
var res = [];
for (var i = 0; i < ctrl.visibleRooms.length; i++) {
var r = rooms[ctrl.visibleRooms[i]];
if (!r || r.id === ctrl.group) {
if (!r) {
continue;
}
res.push(r);
}
return res;
};
$scope.getGroupRoom = function() {
return rooms[ctrl.group];
};
mediaStream.api.e.on("received.chat", function(event, id, from, data, p2p) {
@ -182,22 +179,31 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'], @@ -182,22 +179,31 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
scope.showGroupRoom = function(settings, options) {
var stngs = $.extend({
title: translation._("Room chat")
title: translation._("Room chat"),
group: true
}, settings);
return scope.showRoom(controller.group, stngs, options);
};
scope.hideGroupRoom = function(settings, options) {
return scope.hideRoom(controller.group);
};
scope.showRoom = function(id, settings, opts) {
var options = $.extend({}, opts);
var subscope = controller.rooms[id];
var index = controller.visibleRooms.length;
if (!subscope) {
console.log("Create new chatroom", [id]);
controller.visibleRooms.push(id);
if (settings.group) {
controller.visibleRooms.unshift(id);
} else {
controller.visibleRooms.push(id);
}
subscope = controller.rooms[id] = scope.$new();
translation.inject(subscope);
subscope.id = id;
subscope.isgroupchat = id === controller.group ? true : false;
subscope.isgroupchat = !!settings.group;
subscope.index = index;
subscope.settings = settings;
subscope.visible = false;
@ -474,11 +480,6 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'], @@ -474,11 +480,6 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
scope.currentRoomActive = false;
}
if (!controller.visibleRooms.length) {
scope.showGroupRoom(null, {
restore: true,
noenable: true,
noactivate: true
});
// If last visible room was removed, hide chat.
scope.layout.chat = false;
}
@ -544,18 +545,21 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'], @@ -544,18 +545,21 @@ define(['underscore', 'text!partials/chat.html', 'text!partials/chatroom.html'],
scope.layout.chatMaximized = false;
});
scope.$on("room", function(event, room) {
scope.$on("room.joined", function(event, room) {
var subscope = scope.showGroupRoom(null, {
restore: true,
noenable: true,
noactivate: true
});
if (room) {
var msg = $("<span>").text(translation._("You are now in room %s ...", room));
subscope.$broadcast("display", null, $("<i>").append(msg));
}
scope.currentRoomName = room.name;
var msg = $("<span>").text(translation._("You are now in room %s ...", room.name));
subscope.$broadcast("display", null, $("<i>").append(msg));
});
scope.$on("room.left", function(event) {
scope.hideGroupRoom();
scope.currentRoomName = null;
});
};
};

8
static/js/directives/directives.js

@ -43,7 +43,8 @@ define([ @@ -43,7 +43,8 @@ define([
'directives/odfcanvas',
'directives/presentation',
'directives/youtubevideo',
'directives/bfi'], function(_, onEnter, onEscape, statusMessage, buddyList, buddyPictureCapture, buddyPictureUpload, settings, chat, audioVideo, usability, audioLevel, fileInfo, screenshare, roomBar, socialShare, page, contactRequest, defaultDialog, pdfcanvas, odfcanvas, presentation, youtubevideo, bfi) {
'directives/bfi',
'directives/title'], function(_, onEnter, onEscape, statusMessage, buddyList, buddyPictureCapture, buddyPictureUpload, settings, chat, audioVideo, usability, audioLevel, fileInfo, screenshare, roomBar, socialShare, page, contactRequest, defaultDialog, pdfcanvas, odfcanvas, presentation, youtubevideo, bfi, title) {
var directives = {
onEnter: onEnter,
@ -68,13 +69,14 @@ define([ @@ -68,13 +69,14 @@ define([
odfcanvas: odfcanvas,
presentation: presentation,
youtubevideo: youtubevideo,
bfi: bfi
bfi: bfi,
title: title
};
var initialize = function(angModule) {
_.each(directives, function(directive, name) {
angModule.directive(name, directive);
})
});
};
return {

54
static/js/directives/page.js

@ -20,55 +20,37 @@ @@ -20,55 +20,37 @@
*/
define(['text!partials/page.html', 'text!partials/page/welcome.html'], function(template, welcome) {
return ["$templateCache", "mediaStream", function($templateCache, mediaStream) {
return ["$templateCache", "$timeout", "rooms", function($templateCache, $timeout, rooms) {
$templateCache.put('page/welcome.html', welcome);
var link = function(scope, element, attrs) {
scope.room = false;
scope.page = null;
if (mediaStream.config.DefaultRoomEnabled !== true) {
scope.$on("welcome", function() {
if (!scope.initialized) {
scope.initialized = true;
scope.refresh();
}
});
var link = function($scope, $element, attrs) {
$scope.randomRoom = rooms.randomRoom;
scope.$on("room", function(event, room) {
scope.initialized = true;
scope.room = room !== null ? true : false;
scope.refresh();
});
$scope.$on("room.joined", function(event, name) {
$scope.page = null;
});
scope.$watch("status", function(event) {
if (scope.initialized) {
scope.refresh();
}
$scope.$on("room.random", function(ev, roomdata) {
$scope.page = "page/welcome.html";
$scope.roomdata = roomdata;
$timeout(function() {
$element.find(".btn-roomcreate:visible:enabled:first").focus();
});
});
scope.refresh = function() {
if (scope.roomid || scope.room || scope.status !== "waiting") {
scope.page = null;
} else {
scope.page = "page/welcome.html";
}
};
}
$scope.roomdata = {};
$scope.$watch("roomdata.name", function(name) {
$scope.roomdata.link = rooms.link($scope.roomdata);
});
};
return {
restrict: 'E',
replace: true,
template: template,
controller: "RoomchangeController",
link: link
}
};
}];
});

24
static/js/directives/roombar.js

@ -21,17 +21,16 @@ @@ -21,17 +21,16 @@
define(['underscore', 'text!partials/roombar.html'], function(_, template) {
// roomBar
return ["$window", "$rootScope", "mediaStream", function($window, $rootScope, mediaStream) {
return ["$window", "rooms", function($window, rooms) {
var link = function($scope) {
//console.log("roomBar directive link", arguments);
$scope.newroomid = $rootScope.roomid;
$scope.layout.roombar = false;
$scope.save = function() {
var roomid = mediaStream.changeRoom($scope.newroomid);
if (roomid !== $rootScope.roomid) {
var roomName = rooms.joinByName($scope.newRoomName);
if (roomName !== $scope.currentRoomName) {
$scope.roombarform.$setPristine();
}
$scope.layout.roombar = false;
@ -44,19 +43,20 @@ define(['underscore', 'text!partials/roombar.html'], function(_, template) { @@ -44,19 +43,20 @@ define(['underscore', 'text!partials/roombar.html'], function(_, template) {
};
$scope.exit = function() {
$scope.newroomid = "";
$scope.newRoomName = "";
$scope.save();
};
$rootScope.$watch("roomid", function(newroomid, roomid) {
if (!newroomid) {
newroomid = "";
}
$scope.newroomid = newroomid;
$scope.$on("room.joined", function(ev, room) {
$scope.currentRoomName = $scope.newRoomName = room.name;
});
$scope.$on("room.left", function(ev) {
$scope.currentRoomName = $scope.newRoomName = "";
});
$scope.$watch("newroomid", function(newroomid) {
if (newroomid === $rootScope.roomid) {
$scope.$watch("newRoomName", function(name) {
if (name === $scope.currentRoomName) {
$scope.roombarform.$setPristine();
}
});

10
static/js/directives/socialshare.js

@ -29,7 +29,7 @@ define(['jquery', 'text!partials/socialshare.html'], function($, template) { @@ -29,7 +29,7 @@ define(['jquery', 'text!partials/socialshare.html'], function($, template) {
};
// socialShare
return ["$window", "translation", function($window, translation) {
return ["$window", "translation", "rooms", function($window, translation, rooms) {
var title = $window.encodeURIComponent($window.document.title);
var makeUrl = function(nw, target) {
@ -46,6 +46,14 @@ define(['jquery', 'text!partials/socialshare.html'], function($, template) { @@ -46,6 +46,14 @@ define(['jquery', 'text!partials/socialshare.html'], function($, template) {
template: template,
replace: true,
link: function($scope, $element, $attr) {
$scope.$on("room.joined", function(ev, room) {
$scope.roomlink = rooms.link(room);
});
$scope.$on("room.left", function(ev, name) {
$scope.roomlink = null;
});
$element.on("click", "a", function(event) {
var nw = $(event.currentTarget).data("nw");
var url = makeUrl(nw, $scope.roomlink);

48
static/js/directives/title.js

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
/*
* 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([], function() {
return [function() {
var link = function($scope, $element, attrs) {
var originalText = $element.text();
var updateTitle = function(roomName) {
if (roomName) {
$element.text(roomName+ " - " + originalText);
} else {
$element.text(originalText);
}
};
$scope.$on("room.joined", function(ev, room) {
updateTitle(room.name);
});
$scope.$on("room.left", function(ev) {
updateTitle();
});
};
return {
restrict: 'E',
replace: false,
link: link
};
}];
});

40
static/js/directives/usability.js

@ -22,15 +22,13 @@ define(['jquery', 'underscore', 'text!partials/usability.html'], function($, _, @@ -22,15 +22,13 @@ define(['jquery', 'underscore', 'text!partials/usability.html'], function($, _,
var MEDIA_CHECK = "1" // First version of media check flag.
return ["mediaStream", function(mediaStream) {
return [function() {
var controller = ['$scope', "mediaStream", "safeApply", "$timeout", "localStorage", "continueConnector", function($scope, mediaStream, safeApply, $timeout, localStorage, continueConnector) {
var controller = ['$scope', "webrtc", "safeApply", "$timeout", "localStorage", "continueConnector", function($scope, webrtc, safeApply, $timeout, localStorage, continueConnector) {
var pending = true;
var complete = false;
var initializer = null;
var ctrl = this;
ctrl.setInfo = function(info) {
$scope.usabilityInfo = info;
@ -46,16 +44,7 @@ define(['jquery', 'underscore', 'text!partials/usability.html'], function($, _, @@ -46,16 +44,7 @@ define(['jquery', 'underscore', 'text!partials/usability.html'], function($, _,
localStorage.setItem("mediastream-mediacheck", MEDIA_CHECK)
console.log("Continue with connect after media check ...");
continueDeferred.resolve();
if (mediaStream.config.DefaultRoomEnabled !== true) {
ctrl.setInfo("initializing");
initializer = $timeout(function() {
ctrl.setInfo("ok");
$scope.layout.settings = false;
$scope.$emit("welcome");
}, 1000);
} else {
ctrl.setInfo("ok");
}
ctrl.setInfo("ok");
complete = true;
} else {
ctrl.setInfo("denied");
@ -70,7 +59,7 @@ define(['jquery', 'underscore', 'text!partials/usability.html'], function($, _, @@ -70,7 +59,7 @@ define(['jquery', 'underscore', 'text!partials/usability.html'], function($, _,
// NOTE(longsleep): Checkin for media access makes only sense on
// Chrome for now, as its the only one which remembers this
// decision permanently for https.
mediaStream.webrtc.testMediaAccess($scope.continueConnect);
webrtc.testMediaAccess($scope.continueConnect);
} else {
$scope.continueConnect(true);
}
@ -97,19 +86,16 @@ define(['jquery', 'underscore', 'text!partials/usability.html'], function($, _, @@ -97,19 +86,16 @@ define(['jquery', 'underscore', 'text!partials/usability.html'], function($, _,
}
});
$scope.$on("room", function(event, room) {
//console.log("roomStatus", room !== null ? true : false);
$scope.$on("room.joined", function(event) {
if (complete) {
if (initializer !== null) {
$timeout.cancel(initializer);
initializer = null;
}
// Check if we should show settings per default when in a room.
if(room && !$scope.loadedUser) {
$scope.layout.settings = true;
} else {
$scope.layout.settings = false;
}
$scope.layout.settings = !$scope.loadedUser;
ctrl.setInfo("ok");
}
});
$scope.$on("room.left", function(event) {
if (complete) {
$scope.layout.settings = false;
ctrl.setInfo("ok");
}
});

24
static/js/mediastream/api.js

@ -18,13 +18,13 @@ @@ -18,13 +18,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
define(['jquery', 'underscore'], function($, _) {
define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) {
var alive_check_timeout = 5000;
var alive_check_timeout_2 = 10000;
var Api = function(connector) {
var Api = function(version, connector) {
this.version = version;
this.id = null;
this.sid = null;
this.session = {};
@ -33,6 +33,15 @@ define(['jquery', 'underscore'], function($, _) { @@ -33,6 +33,15 @@ define(['jquery', 'underscore'], function($, _) {
this.e = $({});
var ua = uaparser();
if (ua.os.name && /Spreed Desktop Caller/i.test(ua.ua)) {
this.userAgent = ua.ua.match(/Spreed Desktop Caller\/([\d.]+)/i)[1] + " (" + ua.os.name + ")";
} else if (ua.browser.name) {
this.userAgent = ua.browser.name + " " + ua.browser.major;
} else {
this.userAgent = ua.ua;
}
connector.e.on("received", _.bind(function(event, data) {
this.received(data);
}, this));
@ -217,6 +226,15 @@ define(['jquery', 'underscore'], function($, _) { @@ -217,6 +226,15 @@ define(['jquery', 'underscore'], function($, _) {
};
Api.prototype.sendHello = function(name) {
var data = {
Version: this.version,
Ua: this.userAgent,
Id: name
};
this.send("Hello", data, true);
};
Api.prototype.sendOffer = function(to, payload) {
var data = {

59
static/js/mediastream/connector.js

@ -18,14 +18,12 @@ @@ -18,14 +18,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) {
define(['jquery', 'underscore'], function($, _, uaparser) {
var timeout = 5000;
var timeout_max = 20000;
var Connector = function(version) {
this.version = version;
var Connector = function() {
this.e = $({});
this.error = false;
this.connected = false;
@ -35,18 +33,6 @@ define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) { @@ -35,18 +33,6 @@ define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) {
this.token = null;
this.queue = [];
this.roomid = null;
var ua = uaparser();
if (ua.os.name && /Spreed Desktop Caller/i.test(ua.ua)) {
this.userAgent = ua.ua.match(/Spreed Desktop Caller\/([\d.]+)/i)[1] + " (" + ua.os.name + ")";
} else if (ua.browser.name) {
this.userAgent = ua.browser.name + " " + ua.browser.major;
} else {
this.userAgent = ua.ua;
}
};
Connector.prototype.connect = function(url) {
@ -110,7 +96,6 @@ define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) { @@ -110,7 +96,6 @@ define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) {
Connector.prototype.close = function() {
this.connected = false;
this.roomid = null;
if (this.conn) {
var conn = this.conn;
this.conn = null;
@ -131,42 +116,7 @@ define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) { @@ -131,42 +116,7 @@ define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) {
};
Connector.prototype.room = function(roomid) {
var was_connected = this.connected;
if (was_connected) {
if (this.roomid === roomid) {
return;
}
this.e.triggerHandler("closed", [{
soft: true
}]);
}
this.roomid = roomid;
roomid = this.roomid ? this.roomid : "";
this.send({
Type: "Hello",
Hello: {
Version: this.version,
Ua: this.userAgent,
Id: roomid
}
}, true);
this.e.triggerHandler("helloed", [roomid]);
if (was_connected) {
this.e.triggerHandler("open", [{
soft: true
}]);
}
};
Connector.prototype.onopen = function(event) {
window.clearTimeout(this.connecting);
this.connecting_timeout = timeout;
@ -181,9 +131,6 @@ define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) { @@ -181,9 +131,6 @@ define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) {
data = this.queue.shift();
this.send(data);
}
this.e.triggerHandler("opened");
};
Connector.prototype.onerror = function(event) {
@ -210,8 +157,6 @@ define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) { @@ -210,8 +157,6 @@ define(['jquery', 'underscore', 'ua-parser'], function($, _, uaparser) {
if (!this.error) {
this.e.triggerHandler("close", [null, event]);
}
this.e.triggerHandler("closed", [null, event]);
};
Connector.prototype.onmessage = function(event) {

27
static/js/services/api.js

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
/*
* 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([
'mediastream/api'
], function(Api) {
return ["globalContext", "connector", function(context, connector) {
return new Api(context.Cfg.Version, connector);
}];
});

4
static/js/services/buddypicture.js

@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
define(['underscore'], function(underscore) {
// buddyPicture
return ["mediaStream", "$window", function(mediaStream, $window) {
return ["$window", "restURL", function($window, restURL) {
var buddyPicture = {
@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
}
if (url.indexOf("img:") === 0) {
data.buddyPicture = data.buddyPictureLocalUrl = mediaStream.url.buddy(url.substr(4));
data.buddyPicture = data.buddyPictureLocalUrl = restURL.buddy(url.substr(4));
}
},

27
static/js/services/connector.js

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
/*
* 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([
'mediastream/connector'
], function(Connector) {
return [function() {
return new Connector();
}];
});

141
static/js/services/mediastream.js

@ -23,29 +23,31 @@ define([ @@ -23,29 +23,31 @@ define([
'underscore',
'ua-parser',
'modernizr',
'mediastream/connector',
'mediastream/api',
'mediastream/webrtc',
'mediastream/tokens'
], function($, _, uaparser, Modernizr, Connector, Api, WebRTC, tokens) {
], function($, _, uaparser, Modernizr, tokens) {
return ["globalContext", "$rootScope", "$route", "$location", "$window", "visibility", "alertify", "$http", "safeApply", "$timeout", "$sce", "localStorage", "continueConnector", function(context, $rootScope, $route, $location, $window, visibility, alertify, $http, safeApply, $timeout, $sce, localStorage, continueConnector) {
return ["globalContext", "connector", "api", "webrtc", "$rootScope", "$route", "$location", "$window", "visibility", "alertify", "$http", "safeApply", "$timeout", "$sce", "localStorage", "continueConnector", "restURL", function(context, connector, api, webrtc, $rootScope, $route, $location, $window, visibility, alertify, $http, safeApply, $timeout, $sce, localStorage, continueConnector, restURL) {
var url = (context.Ssl ? "wss" : "ws") + "://" + context.Host + (context.Cfg.B || "/") + "ws";
var version = context.Cfg.Version || "unknown";
var version = context.Cfg.Version;
console.log("Service version: " + version);
console.log("Ws URL: " + url);
console.log("Secure Contextual Escaping: " + $sce.isEnabled());
var connector = new Connector(version);
var api = new Api(connector);
var webrtc = new WebRTC(api);
var connectMarker = null;
// Create encryption key from server token and browser name.
var secureKey = sjcl.codec.base64.fromBits(sjcl.hash.sha256.hash(context.Cfg.Token + uaparser().browser.name));
var authorizing = false;
$rootScope.authorizing = function(value) {
// Boolean flag to indicate that an authentication is currently in progress.
if (typeof(value) !== "undefined") {
authorizing = !!value;
}
return authorizing;
};
var mediaStream = {
version: version,
@ -55,21 +57,9 @@ define([ @@ -55,21 +57,9 @@ define([
connector: connector,
api: api,
tokens: tokens,
url: {
room: function(id) {
id = $window.encodeURIComponent(id);
return $window.location.protocol + '//' + $window.location.host + context.Cfg.B + id;
},
buddy: function(id) {
return $window.location.protocol + '//' + $window.location.host + context.Cfg.B + "static/img/buddy/s46/" + id;
},
api: function(path) {
return (context.Cfg.B || "/") + "api/v1/" + path;
}
},
users: {
register: function(form, success_cb, error_cb) {
var url = mediaStream.url.api("users");
var url = restURL.api("users");
if (form) {
// Form submit mode.
$(form).attr("action", url).attr("method", "POST");
@ -135,16 +125,9 @@ define([ @@ -135,16 +125,9 @@ define([
});
}
},
authorizing: function(value) {
// Boolean flag to indicate that an authentication is currently in progress.
if (typeof(value) !== "undefined") {
authorizing = !!value;
}
return authorizing;
},
authorize: function(data, success_cb, error_cb) {
mediaStream.users.authorizing(true);
var url = mediaStream.url.api("sessions") + "/" + mediaStream.api.id + "/";
$rootScope.authorizing(true);
var url = restURL.api("sessions") + "/" + mediaStream.api.id + "/";
var login = _.clone(data);
login.id = mediaStream.api.id;
login.sid = mediaStream.api.sid;
@ -160,14 +143,14 @@ define([ @@ -160,14 +143,14 @@ define([
if (data.nonce !== "" && data.success) {
success_cb(data, status);
} else {
mediaStream.users.authorizing(false);
$rootScope.authorizing(false);
if (error_cb) {
error_cb(data, status);
}
}
}).
error(function(data, status) {
mediaStream.users.authorizing(false);
$rootScope.authorizing(false);
if (error_cb) {
error_cb(data, status)
}
@ -226,40 +209,12 @@ define([ @@ -226,40 +209,12 @@ define([
}
});
},
changeRoom: function(id, replace) {
id = $window.encodeURIComponent(id);
// Allow room ids to start with @,$ and + without quoting.
id = id.replace(/^%40/, "@");
id = id.replace(/^%24/, "$");
id = id.replace(/^%2B/, "+");
safeApply($rootScope, function(scope) {
$location.path("/" + id);
if (replace) {
$location.replace();
}
});
return id;
},
applyRoom: function() {
if (authorizing) {
// Do nothing while authorizing.
return;
}
var roomid = $rootScope.roomid;
if (roomid !== connector.roomid) {
console.log("Apply room", roomid);
connector.room(roomid);
}
},
initialize: function($rootScope, translation) {
var cont = false;
var ready = false;
$rootScope.version = version;
$rootScope.roomid = null;
$rootScope.roomlink = null;
$rootScope.roomstatus = false;
$rootScope.connect = false;
var connect = function() {
@ -278,61 +233,10 @@ define([ @@ -278,61 +233,10 @@ define([
}
};
var title = (function(e) {
return {
element: e,
text: e.text()
}
}($("title")));
// Room selector.
$rootScope.$on("$locationChangeSuccess", function(event) {
var room;
if ($route.current) {
room = $route.current.params.room;
room = $window.decodeURIComponent(room);
} else {
room = "";
}
console.info("Selected room is:", [room], ready, cont);
$rootScope.roomid = room;
if (!ready || !cont) {
ready = true;
connect();
} else {
// Auto apply room when already connected.
mediaStream.applyRoom();
}
$rootScope.roomlink = room ? mediaStream.url.room(room) : null;
if ($rootScope.roomlink) {
title.element.text(room + " - " + title.text);
} else {
title.element.text(title.text);
}
});
// Cache events, to avoid ui flicker during quick room changes.
var roomStatusCache = $rootScope.roomstatus;
var roomCache = null;
var roomCache2 = null;
$rootScope.$on("roomStatus", function(event, status) {
// roomStatus is triggered by the buddylist when received.users.
roomStatusCache = status ? true : false;
roomCache = status ? $rootScope.roomid : null;
$timeout(function() {
if ($rootScope.roomstatus !== roomStatusCache) {
$rootScope.roomstatus = roomStatusCache;
}
if (roomCache !== roomCache2) {
// Let every one know about the new room.
$rootScope.$broadcast("room", roomCache);
roomCache2 = roomCache;
}
}, 100);
$rootScope.$on("rooms.ready", function(event) {
console.info("Initial room path set, continuing to connect ...");
ready = true;
connect();
});
visibility.afterPrerendering(function() {
@ -356,7 +260,7 @@ define([ @@ -356,7 +260,7 @@ define([
}
}, prompt);
};
var url = mediaStream.url.api("tokens");
var url = restURL.api("tokens");
var check = function(code) {
$http({
method: "POST",
@ -406,9 +310,6 @@ define([ @@ -406,9 +310,6 @@ define([
}
};
// For debugging.
$window.changeRoom = mediaStream.changeRoom;
return mediaStream;
}];

38
static/js/services/resturl.js

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
/*
* 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([
], function() {
return ["globalContext", "$window", function(context, $window) {
return {
room: function(id) {
id = $window.encodeURIComponent(id);
return $window.location.protocol + '//' + $window.location.host + context.Cfg.B + id;
},
buddy: function(id) {
return $window.location.protocol + '//' + $window.location.host + context.Cfg.B + "static/img/buddy/s46/" + id;
},
api: function(path) {
return (context.Cfg.B || "/") + "api/v1/" + path;
}
};
}];
});

152
static/js/services/rooms.js

@ -0,0 +1,152 @@ @@ -0,0 +1,152 @@
/*
* 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([
'jquery'
], function($) {
return ["$window", "$location", "$timeout", "$route", "$rootScope", "$http", "globalContext", "safeApply", "connector", "api", "restURL", function($window, $location, $timeout, $route, $rootScope, $http, globalContext, safeApply, connector, api, restURL) {
var url = restURL.api("rooms");
var requestedRoomName = "";
var currentRoom = null;
var joinRequestedRoom = function() {
if ($rootScope.authorizing()) {
// Do nothing while authorizing.
return;
}
if (!connector.connected || requestedRoomName !== currentRoom) {
if (requestedRoomName !== "" || globalContext.Cfg.DefaultRoomEnabled) {
console.log("Joining room", requestedRoomName);
requestedRoomName = requestedRoomName ? requestedRoomName : "";
api.sendHello(requestedRoomName);
api.requestUsers();
} else {
console.log("Default room disabled, requesting a random room.");
setCurrentRoom(null);
rooms.randomRoom();
}
}
};
// Cache events, to avoid ui flicker during quick room changes.
var nextRoom = null;
var setCurrentRoom = function(room) {
nextRoom = room;
$timeout(function() {
if (nextRoom !== currentRoom) {
var priorRoom = currentRoom;
currentRoom = nextRoom;
if (priorRoom) {
console.log("Left room", priorRoom.name);
$rootScope.$broadcast("room.left", priorRoom);
}
if (currentRoom) {
console.log("Joined room", currentRoom.name);
$rootScope.$broadcast("room.joined", currentRoom);
}
}
}, 100);
};
connector.e.on("close error", function() {
setCurrentRoom(null);
});
api.e.on("received.self", function(event, data) {
joinRequestedRoom();
});
api.e.on("received.users", function() {
setCurrentRoom({
name: requestedRoomName
});
});
$rootScope.$on("$locationChangeSuccess", function(event) {
var roomName;
if ($route.current) {
roomName = $route.current.params.room;
roomName = $window.decodeURIComponent(roomName);
} else {
roomName = "";
}
requestedRoomName = roomName;
if (connector.connected) {
joinRequestedRoom();
} else {
$rootScope.$broadcast("rooms.ready");
}
});
var rooms = {
inDefaultRoom: function() {
return (currentRoom !== null ? currentRoom.name : requestedRoomName) === "";
},
randomRoom: function() {
$http({
method: "POST",
url: url,
data: $.param({}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).
success(function(data, status) {
console.info("Retrieved random room data", data);
if (!data.name) {
data.name = "";
}
$rootScope.$broadcast('room.random', {name: data.name});
}).
error(function() {
console.error("Failed to retrieve random room data.");
$rootScope.$broadcast('room.random', {});
});
},
joinByName: function(name, replace) {
name = $window.encodeURIComponent(name);
name = name.replace(/^%40/, "@");
name = name.replace(/^%24/, "$");
name = name.replace(/^%2B/, "+");
safeApply($rootScope, function(scope) {
$location.path("/" + name);
if (replace) {
$location.replace();
}
});
return name;
},
link: function(room) {
var name = room ? room.name : null;
if (!name) {
name = "";
}
return restURL.room(name);
}
};
return rooms;
}];
});

23
static/js/services/services.js

@ -24,6 +24,9 @@ define([ @@ -24,6 +24,9 @@ define([
'services/desktopnotify',
'services/playsound',
'services/safeapply',
'services/connector',
'services/api',
'services/webrtc',
'services/mediastream',
'services/appdata',
'services/buddydata',
@ -56,10 +59,15 @@ define([ @@ -56,10 +59,15 @@ define([
'services/continueconnector',
'services/chromeextension',
'services/usersettingsdata',
'services/localstatus'], function(_,
'services/localstatus',
'services/rooms',
'services/resturl'], function(_,
desktopNotify,
playSound,
safeApply,
connector,
api,
webrtc,
mediaStream,
appData,
buddyData,
@ -92,12 +100,17 @@ screensharing, @@ -92,12 +100,17 @@ screensharing,
continueConnector,
chromeExtension,
userSettingsData,
localStatus) {
localStatus,
rooms,
restURL) {
var services = {
desktopNotify: desktopNotify,
playSound: playSound,
safeApply: safeApply,
connector: connector,
api: api,
webrtc: webrtc,
mediaStream: mediaStream,
appData: appData,
buddyData: buddyData,
@ -130,13 +143,15 @@ localStatus) { @@ -130,13 +143,15 @@ localStatus) {
continueConnector: continueConnector,
chromeExtension: chromeExtension,
userSettingsData: userSettingsData,
localStatus: localStatus
localStatus: localStatus,
rooms: rooms,
restURL: restURL
};
var initialize = function(angModule) {
_.each(services, function(service, name) {
angModule.factory(name, service);
})
});
};
return {

27
static/js/services/webrtc.js

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
/*
* 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([
'mediastream/webrtc'
], function(WebRTC) {
return ["api", function(api) {
return new WebRTC(api);
}];
});

12
static/partials/chat.html

@ -5,12 +5,14 @@ @@ -5,12 +5,14 @@
<div class="chatheader"><div class="chatstatusicon" ng-click="activateRoom(currentRoom.id, true)"><i class="fa fa-angle-right"></i> <i class="fa fa fa-comments-o"></i></div><div class="chatheadertitle"><span>{{_("Chat sessions")}}</span></div> <div class="ctrl"><i ng-show="layout.chatMaximized" ng-click="toggleMax()" class="fa fa-compress"></i></div></div>
<div class="chatbody">
<div class="list-group nicescroll">
<a ng-if="roomstatus" ng-click="activateRoom('', true)" class="list-group-item" ng-class="{newmessage: getGroupRoom().pending}">
<span class="badge" ng-show="getGroupRoom().pending">{{getGroupRoom().pending}}</span>
<i class="fa fa-users fa-lg"></i> {{_("Room chat")}} {{roomid}}
</a>
<a ng-repeat="room in getVisibleRooms()" ng-click="activateRoom(room.id, true)" class="list-group-item" ng-class="{newmessage: room.pending, disabled: !room.enabled}">
<span class="badge" ng-show="room.pending">{{room.pending}}</span><i class="fa fa-user fa-lg"></i> {{room.id|displayName}} <button class="btn btn-sm btn-default" ng-click="hideRoom(room.id)"><i class="fa fa-trash-o"></i></button>
<span class="badge" ng-show="room.pending">{{room.pending}}</span>
<i class="fa fa-lg" ng-class="{'fa-user': room.id !== '', 'fa-users': room.id === ''}"></i>
<span ng-if="room.id !== ''">{{room.id|displayName}}</span>
<span ng-if="room.id === ''">{{_("Room chat")}} {{currentRoomName}}</span>
<button ng-if="room.id !== ''" class="btn btn-sm btn-default" ng-click="hideRoom(room.id)">
<i class="fa fa-trash-o"></i>
</button>
</a>
</div>
</div>

8
static/partials/page/welcome.html

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<div class="welcome container-fluid" ng-controller="RoomchangeController">
<div class="welcome container-fluid">
<div class="welcome-logo"></div>
<h1>{{_("Create a room and talk together")}}</h1>
<div class="welcome-container">
@ -6,13 +6,13 @@ @@ -6,13 +6,13 @@
<div class="form-group welcome-input">
<input type="text" class="form-control roomdata-link-input input-lg" ng-model="roomdata.name" placeholder="{{_('Creating room ...')}}">
<div class="welcome-input-buttons">
<a class="fa fa-refresh" ng-click="refreshRoom()"></a>
<button class="btn btn-primary btn-roomcreate" type="button" ng-disabled="!roomdata.link" ng-click="changeRoomToId(roomdata.name)">{{_("Create")}}</button>
<a class="fa fa-refresh" ng-click="randomRoom()"></a>
<button class="btn btn-primary btn-roomcreate" type="button" ng-disabled="!roomdata.link" ng-click="joinRoomByName(roomdata.name)">{{_("Create")}}</button>
</div>
</div>
</p>
<center>
<p ng-show="roomdata.name"><i class="fa fa-external-link"></i> <a href="{{roomdata.link}}" ng-click="changeRoomToId(roomdata.name);$event.preventDefault()">{{roomdata.link}}</a></p>
<p ng-show="roomdata.name"><i class="fa fa-external-link"></i> <a href="{{roomdata.link}}" ng-click="joinRoomByName(roomdata.name);$event.preventDefault()">{{roomdata.link}}</a></p>
</center>
</div>
</div>

4
static/partials/roombar.html

@ -4,12 +4,12 @@ @@ -4,12 +4,12 @@
<label class="pull-left control-label hidden-xs">{{_('Room')}}</label>
<div class="pull-left">
<div class="input-group">
<input class="form-control input-sm" ng-model="newroomid" ng-keyup="hitEnter($event)" type="text" placeholder="{{_('Main')}}"></input><span ng-if="roomid && roombarform.$pristine" class="input-group-btn"><a class="btn btn-default btn-sm" title="{{_('Leave room')}}" ng-click="exit()"><i class="fa fa-eraser"></i></a></span><span ng-if="!roomid || !roombarform.$pristine" class="input-group-btn"><a class="btn btn-default btn-sm" title="{{_('Change room')}}" ng-click="save()"><i class="fa fa-arrow-right"></i></a></span>
<input class="form-control input-sm" ng-model="newRoomName" ng-keyup="hitEnter($event)" type="text" placeholder="{{_('Main')}}"></input><span ng-if="currentRoomName && roombarform.$pristine" class="input-group-btn"><a class="btn btn-default btn-sm" title="{{_('Leave room')}}" ng-click="exit()"><i class="fa fa-eraser"></i></a></span><span ng-if="!currentRoomName || !roombarform.$pristine" class="input-group-btn"><a class="btn btn-default btn-sm" title="{{_('Change room')}}" ng-click="save()"><i class="fa fa-arrow-right"></i></a></span>
</div>
</div>
<div class="pull-left">
<social-share/>
</div>
</form>
<label class="control-label overlaybar-overlay" title="{{_('Current room')}}">{{roomid}}</label>
<label class="control-label overlaybar-overlay" title="{{_('Current room')}}">{{currentRoomName}}</label>
</div>

1
static/partials/usability.html

@ -1,7 +1,6 @@ @@ -1,7 +1,6 @@
<div class="fadetogglecontainer" ng-hide="peer">
<div class="animate-show" ng-hide="layout.settings">
<div class="fadetogglecontainer" ng-switch="usabilityInfo">
<div ng-switch-when="initializing"></div>
<div ng-switch-when="checking"><i class="fa fa-refresh fa-spin fa-4x pull-right"></i>{{_("Checking camera and microphone access.")}}</div>
<div ng-switch-when="usermedia"><i><i class="fa fa-hand-o-up fa-4x pull-right"></i>{{_("Please allow access to your camera and microphone.")}}</i></div>
<div ng-switch-when="denied">{{_("Camera / microphone access required.")}}</i></div>

Loading…
Cancel
Save