mirror of
https://github.com/moparisthebest/kaiwa
synced 2025-01-12 06:08:23 -05:00
Disconnected overlay, active contact selection, unread count badges, login screen
This commit is contained in:
parent
67fc48f9be
commit
378f6e0a8b
@ -78,7 +78,7 @@ module.exports = function (client, app) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
client.on('disconnected', function () {
|
client.on('disconnected', function () {
|
||||||
me.connectionStatus = 'disconnected';
|
me.connected = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('auth:failed', function () {
|
client.on('auth:failed', function () {
|
||||||
@ -89,7 +89,7 @@ module.exports = function (client, app) {
|
|||||||
client.on('session:started', function (jid) {
|
client.on('session:started', function (jid) {
|
||||||
me.jid = jid;
|
me.jid = jid;
|
||||||
|
|
||||||
me.connectionStatus = 'connected';
|
me.connected = true;
|
||||||
|
|
||||||
client.getRoster(function (err, resp) {
|
client.getRoster(function (err, resp) {
|
||||||
resp = resp.toJSON();
|
resp = resp.toJSON();
|
||||||
@ -186,6 +186,13 @@ module.exports = function (client, app) {
|
|||||||
if (info.chatState === 'gone') {
|
if (info.chatState === 'gone') {
|
||||||
contact.lockedResource = undefined;
|
contact.lockedResource = undefined;
|
||||||
}
|
}
|
||||||
|
} else if (me.isMe(info.from)) {
|
||||||
|
if (info.chatState === 'active' || info.chatState === 'composing') {
|
||||||
|
contact = me.getContact(info.to);
|
||||||
|
if (contact) {
|
||||||
|
contact.unreadCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -206,6 +213,9 @@ module.exports = function (client, app) {
|
|||||||
// });
|
// });
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
if (!contact.activeContact) {
|
||||||
|
contact.unreadCount++;
|
||||||
|
}
|
||||||
contact.messages.add(message);
|
contact.messages.add(message);
|
||||||
if (!contact.lockedResource) {
|
if (!contact.lockedResource) {
|
||||||
contact.lockedResource = msg.from.full;
|
contact.lockedResource = msg.from.full;
|
||||||
|
@ -66,6 +66,12 @@ module.exports = HumanModel.define({
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
hasUnread: {
|
||||||
|
deps: ['unreadCount'],
|
||||||
|
fn: function () {
|
||||||
|
return this.unreadCount > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
session: {
|
session: {
|
||||||
@ -77,7 +83,9 @@ module.exports = HumanModel.define({
|
|||||||
chatState: ['string', true, 'gone'],
|
chatState: ['string', true, 'gone'],
|
||||||
lockedResource: 'string',
|
lockedResource: 'string',
|
||||||
lastSentMessage: 'object',
|
lastSentMessage: 'object',
|
||||||
timezoneOffset: ['number', false, 0]
|
timezoneOffset: ['number', false, 0],
|
||||||
|
activeContact: ['bool', true, false],
|
||||||
|
unreadCount: ['number', true, 0]
|
||||||
},
|
},
|
||||||
collections: {
|
collections: {
|
||||||
resources: Resources,
|
resources: Resources,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*global app*/
|
/*global app, client*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var HumanModel = require('human-model');
|
var HumanModel = require('human-model');
|
||||||
@ -14,12 +14,29 @@ module.exports = HumanModel.define({
|
|||||||
session: {
|
session: {
|
||||||
jid: ['object', true],
|
jid: ['object', true],
|
||||||
status: ['string', true, ''],
|
status: ['string', true, ''],
|
||||||
avatar: ['string', true, '']
|
avatar: ['string', true, ''],
|
||||||
|
connected: ['bool', true, false],
|
||||||
|
_activeContact: ['string', true, '']
|
||||||
},
|
},
|
||||||
collections: {
|
collections: {
|
||||||
contacts: Contacts
|
contacts: Contacts
|
||||||
},
|
},
|
||||||
|
setActiveContact: function (jid) {
|
||||||
|
var prev = this.getContact(this._activeContact);
|
||||||
|
if (prev) {
|
||||||
|
prev.activeContact = false;
|
||||||
|
}
|
||||||
|
var curr = this.getContact(jid);
|
||||||
|
if (curr) {
|
||||||
|
curr.activeContact = true;
|
||||||
|
curr.unreadCount = 0;
|
||||||
|
}
|
||||||
|
this._activeContact = jid;
|
||||||
|
},
|
||||||
getContact: function (jid, alt) {
|
getContact: function (jid, alt) {
|
||||||
|
if (typeof jid === 'string') jid = new client.JID(jid);
|
||||||
|
if (typeof alt === 'string') alt = new client.JID(alt);
|
||||||
|
|
||||||
if (this.isMe(jid)) {
|
if (this.isMe(jid)) {
|
||||||
jid = alt || jid;
|
jid = alt || jid;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*global $, app*/
|
/*global $, app, me*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
@ -29,6 +29,10 @@ module.exports = HumanView.extend({
|
|||||||
|
|
||||||
this.trigger('pageloaded');
|
this.trigger('pageloaded');
|
||||||
|
|
||||||
|
if (this.model.jid) {
|
||||||
|
me.setActiveContact(this.model.jid);
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
hide: function () {
|
hide: function () {
|
||||||
@ -45,6 +49,8 @@ module.exports = HumanView.extend({
|
|||||||
this.animateRemove();
|
this.animateRemove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
me.setActiveContact('');
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -12,7 +12,7 @@ exports.pages = {};
|
|||||||
exports.body = function anonymous(locals) {
|
exports.body = function anonymous(locals) {
|
||||||
var buf = [];
|
var buf = [];
|
||||||
with (locals || {}) {
|
with (locals || {}) {
|
||||||
buf.push('<body><div class="wrap"><header id="me"><img class="avatar"/><p class="status"></p></header><nav id="contactList"></nav><section id="pages"></section><footer></footer></div></body>');
|
buf.push('<body><div class="wrap"><div id="reconnect"></div><header id="me"><img class="avatar"/><p class="status"></p></header><nav class="main"><li><a href="/logout">Logout</a></li><li><a href="/">Home</a></li></nav><nav id="contactList"></nav><section id="pages"></section><footer></footer></div></body>');
|
||||||
}
|
}
|
||||||
return buf.join("");
|
return buf.join("");
|
||||||
};
|
};
|
||||||
@ -35,7 +35,7 @@ exports.includes.contactListItem = function anonymous(locals) {
|
|||||||
"class": "avatar"
|
"class": "avatar"
|
||||||
}, {
|
}, {
|
||||||
src: true
|
src: true
|
||||||
}) + '/><div class="name">' + jade.escape(null == (jade.interp = contact.displayName) ? "" : jade.interp) + '</div><div class="status">' + jade.escape(null == (jade.interp = contact.status) ? "" : jade.interp) + "</div></li>");
|
}) + '/><div class="name">' + jade.escape(null == (jade.interp = contact.displayName) ? "" : jade.interp) + '</div><div class="unread">' + jade.escape(null == (jade.interp = contact.unreadCount) ? "" : jade.interp) + '</div><div class="status">' + jade.escape(null == (jade.interp = contact.status) ? "" : jade.interp) + "</div></li>");
|
||||||
}
|
}
|
||||||
return buf.join("");
|
return buf.join("");
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
body
|
body
|
||||||
.wrap
|
.wrap
|
||||||
|
#reconnect
|
||||||
header#me
|
header#me
|
||||||
img.avatar
|
img.avatar
|
||||||
p.status
|
p.status
|
||||||
|
nav.main
|
||||||
|
li
|
||||||
|
a(href="/logout") Logout
|
||||||
|
li
|
||||||
|
a(href="/") Home
|
||||||
nav#contactList
|
nav#contactList
|
||||||
section#pages
|
section#pages
|
||||||
footer
|
footer
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
li.contact
|
li.contact
|
||||||
img.avatar(src=contact.avatar)
|
img.avatar(src=contact.avatar)
|
||||||
.name=contact.displayName
|
.name=contact.displayName
|
||||||
|
.unread=contact.unreadCount
|
||||||
.status=contact.status
|
.status=contact.status
|
||||||
|
@ -11,11 +11,14 @@ module.exports = HumanView.extend({
|
|||||||
classBindings: {
|
classBindings: {
|
||||||
show: '',
|
show: '',
|
||||||
subscription: '',
|
subscription: '',
|
||||||
chatState: ''
|
chatState: '',
|
||||||
|
activeContact: '',
|
||||||
|
hasUnread: ''
|
||||||
},
|
},
|
||||||
textBindings: {
|
textBindings: {
|
||||||
displayName: '.name',
|
displayName: '.name',
|
||||||
status: '.status'
|
status: '.status',
|
||||||
|
unreadCount: '.unread'
|
||||||
},
|
},
|
||||||
srcBindings: {
|
srcBindings: {
|
||||||
avatar: '.avatar'
|
avatar: '.avatar'
|
||||||
|
@ -11,6 +11,9 @@ module.exports = HumanView.extend({
|
|||||||
events: {
|
events: {
|
||||||
'click a[href]': 'handleLinkClick'
|
'click a[href]': 'handleLinkClick'
|
||||||
},
|
},
|
||||||
|
classBindings: {
|
||||||
|
connected: '#reconnect'
|
||||||
|
},
|
||||||
render: function () {
|
render: function () {
|
||||||
$('head').append(templates.head());
|
$('head').append(templates.head());
|
||||||
this.renderAndBind();
|
this.renderAndBind();
|
||||||
|
BIN
public/logo.png
Normal file
BIN
public/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
129
public/style.css
129
public/style.css
@ -4,6 +4,7 @@ html, body {
|
|||||||
padding: 0px;
|
padding: 0px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
background-color: #ecf0f2;
|
background-color: #ecf0f2;
|
||||||
|
color: #2e2d2d;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pages {
|
#pages {
|
||||||
@ -14,11 +15,62 @@ html, body {
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#reconnect {
|
||||||
|
z-index: 5000;
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#reconnect.connected {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#me {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.main {
|
||||||
|
background-color: #1C232D;
|
||||||
|
width: 176px;
|
||||||
|
border-right: 1px solid black;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 0px;
|
||||||
|
text-align: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.main li {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.main a {
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: none;
|
||||||
|
height: 20px;
|
||||||
|
padding: 0 1em;
|
||||||
|
color: white;
|
||||||
|
background-color: #333;
|
||||||
|
line-height: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
#contactList {
|
#contactList {
|
||||||
top: 0px;
|
top: 0px;
|
||||||
left: 0px;
|
bottom: 40px;
|
||||||
width: 175px;
|
width: 175px;
|
||||||
height: 100%;
|
|
||||||
background-color: #1C232D;
|
background-color: #1C232D;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@ -122,6 +174,12 @@ html, body {
|
|||||||
color: #777;
|
color: #777;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.contact.activeContact {
|
||||||
|
background-color: #35c8ff;
|
||||||
|
background-image: -moz-linear-gradient(top, #35c8ff, #00aeef);
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #35c8ff), color-stop(1, #00aeef));
|
||||||
|
}
|
||||||
|
|
||||||
.chatView {
|
.chatView {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@ -226,8 +284,18 @@ html, body {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#me {
|
.contact .unread {
|
||||||
display: none;
|
display: none;
|
||||||
|
color: white;
|
||||||
|
width: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact.hasUnread .unread {
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chatInput {
|
#chatInput {
|
||||||
@ -270,9 +338,58 @@ html, body {
|
|||||||
background-color: yellow;
|
background-color: yellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
#loginForm {
|
#loginbox {
|
||||||
margin: 50px;
|
position: relative;
|
||||||
|
margin: auto;
|
||||||
|
margin-top: 5%;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: white;
|
||||||
|
width: 75%;
|
||||||
}
|
}
|
||||||
#loginForm label {
|
#loginbox label {
|
||||||
display: block;
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
#loginbox input {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
height: 35px;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 10px 0.5em;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background-color: #f9fafa;
|
||||||
|
border: 1px solid #eeeeee;
|
||||||
|
color: #2e2d2d;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
#loginbox input:focus {
|
||||||
|
border: 1px solid #a7d9eb;
|
||||||
|
outline: 0px;
|
||||||
|
}
|
||||||
|
#loginbox button {
|
||||||
|
text-decoration: none;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: none;
|
||||||
|
height: 35px;
|
||||||
|
padding: 0 1em;
|
||||||
|
color: white;
|
||||||
|
background-color: #7ec6e2;
|
||||||
|
line-height: 35px;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#loginbox h2 {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom: 1px solid #f8f8f8
|
||||||
|
}
|
||||||
|
.aux header {
|
||||||
|
margin-top: 10%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#logo {
|
||||||
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,9 @@ app.get('/logout', function (req, res) {
|
|||||||
app.get('*', clientApp.html());
|
app.get('*', clientApp.html());
|
||||||
|
|
||||||
|
|
||||||
https.createServer({
|
//https.createServer({
|
||||||
key: fs.readFileSync(config.http.key),
|
// key: fs.readFileSync(config.http.key),
|
||||||
cert: fs.readFileSync(config.http.cert)
|
// cert: fs.readFileSync(config.http.cert)
|
||||||
}, app).listen(config.http.port);
|
//}, app).listen(config.http.port);
|
||||||
|
app.listen(config.http.port);
|
||||||
console.log('demo.stanza.io running at: ' + config.http.baseUrl);
|
console.log('demo.stanza.io running at: ' + config.http.baseUrl);
|
||||||
|
@ -7,7 +7,9 @@ html
|
|||||||
|
|
||||||
link(rel="stylesheet", href="/styles.css")
|
link(rel="stylesheet", href="/styles.css")
|
||||||
block head
|
block head
|
||||||
body
|
body.aux
|
||||||
|
header
|
||||||
|
img#logo(src="/logo.png", alt="OTalk")
|
||||||
block content
|
block content
|
||||||
|
|
||||||
script(src='/zepto.js')
|
script(src='/zepto.js')
|
||||||
|
Loading…
Reference in New Issue
Block a user