diff --git a/assets/css/components/calls/callWindow.css b/assets/css/components/calls/callWindow.css
new file mode 100644
index 00000000..013edba7
--- /dev/null
+++ b/assets/css/components/calls/callWindow.css
@@ -0,0 +1,54 @@
+/**
+ * Calls window stylesheet
+ *
+ * @author Pierre HUBERT
+ */
+
+.call-window {
+ background-color: white;
+ width: 300px;
+ height: 300px;
+ position: fixed;
+ top: 100px;
+ right: 10px;
+ z-index: 100;
+ border: 1px black solid;
+}
+
+
+/**
+ * Loading message
+ */
+.loading-message-container {
+ position: absolute;
+ height: inherit;
+ width: inherit;
+ display: flex;
+ background: 1px #0009;
+ flex-direction: column;
+ justify-content: space-around;
+ text-align: center;
+ font-size: 150%;
+ color: white;
+}
+
+
+/**
+ * Toolbar
+ */
+.call-toolbar {
+ height: 20px;
+ background-color: #000000b3;
+ color: white;
+ display: flex;
+ align-items: center;
+ padding-left: 10px;
+}
+
+.call-toolbar > i:first-child {
+ margin-right: 6px;
+}
+
+.call-title {
+ flex: 1;
+}
\ No newline at end of file
diff --git a/assets/js/common/functionsSchema.js b/assets/js/common/functionsSchema.js
index a5cf4ab3..735382c8 100644
--- a/assets/js/common/functionsSchema.js
+++ b/assets/js/common/functionsSchema.js
@@ -1167,6 +1167,27 @@ var ComunicWeb = {
controller: {
//TODO : implement
},
+
+ /**
+ * Call window
+ */
+ callWindow: {
+ //TODO : implement
+ },
+
+ /**
+ * Current calls list
+ */
+ currentList: {
+ //TODO : implement
+ },
+
+ /**
+ * User media getter
+ */
+ userMedia: {
+ //TODO : implement
+ },
},
/**
diff --git a/assets/js/components/calls/callWindow.js b/assets/js/components/calls/callWindow.js
new file mode 100644
index 00000000..6c65dd1c
--- /dev/null
+++ b/assets/js/components/calls/callWindow.js
@@ -0,0 +1,117 @@
+/**
+ * Single call window management
+ *
+ * @author Pierre HUBERT
+ */
+
+ComunicWeb.components.calls.callWindow = {
+
+ /**
+ * Initialize a call
+ *
+ * @param {Object} info Information about the call to initialize
+ */
+ initCall: function(info){
+
+ /**
+ * Initialize call object
+ */
+ var call = {
+ info: info,
+ open: true,
+ window: {}
+ };
+
+ //We have to begin to draw conversation UI
+ var callContainer = createElem2({
+ appendTo: byId("callsTarget") ? byId("callsTarget") : byId("wrapper"), //If call target is not found, add call in page wrapper
+ type: "div",
+ class: "call-window"
+ });
+ call.window.container = callContainer;
+
+
+ //Create loading message area
+ call.window.loadingMessageContainer = createElem2({
+ appendTo: callContainer,
+ type: "div",
+ class: "loading-message-container",
+ innerHTML: ""
+ });
+
+ call.window.loadingMessageContainer = createElem2({
+ appendTo: call.window.loadingMessageContainer,
+ type: "div",
+ class: "message",
+ innerHTML: "Loading..."
+ });
+
+ /**
+ * Set loading message visiblity
+ *
+ * @param {Boolean} visible TRUE to make it visible / FALSE else
+ */
+ call.setLoadingMessageVisibility = function(visible){
+ call.window.loadingMessageContainer.style.display = visible ? "flex" : "none";
+ }
+
+ /**
+ * Update call loading message
+ *
+ * @param {String} message The new message to show to the
+ * users
+ */
+ call.setLoadingMessage = function(message){
+ call.window.loadingMessageContainer.innerHTML = message;
+ }
+
+
+ //Add toolbar
+ call.window.toolbar = createElem2({
+ appendTo: callContainer,
+ type: "div",
+ class: "call-toolbar",
+ innerHTML: ""
+ });
+
+ //Call title
+ call.window.title = createElem2({
+ appendTo: call.window.toolbar,
+ type: "div",
+ class: "call-title",
+ innerHTML: "Loading..."
+ });
+
+ /**
+ * Update the title of the call
+ */
+ call.setTitle = function(title){
+ call.window.title.innerHTML = title;
+ }
+
+ //Add close button
+ call.window.closeButton = createElem2({
+ appendTo: call.window.toolbar,
+ type: "button",
+ class: "btn btn-box-tool close-btn",
+ innerHTML: ""
+ });
+
+
+ //Get information about related conversation to get the name of the call
+ ComunicWeb.components.conversations.interface.getInfosOne(info.conversation_id, function(conv_info){
+
+ if(conv_info.error)
+ return notify("Could not get information about related conversation!", "danger");
+
+ ComunicWeb.components.conversations.utils.getName(conv_info, function(name){
+ call.setTitle(name);
+ })
+
+ }, false);
+
+ //Load user media
+ call.setLoadingMessage("Waiting for your microphone and camera...");
+ }
+
+}
\ No newline at end of file
diff --git a/assets/js/components/calls/controller.js b/assets/js/components/calls/controller.js
index 89ee9fcb..a5fad5dc 100644
--- a/assets/js/components/calls/controller.js
+++ b/assets/js/components/calls/controller.js
@@ -42,6 +42,33 @@ ComunicWeb.components.calls.controller = {
});
});
+
+ // Each time a page is opened, wec check if we have to create calls target
+ document.addEventListener("openPage", function(){
+
+ //Signed out users can not make calls
+ if(!signed_in())
+ return;
+
+ //Need a wrapper to continue
+ if(!byId("wrapper"))
+ return;
+
+ //Check if calls target already exists
+ if(byId("callsTarget"))
+ return;
+
+ //Call system must be available
+ if(!ComunicWeb.components.calls.controller.isAvailable())
+ return;
+
+ //Create call target
+ createElem2({
+ appendTo: byId("wrapper"),
+ type: "div",
+ id: "callsTarget"
+ });
+ });
},
/**
@@ -65,6 +92,28 @@ ComunicWeb.components.calls.controller = {
//Read configuration
return this.getConfig().enabled;
- }
+ },
+ /**
+ * Initiate a call for a conversation
+ *
+ * @param {Number} conversationID The ID of the target conversation
+ */
+ call: function(conversationID){
+
+ //Create / Get call information for the conversation
+ ComunicWeb.components.calls.interface.createForConversation(conversationID, function(call){
+
+ if(call.error)
+ return notify("Could not get a call for this conversation!", "danger");
+
+ //Add the call to the list of opened calls
+ ComunicWeb.components.calls.currentList.addCallToList(call.id);
+
+ //Initialize call
+ ComunicWeb.components.calls.callWindow.initCall(call);
+
+ });
+
+ }
}
\ No newline at end of file
diff --git a/assets/js/components/calls/currentList.js b/assets/js/components/calls/currentList.js
new file mode 100644
index 00000000..50828e32
--- /dev/null
+++ b/assets/js/components/calls/currentList.js
@@ -0,0 +1,69 @@
+/**
+ * Currents calls list management
+ *
+ * @author Pierre HUBERT
+ */
+
+ComunicWeb.components.calls.currentList = {
+
+ /**
+ * This variable contains the name of the session storage
+ * variable that contains active calls
+ */
+ _local_storage_list_calls_name: "current-calls",
+
+
+ /**
+ * Get the list of active calls
+ *
+ * @return {number[]} The list of calls
+ */
+ getCurrentCallsList: function(){
+ var string = localStorage.getItem(this._local_storage_list_calls_name);
+
+ if(string === null || string == "")
+ return [];
+ else
+ return string.split(",");
+ },
+
+ /**
+ * Save a new list of calls
+ *
+ * @param {number[]} list The new list of calls to save
+ */
+ saveNewCallsList: function(list){
+ localStorage.setItem(this._local_storage_list_calls_name, list.join(","));
+ },
+
+ /**
+ * Add a call to the list of opened call
+ *
+ * @param {number} id The ID of the call to add
+ */
+ addCallToList: function(id){
+ let list = this.getCurrentCallsList();
+
+ if(!list.includes(""+id))
+ list.push(id);
+
+ this.saveNewCallsList(list);
+ },
+
+ /**
+ * Remove a call from the list of calls
+ *
+ * @param {Number} id The ID of the call to remove
+ */
+ removeCallFromList: function(id){
+
+ let list = this.getCurrentCallsList();
+
+ while(list.includes(""+id))
+ list.splice(list.indexOf(""+id), 1);
+
+ this.saveNewCallsList(list);
+
+ },
+
+}
\ No newline at end of file
diff --git a/assets/js/components/calls/interface.js b/assets/js/components/calls/interface.js
index 590a0a23..08ef8ea6 100644
--- a/assets/js/components/calls/interface.js
+++ b/assets/js/components/calls/interface.js
@@ -14,6 +14,22 @@ ComunicWeb.components.calls.interface = {
*/
getConfig: function(callback){
ComunicWeb.common.api.makeAPIrequest("calls/config", {}, true, callback);
- }
+ },
+ /**
+ * Create a call for a conversation
+ *
+ * @param {Number} convID The ID of the target conversation
+ * @param {function} callback
+ */
+ createForConversation : function(convID, callback){
+ ComunicWeb.common.api.makeAPIrequest(
+ "calls/createForConversation",
+ {
+ conversationID: convID
+ },
+ true,
+ callback
+ );
+ }
}
\ No newline at end of file
diff --git a/assets/js/components/calls/userMedia.js b/assets/js/components/calls/userMedia.js
new file mode 100644
index 00000000..1bf6358a
--- /dev/null
+++ b/assets/js/components/calls/userMedia.js
@@ -0,0 +1,43 @@
+/**
+ * User media getter
+ *
+ * @author Pierre HUBERT
+ */
+
+ComunicWeb.components.calls.userMedia = {
+
+ /**
+ * Pointer on current user media
+ */
+ _currMedia: undefined,
+
+ /**
+ * Get user media
+ *
+ * @return {Promise} A promise to get user media
+ */
+ get: function(){
+
+ //Check if we have already got user media
+ if(this._currMedia != undefined && this._currMedia.active)
+ return new Promise(function(resolve, error){
+ resolve(ComunicWeb.components.calls.userMedia._currMedia);
+ });
+
+ //Use latest API
+ return navigator.mediaDevices
+
+ //Request user media
+ .getUserMedia({
+ audio: true,
+ video: true
+ })
+
+ //Save stream
+ .then(function(stream){
+ ComunicWeb.components.calls.userMedia._currMedia = stream;
+ return stream;
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/assets/js/components/conversations/chatWindows.js b/assets/js/components/conversations/chatWindows.js
index f4a008fa..c4494620 100644
--- a/assets/js/components/conversations/chatWindows.js
+++ b/assets/js/components/conversations/chatWindows.js
@@ -594,6 +594,9 @@ ComunicWeb.components.conversations.chatWindows = {
});
conversation.box.callButton = button;
+ button.addEventListener("click", function(){
+ ComunicWeb.components.calls.controller.call(conversation.infos.ID);
+ });
},
diff --git a/system/config/dev.config.php b/system/config/dev.config.php
index 1f5571a4..f5e0ef3b 100644
--- a/system/config/dev.config.php
+++ b/system/config/dev.config.php
@@ -218,6 +218,9 @@ class Dev {
//Incognito mode component
"css/components/incognito/ui.css",
+ //Calls component
+ "css/components/calls/callWindow.css",
+
//Pacman (easter egg) stylesheet
"css/components/pacman.css",
@@ -440,6 +443,9 @@ class Dev {
//Calls compontent
"js/components/calls/interface.js",
"js/components/calls/controller.js",
+ "js/components/calls/callWindow.js",
+ "js/components/calls/currentList.js",
+ "js/components/calls/userMedia.js",
//Pacman component (easter egg)
"js/components/pacman.js",