Commit 365aeeb1 authored by Thibaut Frain's avatar Thibaut Frain

Connection procedure update:

- can login / logout
- login parameters stored in sessionStorage
- error management (all code is in promises)
parent b857476e
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
<div data-role="header" data-position="fixed" data-theme="a"> <div data-role="header" data-position="fixed" data-theme="a">
<a href="#page=contactlist" class="ui-btn-left ui-btn ui-btn-inline ui-mini ui-corner-all ui-btn-icon-left ui-icon-user">Contacts</a> <a href="#page=contactlist" class="ui-btn-left ui-btn ui-btn-inline ui-mini ui-corner-all ui-btn-icon-left ui-icon-user">Contacts</a>
<h1>Jabber Client</h1> <h1>Jabber Client</h1>
<a href="#page=connection" class="ui-btn-right ui-btn ui-btn-inline ui-mini ui-corner-all">Connection</a>
</div> </div>
<div data-role="page" overflow="hidden"> <div data-role="page" overflow="hidden">
<div role="main" class="ui-content gadget-container" overflow="hidden"></div> <div role="main" class="ui-content gadget-container" overflow="hidden"></div>
......
...@@ -38,6 +38,10 @@ ...@@ -38,6 +38,10 @@
rJS(window) rJS(window)
.allowPublicAcquisition('manageService', function (params) {
this.props.app_services.monitor(params[0]);
})
.allowPublicAcquisition('send', function (datas) { .allowPublicAcquisition('send', function (datas) {
console.log('[xmpp datas output] : ' + datas); console.log('[xmpp datas output] : ' + datas);
return this.getDeclaredGadget("connection") return this.getDeclaredGadget("connection")
...@@ -71,24 +75,36 @@ ...@@ -71,24 +75,36 @@
} }
}) })
.allowPublicAcquisition('publishConnectionState', function (options) { .allowPublicAcquisition('jio_put', function (params) {
return this.getDeclaredGadget('jio')
.push(function (jio_gadget) {
return jio_gadget.put(params[0]);
});
})
.allowPublicAcquisition('jio_get', function (params) {
return this.getDeclaredGadget('jio')
.push(function (jio_gadget) {
return jio_gadget.get(params[0]);
});
})
.allowPublicAcquisition('loadGadgetAfterLogin', function () {
var gadget = this, var gadget = this,
state = options[0],
came_from; came_from;
if (state === "connected") { if (this.props.came_from !== undefined) {
if (this.props.came_from !== undefined) { came_from = this.props.came_from;
came_from = this.props.came_from; delete this.props.came_from;
delete this.props.came_from; return this.aq_pleasePublishMyState(came_from)
return this.aq_pleasePublishMyState(came_from) .push(function (hash) {
.push(function () { if (hash === window.location.hash) {
gadget.render(came_from); return gadget.render(came_from);
}); }
} return gadget.pleaseRedirectMyHash(hash);
return this.aq_pleasePublishMyState({page: "contactlist"}) });
.push(this.pleaseRedirectMyHash.bind(this));
} }
return this.aq_pleasePublishMyState({page: "connection"}) return this.aq_pleasePublishMyState({page: "contactlist"})
.push(this.pleaseRedirectMyHash.bind(this)); .push(this.pleaseRedirectMyHash.bind(this));
}) })
...@@ -122,14 +138,17 @@ ...@@ -122,14 +138,17 @@
.declareAcquiredMethod("pleaseRedirectMyHash", "pleaseRedirectMyHash") .declareAcquiredMethod("pleaseRedirectMyHash", "pleaseRedirectMyHash")
// Initialize header toolbar .allowPublicAcquisition('renderConnection', function () {
return this.aq_pleasePublishMyState({page: "connection"})
.push(this.pleaseRedirectMyHash.bind(this));
})
.ready(function (g) { .ready(function (g) {
g.props = {}; g.props = {};
g.chatbox_gadgets = {};
$("[data-role='header']").toolbar(); $("[data-role='header']").toolbar();
return g.getDeclaredGadget('jio') return g.getDeclaredGadget('jio')
.push(function (io_gadget) { .push(function (jio_gadget) {
return io_gadget.createJio({ return jio_gadget.createJio({
"type": "local", "type": "local",
"username": "jabberclient", "username": "jabberclient",
"application_name": "jabberclient" "application_name": "jabberclient"
...@@ -159,6 +178,7 @@ ...@@ -159,6 +178,7 @@
page_element; page_element;
element = gadget.__element.querySelector(".gadget-container"); element = gadget.__element.querySelector(".gadget-container");
return this.getDeclaredGadget("connection") return this.getDeclaredGadget("connection")
.push(function (connection_gadget) { .push(function (connection_gadget) {
return connection_gadget.isConnected(); return connection_gadget.isConnected();
...@@ -174,7 +194,7 @@ ...@@ -174,7 +194,7 @@
gadget.props.came_from = options; gadget.props.came_from = options;
return gadget.getDeclaredGadget("connection") return gadget.getDeclaredGadget("connection")
.push(function (connection_gadget) { .push(function (connection_gadget) {
return connection_gadget.pleaseConnectMe(); return connection_gadget.tryAutoConnect();
}); });
} }
return gadget.getDeclaredGadget(options.page) return gadget.getDeclaredGadget(options.page)
...@@ -189,9 +209,20 @@ ...@@ -189,9 +209,20 @@
} }
element.appendChild(page_element); element.appendChild(page_element);
if (page_gadget.render !== undefined) { if (page_gadget.render !== undefined) {
page_gadget.render(options); return page_gadget.render(options);
}
})
.push(function () {
if (page_gadget.startService !== undefined) {
return page_gadget.startService();
} }
}); });
})
.push(function () {
if (!gadget.props.app_services) {
gadget.props.app_services = new RSVP.Monitor();
return gadget.props.app_services;
}
}); });
}); });
......
...@@ -15,37 +15,42 @@ ...@@ -15,37 +15,42 @@
<script src="../<%= copy.handlebars.relative_dest %>"></script> <script src="../<%= copy.handlebars.relative_dest %>"></script>
<script src="../mixin_promise/mixin_promise.js" ></script> <script src="../mixin_promise/mixin_promise.js" ></script>
<script src="jabberclient_connection.js"></script> <script class="login-template" type="text/x-handlebars-template">
</head> <div class="login-box ui-corner-all ui-shadow">
<body> <h3>Status: Not connected</h3><br/>
<div class="login-box ui-corner-all ui-shadow"> <form class="login-form" data-ajax="false">
<h3>Status: Not connected</h3><br/> <div class="ui-field-contain">
<form class="login-form" data-ajax="false"> <input type="url" name="server" placeholder="Jabber server url" value="{{server}}" required>
<div class="ui-field-contain"> </div>
<input type="url" name="server" placeholder="Jabber server url" value="https://mail.tiolive.com/chat/http-bind/" required> <div class="ui-field-contain">
</div> <input type="text" name="jid" placeholder="Jabber ID" value="{{jid}}" required>
<div class="ui-field-contain"> </div>
<input type="text" name="jid" placeholder="Jabber ID" required> <div class="ui-field-contain">
<input type="password" name="passwd" placeholder="Password" required>
</div>
<fieldset class="ui-btn-inline">
<input type="submit" value="Log In">
</fieldset>
</form>
</div>
</script>
<script class="logout-template" type="text/x-handlebars-template">
<div class="logout-box ui-corner-all ui-shadow">
<h3>Status: Authenticated</h3>
<div class="ui-grid-a">
<div class="ui-block-a"><h4>Server URL</h4></div>
<div class="ui-block-b"><h5 class="server">{{server}}</h5></div>
</div> </div>
<div class="ui-field-contain"> <div class="ui-grid-a">
<input type="password" name="passwd" placeholder="Password" required> <div class="ui-block-a"><h4>Jabber ID</h4></div>
<div class="ui-block-b"><h5 class="jid">{{jid}}</h5></div>
</div> </div>
<fieldset class="ui-btn-inline"> <button class="ui-btn ui-btn-b ui-btn-inline ui-corner-all">Logout</button>
<input type="submit" value="Log In">
</fieldset>
</form>
</div>
<div class="logout-box ui-corner-all ui-shadow" style="display: none;">
<h3>Status: Authenticated</h3>
<div class="ui-grid-a">
<div class="ui-block-a"><h4>Server URL</h4></div>
<div class="ui-block-b"><h5 class="server"></h5></div>
</div> </div>
<div class="ui-grid-a"> </script>
<div class="ui-block-a"><h4>Jabber ID</h4></div>
<div class="ui-block-b"><h5 class="jid"></h5></div> <script src="jabberclient_connection.js"></script>
</div> </head>
<button class="ui-btn ui-btn-b ui-btn-inline ui-corner-all">Logout</button> <body>
</div>
</body>
</html> </html>
.login-box, .logout-box { .login-box, .logout-box {
margin: 0 auto; margin: 0 auto;
max-width: 35ch !important; max-width: 40ch !important;
text-align: center; text-align: center;
padding: 1%; padding: 1%;
} }
......
/*global window, rJS, Strophe, $, $iq, /*global window, rJS, Strophe, $, $iq, Handlebars,
XMLSerializer, DOMParser, RSVP, localStorage*/ XMLSerializer, DOMParser, RSVP, sessionStorage, promiseEventListener*/
/*jslint nomen: true*/ /*jslint nomen: true*/
(function ($, Strophe, rJS) { (function ($, Strophe, rJS, Handlebars) {
"use strict"; "use strict";
var gadget_klass = rJS(window),
login_template_source = gadget_klass.__template_element
.querySelector(".login-template").innerHTML,
login_template = Handlebars.compile(login_template_source),
logout_template_source = gadget_klass.__template_element
.querySelector(".logout-template").innerHTML,
logout_template = Handlebars.compile(logout_template_source);
function parseXML(xmlString) { function parseXML(xmlString) {
return new DOMParser() return new DOMParser()
...@@ -15,29 +22,87 @@ ...@@ -15,29 +22,87 @@
return new XMLSerializer().serializeToString(xml); return new XMLSerializer().serializeToString(xml);
} }
function showLogin(gadget, params) { function logout(gadget) {
var login_box = gadget.props.login_box, sessionStorage.removeItem("connection_params");
logout_box = gadget.props.logout_box; return gadget.render();
$(login_box).find('input[name="server"]').val(params.server);
$(login_box).find('input[name="jid"]').val(params.jid);
$(login_box).find('input[name="passwd"]').val(params.passwd);
$(logout_box).hide();
$(login_box).show();
} }
function showLogout(gadget, params) { function showLogout(gadget) {
var login_box = gadget.props.login_box, return new RSVP.Queue()
logout_box = gadget.props.logout_box; .push(function () {
$(logout_box).find('.server').html(params.server); var jid = Strophe.getBareJidFromJid(gadget.props.connection.jid);
$(logout_box).find('.jid').html(params.jid); $(gadget.__element).html(logout_template({
$(login_box).hide(); server: gadget.props.connection.service,
$(logout_box).show(); jid: jid
}));
})
.push(function () {
return promiseEventListener(
gadget.__element.querySelector('.logout-box button'),
'click',
false
);
})
.push(function () {
if (gadget.props.connection) {
gadget.props.connection.disconnect();
}
});
}
function setInputListener(gadget) {
return new RSVP.Promise(function (resolveInputAssignment) {
function canceller() {
if (gadget.props.connection &&
gadget.props.connection.xmlInput) {
delete gadget.props.connection.xmlInput;
}
}
function resolver(resolve, reject) {
gadget.props.connection.xmlInput = function (domElement) {
try {
[].forEach.call(domElement.children, function (child) {
gadget.manageService(
gadget.receive(serializeXML(child))
);
});
} catch (e) {
reject(e);
}
};
resolveInputAssignment();
}
gadget.manageService(new RSVP.Promise(resolver, canceller));
});
} }
function loopConnectionListener(gadget, params) { function login(gadget, params) {
return new RSVP.Queue()
.push(function () {
return setInputListener(gadget);
})
.push(function () {
sessionStorage.setItem(
"connection_params",
JSON.stringify(params)
);
})
.push(function () {
return gadget.props.connection.send(
$iq({type: 'get'}).c('query', {xmlns: 'jabber:iq:roster'})
.tree()
);
})
.push(function () {
return gadget.loadGadgetAfterLogin();
});
}
function connectionListener(gadget, params) {
var connection = new Strophe.Connection(params.server), var connection = new Strophe.Connection(params.server),
connection_callback; connection_callback;
gadget.props.connection = connection;
function canceller() { function canceller() {
if (connection_callback !== undefined) { if (connection_callback !== undefined) {
...@@ -47,44 +112,53 @@ ...@@ -47,44 +112,53 @@
function resolver(resolve, reject) { function resolver(resolve, reject) {
connection_callback = function (status) { connection_callback = function (status) {
if (status === Strophe.Status.CONNECTED) { new RSVP.Queue()
// init jabber inputs .push(function () {
connection.xmlInput = function (domElement) { if (status === Strophe.Status.CONNECTED) {
[].forEach.call(domElement.children, function (child) { return login(gadget, params);
gadget.receive(serializeXML(child)); }
}); if (status === Strophe.Status.DISCONNECTED) {
}; return logout(gadget);
connection.send( }
$iq({type: 'get'}).c('query', {xmlns: 'jabber:iq:roster'}).tree() })
); .fail(function (e) {
// inform parent gadget reject(e);
gadget.publishConnectionState('connected'); });
// show logout box
showLogout(gadget, params);
// register params in localStorage
localStorage.setItem('jabberclient_login', JSON.stringify(params));
} else if (status === Strophe.Status.DISCONNECTED) {
// Destroy connection object
gadget.props.connection = null;
// Inform parent gadget
gadget.publishConnectionState('disconnected');
// Show login box
showLogin(gadget, params);
// remove params in localStorage
localStorage.removeItem('jabberclient_login');
}
}; };
connection.connect(params.jid, params.passwd, connection_callback); connection.connect(params.jid, params.passwd, connection_callback);
gadget.props.connection = connection;
} }
return new RSVP.Promise(resolver, canceller); return new RSVP.Promise(resolver, canceller);
} }
rJS(window) function showLogin(gadget) {
var params = {
server: "https://mail.tiolive.com/chat/http-bind/"
};
return new RSVP.Queue()
.push(function () {
$(gadget.__element).html(login_template(params));
})
.push(function () {
return promiseEventListener(
gadget.__element.querySelector('form.login-form'),
'submit',
false
);
})
.push(function (submit_event) {
$(submit_event.target).serializeArray()
.forEach(function (field) {
params[field.name] = field.value;
});
gadget.manageService(connectionListener(gadget, params));
});
}
.declareAcquiredMethod('pleaseRedirectMyHash', 'pleaseRedirectMyHash') gadget_klass
.declareAcquiredMethod('publishConnectionState', 'publishConnectionState') .declareAcquiredMethod("manageService", "manageService")
.declareAcquiredMethod('loadGadgetAfterLogin', 'loadGadgetAfterLogin')
.declareMethod("isConnected", function () { .declareMethod("isConnected", function () {
if (this.props.connection) { if (this.props.connection) {
...@@ -103,53 +177,32 @@ ...@@ -103,53 +177,32 @@
return this.props.connection.send(parseXML(xmlString)); return this.props.connection.send(parseXML(xmlString));
}) })
.declareMethod('disconnect', function () { .declareMethod('logout', function () {
if (this.connection && this.connection.connected) { logout(this);
return this.connection.disconnect();
}
}) })
.declareMethod("pleaseConnectMe", function () { .declareAcquiredMethod("renderConnection", "renderConnection")
var params = JSON.parse(localStorage.getItem('jabberclient_login'));
.declareMethod("tryAutoConnect", function () {
var params = JSON.parse(sessionStorage.getItem('connection_params'));
if (params !== null && if (params !== null &&
typeof params === 'object' && typeof params === 'object' &&
Object.keys(params).length === 3) { Object.keys(params).length === 3) {
return loopConnectionListener(this, params); this.manageService(connectionListener(this, params));
} else {
return this.renderConnection();
} }
return this.publishConnectionState("disconnected");
}) })
.ready(function (g) { .ready(function (g) {
g.props = { g.props = {};
login_box: g.__element.querySelector('.login-box'), })
logout_box: g.__element.querySelector('.logout_box')
};
g.submitLoginCallback = function (e) {
e.preventDefault();
g.props.params = {};
$(this).serializeArray().forEach(function (elem) {
g.props.params[elem.name] = elem.value;
});
loopConnectionListener(g, g.props.params);
return false;
};
g.submitLogoutCallback = function (e) {
g.connection.disconnect();
g.publishConnectionState('disconnected');
};
window.g = g;
return new RSVP.Promise(function (resolve) {
$(document).on('submit', 'form.login-form', g.submitLoginCallback);
$(document).on('click', '.logout-box button', g.submitLogoutCallback);
resolve();
}, function () {
$(document).off('submit', 'form.login-form', g.submitLoginCallback);
$(document).off('click', '.logout-box button', g.submitLogoutCallback);
});
.declareMethod('render', function () {
if (this.props.connection &&
this.props.connection.authenticated) {
return showLogout(this);
}
return showLogin(this);
}); });
}($, Strophe, rJS, Handlebars));
}($, Strophe, rJS));
...@@ -113,25 +113,6 @@ ...@@ -113,25 +113,6 @@
.declareMethod('receivePresence', function (presence) { .declareMethod('receivePresence', function (presence) {
updateContactList(this, parseXML(presence)); updateContactList(this, parseXML(presence));
})
.declareMethod('receive', function (message) {
var that = this,
body = parseXML(message);
if ($(body).find('iq').length !== 0 &&
$(body).find('query').length !== 0 &&
$(body).find('query').attr('xmlns') === "jabber:iq:roster") {
this.contactList = new ContactList($(body).find('iq')[0]);
} else if ($(body).find('presence')) {
$(body).find('presence').each(function (index, elem) {
updateContactList(that, elem);
});
}
})
.declareMethod('updatePresence', function (presence) {
presence = parseXML(presence);
updateContactList(this, presence);
}); });
}($, Strophe, rJS(window))); }($, Strophe, rJS(window)));
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