Browse Source

Improved mobile layout

Some modifications from #35
master
Igor Zhukov 11 years ago
parent
commit
8cf5fca521
  1. 306
      app/css/app.css
  2. 326
      app/css/app_mobile.css
  3. 3
      app/index.html
  4. 107
      app/js/controllers.js
  5. 54
      app/js/directives.js
  6. 3
      app/js/lib/config.js
  7. 24
      app/js/services.js
  8. 67
      app/partials/chat_modal.html
  9. 6
      app/partials/contacts_modal.html
  10. 82
      app/partials/head.html
  11. 22
      app/partials/im.html
  12. 2
      app/partials/login.html
  13. 7
      app/partials/message.html
  14. 4
      app/partials/peer_select.html
  15. 17
      app/partials/photo_modal.html
  16. 16
      app/partials/video_modal.html
  17. 3
      app/partials/welcome.html
  18. 2
      app/webogram.appcache

306
app/css/app.css

@ -176,16 +176,15 @@ input[type="number"] { @@ -176,16 +176,15 @@ input[type="number"] {
.tg_page_head .navbar {
min-height: 44px;
}
.tg_page_head .navbar-quick-nav,
.tg_page_head .navbar-toggle {
margin-top: 5px;
margin-bottom: 5px;
display: none;
}
.tg_page_head .container {
display: block;
width: auto;
}
.tg_page_head .navbar-inverse {
/*-webkit-app-region: drag;*/
background: #497495;
border: 0;
@ -205,6 +204,10 @@ input[type="number"] { @@ -205,6 +204,10 @@ input[type="number"] {
line-height: 0;
height: auto;
}
.navbar_offline .navbar-header,
.navbar_offline .navbar-offline > li {
float: left;
}
.navbar-offline {
max-width: 250px;
margin: 0 auto;
@ -274,33 +277,6 @@ input[type="number"] { @@ -274,33 +277,6 @@ input[type="number"] {
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;
}
.icon-back {
display: inline-block;
width: 10px;
height: 18px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -15px -419px no-repeat;
background-size: 42px 710px;
opacity: 0.6;
}
.is_1x .icon-back {
background-image: url(../img/icons/IconsetW_1x.png);
}
.tg_page_head .navbar-quick-nav a:hover .icon-back {
opacity: 1;
}
.tg_progress {
height: 12px;
@ -328,6 +304,9 @@ input[type="number"] { @@ -328,6 +304,9 @@ input[type="number"] {
padding: 5px 14px;
font-size: 13px;
}
.dropdown-header {
padding: 3px 14px;
}
.modal-backdrop {
background: #111111;
@ -418,6 +397,13 @@ input[type="number"] { @@ -418,6 +397,13 @@ input[type="number"] {
background-image: url(../img/icons/PhotoControls_1x.png);
}
.modal {
padding: 10px;
}
.modal-dialog {
margin: 0 auto;
}
.text-invisible {
visibility: hidden;
}
@ -467,7 +453,7 @@ input[type="number"] { @@ -467,7 +453,7 @@ input[type="number"] {
margin: 17px;
opacity: 0.8;
}
.is_1x .icon-back {
.is_1x .modal-close-button i {
background-image: url(../img/icons/IconsetW_1x.png);
}
.modal-close-button:hover i {
@ -1296,11 +1282,11 @@ a.im_dialog_selected .im_dialog_date { @@ -1296,11 +1282,11 @@ a.im_dialog_selected .im_dialog_date {
}
.im_history_appending {
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
-webkit-transition: all ease-in-out 0.2s;
-moz-transition: all ease-in-out 0.2s;
-ms-transition: all ease-in-out 0.2s;
-o-transition: all ease-in-out 0.2s;
transition: all ease-in-out 0.2s;
}
@ -1791,45 +1777,74 @@ img.im_message_document_thumb { @@ -1791,45 +1777,74 @@ img.im_message_document_thumb {
width: 10px;
height: 10px;
border-radius: 7px;
overflow: hidden;
position: absolute;
margin-left: -26px;
margin-top: 13px;
opacity: 0;
}
.icon-message-status-unread {
.im_message_unread .icon-message-status {
opacity: 1.0;
}
.icon-message-status-pending {
.im_message_pending .icon-message-status {
opacity: 0.5;
}
.icon-message-status-error {
.im_message_error_btn {
display: none;
}
.im_message_error .im_message_error_btn {
display: inline;
}
.im_message_error_btn .icon-message-status {
background: #da564d;
opacity: 0.85;
}
.icon-message-status-error:hover {
.im_message_error_btn .icon-message-status:hover {
opacity: 1;
}
.icon-message-status-tick {
display: none;
width: 16px;
height: 10px;
background: url(../img/icons/Checks2_2x.png) 0 0 no-repeat;
background-size: 16px 10px;
top: 2px;
position: relative;
}
.icon-message-status-tick.message-status-unread-tick {
/*width: 13px;*/
background: url(../img/icons/Checks1_2x.png) 0 0 no-repeat;
background-size: 16px 10px;
}
.im_message_date {
color: #adadad;
font-size: 0.85em;
padding: 0 0 20px 10px;
}
@media (max-width: 900px) {
/* Status ticks */
.icon-message-status,
.im_message_error_btn,
.icon-message-status-tick {
display: none;
}
.im_message_out .icon-message-status-tick {
display: inline-block;
width: 16px;
height: 10px;
background: url(../img/icons/Checks2_2x.png);
background-size: 16px 10px;
top: 2px;
position: relative;
}
.is_1x .im_message_out .icon-message-status-tick {
background-image: url(../img/icons/Checks2_1x.png);
}
.im_message_pending .icon-message-status-tick {
display: none;
}
.im_message_unread .icon-message-status-tick {
background: url(../img/icons/Checks1_2x.png);
background-size: 16px 10px;
}
.is_1x .im_message_unread .icon-message-status-tick {
background-image: url(../img/icons/Checks1_1x.png);
}
.im_message_date {
padding: 0;
}
}
div.im_message_author,
div.im_message_body {
display: block;
@ -1882,11 +1897,17 @@ span.emoji { @@ -1882,11 +1897,17 @@ span.emoji {
.im_history_not_selected,
.im_history_empty {
visibility: hidden;
text-align: center;
color: #999;
font-size: 16px;
line-height: 18px;
padding: 1px 50px;
margin: 0;
}
.im_history_not_selected.vertical-aligned,
.im_history_empty.vertical-aligned {
visibility: visible;
}
.im_history_to_bottom .im_history_not_selected,
.im_history_to_bottom .im_history_empty {
@ -2143,21 +2164,19 @@ img.img_fullsize { @@ -2143,21 +2164,19 @@ img.img_fullsize {
}
.user_modal_status {
color: #999;
margin-bottom: 24px;
margin-bottom: 16px;
}
.user_modal_actions_wrap {
margin-top: 8px;
}
.user_modal_main_btn {
border: 0;
font-size: 12px;
padding-left: 16px;
padding-right: 16px;
margin: 8px 10px 0 0;
float: left;
}
.user_modal_other_btn {
margin-left: 10px;
margin: 8px 0 0 0;
float: left;
}
.user_modal_other_btn .dropdown-toggle {
@ -2189,12 +2208,13 @@ img.img_fullsize { @@ -2189,12 +2208,13 @@ img.img_fullsize {
}
.chat_modal_members_count {
color: #999;
margin-bottom: 24px;
margin-bottom: 16px;
}
.chat_modal_actions_wrap {
margin-top: 8px;
position: relative;
}
.chat_modal_main_btn {
border: 0;
font-size: 12px;
@ -2203,6 +2223,8 @@ img.img_fullsize { @@ -2203,6 +2223,8 @@ img.img_fullsize {
float: left;
position: relative;
overflow: hidden;
margin-right: 10px;
margin-top: 8px;
}
.chat_modal_invite_btn {
border: 0;
@ -2212,6 +2234,7 @@ img.img_fullsize { @@ -2212,6 +2234,7 @@ img.img_fullsize {
float: left;
position: relative;
margin-right: 10px;
margin-top: 8px;
}
.chat_modal_delete_btn {
border: 0;
@ -2219,9 +2242,11 @@ img.img_fullsize { @@ -2219,9 +2242,11 @@ img.img_fullsize {
padding-left: 16px;
padding-right: 16px;
float: left;
margin-right: 10px;
margin-top: 8px;
}
.chat_modal_other_btn {
margin-left: 10px;
margin-top: 8px;
float: left;
}
.chat_modal_other_btn .dropdown-toggle {
@ -3039,160 +3064,6 @@ a.contacts_modal_contact:hover .contacts_modal_contact_status { @@ -3039,160 +3064,6 @@ a.contacts_modal_contact:hover .contacts_modal_contact_status {
}
@media (min-width: 480px) {
.tg_page_head .navbar-quick-nav {
display: none;
}
}
@media (max-width: 480px) {
.tg_page_head .navbar > .container .navbar-brand {
padding-left: 9px;
}
.im_history_panel_edit_link {
margin-right: 0;
}
.im_dialogs_panel_dropdown .dropdown-menu {
right: 0;
left: auto;
}
}
@media (max-width: 480px) {
.login_form_wrap {
border-radius: 0;
max-width: auto;
box-shadow: none;
-webkit-box-shadow: none;
margin: 30px auto 20px;
}
}
@media (max-width: 640px) {
.im_page_footer {
display: none;
}
.im_panel_own_photo,
.im_panel_peer_photo {
display: none;
}
.im_history_panel_wrap {
margin: 0 15px;
}
.im_send_panel_wrap {
padding: 10px 15px;
}
.icon-select-tick {
margin: 10px 0 0 -24px
}
.im_content_message_wrap {
margin-left: 0;
}
.im_history_typing {
padding: 0 15px 0 60px;
}
.im_history_panel_info_link {
display: none;
}
.im_send_form {
left: 0;
right: 0;
max-width: none;
}
.im_edit_flush_link,
.im_edit_cancel_link,
.im_edit_delete_btn,
.im_edit_forward_btn {
padding-left: 5px;
padding-right: 5px;
margin: 6px 4px;
}
.im_edit_panel_border {
margin: 0 18px 22px 3px;
}
.im_edit_panel_wrap {
margin: 0 5px;
padding-bottom: 18px;
}
.emoji-wysiwyg-editor {
min-height: 34px;
max-height: 150px;
}
.im_dialog_peer {
white-space: normal;
height: 2.84em;
}
.im_dialog_message {
display: none;
}
}
@media (max-width: 900px) {
.icon-message-status {
z-index: 10;
margin-left: -5px;
border-radius: 0;
height: 34px;
border: 0;
width: 2px;
margin-top: 1px;
border: 0;
}
.im_message_grouped1 .icon-message-status,
.im_message_grouped2 .icon-message-status {
margin-top: -8px;
}
}
@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;
}
}
/* Dialogs modal */
.peer_select_window .modal-dialog {
max-width: 506px;
@ -3579,4 +3450,3 @@ ce671b orange @@ -3579,4 +3450,3 @@ ce671b orange
.changelog_version_changes_list li {
line-height: 20px;
}

326
app/css/app_mobile.css

@ -0,0 +1,326 @@ @@ -0,0 +1,326 @@
@media (max-width: 479px) {
html {
background: #FFF;
}
.tg_page_head .navbar > .container .navbar-brand {
padding-left: 9px;
}
.im_history_panel_edit_link {
margin-right: 0;
}
.navbar-header {
float: none;
}
.navbar-toggle-wrap {
float: right;
display: block;
margin: 5px;
}
.navbar-toggle-wrap .navbar-toggle {
float: none;
display: block;
margin: 0;
}
.navbar-toggle .dropdown-toggle {
display: block;
}
.navbar-toggle-wrap .dropdown-menu {
margin-top: 4px;
right: 0;
left: auto;
}
.tg_page_head .navbar-quick-nav {
display: block;
margin: 0;
}
.tg_page_head .navbar-quick-nav li {
float: left;
}
.tg_page_head .navbar-quick-nav a {
padding-top: 15px;
padding-bottom: 15px;
}
.icon-back {
display: inline-block;
width: 10px;
height: 18px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -15px -419px no-repeat;
background-size: 42px 710px;
opacity: 0.8;
}
.is_1x .icon-back {
background-image: url(../img/icons/IconsetW_1x.png);
}
.tg_page_head .navbar-quick-nav a:hover .icon-back {
opacity: 1;
}
.tg_page_head .navbar > .container .navbar-brand {
display: none;
}
.tg_page_head .navbar_peer_not_selected > .container .navbar-brand {
display: block;
}
.tg_page_head .navbar-inverse .navbar-quick-nav > li > a {
padding-left: 15px;
padding: 6px 10px 2px 25px;
color: #b9cfe3;
font-size: 13px;
height: 44px;
}
.tg_page_head .navbar-inverse .navbar-quick-nav > li > a:hover {
color: #b9cfe3;
background-color: rgba(255,255,255,0.1);
}
.navbar-quick-nav .icon-back {
position: absolute;
margin-left: -15px;
margin-top: 9px;
}
.navbar-quick-nav h4 {
font-size: 14px;
color: #FFF;
white-space: nowrap;
overflow: hidden;
margin: 0;
}
.navbar-quick-media-back h4 {
margin: 9px 0 12px 0;
}
.navbar-quick-profile-back small,
.navbar-quick-group-back small {
white-space: nowrap;
overflow: hidden;
margin-left: 0;
}
.navbar-menu {
display: none;
}
.navbar_offline .navbar-menu {
display: block;
}
.navbar_offline .navbar-offline {
float: left;
margin: 0;
}
.navbar_offline .tg_head_logo_text {
display: none;
}
.tg_page_head .navbar_offline > .container .navbar-brand {
margin-right: 0;
}
.navbar_offline .navbar-quick-nav li > a > h4,
.navbar_offline .navbar-quick-nav li > a > small {
display: none;
}
.login_form_wrap {
border-radius: 0;
max-width: auto;
box-shadow: none;
-webkit-box-shadow: none;
margin: 30px auto 20px;
}
.im_page_wrap {
background: none;
box-shadow: none;
border: 0;
overflow: hidden;
}
.im_page_footer {
display: none;
}
.im_panel_own_photo,
.im_panel_peer_photo {
display: none;
}
.im_history_panel_wrap {
margin: 0 15px;
}
.im_send_panel_wrap {
padding: 10px 10px;
}
.icon-select-tick {
margin: 10px 0 0 -24px
}
.im_message_wrap {
padding: 0 10px;
}
.im_content_message_wrap {
margin-left: 0;
}
.im_history_typing {
padding: 0 15px 0 56px;
}
.im_history_panel_info_link {
display: none;
}
.im_send_form {
left: 0;
right: 0;
max-width: none;
}
.im_edit_flush_link,
.im_edit_cancel_link,
.im_edit_delete_btn,
.im_edit_forward_btn {
padding-left: 5px;
padding-right: 5px;
margin: 6px 4px;
}
.im_edit_panel_border {
margin: 0 18px 22px 3px;
}
.im_edit_panel_wrap {
margin: 0 5px;
padding-bottom: 18px;
}
.emoji-wysiwyg-editor {
min-height: 34px;
max-height: 150px;
}
.im_dialog_peer {
white-space: normal;
height: 2.84em;
}
.im_dialog_message {
display: none;
}
.im_history_col .nano > .pane {
top: 3px;
right: 3px;
width: 6px;
}
.im_history_col .nano > .pane > .slider,
.contacts_modal_col .nano > .pane > .slider,
.im_dialogs_modal_col .nano > .pane > .slider {
background : rgba(3,46,79,0.22);
border-radius: 3px;
margin: 0;
}
.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: 6px;
right: 3px;
}
.im_page_peer_not_selected .im_dialogs_col_wrap .pane > .slider {
background : rgba(3,46,79,0.22);
border-radius: 3px;
margin: 0;
}
.im_dialogs_panel {
padding-left: 9px;
padding-right: 9px;
}
.im_dialogs_panel_dropdown {
display: none;
}
.im_page_split .im_dialogs_search {
margin-right: 0;
}
.im_dialogs_modal_col .im_dialogs_scrollable_wrap,
.im_dialogs_scrollable_wrap {
padding: 0;
}
.peer_select_modal_wrap .modal-body {
padding-left: 0;
padding-right: 0;
}
.im_dialogs_col_wrap,
.im_history_col_wrap {
float: none;
width: auto;
max-width: auto;
min-width: auto;
}
.im_dialogs_modal_col_wrap .im_dialog_peer,
.im_page_peer_not_selected .im_dialog_peer {
white-space: nowrap;
height: auto;
}
.im_dialogs_modal_col_wrap .im_dialog_message,
.im_page_peer_not_selected .im_dialog_message {
display: block;
}
.im_history_panel_wrap {
display: none;
}
.modal.page_modal {
background: #FFF;
}
.page_modal .modal-content {
border-radius: 0;
box-shadow: none;
}
.page_modal .modal-dialog {
margin: 0;
}
.page_modal .modal-content .modal-body {
padding-left: 0;
padding-right: 0;
}
.user_modal_other_btn button {
padding-right: 0;
}
.user_modal_other_btn .dropdown-menu {
left: auto;
right: -9px;
}
.chat_modal_actions_wrap {
clear: both;
}
.chat_modal_other_btn button {
padding-right: 0;
}
.chat_modal_other_btn .dropdown-menu {
left: auto;
right: -9px;
}
.photo_modal_window .modal-content,
.video_modal_window .modal-content {
border-radius: 0;
}
.media_modal_wrap .modal-body {
padding: 0 0 0;
}
.media_modal_actions,
.media_modal_info{
margin: 10px;
}
}

3
app/index.html

@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
<link rel="stylesheet" href="vendor/bootstrap/css/bootstrap.css"/>
<link rel="stylesheet" href="vendor/jquery.nanoscroller/nanoscroller.css"/>
<link rel="stylesheet" href="css/app.css"/>
<link rel="stylesheet" href="css/app_mobile.css"/>
<!-- endbuild -->
<link rel="icon" href="favicon.ico" type="image/x-icon" />
@ -23,7 +24,7 @@ @@ -23,7 +24,7 @@
</head>
<body>
<div ng-view></div>
<div class="page_wrap" ng-view></div>
<!-- build:js js/app.js -->
<script type="text/javascript" src="vendor/console-polyfill/console-polyfill.js"></script>

107
app/js/controllers.js

@ -230,12 +230,14 @@ angular.module('myApp.controllers', []) @@ -230,12 +230,14 @@ angular.module('myApp.controllers', [])
$scope.isLoggedIn = true;
$scope.isEmpty = {};
$scope.historyFilter = {mediaType: false};
$scope.historyPeer = {};
$scope.openSettings = function () {
$modal.open({
templateUrl: 'partials/settings_modal.html',
controller: 'SettingsModalController',
windowClass: 'settings_modal_window'
windowClass: 'settings_modal_window page_modal'
});
}
@ -243,7 +245,7 @@ angular.module('myApp.controllers', []) @@ -243,7 +245,7 @@ angular.module('myApp.controllers', [])
ContactsSelectService.selectContact().then(function (userID) {
$scope.dialogSelect(AppUsersManager.getUserString(userID));
});
}
};
$scope.openGroup = function () {
ContactsSelectService.selectContacts().then(function (userIDs) {
@ -263,7 +265,15 @@ angular.module('myApp.controllers', []) @@ -263,7 +265,15 @@ angular.module('myApp.controllers', [])
}
});
}
};
$scope.importContact = function () {
AppUsersManager.openImportContact().then(function (foundContact) {
if (foundContact) {
$scope.$broadcast('contact_imported');
}
});
};
$scope.dialogSelect = function (peerString, messageID) {
var params = {peerString: peerString};
@ -280,7 +290,27 @@ angular.module('myApp.controllers', []) @@ -280,7 +290,27 @@ angular.module('myApp.controllers', [])
location.reload();
});
})
}
};
$scope.showPeerInfo = function () {
if ($scope.curDialog.peerID > 0) {
$rootScope.openUser($scope.curDialog.peerID)
} else if ($scope.curDialog.peerID < 0) {
$rootScope.openChat(-$scope.curDialog.peerID)
}
};
$scope.toggleEdit = function () {
$scope.$broadcast('history_edit_toggle');
};
$scope.returnToRecent = function () {
$scope.$broadcast('history_return_recent');
};
$scope.toggleMedia = function (mediaType) {
$scope.$broadcast('history_media_toggle', mediaType);
};
updateCurDialog();
@ -353,6 +383,12 @@ angular.module('myApp.controllers', []) @@ -353,6 +383,12 @@ angular.module('myApp.controllers', [])
}
});
$scope.$on('contact_imported', function () {
if (contactsShown) {
loadDialogs();
}
})
var prevMessages = false;
$scope.$watchCollection('search', function () {
if ($scope.search.messages && (!angular.isString($scope.search.query) || !$scope.search.query.length)) {
@ -367,14 +403,6 @@ angular.module('myApp.controllers', []) @@ -367,14 +403,6 @@ angular.module('myApp.controllers', [])
}
});
$scope.importContact = function () {
AppUsersManager.openImportContact().then(function (foundContact) {
if (contactsShown && foundContact) {
loadDialogs();
}
});
};
$scope.importPhonebook = function () {
PhonebookContactsService.openPhonebookImport().result.then(function (foundContacts) {
if (contactsShown && foundContacts.length) {
@ -444,14 +472,6 @@ angular.module('myApp.controllers', []) @@ -444,14 +472,6 @@ angular.module('myApp.controllers', [])
});
};
$scope.importContact = function () {
AppUsersManager.openImportContact().then(function (foundContact) {
if (contactsShown && foundContact) {
loadDialogs();
}
});
};
$scope.importPhonebook = function () {
PhonebookContactsService.openPhonebookImport().result.then(function (foundContacts) {
if (contactsShown && foundContacts.length) {
@ -558,7 +578,6 @@ angular.module('myApp.controllers', []) @@ -558,7 +578,6 @@ angular.module('myApp.controllers', [])
StatusManager.start();
$scope.history = [];
$scope.mediaType = false;
$scope.skippedHistory = false;
$scope.selectedMsgs = {};
$scope.selectedCount = 0;
@ -572,10 +591,16 @@ angular.module('myApp.controllers', []) @@ -572,10 +591,16 @@ angular.module('myApp.controllers', [])
$scope.selectedForward = selectedForward;
$scope.selectedCancel = selectedCancel;
$scope.selectedFlush = selectedFlush;
$scope.toggleEdit = toggleEdit;
$scope.toggleMedia = toggleMedia;
$scope.returnToRecent = returnToRecent;
$scope.showPeerInfo = showPeerInfo;
$scope.$on('history_edit_toggle', toggleEdit);
$scope.$on('history_media_toggle', function (e, mediaType) {
toggleMedia(mediaType);
});
$scope.$on('history_return_recent', returnToRecent);
var peerID,
hasMore = false,
@ -603,7 +628,7 @@ angular.module('myApp.controllers', []) @@ -603,7 +628,7 @@ angular.module('myApp.controllers', [])
$scope.curDialog.peerID = peerID;
$scope.curDialog.inputPeer = AppPeersManager.getInputPeer(newPeer);
$scope.mediaType = false;
$scope.historyFilter.mediaType = false;
selectedCancel(true);
@ -629,11 +654,11 @@ angular.module('myApp.controllers', []) @@ -629,11 +654,11 @@ angular.module('myApp.controllers', [])
$scope.history = [];
$scope.historyPeer = {
safeReplaceObject($scope.historyPeer, {
id: peerID,
data: peerData,
photo: AppPeersManager.getPeerPhoto(peerID, 'User', 'Group')
};
});
MtpApiManager.getUserID().then(function (id) {
$scope.ownPhoto = AppUsersManager.getUserPhoto(id, 'User');
@ -734,7 +759,7 @@ angular.module('myApp.controllers', []) @@ -734,7 +759,7 @@ angular.module('myApp.controllers', [])
var curJump = jump,
curMoreJump = moreJump,
inputMediaFilter = $scope.mediaType && {_: inputMediaFilters[$scope.mediaType]},
inputMediaFilter = $scope.historyFilter.mediaType && {_: inputMediaFilters[$scope.historyFilter.mediaType]},
getMessagesPromise = inputMediaFilter
? AppMessagesManager.getSearch($scope.curDialog.inputPeer, '', inputMediaFilter, maxID)
: AppMessagesManager.getHistory($scope.curDialog.inputPeer, maxID);
@ -777,7 +802,7 @@ angular.module('myApp.controllers', []) @@ -777,7 +802,7 @@ angular.module('myApp.controllers', [])
}
var curJump = ++jump,
inputMediaFilter = $scope.mediaType && {_: inputMediaFilters[$scope.mediaType]},
inputMediaFilter = $scope.historyFilter.mediaType && {_: inputMediaFilters[$scope.historyFilter.mediaType]},
getMessagesPromise = inputMediaFilter
? AppMessagesManager.getSearch($scope.curDialog.inputPeer, '', inputMediaFilter, maxID)
: AppMessagesManager.getHistory($scope.curDialog.inputPeer, maxID, limit, backLimit);
@ -814,7 +839,7 @@ angular.module('myApp.controllers', []) @@ -814,7 +839,7 @@ angular.module('myApp.controllers', [])
if (historyResult.unreadOffset) {
$scope.historyUnreadAfter = historyResult.history[historyResult.unreadOffset - 1];
} else {
$scope.historyUnreadAfter = {};
delete $scope.historyUnreadAfter;
}
$scope.historyFocus = $scope.curDialog.messageID || 0;
@ -950,13 +975,13 @@ angular.module('myApp.controllers', []) @@ -950,13 +975,13 @@ angular.module('myApp.controllers', [])
}
function toggleMedia (mediaType) {
$scope.mediaType = mediaType || false;
$scope.historyFilter.mediaType = mediaType || false;
$scope.history = [];
loadHistory();
}
function returnToRecent () {
if ($scope.mediaType) {
if ($scope.historyFilter.mediaType) {
toggleMedia();
} else {
if ($scope.curDialog.messageID) {
@ -967,14 +992,6 @@ angular.module('myApp.controllers', []) @@ -967,14 +992,6 @@ angular.module('myApp.controllers', [])
}
}
function showPeerInfo () {
if ($scope.curDialog.peerID > 0) {
$rootScope.openUser($scope.curDialog.peerID)
} else if ($scope.curDialog.peerID < 0) {
$rootScope.openChat(-$scope.curDialog.peerID)
}
}
var typingTimeouts = {};
@ -982,7 +999,7 @@ angular.module('myApp.controllers', []) @@ -982,7 +999,7 @@ angular.module('myApp.controllers', [])
$scope.$on('history_append', function (e, addedMessage) {
if (addedMessage.peerID == $scope.curDialog.peerID) {
if ($scope.mediaType || $scope.skippedHistory) {
if ($scope.historyFilter.mediaType || $scope.skippedHistory) {
if (addedMessage.my) {
returnToRecent();
} else {
@ -997,7 +1014,7 @@ angular.module('myApp.controllers', []) @@ -997,7 +1014,7 @@ angular.module('myApp.controllers', [])
$scope.typing = {};
$scope.$broadcast('ui_history_append_new', {my: addedMessage.my});
if (addedMessage.my) {
$scope.historyUnread = {};
delete $scope.historyUnreadAfter;
}
// console.log('append check', $rootScope.idle.isIDLE, addedMessage.peerID, $scope.curDialog.peerID);
@ -1030,7 +1047,7 @@ angular.module('myApp.controllers', []) @@ -1030,7 +1047,7 @@ angular.module('myApp.controllers', [])
});
$scope.$on('history_focus', function (e, peerData) {
if ($scope.mediaType) {
if ($scope.historyFilter.mediaType) {
toggleMedia();
}
});
@ -1068,7 +1085,7 @@ angular.module('myApp.controllers', []) @@ -1068,7 +1085,7 @@ angular.module('myApp.controllers', [])
$scope.$on('history_need_more', showMoreHistory);
$rootScope.$watch('idle.isIDLE', function (newVal) {
if (!newVal && $scope.curDialog && $scope.curDialog.peerID && !$scope.mediaType && !$scope.skippedHistory) {
if (!newVal && $scope.curDialog && $scope.curDialog.peerID && !$scope.historyFilter.mediaType && !$scope.skippedHistory) {
AppMessagesManager.readHistory($scope.curDialog.inputPeer);
}
});
@ -1152,7 +1169,7 @@ angular.module('myApp.controllers', []) @@ -1152,7 +1169,7 @@ angular.module('myApp.controllers', [])
// console.trace('ctrl text changed', newVal);
if (newVal && newVal.length) {
if (!$scope.mediaType && !$scope.skippedHistory) {
if (!$scope.historyFilter.mediaType && !$scope.skippedHistory) {
AppMessagesManager.readHistory($scope.curDialog.inputPeer);
}
@ -1530,7 +1547,7 @@ angular.module('myApp.controllers', []) @@ -1530,7 +1547,7 @@ angular.module('myApp.controllers', [])
$modal.open({
templateUrl: edit ? 'partials/edit_contact_modal.html' : 'partials/import_contact_modal.html',
controller: 'ImportContactModalController',
windowClass: 'import_contact_modal_window',
windowClass: 'import_contact_modal_window page_modal',
scope: scope
}).result.then(function (foundUserID) {
if ($scope.userID == foundUserID) {
@ -1820,7 +1837,7 @@ angular.module('myApp.controllers', []) @@ -1820,7 +1837,7 @@ angular.module('myApp.controllers', [])
$modal.open({
templateUrl: 'partials/profile_edit_modal.html',
controller: 'ProfileEditModalController',
windowClass: 'profile_edit_modal_window'
windowClass: 'profile_edit_modal_window page_modal'
});
};

54
app/js/directives.js

@ -11,6 +11,15 @@ @@ -11,6 +11,15 @@
angular.module('myApp.directives', ['myApp.filters'])
.directive('myHead', function() {
return {
restrict: 'AE',
scope: true,
templateUrl: 'partials/head.html'
};
})
.directive('myDialog', function() {
return {
restrict: 'AE',
@ -236,7 +245,8 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -236,7 +245,8 @@ angular.module('myApp.directives', ['myApp.filters'])
function updateSizes () {
if (attrs.modal) {
$(element).css({
height: $($window).height() - 200
height: $($window).height() -
(Config.Navigator.mobile ? 100 : 200)
});
updateScroller();
return;
@ -281,7 +291,10 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -281,7 +291,10 @@ angular.module('myApp.directives', ['myApp.filters'])
function updateSizes () {
$(element).css({
height: $($window).height() - (panelWrap && panelWrap.offsetHeight || 0) - (searchWrap && searchWrap.offsetHeight || 0) - 200
height: $($window).height() -
(panelWrap && panelWrap.offsetHeight || 0) -
(searchWrap && searchWrap.offsetHeight || 0) -
(Config.Navigator.mobile ? 60 : 200)
});
$(contactsWrap).nanoScroller();
}
@ -370,21 +383,24 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -370,21 +383,24 @@ angular.module('myApp.directives', ['myApp.filters'])
}
}
var animated = transform && !$rootScope.idle.isIDLE ? true : false,
var animated = transform ? true : false,
curAnimation = false;
$scope.$on('ui_history_append_new', function (e, options) {
if (!atBottom && !options.my) {
return;
}
if (!animated) {
var curAnimated = animated && !$rootScope.idle.isIDLE,
wasH;
if (!curAnimated) {
$(scrollable).css({bottom: 0});
$(scrollableWrap).addClass('im_history_to_bottom');
} else {
wasH = scrollableWrap.scrollHeight;
}
var wasH = scrollableWrap.scrollHeight;
onContentLoaded(function () {
if (animated) {
if (curAnimated) {
curAnimation = true;
$(historyMessagesEl).removeClass('im_history_appending');
scrollableWrap.scrollTop = scrollableWrap.scrollHeight;
@ -740,7 +756,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -740,7 +756,7 @@ angular.module('myApp.directives', ['myApp.filters'])
$(richTextarea).on('DOMNodeInserted', onPastedImageEvent);
}
if (!Config.Navigator.mobile) {
if (!Config.Navigator.touch) {
$scope.$on('ui_peer_change', focusField);
$scope.$on('ui_history_focus', focusField);
$scope.$on('ui_history_change', focusField);
@ -761,7 +777,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -761,7 +777,7 @@ angular.module('myApp.directives', ['myApp.filters'])
}
});
if (!Config.Navigator.mobile) {
if (!Config.Navigator.touch) {
focusField();
}
@ -1221,7 +1237,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1221,7 +1237,7 @@ angular.module('myApp.directives', ['myApp.filters'])
.directive('myFocused', function(){
return {
link: function($scope, element, attrs) {
if (Config.Navigator.mobile) {
if (Config.Navigator.touch) {
return false;
}
setTimeout(function () {
@ -1235,7 +1251,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1235,7 +1251,7 @@ angular.module('myApp.directives', ['myApp.filters'])
return {
link: function($scope, element, attrs) {
$scope.$on(attrs.myFocusOn, function () {
if (Config.Navigator.mobile) {
if (Config.Navigator.touch) {
return false;
}
onContentLoaded(function () {
@ -1276,7 +1292,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1276,7 +1292,7 @@ angular.module('myApp.directives', ['myApp.filters'])
function link($scope, element, attrs) {
attrs.$observe('myModalWidth', function (newW) {
$(element[0].parentNode.parentNode).css({width: parseInt(newW) + 36});
$(element[0].parentNode.parentNode).css({width: parseInt(newW) + (Config.Navigator.mobile ? 0 : 36)});
});
};
@ -1379,6 +1395,10 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1379,6 +1395,10 @@ angular.module('myApp.directives', ['myApp.filters'])
function link($scope, element, attrs) {
var updateMargin = function () {
if (Config.Navigator.mobile &&
$(element[0].parentNode.parentNode.parentNode).hasClass('page_modal')) {
return;
}
var height = element[0].parentNode.offsetHeight,
contHeight = element[0].parentNode.parentNode.parentNode.offsetHeight;
@ -1416,15 +1436,21 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1416,15 +1436,21 @@ angular.module('myApp.directives', ['myApp.filters'])
function link($scope, element, attrs) {
var prevMargin = false;
var usePadding = attrs.padding === 'true',
prevMargin = 0;
var updateMargin = function () {
var height = element[0].offsetHeight,
fullHeight = height - (height && usePadding ? 2 * prevMargin : 0),
contHeight = $($window).height(),
ratio = attrs.myVerticalPosition && parseFloat(attrs.myVerticalPosition) || 0.5,
margin = height < contHeight ? parseInt((contHeight - height) * ratio) : '';
margin = fullHeight < contHeight ? parseInt((contHeight - fullHeight) * ratio) : '',
styles = usePadding
? {paddingTop: margin, paddingBottom: margin}
: {marginTop: margin, marginBottom: margin};
element.css({marginTop: margin, marginBottom: margin});
element.css(styles);
element.addClass('vertical-aligned');
if (prevMargin !== margin) {
$scope.$emit('ui_height');

3
app/js/lib/config.js

@ -35,7 +35,8 @@ Config.Navigator = { @@ -35,7 +35,8 @@ Config.Navigator = {
osX: (navigator.platform || '').toLowerCase().indexOf('mac') != -1 ||
(navigator.userAgent || '').toLowerCase().indexOf('mac') != -1,
retina: window.devicePixelRatio > 1,
mobile: $(window).height() < 600
touch: $(window).width() <= 768,
mobile: $(window).width() < 480
};
Config.Schema = Config.Schema || {};

24
app/js/services.js

@ -284,7 +284,7 @@ angular.module('myApp.services', []) @@ -284,7 +284,7 @@ angular.module('myApp.services', [])
templateUrl: 'partials/user_modal.html',
controller: 'UserModalController',
scope: scope,
windowClass: 'user_modal_window'
windowClass: 'user_modal_window page_modal'
});
};
$rootScope.openUser = openUser;
@ -377,7 +377,7 @@ angular.module('myApp.services', []) @@ -377,7 +377,7 @@ angular.module('myApp.services', [])
return $modal.open({
templateUrl: 'partials/import_contact_modal.html',
controller: 'ImportContactModalController',
windowClass: 'import_contact_modal_window'
windowClass: 'import_contact_modal_window page_modal'
}).result.then(function (foundUserID) {
if (!foundUserID) {
return $q.reject();
@ -457,7 +457,7 @@ angular.module('myApp.services', []) @@ -457,7 +457,7 @@ angular.module('myApp.services', [])
return $modal.open({
templateUrl: 'partials/phonebook_modal.html',
controller: 'PhonebookModalController',
windowClass: 'phonebook_modal_window'
windowClass: 'phonebook_modal_window page_modal'
});
}
@ -598,7 +598,7 @@ angular.module('myApp.services', []) @@ -598,7 +598,7 @@ angular.module('myApp.services', [])
var modalInstance = $modal.open({
templateUrl: 'partials/chat_modal.html',
controller: 'ChatModalController',
windowClass: 'chat_modal_window',
windowClass: 'chat_modal_window page_modal',
scope: scope
});
}
@ -985,15 +985,16 @@ angular.module('myApp.services', []) @@ -985,15 +985,16 @@ angular.module('myApp.services', [])
}
}
if (!offsetNotFound && historyStorage.count !== null && historyStorage.history.length == historyStorage.count ||
historyStorage.history.length >= offset + (limit || 1)
) {
if (!offsetNotFound && (
historyStorage.count !== null && historyStorage.history.length == historyStorage.count ||
historyStorage.history.length >= offset + (limit || 1)
)) {
if (backLimit) {
backLimit = Math.min(offset, backLimit);
offset = Math.max(0, offset - backLimit);
limit += backLimit;
} else {
limit = limit || 20;
limit = limit || (offset ? 20 : 5);
}
return $q.when({
@ -2291,7 +2292,7 @@ angular.module('myApp.services', []) @@ -2291,7 +2292,7 @@ angular.module('myApp.services', [])
function wrapForFull (photoID) {
var photo = wrapForHistory(photoID),
fullWidth = $(window).width() - 36,
fullWidth = $(window).width() - (Config.Navigator.mobile ? 20 : 36),
fullHeight = $($window).height() - 150,
fullPhotoSize = choosePhotoSize(photo, fullWidth, fullHeight),
full = {
@ -2522,7 +2523,8 @@ angular.module('myApp.services', []) @@ -2522,7 +2523,8 @@ angular.module('myApp.services', [])
var modalInstance = $modal.open({
templateUrl: 'partials/video_modal.html',
controller: 'VideoModalController',
scope: scope
scope: scope,
windowClass: 'video_modal_window'
});
}
@ -3723,7 +3725,7 @@ angular.module('myApp.services', []) @@ -3723,7 +3725,7 @@ angular.module('myApp.services', [])
$modal.open({
templateUrl: 'partials/changelog_modal.html',
scope: $scope,
windowClass: 'changelog_modal_window'
windowClass: 'changelog_modal_window page_modal'
});
}

67
app/partials/chat_modal.html

@ -22,42 +22,39 @@ @@ -22,42 +22,39 @@
</ng-pluralize>
</p>
<div class="chat_modal_settings_wrap">
<div class="chat_modal_actions_wrap clearfix">
<button ng-if="!chatFull.chat.left &amp;&amp; chatFull.participants.participants.length" class="btn btn-primary chat_modal_invite_btn" ng-click="inviteToGroup()">Add member</button>
<button ng-if="chatFull.chat._ != 'chatForbidden' &amp;&amp; chatFull.chat.left" class="btn btn-primary chat_modal_main_btn" ng-click="returnToGroup()">Return to group</button>
<button ng-if="chatFull.chat._ == 'chatForbidden'" class="btn btn-danger chat_modal_delete_btn" ng-click="flushHistory()">Delete chat</button>
<span ng-if="chatFull.chat._ != 'chatForbidden' &amp;&amp; !chatFull.chat.left &amp;&amp; !photo.updating" class="btn btn-primary chat_modal_main_btn" >
<input my-file-upload type="file" multiple="false" class="im_attach_input" size="120" multiple="false" accept="image/x-png, image/png, image/gif, image/jpeg" />
Update photo
</span>
<span ng-if="photo.updating" class="btn btn-primary chat_modal_main_btn disabled" disabled>
Updating<span my-loading-dots></span>
</span>
<div class="dropdown chat_modal_other_btn" ng-if="chatFull.chat._ != 'chatForbidden' &amp;&amp; !chatFull.chat.left">
<button class="btn btn-link dropdown-toggle">More<i class="icon icon-caret"></i></button>
<ul class="dropdown-menu">
<li ng-if="chatFull.thumb.location">
<a ng-click="deletePhoto()">Delete photo</a>
</li>
<li>
<a ng-click="editTitle()">Edit group</a>
</li>
<li>
<a ng-click="leaveGroup()">Leave group</a>
</li>
<li>
<a ng-click="flushHistory()">Delete chat</a>
</li>
</ul>
</div>
<div class="chat_modal_actions_wrap clearfix">
<button ng-if="!chatFull.chat.left &amp;&amp; chatFull.participants.participants.length" class="btn btn-primary chat_modal_invite_btn" ng-click="inviteToGroup()">Add member</button>
<button ng-if="chatFull.chat._ != 'chatForbidden' &amp;&amp; chatFull.chat.left" class="btn btn-primary chat_modal_main_btn" ng-click="returnToGroup()">Return to group</button>
<button ng-if="chatFull.chat._ == 'chatForbidden'" class="btn btn-danger chat_modal_delete_btn" ng-click="flushHistory()">Delete chat</button>
<span ng-if="chatFull.chat._ != 'chatForbidden' &amp;&amp; !chatFull.chat.left &amp;&amp; !photo.updating" class="btn btn-primary chat_modal_main_btn" >
<input my-file-upload type="file" multiple="false" class="im_attach_input" size="120" multiple="false" accept="image/x-png, image/png, image/gif, image/jpeg" />
Update photo
</span>
<span ng-if="photo.updating" class="btn btn-primary chat_modal_main_btn disabled" disabled>
Updating<span my-loading-dots></span>
</span>
<div class="dropdown chat_modal_other_btn" ng-if="chatFull.chat._ != 'chatForbidden' &amp;&amp; !chatFull.chat.left">
<button class="btn btn-link dropdown-toggle">More<i class="icon icon-caret"></i></button>
<ul class="dropdown-menu">
<li ng-if="chatFull.thumb.location">
<a ng-click="deletePhoto()">Delete photo</a>
</li>
<li>
<a ng-click="editTitle()">Edit group</a>
</li>
<li>
<a ng-click="leaveGroup()">Leave group</a>
</li>
<li>
<a ng-click="flushHistory()">Delete chat</a>
</li>
</ul>
</div>
</div>
</div>

6
app/partials/contacts_modal.html

@ -1,7 +1,11 @@ @@ -1,7 +1,11 @@
<div class="contacts_modal_wrap" my-modal-position>
<a class="modal-close-button visible-xs" ng-click="$dismiss()"><i></i></a>
<div class="modal-body">
<h4 class="modal_simple_header visible-xs">Contacts</h4>
<div class="contacts_modal_search">
<input class="form-control contacts_modal_search_field" my-focused type="search" placeholder="Search" ng-model="search.query"/>
<a class="contacts_modal_search_clear" ng-click="search.query = ''" ng-show="search.query.length"></a>
@ -44,7 +48,7 @@ @@ -44,7 +48,7 @@
</div>
<div class="modal-footer" ng-switch="multiSelect">
<div class="modal-footer contacts_modal_panel" ng-switch="multiSelect">
<button ng-switch-when="true" class="btn btn-success btn-block" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" ng-click="submitSelected()" type="submit">
Next »
</button>

82
app/partials/head.html

@ -1,19 +1,78 @@ @@ -1,19 +1,78 @@
<div class="tg_page_head">
<div class="navbar navbar-static-top navbar-inverse" role="navigation">
<div class="navbar navbar-static-top navbar-inverse" role="navigation" ng-class="{navbar_peer_not_selected: !curDialog.peer, navbar_offline: offline}">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="{{isLoggedIn ? '#/im' : '#/'}}"><span class="tg_head_logo"></span><span class="tg_head_logo_text"></span></a>
<ul class="nav navbar-nav navbar-quick-nav" ng-show="curDialog.peer">
<li>
<a href="#/im">
<i class="icon icon-back"></i> Back
</a>
</li>
<div class="navbar-toggle-wrap dropdown">
<a class="dropdown-toggle navbar-toggle">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<ul ng-if="!curDialog.peer &amp;&amp; isLoggedIn" class="dropdown-menu">
<li><a ng-click="openGroup()">New Group</a></li>
<li><a ng-click="importContact()">New Contact</a></li>
<li><a ng-click="openContacts()">Contacts</a></li>
<li><a ng-click="openSettings()">Settings</a></li>
<li><a ng-click="logOut()">Log Out</a></li>
</ul>
<ul ng-if="curDialog.peer &amp;&amp; isLoggedIn" class="dropdown-menu">
<li><a ng-click="showPeerInfo()" ng-switch="historyPeer.id > 0">
<span ng-switch-when="true">Profile</span>
<span ng-switch-default>Group info</span>
</a></li>
<li><a ng-click="toggleEdit()">Edit chat</a></li>
<li ng-if="!historyFilter.mediaType" class="divider"></li>
<li ng-if="!historyFilter.mediaType" class="dropdown-header">Media</li>
<li ng-if="!historyFilter.mediaType"><a ng-click="toggleMedia('photos')">Photos</a></li>
<li ng-if="!historyFilter.mediaType"><a ng-click="toggleMedia('video')">Videos</a></li>
<li ng-if="!historyFilter.mediaType"><a ng-click="toggleMedia('documents')">Documents</a></li>
<li ng-if="!historyFilter.mediaType"><a ng-click="toggleMedia('audio')">Voice messages</a></li>
</ul>
<ul ng-if="!isLoggedIn" class="dropdown-menu">
<li><a href="https://github.com/zhukov/webogram" target="_blank">About</a></li>
</ul>
</div>
<div class="navbar-header">
<div class="navbar-collapse collapse" ng-switch="offline">
<a class="navbar-brand" href="{{isLoggedIn ? '#/im' : '#/'}}"><span class="tg_head_logo"></span><span class="tg_head_logo_text"></span></a>
<div ng-show="curDialog.peer" ng-switch="curDialog.peer &amp;&amp; historyFilter.mediaType.length">
<ul ng-switch-when="true" class="nav navbar-nav navbar-quick-nav">
<li>
<a ng-click="toggleMedia()" class="navbar-quick-media-back" ng-switch="historyFilter.mediaType">
<i class="icon icon-back"></i>
<h4 ng-switch-when="photos">Photos</h4>
<h4 ng-switch-when="video">Videos</h4>
<h4 ng-switch-when="documents">Documents</h4>
<h4 ng-switch-when="audio">Voice messages</h4>
</a>
</li>
</ul>
<ul ng-switch-default class="nav navbar-nav navbar-quick-nav" ng-switch="historyPeer.id > 0">
<li ng-switch-when="true">
<a href="#/im" class="navbar-quick-profile-back">
<i class="icon icon-back"></i>
<h4 ng-bind-html="historyPeer.data.rFullName"></h4>
<small ng-bind="historyPeer.data | userStatus"></small>
</a>
</li>
<li ng-switch-default>
<a href="#/im" class="navbar-quick-group-back">
<i class="icon icon-back"></i>
<h4 ng-bind-html="historyPeer.data.rTitle"></h4>
<small>
<ng-pluralize count="historyPeer.data.participants_count"
when="{'0': 'No members', 'one': '1 member', 'other': '{} members'}">
</ng-pluralize>
</small>
</a>
</li>
</ul>
</div>
</div>
<div class="navbar-menu" ng-switch="offline">
<ul ng-switch-when="true" class="nav navbar-nav navbar-offline">
<li ng-show="!offlineConnecting"><span class="navbar-offline-text">Waiting for network<span my-loading-dots></span></span></li>
@ -29,6 +88,7 @@ @@ -29,6 +88,7 @@
</ul>
</div>
</div>
</div>
</div>
</div>

22
app/partials/im.html

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<div ng-include="'partials/head.html'"></div>
<div my-head></div>
<div class="im_page_wrap" ng-class="{im_page_peer_not_selected: !curDialog.peer}">
@ -89,11 +89,11 @@ @@ -89,11 +89,11 @@
<p class="im_dialogs_empty_lead">Welcome to Telegram Web. You can always set your profile photo and change your name in Settings.</p>
<button type="button" class="btn btn-primary btn-sm" ng-click="openSettings()">Open Settings</button>
</div>
<div ng-switch-default class="im_history_not_selected" my-vertical-position="0.35">
<div ng-switch-default class="im_history_not_selected" my-vertical-position="0.35" padding="true">
Please select a chat to start messaging
</div>
</div>
<div ng-show="!state.notSelected &amp;&amp; !state.loaded" class="im_history_not_selected" my-vertical-position="0.35">
<div ng-show="!state.notSelected &amp;&amp; !state.loaded" class="im_history_not_selected" my-vertical-position="0.35" padding="true">
Loading history<span my-loading-dots></span>
</div>
@ -117,13 +117,13 @@ @@ -117,13 +117,13 @@
<li><a ng-click="toggleMedia('audio')">Voice messages</a></li>
</ul>
</div>
<a ng-show="mediaType !== false || skippedHistory" class="im_history_panel_return_link pull-right" ng-click="returnToRecent()" ng-switch="skippedHistory">
<a ng-show="historyFilter.mediaType.length || skippedHistory" class="im_history_panel_return_link pull-right" ng-click="returnToRecent()" ng-switch="skippedHistory">
<span ng-switch-when="true">Show recent messages</span>
<span ng-switch-default>Show all messages</span>
<strong class="im_history_panel_return_count" ng-show="missedCount > 0" ng-bind="'+' + missedCount"></strong>
</a>
<div ng-switch="mediaType">
<div ng-switch="historyFilter.mediaType">
<h4 ng-switch-when="photos">Photos</h4>
<h4 ng-switch-when="video">Videos</h4>
<h4 ng-switch-when="documents">Documents</h4>
@ -157,13 +157,9 @@ @@ -157,13 +157,9 @@
<div class="im_history_scrollable">
<div class="im_history" ng-class="{im_history_selectable: selectActions}">
<div ng-if="!history.length" class="im_history_empty" ng-switch="state.mayBeHasMore">
<div my-vertical-position="0.25" ng-switch-when="true">
Loading history<span my-loading-dots></span>
</div>
<div my-vertical-position="0.25" ng-switch-default>
No messages here yet...
</div>
<div ng-if="!history.length" class="im_history_empty" ng-switch="state.mayBeHasMore" my-vertical-position="0.25" padding="true">
<span ng-switch-when="true">Loading history<span my-loading-dots></span></span>
<span ng-switch-default>No messages here yet...</span>
</div>
<div class="im_history_messages">
@ -172,7 +168,7 @@ @@ -172,7 +168,7 @@
</div>
<div class="im_history_typing_wrap">
<div class="im_history_typing" ng-show="typing.user &amp;&amp; !mediaType">
<div class="im_history_typing" ng-show="typing.user &amp;&amp; !historyFilter.mediaType">
<strong class="im_history_typing_author" ng-bind-html="typing.user.rFullName"></strong> is typing<span my-loading-dots></span>
</div>
</div>

2
app/partials/login.html

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<div ng-include="'partials/head.html'"></div>
<div my-head></div>
<div class="login_form_wrap" my-vertical-position="0.4">

7
app/partials/message.html

@ -57,13 +57,13 @@ @@ -57,13 +57,13 @@
</div>
<div bindonce bo-if="historyMessage._ != 'messageService'" class="im_content_message_wrap">
<div bindonce bo-if="historyMessage._ != 'messageService'" class="im_content_message_wrap" ng-class="{im_message_unread: historyMessage.unread, im_message_out: historyMessage.out, im_message_in: !historyMessage.out, im_message_error: historyMessage.error, im_message_pending: historyMessage.pending}">
<div class="im_content_message_select_area">
<i class="icon icon-select-tick"></i>
</div>
<a bo-if="historyMessage.pending || historyMessage.error" ng-click="historyMessage.send()" ng-show="historyMessage.error">
<i class="icon-message-status icon-message-status-error" tooltip="Try again"></i>
<a class="im_message_error_btn" bo-if="historyMessage.pending || historyMessage.error" ng-click="historyMessage.send()">
<i class="icon-message-status" tooltip="Try again"></i>
</a>
<i bo-if="historyMessage.unread || historyMessage.pending" class="icon-message-status" ng-class="{'icon-message-status-unread': historyMessage.unread, 'icon-message-status-pending': historyMessage.pending}" ng-show="!historyMessage.error"></i>
@ -76,6 +76,7 @@ @@ -76,6 +76,7 @@
/>
</a>
<div class="im_message_meta pull-right text-right">
<i class="icon-message-status-tick"></i>
<span class="im_message_date" bo-bind="historyMessage.date | dateOrTime"></span>
</div>

4
app/partials/peer_select.html

@ -1,7 +1,11 @@ @@ -1,7 +1,11 @@
<div class="peer_select_modal_wrap" my-modal-position>
<a class="modal-close-button visible-xs" ng-click="$dismiss()"><i></i></a>
<div class="modal-body">
<h4 class="modal_simple_header visible-xs">Contacts</h4>
<div class="im_dialogs_modal_col_wrap" ng-controller="AppImDialogsController" my-dialogs>
<div class="im_dialogs_panel">
<div class="im_dialogs_search">

17
app/partials/photo_modal.html

@ -4,15 +4,18 @@ @@ -4,15 +4,18 @@
<div class="photo_modal_image_wrap" my-load-full-photo full-photo="photo.full" thumb-location="photo.thumb.location" ng-click="nav.next()"> </div>
<div class="media_modal_actions pull-right">
<a href="" class="media_modal_action_link" ng-click="download()">Download</a>
<a href="" class="media_modal_action_link" ng-if="canForward" ng-click="forward()">Forward</a>
<a href="" class="media_modal_action_link" ng-if="canDelete" ng-click="delete()">Delete</a>
<div class="media_meta_wrap clearfix">
<div class="media_modal_actions pull-right">
<a href="" class="media_modal_action_link" ng-click="download()">Download</a>
<a href="" class="media_modal_action_link" ng-if="canForward" ng-click="forward()">Forward</a>
<a href="" class="media_modal_action_link" ng-if="canDelete" ng-click="delete()">Delete</a>
</div>
<p class="media_modal_info">
<span class="media_modal_author" ng-bind-html="photo.fromUser.rFullName"></span>, {{photo.date | dateOrTime}}
</p>
</div>
<p class="media_modal_info">
<span class="media_modal_author" ng-bind-html="photo.fromUser.rFullName"></span>, {{photo.date | dateOrTime}}
</p>
</div>

16
app/partials/video_modal.html

@ -4,14 +4,16 @@ @@ -4,14 +4,16 @@
<div class="video_modal_image_wrap" my-load-video video="video"></div>
<div class="media_modal_actions pull-right" ng-if="messageID">
<a href="" class="media_modal_action_link" ng-click="forward()">Forward</a>
<a href="" class="media_modal_action_link" ng-click="delete()">Delete</a>
</div>
<div class="media_meta_wrap clearfix">
<div class="media_modal_actions pull-right" ng-if="messageID">
<a href="" class="media_modal_action_link" ng-click="forward()">Forward</a>
<a href="" class="media_modal_action_link" ng-click="delete()">Delete</a>
</div>
<p class="media_modal_info">
<span class="media_modal_author" ng-bind-html="video.fromUser.rFullName" ></span>, {{video.date | dateOrTime}}
</p>
<p class="media_modal_info">
<span class="media_modal_author" ng-bind-html="video.fromUser.rFullName" ></span>, {{video.date | dateOrTime}}
</p>
</div>
</div>

3
app/partials/welcome.html

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
<div ng-include="'partials/head.html'"></div>
<div my-head></div>
<div ng-if="showWelcome">

2
app/webogram.appcache

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
CACHE MANIFEST
# 8
# 12
NETWORK:
*

Loading…
Cancel
Save