Add very basic login page

This commit is contained in:
Lance Stout 2013-09-03 15:25:14 -07:00
parent 3ec2805cd9
commit 5c6655e7be
15 changed files with 178 additions and 5084 deletions

View File

@ -31,24 +31,16 @@ module.exports = {
new Router();
app.history = Backbone.history;
if (!localStorage.config) {
return app.navigate('signin');
}
app.view = new MainView({
model: me,
el: document.body
});
app.view.render();
var rosterVer = localStorage.rosterVersion;
var config = JSON.parse(localStorage.config);
config.rosterVer = rosterVer;
var client = window.client = app.client = XMPP.createClient(config);
var client = window.client = app.client = XMPP.createClient({
rosterVer: localStorage.rosterVersion || undefined
});
xmppEventHandlers(client, app);
client.connect();
// we have what we need, we can now start our router and show the appropriate page
app.history.start({pushState: true, root: '/'});

View File

@ -4,50 +4,16 @@
var crypto = XMPP.crypto;
var _ = require('underscore');
var log = require('andlog');
var Contact = require('../models/contact');
var Resource = require('../models/resource');
var Message = require('../models/message');
function logScroll() {
window.scrollTo(0, document.body.scrollHeight);
}
function log(name, data) {
var container = document.getElementById('log');
var logEntry = document.createElement('div'),
header = document.createElement('h2'),
entry = document.createElement('p'),
altEntry = document.createElement('p');
header.textContent = name;
logEntry.appendChild(header);
if (data && data.toJSON) {
var codeJSON = document.createElement('code');
codeJSON.textContent = JSON.stringify(data.toJSON());
altEntry.appendChild(codeJSON);
logEntry.appendChild(altEntry);
logEntry.appendChild(document.createElement('hr'));
}
var codeData = document.createElement('code');
codeData.textContent = data;
entry.appendChild(codeData);
logEntry.appendChild(entry);
if (container) {
container.appendChild(logEntry);
_.throttle(logScroll, 300);
}
}
module.exports = function (client, app) {
client.on('*', function (name, data) {
log(name, data);
log.debug(name, data);
});
client.on('session:started', function (jid) {
@ -157,13 +123,14 @@ module.exports = function (client, app) {
message.cid = msg.id;
message.set(msg);
if (msg.archived) {
msg.archived.forEach(function (archived) {
if (me.isMe(archived.by)) {
message.id = archived.id;
}
});
}
//if (msg.archived) {
// msg.archived.forEach(function (archived) {
// if (me.isMe(archived.by)) {
// message.id = archived.id;
// message.cid = msg.id;
// }
// });
//}
contact.messages.add(message);
if (!contact.lockedResource) {

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ module.exports = StrictModel.extend({
this.setAvatar(attrs.avatarID);
this.resources.bind('add remove reset change', this.resourceChange, this);
this.bind('change:lockedResource', this.fetchTimezone, this);
},
type: 'contact',
props: {
@ -46,13 +47,20 @@ module.exports = StrictModel.extend({
return this.offlineStatus;
}
},
lockedJID: {
deps: ['jid', 'lockedResource'],
formattedTZO: {
deps: ['timezoneOffset', 'displayName'],
fn: function () {
if (this.lockedResource) {
return this.jid + '/' + this.lockedResource;
if (this.timezoneOffset !== undefined) {
var localTZO = (new Date()).getTimezoneOffset();
var diff = Math.abs(localTZO - this.timezoneOffset) / 60;
if (diff === 0) {
return this.displayName + ' is in the same timezone as you';
}
var dir = (localTZO > this.timezoneOffset) ? 'ahead' : 'behind';
return this.displayName + ' is ' + diff + 'hrs ' + dir + ' you';
} else {
return '';
}
return this.jid;
}
}
},
@ -64,7 +72,8 @@ module.exports = StrictModel.extend({
show: ['string', true, 'offline'],
chatState: ['string', true, 'gone'],
lockedResource: 'string',
lastSentMessage: 'object'
lastSentMessage: 'object',
timezoneOffset: ['number', false, 0]
},
collections: {
resources: Resources,
@ -127,9 +136,23 @@ module.exports = StrictModel.extend({
this.show = 'offline';
}
},
fetchTimezone: function () {
var self = this;
app.whenConnected(function () {
if (self.lockedResource) {
client.getTime(self.lockedResource, function (err, res) {
if (err) return;
console.log('RECV' + res.time.tzo);
console.log('RECV UTC' + res.time.utc);
self.timezoneOffset = res.time.tzo;
});
} else {
self.timezoneOffset = undefined;
}
});
},
fetchHistory: function () {
var self = this;
app.whenConnected(function () {
client.getHistory({
with: self.jid,

View File

@ -12,6 +12,7 @@ module.exports = BasePage.extend({
template: templates.pages.chat,
initialize: function (spec) {
this.editMode = false;
this.model.fetchTimezone();
this.model.fetchHistory();
this.render();
},
@ -23,7 +24,8 @@ module.exports = BasePage.extend({
avatar: 'header .avatar'
},
textBindings: {
name: 'header .name'
displayName: 'header .name',
formattedTZO: 'header #tzo'
},
render: function () {
this.renderAndBind();
@ -60,7 +62,7 @@ module.exports = BasePage.extend({
if (val) {
message = {
to: this.model.lockedJID,
to: this.model.lockedResource || this.model.jid,
type: 'chat',
body: val,
chatState: 'active'

View File

@ -3,16 +3,11 @@
var BasePage = require('./base');
var templates = require('../templates');
var ContactListItem = require('../views/contactListItem');
module.exports = BasePage.extend({
template: templates.pages.main,
initialize: function (spec) {
this.render();
},
render: function () {
this.renderAndBind();
return this;
}
});

44
clientapp/pages/signin.js Normal file
View File

@ -0,0 +1,44 @@
/*global app, client*/
"use strict";
var BasePage = require('./base');
var templates = require('../templates');
module.exports = BasePage.extend({
template: templates.pages.signin,
events: {
'submit #loginForm form': 'login'
},
initialize: function (spec) {
this.renderAndBind();
},
login: function (e) {
e.preventDefault();
var jid = this.$('#jid').val();
var password = this.$('#password').val();
var wsURL = this.$('#wsURL').val();
client.connect({
jid: jid,
server: jid.slice(jid.indexOf('@') + 1),
wsURL: wsURL,
credentials: {
password: password
}
});
client.once('auth:success', 'signin', function () {
client.releaseGroup('signin');
app.navigate('/');
});
client.once('auth:failed', 'signin', function () {
client.releaseGroup('signin');
console.log('Failed Auth');
});
return false;
}
});

View File

@ -2,16 +2,23 @@
"use strict";
var Backbone = require('backbone');
var SigninPage = require('./pages/signin');
var MainPage = require('./pages/main');
var ChatPage = require('./pages/chat');
module.exports = Backbone.Router.extend({
routes: {
'': 'main',
'': 'signin',
'signin': 'signin',
'chat/:jid': 'chat'
},
// ------- ROUTE HANDLERS ---------
signin: function () {
app.renderPage(new SigninPage({
model: me
}));
},
main: function () {
app.renderPage(new MainPage({
model: me

View File

@ -62,7 +62,7 @@ exports.includes.message = function anonymous(locals) {
exports.pages.chat = function anonymous(locals) {
var buf = [];
with (locals || {}) {
buf.push('<section class="page chat"><header class="contactInfo"><img width="30" height="30" class="avatar"/><h1 class="name"></h1></header><ul id="conversation"></ul><div id="chatInput"><form><textarea id="chatBuffer" name="chatInput" type="text" placeholder="Send a message..." autocomplete="off"></textarea></form></div></section>');
buf.push('<section class="page chat"><header class="contactInfo"><img width="30" height="30" class="avatar"/><h1 class="name"></h1><div id="tzo"></div></header><ul id="conversation"></ul><div id="chatInput"><form><textarea id="chatBuffer" name="chatInput" type="text" placeholder="Send a message..." autocomplete="off"></textarea></form></div></section>');
}
return buf.join("");
};
@ -71,7 +71,16 @@ exports.pages.chat = function anonymous(locals) {
exports.pages.main = function anonymous(locals) {
var buf = [];
with (locals || {}) {
buf.push('<section class="page main"><div id="log"><h2>Event Log</h2></div></section>');
buf.push('<section class="page main"></section>');
}
return buf.join("");
};
// signin.jade compiled template
exports.pages.signin = function anonymous(locals) {
var buf = [];
with (locals || {}) {
buf.push('<section class="page signin"><div id="loginForm"><form><label>JID:<input type="text" id="jid" placeholder="you@aweso.me"/></label><label>Password:<input type="password" id="password"/></label><label>WebSocket URL:<input type="text" id="wsURL" placeholder="wss://aweso.me:5281/xmpp-websocket"/></label><input type="submit" value="Connect"/></form></div></section>');
}
return buf.join("");
};

View File

@ -2,6 +2,7 @@ section.page.chat
header.contactInfo
img.avatar(width=30, height=30)
h1.name
#tzo
ul#conversation
div#chatInput
form

View File

@ -1,3 +1 @@
section.page.main
#log
h2 Event Log

View File

@ -0,0 +1,10 @@
section.page.signin
div#loginForm
form
label JID:
input(type="text", id="jid", placeholder="you@aweso.me")
label Password:
input(type="password", id="password")
label WebSocket URL:
input(type="text", id="wsURL", placeholder="wss://aweso.me:5281/xmpp-websocket")
input(type="submit", value="Connect")

View File

@ -8,10 +8,26 @@ var ContactListItem = require('../views/contactListItem');
module.exports = StrictView.extend({
template: templates.body,
events: {
'click a[href]': 'handleLinkClick'
},
render: function () {
$('head').append(templates.head());
this.renderAndBind();
this.renderCollection(me.contacts, ContactListItem, this.$('#contactList'));
return this;
},
handleLinkClick: function (e) {
console.log(e);
var t = $(e.target);
var aEl = t.is('a') ? t[0] : t.closest('a')[0];
var local = window.location.host === aEl.host;
var path = aEl.pathname.slice(1);
if (local) {
e.preventDefault();
app.navigate(path);
return false;
}
}
});

View File

@ -19,7 +19,7 @@
"semi-static": "0.0.4",
"sound-effect-manager": "0.0.5",
"strictmodel": "0.1.1",
"strictview": "1.0.0",
"strictview": "1.0.2",
"templatizer": "0.1.2",
"underscore": "1.5.1"
},

View File

@ -264,3 +264,10 @@ html, body {
#chatBuffer.editing {
background-color: yellow;
}
#loginForm {
margin: 50px;
}
#loginForm label {
display: block;
}