Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

mobilefy subway #192

Merged
merged 1 commit into from

2 participants

Kevin Ngo David Petersen
Kevin Ngo

This is about 90% of the way there. As a frontend enhancement, it shouldn't break anything. It's mostly CSS that only applies itself at 720px, where Subway become unusable anyway.

Wrote this 3 months ago, but I think it's good to merge. Tested on Firefox OS as an app, works well.

David Petersen thedjpetersen merged commit 5bfefdc into from
David Petersen

Thanks Kevin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 23, 2012
  1. Kevin Ngo

    mobilefy subway

    ngokevin authored
This page is out of date. Refresh to see the latest.
2  .gitignore
View
@@ -1,3 +1,5 @@
node_modules/
builtAssets/
run.sh
+*.swp
+.sass-cache
157 assets/css/subway-mobile.css
View
@@ -0,0 +1,157 @@
+@media screen and (max-width: 720px) {
+ .container-fluid {
+ /* Overview. */
+ /* Convert channel sidebar to browser-like tabs. */
+ /* Toggleable sliding sidebar replacement for user window. */ }
+ .container-fluid #overview {
+ left: 0;
+ margin-top: 0;
+ bottom: 0;
+ position: fixed;
+ padding: 0;
+ width: 100%;
+ z-index: 1; }
+ .container-fluid #overview ul {
+ margin: 0; }
+ .container-fluid #overview ul li {
+ margin: 0;
+ padding: 10px 0;
+ width: 50%; }
+ .container-fluid #logo, .container-fluid .sidebar h2 {
+ display: block;
+ position: fixed;
+ margin-left: auto;
+ margin-right: auto;
+ width: 100%;
+ z-index: 1; }
+ .container-fluid .sidebar h2 {
+ margin-top: 120px; }
+ .container-fluid .sidebar {
+ margin-top: 2%; }
+ .container-fluid form.form-inline {
+ padding: 0 10px; }
+ .container-fluid #home {
+ margin: 10px 17px 0; }
+ .container-fluid p#settings-soon {
+ text-align: center; }
+ .container-fluid .sidebar {
+ width: 0; }
+ .container-fluid #user-window {
+ -webkit-box-shadow: 0 0 4px 2px #333333;
+ -moz-box-shadow: 0 0 4px 2px #333333;
+ box-shadow: 0 0 4px 2px #333333;
+ display: none;
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: 75%;
+ z-index: 3; }
+ .container-fluid .content {
+ margin-left: 0;
+ margin-right: 0;
+ width: 100%; }
+ .container-fluid .content.user-window-toggled {
+ right: 75%; }
+ .container-fluid #chat-window {
+ width: 100%; }
+ .container-fluid #chat-window div {
+ z-index: 2; }
+ .container-fluid #channels {
+ display: inline-block;
+ height: 34px;
+ left: 34px;
+ position: fixed;
+ overflow: visible;
+ top: 0;
+ white-space: nowrap;
+ z-index: 2; }
+ .container-fluid #channels div.channel {
+ border: 1px solid rgba(10, 10, 10, 0.5);
+ border-radius: 25px 0 0;
+ display: inline-block;
+ height: 34px;
+ left: 0;
+ padding: 7px 0;
+ position: relative;
+ text-align: left;
+ width: 120px; }
+ .container-fluid #channels div.channel span.channel-name {
+ display: inline-block;
+ margin-left: 8px;
+ overflow: none;
+ text-overflow: ellipsis;
+ width: 45%; }
+ .container-fluid #channels div.channel span.unread, .container-fluid #channels div.channel span.unread-mentions {
+ float: none;
+ vertical-align: 6px; }
+ .container-fluid #channels div.channel div.close-button {
+ position: absolute;
+ right: 0;
+ top: 7px;
+ visibility: visible; }
+ .container-fluid #channels .slide {
+ background: rgba(67, 73, 80, 0.75);
+ color: white;
+ font-size: 24px;
+ display: none;
+ height: 34px;
+ padding-top: 4px;
+ position: fixed;
+ text-align: center;
+ width: 34px;
+ z-index: 2; }
+ .container-fluid #channels .slide:hover {
+ background: rgba(67, 73, 80, 0.95);
+ cursor: pointer; }
+ .container-fluid #channels #slide-prev {
+ left: 0; }
+ .container-fluid #channels #slide-prev:after {
+ content: "<"; }
+ .container-fluid #channels #slide-next {
+ right: 0; }
+ .container-fluid #channels #slide-next:after {
+ content: ">"; }
+ .container-fluid #chat-bar {
+ position: fixed;
+ left: 0;
+ top: 34px; }
+ .container-fluid #chat-bar.user-window-toggled {
+ left: -75%; }
+ .container-fluid #chat-contents {
+ margin-top: 34px; }
+ .container-fluid #user-window-toggle {
+ background: rgba(67, 73, 80, 0.1);
+ border: 1px solid rgba(67, 73, 80, 0.3);
+ border-radius: 50px 0 0;
+ bottom: 56px;
+ display: block;
+ height: 55px;
+ position: fixed;
+ right: 0;
+ width: 55px;
+ z-index: 3; }
+ .container-fluid #user-window-toggle img {
+ position: absolute;
+ top: 18px;
+ left: 18px;
+ height: 30px;
+ width: 30px; }
+ .container-fluid #user-window-toggle:hover {
+ background: rgba(67, 73, 80, 0.5);
+ cursor: pointer; }
+ .container-fluid #user-window-toggle.user-window-toggled {
+ right: 75%; }
+ .container-fluid #input-container {
+ text-align: center; }
+ .container-fluid #input-container .input {
+ padding-top: 12px; }
+ .container-fluid input#chat-input {
+ float: none;
+ width: 65%; }
+ .container-fluid #chat-button {
+ width: 20%;
+ padding-left: 0;
+ padding-right: 0; }
+
+ .channel {
+ background: #e8e8e8; } }
202 assets/css/subway-mobile.scss
View
@@ -0,0 +1,202 @@
+@mixin box-shadow($shadow) {
+ -webkit-box-shadow: $shadow;
+ -moz-box-shadow: $shadow;
+ box-shadow: $shadow;
+}
+
+@media screen and (max-width: 720px) {
+ .container-fluid {
+ /* Overview. */
+ #overview {
+ left: 0;
+ margin-top: 0;
+ bottom: 0;
+ position: fixed;
+ padding: 0;
+ width: 100%;
+ z-index: 1;
+ ul {
+ margin: 0;
+ li {
+ margin: 0;
+ padding: 10px 0;
+ width: 50%;
+ }
+ }
+ }
+ #logo, .sidebar h2 {
+ display: block;
+ position: fixed;
+ margin-left: auto;
+ margin-right: auto;
+ width: 100%;
+ z-index: 1;
+ }
+ .sidebar h2 {
+ margin-top: 120px;
+ }
+ .sidebar {
+ margin-top: 2%;
+ }
+ form.form-inline {
+ padding: 0 10px;
+ }
+ #home {
+ margin: 10px 17px 0;
+ }
+ p#settings-soon {
+ text-align: center;
+ }
+
+ /* Convert channel sidebar to browser-like tabs. */
+ .sidebar {
+ width: 0;
+ }
+ #user-window {
+ @include box-shadow(0 0 4px 2px #333);
+ display: none;
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: 75%;
+ z-index: 3;
+ }
+ .content {
+ margin-left: 0;
+ margin-right: 0;
+ width: 100%;
+ &.user-window-toggled {
+ right: 75%;
+ }
+ }
+ #chat-window {
+ width: 100%;
+ div {
+ z-index: 2;
+ }
+ }
+ #channels {
+ display: inline-block;
+ height: 34px;
+ left: 34px;
+ position: fixed;
+ overflow: visible;
+ top: 0;
+ white-space: nowrap;
+ z-index: 2;
+ div.channel {
+ border: 1px solid rgba(10, 10, 10, .5);
+ border-radius: 25px 0 0;
+ display: inline-block;
+ height: 34px;
+ left: 0;
+ padding: 7px 0;
+ position: relative;
+ text-align: left;
+ width: 120px;
+ span.channel-name {
+ display: inline-block;
+ margin-left: 8px;
+ overflow: none;
+ text-overflow: ellipsis;
+ width: 45%;
+ }
+ span.unread, span.unread-mentions {
+ float: none;
+ vertical-align: 6px;
+ }
+ div.close-button {
+ position: absolute;
+ right: 0;
+ top: 7px;
+ visibility: visible;
+ }
+ }
+ .slide {
+ background: rgba(67, 73, 80, .75);
+ color: white;
+ font-size: 24px;
+ display: none;
+ height: 34px;
+ padding-top: 4px;
+ position: fixed;
+ text-align: center;
+ width: 34px;
+ z-index: 2;
+ &:hover {
+ background: rgba(67, 73, 80, .95);
+ cursor: pointer;
+ }
+ }
+ #slide-prev {
+ left: 0;
+ &:after {
+ content: "<";
+ }
+ }
+ #slide-next {
+ right: 0;
+ &:after {
+ content: ">";
+ }
+ }
+ }
+ #chat-bar {
+ position: fixed;
+ left: 0;
+ top: 34px;
+ &.user-window-toggled {
+ left: -75%;
+ }
+ }
+ #chat-contents {
+ margin-top: 34px;
+ }
+
+ /* Toggleable sliding sidebar replacement for user window. */
+ #user-window-toggle {
+ background: rgba(67, 73, 80, .1);
+ border: 1px solid rgba(67, 73, 80, .3);
+ border-radius: 50px 0 0;
+ bottom: 56px;
+ display: block;
+ height: 55px;
+ position: fixed;
+ right: 0;
+ width: 55px;
+ z-index: 3;
+ img {
+ position: absolute;
+ top: 18px;
+ left: 18px;
+ height: 30px;
+ width: 30px;
+ }
+ &:hover {
+ background: rgba(67, 73, 80, .5);
+ cursor: pointer;
+ }
+ &.user-window-toggled {
+ right: 75%;
+ }
+ }
+ #input-container {
+ text-align: center;
+ .input {
+ padding-top: 12px;
+ }
+ }
+ input#chat-input {
+ float: none;
+ width: 65%;
+ }
+ #chat-button {
+ width: 20%;
+ padding-left: 0;
+ padding-right: 0;
+ }
+ }
+ .channel {
+ background: darken(#F5F5F5, 5%);
+ }
+}
11 assets/css/subway.css
View
@@ -229,6 +229,12 @@ html { overflow: hidden; }
margin-right: 0.3em;
}
+.slide {
+ position: fixed;
+ width: 0;
+ height: 0;
+}
+
#logo {
text-align: center;
}
@@ -379,6 +385,11 @@ html { overflow: hidden; }
white-space: pre;
}
+div.embed-toggle {
+ display: inline;
+ margin-left: 5px;
+}
+
.chat-message .embed img{
display: block;
max-width: 100%;
69 assets/js/client.js
View
@@ -30,7 +30,7 @@ $(function() {
try {
window.unity.api = external.getUnityObject(1.0);
window.unity.init({
- name: "Subay IRC",
+ name: "Subway IRC",
iconUrl: window.location.protocol+"//"+window.location.host+"/assets/images/subway.png",
onInit: function() {
window.unity.connected = true;
@@ -87,7 +87,7 @@ $(function() {
alert('You were disconnected from the server.');
$('.container-fluid').css('opacity', '0.5');
});
-
+
irc.socket.on('register_success', function(data) {
window.irc.loggedIn = true;
@@ -103,9 +103,9 @@ $(function() {
$.each(data.channels, function(key, value){
var chanName = value.serverName.toLowerCase();
if(chanName[0] == '#'){
- irc.chatWindows.add({name: chanName});
+ irc.chatWindows.add({name: chanName, initial: true});
} else {
- irc.chatWindows.add({name: chanName, type: 'pm'});
+ irc.chatWindows.add({name: chanName, type: 'pm', initial: true});
}
var channel = irc.chatWindows.getByName(chanName);
var channelTabs = irc.appView.channelList.channelTabs;
@@ -309,38 +309,41 @@ $(function() {
var output = '';
channel = irc.chatWindows.getByName(data.name);
- $.each(data.messages.reverse(), function(index, message){
- if($('#' + message._id).length) {
- return true; //continue to next iteration
- }
-
- var type = '';
- var message_html;
- if (message.message.substr(1, 6) === 'ACTION') {
- message_html = ich.action({
- user: message.user,
- content: message.message.substr(8),
- renderedTime: utils.formatDate(message.date)
- }, true);
- } else {
- message_html = ich.message({
- user: message.user,
- content: message.message,
- renderedTime: utils.formatDate(message.date)
- }, true);
- }
+ if (data.messages) {
+ $.each(data.messages.reverse(), function(index, message){
+ if($('#' + message._id).length) {
+ return true; //continue to next iteration
+ }
+ var type = '';
+ var message_html;
+ if (message.message.substr(1, 6) === 'ACTION') {
+ message_html = ich.action({
+ user: message.user,
+ content: message.message.substr(8),
+ renderedTime: utils.formatDate(message.date)
+ }, true);
+ } else {
+ message_html = ich.message({
+ user: message.user,
+ content: message.message,
+ renderedTime: utils.formatDate(message.date)
+ }, true);
+ }
- if(message.user == irc.me.get('nick')){
- type = 'message-me';
- } else {
- message_html = utils.mentions(message_html);
- }
- message_html = utils.linkify(message_html);
- message_html = "<div id=\"" + message._id + "\" class=\"message-box " + type + "\">" + message_html + "</div>";
- output += message_html;
- });
+ if(message.user == irc.me.get('nick')){
+ type = 'message-me';
+ } else {
+ message_html = utils.mentions(message_html);
+ }
+
+ message_html = utils.linkify(message_html);
+ message_html = "<div id=\"" + message._id + "\" class=\"message-box " + type + "\">" + message_html + "</div>";
+ output += message_html;
+ });
+ }
+
var old_height = channel.view.$('#chat-contents')[0].scrollHeight;
channel.view.$('#chat-contents').prepend(output);
var new_height = channel.view.$('#chat-contents')[0].scrollHeight+1000-old_height;
50 assets/js/views/channel_list.js
View
@@ -1,19 +1,65 @@
+var TAB_WIDTH = 120;
+var BTN_WIDTH = 34;
+
var ChannelListView = Backbone.View.extend({
el: '#channels',
+ events: {
+ 'click #slide-prev': 'slidePrev',
+ 'click #slide-next': 'slideNext'
+ },
+
initialize: function() {
irc.chatWindows.bind('add', this.addChannel, this);
+ $('.slide').css('display', 'inline-block');
this.channelTabs = []
},
addChannel: function(chatWindow) {
+ var $el = $(this.el);
var view = new ChannelTabView({model: chatWindow});
this.channelTabs.push(view);
- $(this.el).append(view.render().el);
+ $el.append(view.render().el);
var name = chatWindow.get('name');
if(name[0] === '#' || name === 'status'){
view.setActive();
+
+ if ($el.css('position') == 'fixed' && !(chatWindow.get('initial'))) {
+ // MOBILE: navigate the tab list all the way to the right, to the
+ // newest tab.
+ $el.css('left', -1 * (this.channelTabs.length - 1) *
+ TAB_WIDTH + BTN_WIDTH + 'px');
+ }
}
- }
+ },
+
+ slidePrev: function() {
+ // MOBILE: slide the tab list left, but don't let first tab hit the left.
+ var that = this;
+ setTimeout(function() {
+ var $el = $(that.el);
+ if ($el.css('position') != 'fixed') { return; }
+
+ var left = parseInt($el.css('left'), 10);
+ if (left < BTN_WIDTH) {
+ $el.animate({'left': left + TAB_WIDTH + 'px'}, 100);
+ }
+ }, 200);
+ },
+
+ slideNext: function() {
+ // MOBILE: slide the tab list right, but don't go farther than last tabs.
+ var that = this;
+ setTimeout(function() {
+ var $el = $(that.el);
+ if ($el.css('position') != 'fixed') { return; }
+
+ var left = parseInt($el.css('left'), 10);
+ if (left >= -1 * (that.channelTabs.length - 2) * TAB_WIDTH) {
+ $el.animate({'left': left - TAB_WIDTH + 'px'}, 100);
+ }
+ }, 200);
+ },
+
});
8 assets/js/views/chat.js
View
@@ -211,5 +211,13 @@ var ChatView = Backbone.View.extend({
$(this).siblings('.hide_embed').removeClass('hide');
$(this).addClass('hide');
});
+
+ // MOBILE: toggler slides user list in from the left.
+ $('.content').removeClass('user-window-toggled');
+ $('#user-window-toggle').click(function() {
+ $('#user-window').toggle();
+ $('.content, #channels, #chat-bar').toggleClass('user-window-toggled');
+ $(this).toggleClass('user-window-toggled');
+ });
}
});
1  assets/js/views/chat_application.js
View
@@ -44,6 +44,7 @@ var ChatApplicationView = Backbone.View.extend({
this.overview = new OverviewView;
} else {
this.channelList = new ChannelListView;
+ $('.slide').css('display', 'inline-block');
}
return this;
},
1  views/layout.jade
View
@@ -5,6 +5,7 @@ html
link(href='/assets/images/favicon.ico', rel='icon', type='image/x-icon')
!= css('bootstrap.min')
!= css('subway')
+ != css('subway-mobile')
script
var ENV = '#{env}',
10 views/templates.jade
View
@@ -4,9 +4,11 @@ script(id="chat_application", type="text/html")
img(src='/assets/images/subway.png')
h2 Subway
br
- small IRC client
+ small IRC Client
#user-box
#channels
+ #slide-prev.slide
+ #slide-next.slide
.content
script(id="load_image", type="text/html")
@@ -98,7 +100,7 @@ script(id="overview_connection", type="text/html")
script(id="overview_settings", type="text/html")
#home_parent
a.overview_button#home Home
- p Coming soon.
+ p#settings-soon Coming soon.
script(id="overview_login", type="text/html")
#home_parent
@@ -143,6 +145,8 @@ script(id="chat", type="text/html")
.titlebar
span(class='window_title') User List
#user-list.bar
+ #user-window-toggle
+ img(src="/assets/images/register.svg")
script(id="channel", type="text/html")
span(class="channel-name") {{name}}
@@ -173,7 +177,7 @@ script(id="link", type="text/html")
a(target="_blank", href="{{link}}") {{link}}
script(id="image_embed", type="text/html")
- div
+ div.embed-toggle
a.hide_embed
i(class="icon-chevron-up")
a.show_embed.hide
Something went wrong with that request. Please try again.