From 02f8f5fa6179b4a3c9912df357226aafbae70060 Mon Sep 17 00:00:00 2001 From: Igor Zhukov Date: Mon, 10 Feb 2014 21:25:21 +0400 Subject: [PATCH] Improved mobile layout, supported chrome packaged notifications --- app/css/app.css | 164 +- app/index.html | 20 +- app/js/app.js | 6 +- app/js/background.js | 2 +- app/js/controllers.js | 13 +- app/js/directives.js | 41 +- app/js/services.js | 6 +- app/js/util.js | 13 + app/manifest.json | 1 + app/partials/head.html | 19 +- app/partials/im.html | 4 +- app/partials/login.html | 2 +- app/partials/welcome.html | 2 +- app/vendor/bootstrap/config.json | 411 ++ app/vendor/bootstrap/css/bootstrap-theme.css | 346 ++ .../bootstrap/css/bootstrap-theme.min.css | 7 + app/vendor/bootstrap/css/bootstrap.css | 3532 ++++++----------- app/vendor/bootstrap/css/bootstrap.min.css | 7 + .../fonts/glyphicons-halflings-regular.eot | Bin .../fonts/glyphicons-halflings-regular.svg | 0 .../fonts/glyphicons-halflings-regular.ttf | Bin .../fonts/glyphicons-halflings-regular.woff | Bin app/vendor/bootstrap/js/bootstrap.js | 1227 +++--- app/vendor/bootstrap/js/bootstrap.min.js | 7 + .../ui-bootstrap-custom-0.10.0.js | 186 +- .../ui-bootstrap-custom-0.10.0.min.js | 4 +- .../ui-bootstrap-custom-tpls-0.10.0.js | 192 +- .../ui-bootstrap-custom-tpls-0.10.0.min.js | 4 +- 28 files changed, 2980 insertions(+), 3236 deletions(-) create mode 100755 app/vendor/bootstrap/config.json create mode 100755 app/vendor/bootstrap/css/bootstrap-theme.css create mode 100755 app/vendor/bootstrap/css/bootstrap-theme.min.css mode change 100644 => 100755 app/vendor/bootstrap/css/bootstrap.css create mode 100755 app/vendor/bootstrap/css/bootstrap.min.css mode change 100644 => 100755 app/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot mode change 100644 => 100755 app/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg mode change 100644 => 100755 app/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf mode change 100644 => 100755 app/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff mode change 100644 => 100755 app/vendor/bootstrap/js/bootstrap.js create mode 100755 app/vendor/bootstrap/js/bootstrap.min.js diff --git a/app/css/app.css b/app/css/app.css index fc4674cb..6ec303d1 100644 --- a/app/css/app.css +++ b/app/css/app.css @@ -117,7 +117,6 @@ fieldset[disabled] .btn-tg.active { .tg_page_head .container { display: block; width: auto; - padding: 0; } .tg_page_head .navbar-inverse { /*-webkit-app-region: drag;*/ @@ -131,18 +130,24 @@ fieldset[disabled] .btn-tg.active { margin: 0; } .tg_page_head .navbar > .container .navbar-brand { - padding: 9px; + padding: 9px 15px; opacity: 0.9; margin-left: 0; -webkit-transition: opacity swing .9s; } +@media (max-width: 480px) { + .tg_page_head .navbar > .container .navbar-brand { + padding-left: 9px; + } +} -.tg_page_head .navbar > .container .navbar-brand-alpha { - color: #FFFFFF; - font-size: 12px; - padding-left: 5px; +@media (min-width: 480px) { + .tg_page_head .navbar-quick-nav { + display: none; + } } + .tg_head_logo { background: url(../img/Logo_2x.png) 0 0 no-repeat; background-size: 110px 31px; @@ -162,6 +167,31 @@ fieldset[disabled] .btn-tg.active { .tg_page_head .navbar-inverse .navbar-nav > li > a:hover { color: #FFF; } +.tg_page_head .navbar-inverse .navbar-toggle { + border-color: #497495; + outline: 0; +} +.tg_page_head .navbar-inverse .navbar-collapse, +.tg_page_head .navbar-inverse .navbar-form { + border-color: #497495; +} + +.tg_page_head .navbar-inverse .navbar-toggle:hover, +.tg_page_head .navbar-inverse .navbar-toggle:active, +.tg_page_head .navbar-inverse .navbar-toggle:focus { + background-color: rgba(255,255,255,0.1); +} + +.tg_page_head .navbar-quick-nav { + margin: 0; +} +.tg_page_head .navbar-quick-nav li { + float: left; +} +.tg_page_head .navbar-quick-nav a { + padding-top: 15px; + padding-bottom: 15px; +} .tg_progress { height: 12px; @@ -329,19 +359,19 @@ fieldset[disabled] .btn-tg.active { .im_page_wrap { background: #FFF; - /*max-width: 1000px;*/ - width: 1000px; + max-width: 1000px; + min-width: 300px; margin: 0 auto; -webkit-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1); box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1); - /*margin-bottom: 40px;*/ border-radius: 0 0 3px 3px; overflow: hidden; } + .im_page_footer { font-size: 11px; text-align: center; @@ -360,20 +390,21 @@ fieldset[disabled] .btn-tg.active { .im_dialogs_col_wrap { float: left; - width: 310px; + width: 31%; border-right: 2px solid #E9EBED; padding-bottom: 10px; } .im_history_col_wrap { float: left; - width: 690px; + width: 69%; } /* Dialogs list */ .im_dialogs_col { - width: 315px; + /*min-width: 315px;*/ + margin-right: -7px; } .im_dialogs_col .nano > .pane { background : rgba(0,0,0,.0); @@ -397,7 +428,7 @@ fieldset[disabled] .btn-tg.active { .im_dialogs_search { padding: 14px 12px; - /*border-right: 2px solid #E9EBED;*/ + position: relative; } .im_dialogs_search_field { font-size: 12px; @@ -421,7 +452,7 @@ fieldset[disabled] .btn-tg.active { .im_dialogs_search_clear { position: absolute; - margin-left: 262px; + right: 19px; margin-top: -23px; color: #999; width: 13px; @@ -662,9 +693,9 @@ a.im_dialog:hover .im_dialog_date { } .im_history { padding: 20px 0 0 3px; - /*max-width: 555px;*/ max-width: 500px; margin: 0 auto; + position: relative; } .im_history_typing_wrap { @@ -1061,21 +1092,20 @@ span.emoji { } .im_send_panel_wrap { - width: 526px; + max-width: 526px; margin: 0 auto; padding: 10px 12px 22px 0; } -.im_panel_fixed_bottom .im_send_form_wrap1 { +.im_send_form_wrap { position: relative; } -.im_panel_fixed_bottom .im_send_form { +.im_send_form { + max-width: 389px; + margin: 0 auto; position: absolute; bottom: 0; left: 62px; -} -.im_send_form { - width: 389px; - float: left; + right: 62px; } .im_submit { padding: 5px 12px; @@ -1550,8 +1580,98 @@ img.img_fullsize { margin: 30px auto 10px; } + .im_page_footer { + display: none; + } + .im_panel_own_photo, + .im_panel_peer_photo { + display: none; + } + + .im_send_form { + left: 0; + right: 0; + max-width: none; + } +} + +@media (max-width: 640px) { + .im_dialog_peer { + white-space: normal; + height: 2.84em; + } + .im_dialog_message { + display: none; + } +} + +@media (max-width: 900px) { + /*.icon-message-status { + margin-left: 0; + margin-top: 18px; + right: -1px; + }*/ + + .icon-message-status { + z-index: 10; + margin-left: -5px; + border-radius: 0; + height: 34px; + border: 0; + width: 2px; + margin-top: 1px; + border: 0; + } + /*.icon-message-status { + z-index: 10; + margin-left: -15px; + }*/ +} + +@media (max-width: 480px) { + .im_dialogs_col_wrap, + .im_page_peer_not_selected .im_history_col_wrap { + display: none; + } + .im_page_peer_not_selected .im_dialogs_col_wrap { + display: block; + border-right: 0; + } + + .im_page_peer_not_selected .im_dialogs_col { + margin-right: 0; + } + .im_page_peer_not_selected .im_dialogs_col_wrap .pane { + width: 12px; + right: 0px; + } + .im_page_peer_not_selected .im_dialogs_col_wrap .pane > .slider { + border-radius: 3px; + margin: 0 3px; + } + + .im_dialogs_scrollable_wrap { + padding: 0 12px 0 12px; + } + + .im_dialogs_col_wrap, + .im_history_col_wrap { + float: none; + width: auto; + max-width: auto; + min-width: auto; + } + + .im_page_peer_not_selected .im_dialog_peer { + white-space: nowrap; + height: auto; + } + .im_page_peer_not_selected .im_dialog_message { + display: block; + } } + .settings_modal_window .modal-dialog { max-width: 502px; } diff --git a/app/index.html b/app/index.html index 00c04702..fbeb4906 100644 --- a/app/index.html +++ b/app/index.html @@ -1,13 +1,13 @@ - + Webogram - + - + @@ -40,7 +40,7 @@ - + @@ -50,12 +50,12 @@ - - - - - - + + + + + + diff --git a/app/js/app.js b/app/js/app.js index f4dc5422..c882d9ea 100644 --- a/app/js/app.js +++ b/app/js/app.js @@ -55,9 +55,9 @@ config(['$locationProvider', '$routeProvider', '$compileProvider', function($loc // $locationProvider.html5Mode(true); - $routeProvider.when('/', {templateUrl: 'partials/welcome.html?3', controller: 'AppWelcomeController'}); - $routeProvider.when('/login', {templateUrl: 'partials/login.html?4', controller: 'AppLoginController'}); - $routeProvider.when('/im', {templateUrl: 'partials/im.html?12', controller: 'AppIMController', reloadOnSearch: false}); + $routeProvider.when('/', {templateUrl: 'partials/welcome.html?4', controller: 'AppWelcomeController'}); + $routeProvider.when('/login', {templateUrl: 'partials/login.html?5', controller: 'AppLoginController'}); + $routeProvider.when('/im', {templateUrl: 'partials/im.html?13', controller: 'AppIMController', reloadOnSearch: false}); $routeProvider.otherwise({redirectTo: '/'}); }]); diff --git a/app/js/background.js b/app/js/background.js index 7a4e625d..095e5b8f 100644 --- a/app/js/background.js +++ b/app/js/background.js @@ -11,7 +11,7 @@ chrome.app.runtime.onLaunched.addListener(function(launchData) { width: 1100, height: 700 }, - minWidth: 1050, + minWidth: 320, minHeight: 400, frame: 'chrome' }); diff --git a/app/js/controllers.js b/app/js/controllers.js index 5ab48fcc..47e8f1d2 100644 --- a/app/js/controllers.js +++ b/app/js/controllers.js @@ -220,7 +220,7 @@ angular.module('myApp.controllers', []) var wrappedDialog = AppMessagesManager.wrapForDialog(dialog.top_message, dialog.unread_count); if (pos !== false) { var prev = $scope.dialogs.splice(pos, 1); - // wrappedDialog = angular.extend(prev[0], wrappedDialog); + safeReplaceObject(prev, wrappedDialog); offset++; } $scope.dialogs.unshift(wrappedDialog); @@ -300,6 +300,7 @@ angular.module('myApp.controllers', []) $scope.history = []; $scope.typing = {}; + $scope.state = {}; var peerID, offset = 0, @@ -345,9 +346,9 @@ angular.module('myApp.controllers', []) if (preload) { $scope.typing = {}; - $scope.state = {loaded: true}; $scope.$broadcast('ui_peer_change'); $scope.$broadcast('ui_history_change'); + safeReplaceObject($scope.state, {loaded: true}); } } @@ -368,7 +369,7 @@ angular.module('myApp.controllers', []) $scope.$broadcast('ui_history_prepend'); }, function () { - $scope.state = {error: true}; + safeReplaceObject($scope.state, {error: true}); }); } @@ -388,19 +389,19 @@ angular.module('myApp.controllers', []) }); $scope.history.reverse(); - $scope.state = {loaded: true}; + safeReplaceObject($scope.state, {loaded: true}); $scope.$broadcast('ui_history_change'); AppMessagesManager.readHistory($scope.curDialog.inputPeer); }, function () { - $scope.state = {error: true}; + safeReplaceObject($scope.state, {error: true}); }); } function showEmptyHistory () { - $scope.state = {notSelected: true}; + safeReplaceObject($scope.state, {notSelected: true}); $scope.history = []; $scope.$broadcast('ui_history_change'); diff --git a/app/js/directives.js b/app/js/directives.js index c9c50fed..6b9c2e7c 100644 --- a/app/js/directives.js +++ b/app/js/directives.js @@ -41,6 +41,7 @@ angular.module('myApp.directives', ['myApp.filters']) var dialogsWrap = $('.im_dialogs_wrap', element)[0], scrollableWrap = $('.im_dialogs_scrollable_wrap', element)[0], + footer = $('.im_page_footer')[0], // dialogsSearch = $('im_dialogs_search', element)[0], moreNotified = false; @@ -83,7 +84,7 @@ angular.module('myApp.directives', ['myApp.filters']) function updateSizes () { $(element).css({ - height: $($window).height() - 162 + height: $($window).height() - footer.offsetHeight - 122 }); } @@ -107,8 +108,10 @@ angular.module('myApp.directives', ['myApp.filters']) scrollable = $('.im_history_scrollable', element)[0], panelWrap = $('.im_history_panel_wrap', element)[0], sendPanelWrap = $('.im_send_panel_wrap', element)[0], - sendFormWrap1 = $('.im_send_form_wrap1', element)[0], sendFormWrap = $('.im_send_form_wrap', element)[0], + headWrap = $('.tg_page_head')[0], + footer = $('.im_page_footer')[0], + sendForm = $('.im_send_form', element)[0], moreNotified = false; onContentLoaded(function () { @@ -199,18 +202,6 @@ angular.module('myApp.directives', ['myApp.filters']) }); }); - scope.$on('ui_editor_change', function (e, data) { - if (data.start) { - if (!$(sendPanelWrap).hasClass('im_panel_fixed_bottom')) { - sendFormWrap1.style.height = sendFormWrap.offsetHeight + 'px'; - $(sendPanelWrap).addClass('im_panel_fixed_bottom'); - } - } else { - sendFormWrap1.style.height = 'auto'; - $(sendPanelWrap).removeClass('im_panel_fixed_bottom'); - } - }); - scope.$on('ui_editor_resize', updateSizes); var atBottom = true; @@ -230,11 +221,16 @@ angular.module('myApp.directives', ['myApp.filters']) }); function updateSizes (heightOnly) { + $(sendFormWrap).css({ + height: $(sendForm).height() + }); + + var historyH = $($window).height() - panelWrap.offsetHeight - sendPanelWrap.offsetHeight - headWrap.offsetHeight - footer.offsetHeight; $(historyWrap).css({ - height: $($window).height() - panelWrap.offsetHeight - sendPanelWrap.offsetHeight - 90 + height: historyH }); $(historyEl).css({ - minHeight: $($window).height() - panelWrap.offsetHeight - sendPanelWrap.offsetHeight - 90 - 44 + minHeight: historyH - 44 }); if (heightOnly == true) return; @@ -242,7 +238,6 @@ angular.module('myApp.directives', ['myApp.filters']) onContentLoaded(function () { scrollableWrap.scrollTop = scrollableWrap.scrollHeight; updateScroller(); - // $(historyWrap).nanoScroller({scroll: 'bottom'}); }); } updateScroller(100); @@ -282,7 +277,6 @@ angular.module('myApp.directives', ['myApp.filters']) var updatePromise; $(richTextarea).on('keyup', function (e) { - scope.$emit('ui_editor_change', {start: false}); updateHeight(); scope.draftMessage.text = richTextarea.innerText; @@ -316,6 +310,10 @@ angular.module('myApp.directives', ['myApp.filters']) updateSendSettings(); $(editorElement).on('keydown', function (e) { + if (richTextarea) { + updateHeight(); + } + if (e.keyCode == 13) { var submit = false; if (sendOnEnter && !e.shiftKey) { @@ -325,17 +323,11 @@ angular.module('myApp.directives', ['myApp.filters']) } if (submit) { - scope.$emit('ui_editor_change', {start: false}); - updateHeight(); $(element).trigger('submit'); return cancelEvent(e); } } - if (richTextarea) { - scope.$emit('ui_editor_change', {start: true}); - updateHeight(); - } }); var lastTyping = 0; @@ -370,7 +362,6 @@ angular.module('myApp.directives', ['myApp.filters']) var newHeight = richTextarea.offsetHeight; if (height != newHeight) { height = newHeight; - scope.$emit('ui_editor_change', {start: false}); scope.$emit('ui_editor_resize'); } }; diff --git a/app/js/services.js b/app/js/services.js index 6337588d..8b4235c8 100644 --- a/app/js/services.js +++ b/app/js/services.js @@ -2393,7 +2393,11 @@ angular.module('myApp.services', []) notification.onclick = function () { notification.close(); - window.focus(); + if (window.chrome && chrome.app) { + chrome.app.window.current().focus(); + } else { + window.focus(); + } notificationsClear(); if (data.onclick) { data.onclick(); diff --git a/app/js/util.js b/app/js/util.js index 3d2d0b5a..e842483f 100644 --- a/app/js/util.js +++ b/app/js/util.js @@ -57,3 +57,16 @@ function onContentLoaded (cb) { function tsNow () { return +new Date(); } + +function safeReplaceObject (wasObject, newObject) { + for (var key in wasObject) { + if (!newObject.hasOwnProperty(key) && key.charAt(0) != '$') { + delete wasObject[key]; + } + } + for (var key in newObject) { + if (newObject.hasOwnProperty(key)) { + wasObject[key] = newObject[key]; + } + } +} diff --git a/app/manifest.json b/app/manifest.json index 35321ee1..b08981c9 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -9,6 +9,7 @@ } }, "permissions": [ + "notifications", "webview", {"fileSystem": ["write"]}, "storage" diff --git a/app/partials/head.html b/app/partials/head.html index ecf994a8..c3b27b2a 100644 --- a/app/partials/head.html +++ b/app/partials/head.html @@ -1,10 +1,25 @@