diff --git a/clientapp/models/me.js b/clientapp/models/me.js
index 7cfeeca..f3f921c 100644
--- a/clientapp/models/me.js
+++ b/clientapp/models/me.js
@@ -31,9 +31,10 @@ module.exports = HumanModel.define({
},
props: {
jid: ['object', true],
- status: ['string', true, ''],
- avatarID: ['string', true, ''],
- rosterVer: ['string', true, '']
+ status: 'string',
+ avatarID: 'string',
+ rosterVer: 'string',
+ nick: 'string'
},
session: {
avatar: ['string', true, ''],
@@ -41,7 +42,6 @@ module.exports = HumanModel.define({
shouldAskForAlertsPermission: ['bool', true, false],
hasFocus: ['bool', true, false],
_activeContact: ['string', true, ''],
- displayName: ['string', true, 'Me'],
stream: 'object'
},
collections: {
@@ -51,9 +51,14 @@ module.exports = HumanModel.define({
calls: Calls
},
derived: {
+ displayName: {
+ deps: ['nick', 'jid'],
+ fn: function () {
+ return this.nick || this.jid.bare;
+ }
+ },
streamUrl: {
deps: ['stream'],
- cache: true,
fn: function () {
if (!this.stream) return '';
return URL.createObjectURL(this.stream);
diff --git a/clientapp/pages/chat.js b/clientapp/pages/chat.js
index 45f5979..a4176be 100644
--- a/clientapp/pages/chat.js
+++ b/clientapp/pages/chat.js
@@ -132,6 +132,7 @@ module.exports = BasePage.extend(chatHelpers).extend({
if (!this.typing || this.paused) {
this.typing = true;
this.paused = false;
+ this.$chatInput.addClass('typing');
client.sendMessage({
to: this.model.lockedResource || this.model.jid,
chatState: 'composing'
@@ -143,6 +144,7 @@ module.exports = BasePage.extend(chatHelpers).extend({
this.resizeInput();
if (this.typing && this.$chatInput.val().length === 0) {
this.typing = false;
+ this.$chatInput.removeClass('typing');
client.sendMessage({
to: this.model.lockedResource || this.model.jid,
chatState: 'active'
@@ -192,6 +194,7 @@ module.exports = BasePage.extend(chatHelpers).extend({
this.editMode = false;
this.typing = false;
this.paused = false;
+ this.$chatInput.removeClass('typing');
this.$chatInput.removeClass('editing');
this.$chatInput.val('');
},
diff --git a/clientapp/router.js b/clientapp/router.js
index 0d0a630..aaa2e02 100644
--- a/clientapp/router.js
+++ b/clientapp/router.js
@@ -11,6 +11,7 @@ module.exports = Backbone.Router.extend({
routes: {
'': 'main',
'chat/:jid': 'chat',
+ 'chat/:jid/:resource': 'chat',
'groupchat/:jid': 'groupchat',
'logout': 'logout'
},
diff --git a/clientapp/templates.js b/clientapp/templates.js
index c8ed69f..c3a58b9 100644
--- a/clientapp/templates.js
+++ b/clientapp/templates.js
@@ -13,7 +13,7 @@ exports.pages = {};
exports.body = function anonymous(locals) {
var buf = [];
with (locals || {}) {
- buf.push('
');
+ buf.push('');
}
return buf.join("");
};
diff --git a/clientapp/templates/body.jade b/clientapp/templates/body.jade
index 1fb4df2..7edc118 100644
--- a/clientapp/templates/body.jade
+++ b/clientapp/templates/body.jade
@@ -5,7 +5,6 @@ body
| You're currently
strong disconnected
button.primary.reconnect Reconnect
- header#calls
#wrapper
aside#menu
nav.main
@@ -24,4 +23,9 @@ body
section#bookmarks
h1 Bookmarks
nav
- main#pages
+ header#me
+ h1
+ img.avatar
+ span.name
+ span.status(contenteditable="true")
+ main#pages
diff --git a/clientapp/views/main.js b/clientapp/views/main.js
index e575748..61e5352 100644
--- a/clientapp/views/main.js
+++ b/clientapp/views/main.js
@@ -16,7 +16,8 @@ module.exports = HumanView.extend({
},
events: {
'click a[href]': 'handleLinkClick',
- 'click .reconnect': 'handleReconnect'
+ 'click .reconnect': 'handleReconnect',
+ 'blur #me .status': 'handleStatusChange'
},
classBindings: {
connected: '#connectionOverlay',
@@ -28,7 +29,16 @@ module.exports = HumanView.extend({
this.renderAndBind();
this.renderCollection(me.contacts, ContactListItem, this.$('#roster nav'));
this.renderCollection(me.mucs, MUCListItem, this.$('#bookmarks nav'));
- //this.renderCollection(me.calls, CallView, this.$('#calls'));
+
+ this.registerBindings(me, {
+ textBindings: {
+ displayName: '#me .name',
+ status: '#me .status'
+ },
+ srcBindings: {
+ avatar: '#me .avatar'
+ }
+ });
return this;
},
handleReconnect: function (e) {
@@ -49,5 +59,13 @@ module.exports = HumanView.extend({
handleTitle: function (e) {
document.title = app.state.title;
app.desktop.updateBadge(app.state.badge);
+ },
+ handleStatusChange: function (e) {
+ var text = e.target.textContent;
+ me.status = text;
+ client.sendPresence({
+ status: text,
+ caps: client.disco.caps
+ });
}
});
diff --git a/public/css/otalk.css b/public/css/otalk.css
index 1e3fae0..8fc458c 100644
--- a/public/css/otalk.css
+++ b/public/css/otalk.css
@@ -701,7 +701,7 @@ button.secondary:hover:not(:disabled) {
}
#roster li.paused:after,
#bookmarks li.paused:after {
- background: #878787;
+ background: #ababab;
}
#roster li.idle,
#bookmarks li.idle {
@@ -868,11 +868,8 @@ button.secondary:hover:not(:disabled) {
overflow-x: hidden;
}
.conversation {
- bottom: 0px;
- left: 0px;
- right: 0px;
padding: 0px;
- width: 100%;
+ overflow: hidden;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -880,8 +877,9 @@ button.secondary:hover:not(:disabled) {
.conversation header {
padding: 0px;
padding-left: 6px;
- border-bottom: 2px solid #eee;
+ border-bottom: 1px solid #d6d6d6;
position: fixed;
+ top: 40px;
right: 0px;
left: 201px;
z-index: 10;
@@ -890,11 +888,7 @@ button.secondary:hover:not(:disabled) {
box-sizing: border-box;
background: #f7f7f7;
}
-.conversation header.online:not(.idle):before,
-.conversation header.chat:before,
-.conversation header.dnd:before,
-.conversation header.away:before,
-.conversation header.xa:before {
+.conversation header:before {
content: '';
position: absolute;
top: 50%;
@@ -920,29 +914,17 @@ button.secondary:hover:not(:disabled) {
.conversation header.xa:before {
background: #f18902;
}
-.conversation header.offline:not(:hover) .name {
- color: #515151;
-}
-.conversation header.offline:not(:hover) .status {
- color: #2f2f2f;
-}
-.conversation header.offline:not(:hover) .avatar {
- opacity: 0.25;
+.conversation header.offline:before {
+ background: #2d2d2d;
}
.conversation header.composing:before {
animation: pulsate 1.5s infinite ease-in;
-webkit-animation: pulsate 1.5s infinite ease-in;
-moz-animation: pulsate 1.5s infinite ease-in;
}
-.conversation header.paused:before {
- background: #878787;
-}
-.conversation header.idle {
- padding-right: 15px;
-}
-.conversation header.idle .name {
- color: #878787;
- max-width: 60%;
+.conversation header.paused:before,
+.conversation header.idle:before {
+ background: #ababab;
}
.conversation header .controls {
float: right;
@@ -1070,11 +1052,10 @@ button.secondary:hover:not(:disabled) {
padding: 0px;
overflow-y: auto;
overflow-x: hidden;
- position: absolute;
+ position: fixed;
top: 0px;
bottom: 55px;
- padding-top: 35px;
- width: 100%;
+ padding-top: 75px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -1208,7 +1189,6 @@ button.secondary:hover:not(:disabled) {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
- border-top: 1px solid #eee;
bottom: 0px;
position: fixed;
right: 0px;
@@ -1231,7 +1211,8 @@ button.secondary:hover:not(:disabled) {
height: 30px;
padding: 6px 10px;
}
-.chatBox textarea:focus {
+.chatBox textarea.typing:focus,
+.chatBox textarea.editing:focus {
transition: none;
-webkit-transition: none;
}
@@ -1476,3 +1457,65 @@ rgba(0,0,0,0.7)
right: 40px;
margin: 0;
}
+#me {
+ position: fixed;
+ left: 200px;
+ top: 0px;
+ height: 40px;
+ width: 100%;
+ background-color: #fff;
+ border-bottom: 1px solid #d6d6d6;
+ z-index: 100;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ color: #fff;
+}
+#me .avatar {
+ width: 30px;
+ height: 30px;
+ vertical-align: middle;
+ margin-right: 5px;
+ -moz-border-radius: 15px;
+ -webkit-border-radius: 15px;
+ -khtml-border-radius: 15px;
+ -o-border-radius: 15px;
+ -border-radius: 15px;
+ border-radius: 15px;
+}
+#me h1 {
+ font-size: 13px;
+ line-height: 12px;
+ margin: 5px;
+ padding: 0px;
+ white-space: nowrap;
+ max-width: 75%;
+}
+#me .status {
+ font-weight: normal;
+ font-size: 12px;
+ line-height: 12px;
+ border-width: 0px;
+ margin: 0px;
+ padding: 0px;
+ line-height: 20px;
+ height: 20px;
+ max-width: 75%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+#me .status:before {
+ content: '-';
+ padding-left: 5px;
+ padding-right: 5px;
+}
+#me .name:focus,
+#me .status:focus {
+ background-color: #fffcea;
+ border: 1px solid #efe391;
+ color: #d2bd2d;
+}
diff --git a/public/css/otalk.styl b/public/css/otalk.styl
index c32dd5e..595edd6 100644
--- a/public/css/otalk.styl
+++ b/public/css/otalk.styl
@@ -12,3 +12,4 @@
@import 'pages/settings'
@import 'pages/aux'
@import 'pages/callbar'
+@import 'pages/header'
diff --git a/public/css/pages/chat.styl b/public/css/pages/chat.styl
index 4c9d038..c103d38 100644
--- a/public/css/pages/chat.styl
+++ b/public/css/pages/chat.styl
@@ -8,74 +8,55 @@
overflow-x: hidden
.conversation
- bottom: 0px
- left: 0px
- right: 0px
padding: 0px
- width: 100%
+ overflow: hidden
borderbox()
header
padding: 0px
padding-left: 6px
- border-bottom: 2px solid $gray-lighter
+ border-bottom: 1px solid darken($gray-lighter, 10%)
position: fixed
+ top: 40px
right: 0px
left: 201px
z-index: 10
borderbox()
background: lighten($gray-light, 93%)
- &.online:not(.idle), &.chat, &.dnd, &.away, &.xa
- &:before
- content: ''
- position: absolute
- top: 50%
- left: 5px
- height: 6px
- width: 6px
- margin-top: -3px
- roundall(10px)
+ &:before
+ content: ''
+ position: absolute
+ top: 50%
+ left: 5px
+ height: 6px
+ width: 6px
+ margin-top: -3px
+ roundall(10px)
&.online,
&.chat
&:before
background: $green
- &.dnd
- &:before
- background: $red
+ &.dnd:before
+ background: $red
- &.away,
- &.xa
- &:before
- background: $orange
+ &.away:before,
+ &.xa:before
+ background: $orange
- &.offline:not(:hover)
- .name
- color: darken($gray-light, 40%)
+ &.offline:before
+ background: $gray-dark
- .status
- color: darken($gray-light, 65%)
+ &.composing:before
+ animation: pulsate 1.5s infinite ease-in
+ -webkit-animation: pulsate 1.5s infinite ease-in
+ -moz-animation: pulsate 1.5s infinite ease-in
- .avatar
- opacity: .25
-
- &.composing
- &:before
- animation: pulsate 1.5s infinite ease-in
- -webkit-animation: pulsate 1.5s infinite ease-in
- -moz-animation: pulsate 1.5s infinite ease-in
-
- &.paused
- &:before
- background: $gray-light
-
- &.idle
- padding-right: 15px
- .name
- color: $gray-light
- max-width: 60%
+ &.paused:before,
+ &.idle:before
+ background: lighten($gray-light, 30%)
.controls
float: right
@@ -192,11 +173,10 @@
padding: 0px
overflow-y: auto
overflow-x: hidden
- position: absolute
+ position: fixed
top: 0px
bottom: 55px
- padding-top: 35px
- width: 100%
+ padding-top: 75px
borderbox()
-webkit-overflow-scrolling: touch
@@ -317,7 +297,6 @@
.chatBox
borderbox()
- border-top: 1px solid $gray-lighter
bottom: 0px
position: fixed
right: 0px
@@ -338,7 +317,8 @@
height: 30px
padding: 6px 10px
- &:focus
+ &.typing:focus,
+ &.editing:focus
transition: none
-webkit-transition: none
diff --git a/public/css/pages/header.css b/public/css/pages/header.css
new file mode 100644
index 0000000..681f394
--- /dev/null
+++ b/public/css/pages/header.css
@@ -0,0 +1,9 @@
+#me {
+ position: fixed;
+ left: 0px;
+ right: 0px;
+ top: 0px;
+ height: 40px;
+ background-color: #fff;
+ border-bottom: 1px solid #d6d6d6;
+}
diff --git a/public/css/pages/header.styl b/public/css/pages/header.styl
new file mode 100644
index 0000000..4d1a9d5
--- /dev/null
+++ b/public/css/pages/header.styl
@@ -0,0 +1,56 @@
+@import '../_variables'
+@import '../_mixins'
+
+#me
+ position: fixed
+ left: 200px
+ top: 0px
+ height: 40px
+ width: 100%
+ background-color: #fff
+ border-bottom: 1px solid darken($gray-lighter, 10%)
+ z-index: 100
+ noselect()
+ color: #fff
+
+ .avatar
+ width: 30px
+ height: 30px
+ vertical-align: middle
+ margin-right: 5px
+ roundall(15px)
+
+ h1
+ font-size: 13px
+ line-height: 12px
+ margin: 5px
+ padding: 0px
+ white-space: nowrap
+ max-width: 75%
+
+ .status
+ font-weight: normal
+ font-size: 12px
+ line-height: 12px
+ border-width: 0px
+ margin: 0px
+ padding: 0px
+ line-height: 20px
+ height: 20px
+
+ max-width: 75%
+ white-space: nowrap
+ overflow: hidden
+ text-overflow: ellipsis
+
+ &:before
+ content: '-'
+ padding-left: 5px
+ padding-right: 5px
+
+ .name,
+ .status
+ &:focus
+ background-color: #fffcea
+ border: 1px solid #efe391
+ color: #d2bd2d
diff --git a/public/css/pages/roster.styl b/public/css/pages/roster.styl
index 96230b8..a2200ba 100644
--- a/public/css/pages/roster.styl
+++ b/public/css/pages/roster.styl
@@ -121,7 +121,7 @@
&.paused
&:after
- background: $gray-light
+ background: lighten($gray-light, 30%)
&.idle
padding-right: 15px
diff --git a/public/x-manifest.cache b/public/x-manifest.cache
index cd87e53..076020e 100644
--- a/public/x-manifest.cache
+++ b/public/x-manifest.cache
@@ -1,5 +1,5 @@
CACHE MANIFEST
-# 0.0.1 1387527074335
+# 0.0.1 1387539451203
CACHE:
/app.js