Commit 6cdfcbfa authored by Eugene Shen's avatar Eugene Shen

Add miscellaneous chat functionality

Abstract WebRTC signalling to prepare for ERP5,
detect client browser unloading and send message,
directly display URLs of images as an actual <img>,
add global "notifications" such as joining and /help,
clean names to avoid OAuth2 state conflicts in the URL,
make Dropbox authentication more robust against failures,
and parse non-image URLs as <a> using a regular expression.
parent 6a2c3380
......@@ -7,6 +7,10 @@ h3 {
p {
margin: 0;
}
img {
max-width: 100%;
max-height: 100%;
}
.chat {
border: 1px solid;
width: 680px;
......
......@@ -68,6 +68,7 @@
<value>
<tuple>
<string>classification/collaborative/team</string>
<string>contributor/person_module/1</string>
</tuple>
</value>
</item>
......
(function (window, document, loopEventListener, rJS, RSVP) {
function cleanId(input_id) {
var reserved = ["_", "&", "=", ",", ";"];
for (var i = 0, i_len = reserved.length; i < i_len; i++) {
input_id = input_id.replace(reserved[i], "-");
}
return input_id;
}
function getQueryValue(query) {
if (document.URL.indexOf(query + "=") != -1) {
var start = document.URL.indexOf(query + "=") + query.length + 1;
......@@ -7,7 +15,7 @@
if (end === -1) {
end = document.URL.length;
}
return document.URL.slice(start, end);
return decodeURIComponent(document.URL.slice(start, end));
} else if (document.URL.indexOf(query + "%3D") != -1) {
var start = document.URL.indexOf(query + "%3D") + query.length + 3;
var end = document.URL.indexOf("%2C", start);
......@@ -17,7 +25,7 @@
end = document.URL.length;
}
}
return document.URL.slice(start, end);
return decodeURIComponent(document.URL.slice(start, end));
} else {
return "";
}
......@@ -32,11 +40,9 @@
})
.push(function (webrtc_gadget) {
var form = my_event.target.elements;
webrtc_gadget.state_parameter_dict.name = form.name.value;
webrtc_gadget.state_parameter_dict.folder = form.folder.value;
// Change underscores to hyphens because underscores are separators
webrtc_gadget.state_parameter_dict.room =
form.room.value.replace("_", "-");
webrtc_gadget.state_parameter_dict.name = cleanId(form.name.value);
webrtc_gadget.state_parameter_dict.folder = cleanId(form.folder.value);
webrtc_gadget.state_parameter_dict.room = cleanId(form.room.value);
webrtc_gadget.state_parameter_dict.role = form.role.value;
var element = my_gadget.state_parameter_dict.element;
while (element.firstChild) {
......
......@@ -68,6 +68,7 @@
<value>
<tuple>
<string>classification/collaborative/team</string>
<string>contributor/person_module/1</string>
</tuple>
</value>
</item>
......
......@@ -68,6 +68,7 @@
<value>
<tuple>
<string>classification/collaborative/team</string>
<string>contributor/person_module/1</string>
</tuple>
</value>
</item>
......
......@@ -68,6 +68,7 @@
<value>
<tuple>
<string>classification/collaborative/team</string>
<string>contributor/person_module/1</string>
</tuple>
</value>
</item>
......
......@@ -66,7 +66,7 @@
.push(function () {
return dropbox_gadget.put(folder, {});
})
.push(function () {
.push(null, function () {
return dropbox_gadget.allAttachments(folder);
})
.push(function (attachment_list) {
......@@ -108,21 +108,13 @@
.push(null, logError);
}
function removeDropboxContent(dropbox_gadget, folder, name) {
return new RSVP.Queue()
.push(function () {
return dropbox_gadget.removeAttachment(folder, name);
})
.push(null, logError);
function putDropboxContent(dropbox_gadget, folder, name, content) {
return dropbox_gadget.putAttachment(
folder, name, new Blob([content], {type: "text"}));
}
function putDropboxContent(dropbox_gadget, folder, name, content) {
return new RSVP.Queue()
.push(function () {
return dropbox_gadget.putAttachment(
folder, name, new Blob([content], {type: "text"}));
})
.push(null, logError);
function removeDropboxContent(dropbox_gadget, folder, name) {
return dropbox_gadget.removeAttachment(folder, name);
}
function authenticateDropbox(my_gadget) {
......@@ -138,81 +130,138 @@
.push(function () {
if (my_gadget.state_parameter_dict.role === "host") {
hideElementByClass(my_gadget, ".dropbox-form");
my_gadget.state_parameter_dict.storage_list.dropbox = true;
return authenticateDropboxHost(my_gadget);
return authenticateHost(my_gadget, "dropbox_gadget", {
getOffer: getDropboxOffer,
getContent: getDropboxContent,
putContent: putDropboxContent,
removeContent: removeDropboxContent
});
} else if (my_gadget.state_parameter_dict.role === "guest") {
return authenticateDropboxGuest(my_gadget);
return authenticateGuest(my_gadget, "dropbox_gadget", {
getOffer: getDropboxOffer,
getContent: getDropboxContent,
putContent: putDropboxContent,
removeContent: removeDropboxContent
});
}
})
.push(null, logError);
}
function authenticateDropboxHost(my_gadget) {
function authenticateHost(my_gadget, jio_gadget_name, jio_function_dict) {
var folder = my_gadget.state_parameter_dict.dropbox_folder;
var room = my_gadget.state_parameter_dict.room;
var name;
var dropbox_gadget;
var jio_gadget;
return new RSVP.Queue()
.push(function () {
return my_gadget.getDeclaredGadget("dropbox_gadget");
return my_gadget.getDeclaredGadget(jio_gadget_name);
})
.push(function (jio_gadget) {
dropbox_gadget = jio_gadget;
.push(function (storage_gadget) {
jio_gadget = storage_gadget;
return pollUntilNotNull(500, 7200000, function () {
return getDropboxOffer(dropbox_gadget, folder, room);
console.log("getting offer name");
return jio_function_dict.getOffer(jio_gadget, folder, room);
}, function (offer_name) {
name = offer_name;
});
})
.push(function () {
return pollUntilNotNull(50, 1000, function () {
return getDropboxContent(dropbox_gadget, folder, "offer_" + name);
var num = 10;
return pollUntilNotNull(50, 5000, function () {
num++;
if (num >= 10) {
num = 0;
console.log("getting offer");
}
return jio_function_dict.getContent(
jio_gadget, folder, "offer_" + name);
}, function (guest_offer) {
return sendOffer(my_gadget, guest_offer);
});
}, function () {
console.log("1");
})
.push(function () {
var num = 10;
return pollUntilNotNull(50, 10000, function () {
num++;
if (num >= 10) {
num = 0;
console.log("getting candidate");
}
return my_gadget.state_parameter_dict.candidate;
}, function (host_answer) {
return putDropboxContent(
dropbox_gadget, folder, "answer_" + name, host_answer)
return jio_function_dict.putContent(
jio_gadget, folder, "answer_" + name, host_answer)
});
}, function () {
console.log("2");
})
.push(function () {
return removeDropboxContent(dropbox_gadget, folder, "offer_" + name);
console.log('removing content');
return jio_function_dict.removeContent(
jio_gadget, folder, "offer_" + name);
}, function () {
console.log("3");
})
.push(function () {
return authenticateHost(my_gadget, jio_gadget_name, jio_function_dict);
}, function () {
return authenticateHost(my_gadget, jio_gadget_name, jio_function_dict);
})
.push(null, logError);
}
function authenticateDropboxGuest(my_gadget) {
function authenticateGuest(my_gadget, jio_gadget_name, jio_function_dict) {
var folder = my_gadget.state_parameter_dict.dropbox_folder;
var room = my_gadget.state_parameter_dict.room;
var name;
var dropbox_gadget;
var jio_gadget;
return new RSVP.Queue()
.push(function () {
return my_gadget.getDeclaredGadget("dropbox_gadget");
})
.push(function (jio_gadget) {
dropbox_gadget = jio_gadget;
return pollUntilNotNull(50, 10000, function () {
return my_gadget.getDeclaredGadget(jio_gadget_name);
})
.push(function (storage_gadget) {
jio_gadget = storage_gadget;
var num = 10;
return pollUntilNotNull(50, 15000, function () {
num++;
if (num >= 10) {
num = 0;
console.log("getting candidate");
}
return my_gadget.state_parameter_dict.candidate;
}, function (guest_offer) {
name = room + "_" + my_gadget.state_parameter_dict.name + ".txt";
return putDropboxContent(
dropbox_gadget, folder, "offer_" + name, guest_offer);
return jio_function_dict.putContent(
jio_gadget, folder, "offer_" + name, guest_offer);
});
}, function () {
console.log("4");
})
.push(function () {
var num = 10;
return pollUntilNotNull(50, 30000, function () {
return getDropboxContent(dropbox_gadget, folder, "answer_" + name);
num++;
if (num >= 10) {
num = 0;
console.log('getting answer');
}
return jio_function_dict.getContent(
jio_gadget, folder, "answer_" + name);
}, function (host_answer) {
return sendAnswer(my_gadget, host_answer);
});
}, function () {
console.log("5");
})
.push(function () {
return removeDropboxContent(dropbox_gadget, folder, "answer_" + name);
console.log("removing content");
return jio_function_dict.removeContent(
jio_gadget, folder, "answer_" + name);
}, function () {
console.log("6");
})
.push(null, logError);
}
......@@ -273,17 +322,6 @@
.push(null, logError);
}
})
.push(function () {
var promise_list = [];
var storage_list = my_gadget.state_parameter_dict.storage_list;
if (storage_list.dropbox) {
promise_list.push(authenticateDropboxHost(my_gadget));
}
if (storage_list.erp5) {
// XXX work in progress
}
return RSVP.all(promise_list);
})
.push(null, logError);
}
......@@ -345,7 +383,7 @@
return my_gadget.getDeclaredGadget("chat_gadget");
})
.push(function (chat_gadget) {
if (message.type === "message") {
if (message.type === "message" || message.type === "notification") {
return new RSVP.Queue()
.push(function () {
return chat_gadget.getMessage(message);
......@@ -427,10 +465,6 @@
dropbox_token: "igeiyv4pkt0y0mm",
document_url: "https://softinst75770.host.vifib.net/"
+ "erp5/web_site_module/web_chat/",
storage_list: {
dropbox: false,
erp5: false
},
ice_config: {
iceServers: [{ url: "stun:stun.1.google.com:19302" }]
},
......@@ -460,11 +494,7 @@
.allowPublicAcquisition('sendMessage', function (message_string) {
var gadget = this;
return new RSVP.Queue()
.push(function () {
return gadget.sendMessage(message_string);
})
.push(null, logError);
return gadget.sendMessage(message_string);
})
.declareMethod('sendMessage', function (message_string, source) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment