Browse Source

Merge branch 'material-design'

Conflicts:
	app/css/desktop.css
	app/js/directives.js
	app/partials/desktop/photo_modal.html
	app/partials/desktop/user_modal.html
master
Igor Zhukov 10 years ago
parent
commit
7bc6e36ec6
  1. 767
      app/css/app.css
  2. 166
      app/css/desktop.css
  3. 35
      app/css/mobile.css
  4. BIN
      app/img/Telegram72.png
  5. BIN
      app/img/Telegram72_2x.png
  6. BIN
      app/img/icons/ProfileIcons.png
  7. BIN
      app/img/icons/ProfileIcons_2x.png
  8. 392
      app/js/controllers.js
  9. 143
      app/js/directives.js
  10. 2
      app/js/lib/config.js
  11. 1
      app/js/lib/schema.tl.txt
  12. 26
      app/js/lib/utils.js
  13. 17
      app/js/locales/en-us.json
  14. 143
      app/js/services.js
  15. 256
      app/partials/desktop/changelog_modal.html
  16. 21
      app/partials/desktop/chat_create_modal.html
  17. 19
      app/partials/desktop/chat_edit_modal.html
  18. 153
      app/partials/desktop/chat_modal.html
  19. 18
      app/partials/desktop/confirm_modal.html
  20. 71
      app/partials/desktop/contacts_modal.html
  21. 9
      app/partials/desktop/dialog.html
  22. 12
      app/partials/desktop/document_modal.html
  23. 31
      app/partials/desktop/edit_contact_modal.html
  24. 18
      app/partials/desktop/error_modal.html
  25. 30
      app/partials/desktop/im.html
  26. 32
      app/partials/desktop/import_contact_modal.html
  27. 2
      app/partials/desktop/message.html
  28. 2
      app/partials/desktop/message_attach_contact.html
  29. 2
      app/partials/desktop/message_attach_photo.html
  30. 2
      app/partials/desktop/message_attach_video.html
  31. 50
      app/partials/desktop/peer_select.html
  32. 13
      app/partials/desktop/photo_modal.html
  33. 23
      app/partials/desktop/profile_edit_modal.html
  34. 212
      app/partials/desktop/settings_modal.html
  35. 146
      app/partials/desktop/user_modal.html
  36. 24
      app/partials/desktop/username_edit_modal.html
  37. 12
      app/partials/desktop/video_modal.html
  38. 2
      app/partials/mobile/message.html
  39. 2
      app/partials/mobile/message_attach_photo.html
  40. 4
      app/partials/mobile/settings_modal.html
  41. 2
      app/partials/mobile/user_modal.html

767
app/css/app.css

File diff suppressed because it is too large Load Diff

166
app/css/desktop.css

@ -159,13 +159,16 @@ a.footer_link.active:active { @@ -159,13 +159,16 @@ a.footer_link.active:active {
padding-bottom: 10px;
}
.im_dialogs_scrollable_wrap {
padding: 0 19px 0 12px;
padding: 0 7px 0 0;
/* Hardware acceleration in Safari */
-webkit-transform: translateZ(0);
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
}
.im_dialogs_modal_col_wrap .im_dialogs_scrollable_wrap {
padding: 0;
}
.im_dialogs_col .nano > .nano-pane {
background : rgba(0,0,0,0.0);
width : 12px;
@ -213,23 +216,14 @@ a.footer_link.active:active { @@ -213,23 +216,14 @@ a.footer_link.active:active {
transition : none;
}
.contacts_modal_col .nano > .nano-pane {
width: 6px;
right: 7px;
width: 5px;
right: 4px;
}
.im_dialogs_modal_col .nano > .nano-pane {
width: 6px;
right: 2px;
}
.im_dialogs_modal_col .im_dialogs_scrollable_wrap {
padding: 0 12px 0 12px;
}
.contacts_modal_col {
margin-right: -17px;
}
.contacts_scrollable_wrap {
padding: 0 17px 0 0;
}
.im_history_col .nano > .nano-pane {
top: 10px;
@ -323,38 +317,25 @@ a.footer_link.active:active { @@ -323,38 +317,25 @@ a.footer_link.active:active {
/* Contacts modal */
.contacts_modal_window .modal-dialog {
max-width: 456px;
max-width: 420px;
}
.contacts_modal_header {
padding: 6px 0 18px;
.contacts_modal_search {
padding: 15px 12px 12px;
position: relative;
}
.contacts_modal_edit_wrap {
position: absolute;
margin-top: -1px;
.contacts_modal_members_list a.contacts_modal_contact {
padding: 8px 16px;
}
.contacts_modal_edit_link {
font-size: 14px;
padding: 5px 7px;
.contacts_modal_members_list .active a.contacts_modal_contact,
.contacts_modal_members_list .active a.contacts_modal_contact:hover {
background: #6490b1;
color: #FFF;
}
.contacts_modal_title {
font-size: 14px;
margin: 0;
text-align: center;
font-weight: bold;
.contacts_modal_members_list .active a.contacts_modal_contact .md_modal_list_peer_description,
.contacts_modal_members_list .active a.contacts_modal_contact:hover .md_modal_list_peer_description {
color: #FFF;
}
.icon-message-status {
background: #6ba2cb;
border: 0;
display: block;
width: 10px;
height: 10px;
border-radius: 7px;
position: absolute;
margin-left: -26px;
margin-top: 13px;
opacity: 0;
}
.im_message_unread .icon-message-status {
opacity: 1.0;
}
@ -448,10 +429,33 @@ a.footer_link.active:active { @@ -448,10 +429,33 @@ a.footer_link.active:active {
/* Dialogs modal */
.peer_select_window .modal-dialog {
max-width: 506px;
max-width: 420px;
}
.peer_select_window .im_dialogs_panel {
padding-top: 15px;
}
.peer_select_modal_wrap .modal-body {
padding: 0 2px 14px;
.peer_select_modal_footer {
box-shadow: 0 -1px 0px rgba(0,0,0,0.05);
padding: 15px 10px 15px;
}
.peer_select_modal_recipients_wrap {
padding: 6px 0 0 10px;
white-space: nowrap;
max-width: 300px;
overflow: hidden;
text-overflow: ellipsis;
}
.peer_select_modal_recipients_empty,
.peer_select_modal_recipients_name {
color: #999;
}
.peer_select_modal_recipient {
display: inline-block;
white-space: nowrap;
max-width: 120px;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: bottom;
}
@ -513,10 +517,12 @@ a.footer_link.active:active { @@ -513,10 +517,12 @@ a.footer_link.active:active {
.im_panel_own_photo {
width: 50px;
height: 50px;
border-radius: 0;
line-height: 50px;
border-radius: 25px;
overflow: hidden;
}
div.im_panel_peer_photo {
div.im_panel_peer_photo,
a.im_panel_peer_photo {
cursor: pointer;
margin-left: 12px;
height: 55px;
@ -534,8 +540,8 @@ div.im_panel_own_photo { @@ -534,8 +540,8 @@ div.im_panel_own_photo {
border-radius: 6px;
overflow: hidden;
position: absolute;
margin-top: -7px;
margin-left: 43px;
margin-top: -12px;
margin-left: 36px;
}
.emoji-wysiwyg-editor,
.im_message_field {
@ -544,7 +550,7 @@ div.im_panel_own_photo { @@ -544,7 +550,7 @@ div.im_panel_own_photo {
/* Peer modals */
.user_modal_window .modal-dialog {
max-width: 506px;
max-width: 480px;
}
.user_modal_photo_profile_wrap {
padding: 13px 12px;
@ -610,9 +616,8 @@ div.im_panel_own_photo { @@ -610,9 +616,8 @@ div.im_panel_own_photo {
.chat_modal_window .modal-dialog {
max-width: 506px;
max-width: 480px;
}
.chat_modal_header {
font-weight: bold;
margin: 0 0 10px;
@ -698,7 +703,7 @@ div.im_panel_own_photo { @@ -698,7 +703,7 @@ div.im_panel_own_photo {
}
.settings_modal_window .modal-dialog {
max-width: 482px;
max-width: 480px;
}
.settings_modal_settings {
padding: 4px 0;
@ -951,14 +956,36 @@ div.im_panel_own_photo { @@ -951,14 +956,36 @@ div.im_panel_own_photo {
margin-bottom: 0;
}
.im_dialogs_panel_dropdown.open .dropdown-toggle {
background: #6690b0;
}
.im_dialogs_panel_dropdown.open .dropdown-toggle .icon-bar {
background: #fff;
}
.im_dialogs_scrollable_wrap a.im_dialog {
padding: 8px 16px;
}
.im_dialogs_scrollable_wrap .active a.im_dialog {
margin-right: -2px;
padding-right: 18px;
}
.im_dialog_photo {
width: 48px;
height: 48px;
line-height: 48px;
border-radius: 50%;
}
div.im_dialog_photo {
margin-right: 12px;
}
.im_dialog_message {
margin-top: 4px;
}
.active .im_dialog_date,
.active a.im_dialog:hover .im_dialog_date,
.active a.im_dialog_selected .im_dialog_date {
color: #FFF;
}
/* Import contact modal */
.import_contact_modal_window .modal-dialog {
@ -974,10 +1001,6 @@ div.im_panel_own_photo { @@ -974,10 +1001,6 @@ div.im_panel_own_photo {
max-height: 350px;
}
.changelog_modal_window .modal-dialog {
max-width: 506px;
}
.modal_close_wrap {
display: none;
@ -1106,19 +1129,39 @@ div.im_panel_own_photo { @@ -1106,19 +1129,39 @@ div.im_panel_own_photo {
}
.media_modal_info_wrap {
line-height: 16px;
padding: 24px 20px;
position: absolute;
left: 0;
padding: 15px 16px;
width: 200px;
}
.media_modal_author {
.media_modal_author_photo {
width: 32px;
height: 32px;
border-radius: 50%;
overflow: hidden;
}
.media_modal_author_photo .peer_initials {
line-height: 32px;
}
a.media_modal_author_photo {
margin: 1px 10px 1px 0;
}
div.media_modal_author_name {
font-size: 13px;
margin-right: 4px;
margin-top: 1px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.media_modal_date,
a.media_modal_date:hover {
font-size: 11px;
color: rgba(255, 255, 255, 0.4);
}
div.media_modal_date {
margin-top: 2px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.photo_modal_window,
.video_modal_window,
@ -1177,6 +1220,3 @@ a.media_modal_date:hover { @@ -1177,6 +1220,3 @@ a.media_modal_date:hover {
height: 18px;
margin: 23px 27px;
}

35
app/css/mobile.css

@ -510,13 +510,13 @@ img.im_message_video_thumb, @@ -510,13 +510,13 @@ img.im_message_video_thumb,
max-width: 100%;
}
.im_message_out.im_content_message_wrap {
padding-left: 60px;
padding-left: 80px;
padding-right: 0;
float: right;
}
.im_message_in.im_content_message_wrap {
padding-left: 0;
padding-right: 42px;
padding-right: 60px;
}
.im_history_messages_group .im_message_in.im_content_message_wrap,
.im_history_messages_group .im_grouped_short .im_message_in.im_content_message_wrap,
@ -534,16 +534,25 @@ img.im_message_video_thumb, @@ -534,16 +534,25 @@ img.im_message_video_thumb,
.im_message_meta {
float: none;
position: absolute;
bottom: 6px;
right: -12px;
bottom: 5px;
left: 100%;
white-space: nowrap;
margin-left: -60px;
width: 60px;
padding: 0 0 0 8px;
overflow: hidden;
}
.im_message_date {
font-size: 12px;
padding-left: 4px;
font-size: 10px;
/*font-size: 12px;*/
padding: 0;
}
.im_message_out .im_message_meta {
right: auto;
left: -12px;
width: 80px;
left: 0;
text-align: right;
margin-left: 0;
padding: 0 8px 0 0;
}
.im_message_out .im_message_fwd_date {
@ -627,7 +636,7 @@ a.im_message_from_photo { @@ -627,7 +636,7 @@ a.im_message_from_photo {
vertical-align: text-top;
margin-right: 2px;
opacity: 1;
margin-top: 5px;
margin-top: 6px;
}
.im_message_out .icon-message-status-tick,
.is_1x .im_message_out .icon-message-status-tick {
@ -740,14 +749,6 @@ a.im_dialog_selected .im_dialog_date { @@ -740,14 +749,6 @@ a.im_dialog_selected .im_dialog_date {
font-size: 12px;
margin-right: 3px;
}
.im_dialog_badge {
background: #64c270;
font-size: 11px;
padding: 5px;
border-radius: 10px;
min-width: 21px;
text-align: center;
}
.im_dialog_unread,
.active .im_dialog_unread,
a.im_dialog:hover .im_dialog_unread,

BIN
app/img/Telegram72.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
app/img/Telegram72_2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
app/img/icons/ProfileIcons.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
app/img/icons/ProfileIcons_2x.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

392
app/js/controllers.js

@ -355,7 +355,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -355,7 +355,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
templateUrl: templateUrl('chat_create_modal'),
controller: 'ChatCreateModalController',
scope: scope,
windowClass: 'group_edit_modal_window mobile_modal'
windowClass: 'md_simple_modal_window mobile_modal'
});
}
@ -889,6 +889,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -889,6 +889,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
});
MtpApiManager.getUserID().then(function (id) {
$scope.ownID = id;
$scope.ownPhoto = AppUsersManager.getUserPhoto(id, 'User');
});
@ -1211,11 +1212,15 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1211,11 +1212,15 @@ angular.module('myApp.controllers', ['myApp.i18n'])
selectedMessageIDs.push(messageID);
});
PeersSelectService.selectPeer({confirm_type: 'FORWARD_PEER'}).then(function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.forwardMessages(peerID, selectedMessageIDs).then(function () {
selectedCancel();
$rootScope.$broadcast('history_focus', {peerString: peerString});
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) {
angular.forEach(peerStrings, function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.forwardMessages(peerID, selectedMessageIDs).then(function () {
selectedCancel();
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerString});
}
});
});
});
@ -1517,10 +1522,14 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1517,10 +1522,14 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.forward = function () {
var messageID = $scope.messageID;
PeersSelectService.selectPeer({confirm_type: 'FORWARD_PEER'}).then(function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () {
$rootScope.$broadcast('history_focus', {peerString: peerString});
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) {
angular.forEach(peerStrings, function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () {
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerString});
}
});
});
});
};
@ -1695,15 +1704,21 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1695,15 +1704,21 @@ angular.module('myApp.controllers', ['myApp.i18n'])
})
.controller('UserpicModalController', function ($q, $scope, $rootScope, $modalInstance, AppPhotosManager, AppUsersManager, AppPeersManager, AppMessagesManager, PeersSelectService, ErrorService) {
.controller('UserpicModalController', function ($q, $scope, $rootScope, $modalInstance, MtpApiManager, AppPhotosManager, AppUsersManager, AppPeersManager, AppMessagesManager, ApiUpdatesManager, PeersSelectService, ErrorService) {
$scope.photo = AppPhotosManager.wrapForFull($scope.photoID);
$scope.photo.thumb = {
location: AppPhotosManager.choosePhotoSize($scope.photo, 0, 0).location
};
$scope.nav = {};
$scope.canForward = true;
var inputUser = AppUsersManager.getUserInput($scope.userID),
list = [$scope.photoID],
maxID = $scope.photoID,
preloaded = {},
myID = 0,
hasMore = true;
updatePrevNext();
@ -1712,15 +1727,19 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1712,15 +1727,19 @@ angular.module('myApp.controllers', ['myApp.i18n'])
if (userpicCachedResult.photos.indexOf($scope.photoID) >= 0) {
list = userpicCachedResult.photos;
maxID = list[list.length - 1];
hasMore = list.length < userpicCachedResult.count;
updatePrevNext();
}
hasMore = list.length < userpicCachedResult.count;
updatePrevNext();
});
MtpApiManager.getUserID().then(function (id) {
myID = id;
$scope.canDelete = $scope.photo.user_id == myID;
});
var jump = 0;
function movePosition (sign) {
function movePosition (sign, deleteCurrent) {
var curIndex = list.indexOf($scope.photoID),
index = curIndex >= 0 ? curIndex + sign : 0,
curJump = ++jump;
@ -1733,32 +1752,80 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1733,32 +1752,80 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.photoID = list[index];
$scope.photo = AppPhotosManager.wrapForFull($scope.photoID);
$scope.photo.thumb = {
location: AppPhotosManager.choosePhotoSize($scope.photo, 0, 0).location
};
var newCount;
if (deleteCurrent) {
list.splice(curIndex, 1);
newCount = $scope.count - 1;
}
updatePrevNext(newCount);
preloaded[$scope.photoID] = true;
updatePrevNext();
if (sign > 0 && hasMore && list.indexOf($scope.photoID) + 1 >= list.length) {
loadMore();
} else {
preloadPhotos(sign);
}
});
};
function preloadPhotos (sign) {
var preloadOffsets = sign < 0 ? [-1,-2] : [1,2];
var index = list.indexOf($scope.photoID);
angular.forEach(preloadOffsets, function (offset) {
var photoID = list[index + offset];
if (photoID !== undefined && preloaded[photoID] === undefined) {
preloaded[photoID] = true;
AppPhotosManager.preloadPhoto(photoID);
}
})
}
var loadingPromise = false;
function loadMore () {
if (loadingPromise) return loadingPromise;
return loadingPromise = AppPhotosManager.getUserPhotos(inputUser, maxID).then(function (userpicResult) {
maxID = userpicResult.photos[userpicResult.photos.length - 1];
list = list.concat(userpicResult.photos);
if (userpicResult.photos.length) {
maxID = userpicResult.photos[userpicResult.photos.length - 1];
list = list.concat(userpicResult.photos);
hasMore = list.length < userpicResult.count;
hasMore = list.length < userpicResult.count;
} else {
hasMore = false;
}
updatePrevNext();
loadingPromise = false;
}, function () {
updatePrevNext(userpicResult.count);
loadingPromise = false;
if (userpicResult.photos.length) {
return $q.reject();
}
preloadPhotos(+1);
});
};
function updatePrevNext () {
function updatePrevNext (count) {
var index = list.indexOf($scope.photoID);
if (hasMore) {
if (count) {
$scope.count = Math.max(count, list.length);
}
} else {
$scope.count = list.length;
}
$scope.pos = $scope.count - index;
$scope.nav.hasNext = index > 0;
$scope.nav.hasPrev = hasMore || index < list.length - 1;
$scope.canDelete = $scope.photo.user_id == myID;
};
$scope.nav.next = function () {
@ -1777,25 +1844,109 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1777,25 +1844,109 @@ angular.module('myApp.controllers', ['myApp.i18n'])
};
$scope.forward = function () {
var messageID = $scope.photoID;
PeersSelectService.selectPeer({confirm_type: 'FORWARD_PEER'}).then(function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.sendOther(peerID, {
_: 'inputMediaPhoto',
id: {
_: 'inputPhoto',
id: $scope.photoID,
access_hash: $scope.photo.access_hash,
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) {
angular.forEach(peerStrings, function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.sendOther(peerID, {
_: 'inputMediaPhoto',
id: {
_: 'inputPhoto',
id: $scope.photoID,
access_hash: $scope.photo.access_hash,
}
});
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerStrings[0]});
}
});
$rootScope.$broadcast('history_focus', {peerString: peerString});
});
};
$scope['delete'] = function () {
var messageID = $scope.photoID;
ErrorService.confirm({type: 'MESSAGE_DELETE'}).then(function () {
AppMessagesManager.deleteMessages([messageID]);
var photoID = $scope.photoID;
var myUser = AppUsersManager.getUser(myID);
var onDeleted = function () {
if (!$scope.nav.hasNext && !$scope.nav.hasPrev) {
return $modalInstance.dismiss();
}
movePosition($scope.nav.hasNext ? -1 : +1, true);
};
ErrorService.confirm({type: 'PHOTO_DELETE'}).then(function () {
if (myUser && myUser.photo && myUser.photo.photo_id == photoID) {
MtpApiManager.invokeApi('photos.updateProfilePhoto', {
id: {_: 'inputPhotoEmpty'},
crop: {_: 'inputPhotoCropAuto'}
}).then(function (updateResult) {
ApiUpdatesManager.processUpdateMessage({
_: 'updateShort',
update: {
_: 'updateUserPhoto',
user_id: myID,
date: tsNow(true),
photo: updateResult,
previous: true
}
});
onDeleted();
});
}
else {
MtpApiManager.invokeApi('photos.deletePhotos', {
id: [{_: 'inputPhoto', id: photoID, access_hash: 0}]
}).then(onDeleted);
}
});
};
$scope.download = function () {
AppPhotosManager.downloadPhoto($scope.photoID);
};
})
.controller('ChatpicModalController', function ($q, $scope, $rootScope, $modalInstance, MtpApiManager, AppPhotosManager, AppChatsManager, AppPeersManager, AppMessagesManager, PeersSelectService, ErrorService) {
$scope.photo = AppPhotosManager.wrapForFull($scope.photoID);
$scope.photo.thumb = {
location: AppPhotosManager.choosePhotoSize($scope.photo, 0, 0).location
};
$scope.canForward = true;
$scope.canDelete = true;
$scope.forward = function () {
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) {
angular.forEach(peerStrings, function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.sendOther(peerID, {
_: 'inputMediaPhoto',
id: {
_: 'inputPhoto',
id: $scope.photoID,
access_hash: $scope.photo.access_hash,
}
});
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerStrings[0]});
}
});
});
};
$scope['delete'] = function () {
ErrorService.confirm({type: 'PHOTO_DELETE'}).then(function () {
$scope.photo.updating = true;
MtpApiManager.invokeApi('messages.editChatPhoto', {
chat_id: $scope.chatID,
photo: {_: 'inputChatPhotoEmpty'}
}).then(function (updateResult) {
AppMessagesManager.onStatedMessage(updateResult);
$modalInstance.dismiss();
$rootScope.$broadcast('history_focus', {peerString: AppChatsManager.getChatString($scope.chatID)});
})['finally'](function () {
$scope.photo.updating = false;
});
});
};
@ -1815,10 +1966,14 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1815,10 +1966,14 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.forward = function () {
var messageID = $scope.messageID;
PeersSelectService.selectPeer({confirm_type: 'FORWARD_PEER'}).then(function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () {
$rootScope.$broadcast('history_focus', {peerString: peerString});
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) {
angular.forEach(peerStrings, function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () {
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerString});
}
});
});
});
};
@ -1847,10 +2002,14 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1847,10 +2002,14 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$scope.forward = function () {
var messageID = $scope.messageID;
PeersSelectService.selectPeer({confirm_type: 'FORWARD_PEER'}).then(function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () {
$rootScope.$broadcast('history_focus', {peerString: peerString});
PeersSelectService.selectPeers({confirm_type: 'FORWARD_PEER'}).then(function (peerStrings) {
angular.forEach(peerStrings, function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.forwardMessages(peerID, [messageID]).then(function () {
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerString});
}
});
});
});
};
@ -1897,9 +2056,6 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1897,9 +2056,6 @@ angular.module('myApp.controllers', ['myApp.i18n'])
AppUsersManager.saveApiUser(userFullResult.user, true);
}
AppPhotosManager.savePhoto(userFullResult.profile_photo);
if (userFullResult.profile_photo._ != 'photoEmpty') {
$scope.userPhoto.id = userFullResult.profile_photo.id;
}
$scope.blocked = userFullResult.blocked;
NotificationsManager.savePeerSettings($scope.userID, userFullResult.notify_settings);
@ -1946,7 +2102,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1946,7 +2102,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$modal.open({
templateUrl: templateUrl(edit ? 'edit_contact_modal' : 'import_contact_modal'),
controller: 'ImportContactModalController',
windowClass: 'import_contact_modal_window mobile_modal',
windowClass: 'md_simple_modal_window mobile_modal',
scope: scope
}).result.then(function (foundUserID) {
if ($scope.userID == foundUserID) {
@ -1970,23 +2126,26 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1970,23 +2126,26 @@ angular.module('myApp.controllers', ['myApp.i18n'])
};
$scope.shareContact = function () {
PeersSelectService.selectPeer({confirm_type: 'SHARE_CONTACT_PEER'}).then(function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.sendOther(peerID, {
_: 'inputMediaContact',
phone_number: $scope.user.phone,
first_name: $scope.user.first_name,
last_name: $scope.user.last_name,
user_id: $scope.user.id
PeersSelectService.selectPeers({confirm_type: 'SHARE_CONTACT_PEER'}).then(function (peerStrings) {
angular.forEach(peerStrings, function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
AppMessagesManager.sendOther(peerID, {
_: 'inputMediaContact',
phone_number: $scope.user.phone,
first_name: $scope.user.first_name,
last_name: $scope.user.last_name,
user_id: $scope.user.id
});
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerStrings[0]});
}
});
$rootScope.$broadcast('history_focus', {peerString: peerString});
})
});
}
})
.controller('ChatModalController', function ($scope, $timeout, $rootScope, $modal, AppUsersManager, AppChatsManager, MtpApiManager, MtpApiFileManager, NotificationsManager, AppMessagesManager, AppPeersManager, ApiUpdatesManager, ContactsSelectService, ErrorService) {
.controller('ChatModalController', function ($scope, $timeout, $rootScope, $modal, AppUsersManager, AppChatsManager, AppPhotosManager, MtpApiManager, MtpApiFileManager, NotificationsManager, AppMessagesManager, AppPeersManager, ApiUpdatesManager, ContactsSelectService, ErrorService) {
$scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, {});
@ -1995,6 +2154,9 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1995,6 +2154,9 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}).then(function (result) {
AppChatsManager.saveApiChats(result.chats);
AppUsersManager.saveApiUsers(result.users);
if (result.full_chat && result.full_chat.chat_photo.id) {
AppPhotosManager.savePhoto(result.full_chat.chat_photo);
}
$scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, result.full_chat);
$scope.$broadcast('ui_height');
@ -2021,18 +2183,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2021,18 +2183,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
});
function onStatedMessage (statedMessage) {
ApiUpdatesManager.processUpdateMessage({
_: 'updates',
users: statedMessage.users,
chats: statedMessage.chats,
seq: statedMessage.seq,
updates: [{
_: 'updateNewMessage',
message: statedMessage.message,
pts: statedMessage.pts
}]
});
AppMessagesManager.onStatedMessage(statedMessage);
$rootScope.$broadcast('history_focus', {peerString: $scope.chatFull.peerString});
}
@ -2148,7 +2299,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2148,7 +2299,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
templateUrl: templateUrl('chat_edit_modal'),
controller: 'ChatEditModalController',
scope: scope,
windowClass: 'group_edit_modal_window mobile_modal'
windowClass: 'md_simple_modal_window mobile_modal'
});
}
@ -2170,9 +2321,6 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2170,9 +2321,6 @@ angular.module('myApp.controllers', ['myApp.i18n'])
}).then(function (userFullResult) {
AppUsersManager.saveApiUser(userFullResult.user);
AppPhotosManager.savePhoto(userFullResult.profile_photo);
if (userFullResult.profile_photo._ != 'photoEmpty') {
$scope.photo.id = userFullResult.profile_photo.id;
}
});
$scope.notify = {volume: 0.5};
@ -2193,6 +2341,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2193,6 +2341,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
crop: {_: 'inputPhotoCropAuto'}
}).then(function (updateResult) {
AppUsersManager.saveApiUsers(updateResult.users);
AppPhotosManager.savePhoto(updateResult.photo);
MtpApiManager.getUserID().then(function (id) {
ApiUpdatesManager.processUpdateMessage({
_: 'updateShort',
@ -2208,7 +2357,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2208,7 +2357,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
});
});
})['finally'](function () {
delete $scope.updating;
delete $scope.photo.updating;
});
};
@ -2240,7 +2389,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2240,7 +2389,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$modal.open({
templateUrl: templateUrl('profile_edit_modal'),
controller: 'ProfileEditModalController',
windowClass: 'profile_edit_modal_window mobile_modal'
windowClass: 'md_simple_modal_window mobile_modal'
});
};
@ -2248,7 +2397,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2248,7 +2397,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$modal.open({
templateUrl: templateUrl('username_edit_modal'),
controller: 'UsernameEditModalController',
windowClass: 'username_edit_modal_window mobile_modal'
windowClass: 'md_simple_modal_window mobile_modal'
});
};
@ -2339,11 +2488,41 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2339,11 +2488,41 @@ angular.module('myApp.controllers', ['myApp.i18n'])
})
.controller('ChangelogModalController', function ($scope, $modal) {
$scope.currentVersion = Config.App.version;
if (!$scope.lastVersion) {
var versionParts = $scope.currentVersion.split('.');
$scope.lastVersion = versionParts[0] + '.' + versionParts[1] + '.' + Math.max(0, versionParts[2] - 1);
}
$scope.changelogHidden = false;
$scope.changelogShown = false;
$scope.canShowVersion = function (curVersion) {
if ($scope.changelogShown) {
return true;
}
var show = versionCompare(curVersion, $scope.lastVersion) >= 0;
if (!show) {
$scope.changelogHidden = true;
}
return show;
};
$scope.showAllVersions = function () {
$scope.changelogShown = true;
$scope.changelogHidden = false;
$scope.$emit('ui_height');
$scope.$broadcast('ui_height');
};
$scope.changeUsername = function () {
$modal.open({
templateUrl: templateUrl('username_edit_modal'),
controller: 'UsernameEditModalController',
windowClass: 'username_edit_modal_window mobile_modal'
windowClass: 'md_simple_modal_window mobile_modal'
});
};
})
@ -2583,22 +2762,53 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -2583,22 +2762,53 @@ angular.module('myApp.controllers', ['myApp.i18n'])
.controller('PeerSelectController', function ($scope, $modalInstance, $q, AppPeersManager, ErrorService) {
$scope.selectedPeers = {};
$scope.selectedPeerIDs = [];
$scope.selectedCount = 0;
$scope.dialogSelect = function (peerString) {
var promise;
if ($scope.confirm_type) {
var peerID = AppPeersManager.getPeerID(peerString),
peerData = AppPeersManager.getPeer(peerID);
promise = ErrorService.confirm({
type: $scope.confirm_type,
peer_id: peerID,
peer_data: peerData
if (!$scope.multiSelect) {
var promise;
if ($scope.confirm_type) {
var peerID = AppPeersManager.getPeerID(peerString),
peerData = AppPeersManager.getPeer(peerID);
promise = ErrorService.confirm({
type: $scope.confirm_type,
peer_id: peerID,
peer_data: peerData
});
} else {
promise = $q.when();
}
promise.then(function () {
$modalInstance.close(peerString);
});
return;
}
var peerID = AppPeersManager.getPeerID(peerString);
if ($scope.selectedPeers[peerID]) {
delete $scope.selectedPeers[peerID];
$scope.selectedCount--;
var pos = $scope.selectedPeerIDs.indexOf(peerID);
if (pos >= 0) {
$scope.selectedPeerIDs.splice(pos, 1);
}
} else {
promise = $q.when();
$scope.selectedPeers[peerID] = AppPeersManager.getPeer(peerID);
$scope.selectedCount++;
$scope.selectedPeerIDs.unshift(peerID);
}
};
$scope.submitSelected = function () {
if ($scope.selectedCount > 0) {
var selectedPeerStrings = [];
angular.forEach($scope.selectedPeers, function (t, peerID) {
selectedPeerStrings.push(AppPeersManager.getPeerString(peerID));
});
return $modalInstance.close(selectedPeerStrings);
}
promise.then(function () {
$modalInstance.close(peerString);
});
};
$scope.toggleSearch = function () {

143
app/js/directives.js

@ -1744,7 +1744,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1744,7 +1744,7 @@ angular.module('myApp.directives', ['myApp.filters'])
function link ($scope, element, attrs) {
element.html(isAnimationSupported(element[0])
? '<div class="loading_dots"><span></span><span></span><span></span></div>'
? '<div class="loading_dots"><i></i><i></i><i></i></div>'
: '...'
);
}
@ -2132,6 +2132,108 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -2132,6 +2132,108 @@ angular.module('myApp.directives', ['myApp.filters'])
}
})
.directive('myPeerPhotolink', function (AppPeersManager, AppUsersManager, AppChatsManager, MtpApiFileManager, FileManager) {
return {
link: link
};
function link($scope, element, attrs) {
element.addClass('peer_photo_init');
var peerID, peer, peerPhoto;
var imgEl = $('<img class="' + (attrs.imgClass || '') + '">');
var initEl = $('<span class="peer_initials ' + (attrs.imgClass || '') + '"></span>');
var jump = 0;
var prevClass = false;
var setPeerID = function (newPeerID) {
if (peerID == newPeerID) {
return false;
}
peerID = newPeerID;
peer = AppPeersManager.getPeer(peerID);
var newClass = 'user_bgcolor_' + (peer.num || 1);
if (newClass != prevClass) {
if (prevClass) {
initEl.removeClass(prevClass);
}
initEl.addClass(newClass);
}
updatePeerPhoto();
return true;
}
var updatePeerPhoto = function () {
peerPhoto = peer.photo && angular.copy(peer.photo.photo_small);
var hasPhoto = peerPhoto !== undefined;
if (hasPhoto) {
var cachedBlob = MtpApiFileManager.getCachedFile(peer.photo.photo_small);
if (cachedBlob) {
initEl.remove();
imgEl.prependTo(element).attr('src', FileManager.getUrl(cachedBlob, 'image/jpeg'));
return;
}
}
initEl.text(peer.initials).prependTo(element);
imgEl.remove();
if (hasPhoto) {
var curJump = ++jump;
MtpApiFileManager.downloadSmallFile(peer.photo.photo_small).then(function (blob) {
if (curJump != jump) {
return;
}
initEl.remove();
imgEl.prependTo(element).attr('src', FileManager.getUrl(blob, 'image/jpeg'));
}, function (e) {
console.log('Download image failed', e, peer.photo.photo_small, element[0]);
});
}
};
if (element[0].tagName == 'A' && !attrs.noOpen) {
element.on('click', function (e) {
if (peerID > 0) {
AppUsersManager.openUser(peerID, attrs.userOverride && $eval(attrs.userOverride));
} else {
AppChatsManager.openChat(-peerID);
}
});
}
$scope.$watch(attrs.myPeerPhotolink, setPeerID);
if (attrs.watch) {
$scope.$on('user_update', function (e, updUserID) {
if (peerID == updUserID) {
if (!angular.equals(peer.photo && peer.photo.photo_small, peerPhoto)) {
updatePeerPhoto();
}
}
});
$scope.$on('chat_update', function (e, updChatID) {
if (peerID == -updChatID) {
if (!angular.equals(peer.photo && peer.photo.photo_small, peerPhoto)) {
updatePeerPhoto();
}
}
});
}
}
})
.directive('myAudioPlayer', function ($timeout, $q, Storage, AppAudioManager, AppDocsManager, ErrorService) {
var currentPlayer = false;
@ -2382,3 +2484,42 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -2382,3 +2484,42 @@ angular.module('myApp.directives', ['myApp.filters'])
}
})
.directive('myLabeledInput', function () {
return {
link: link
};
function link($scope, element, attrs) {
var input = $('.md-input:first', element);
var label = $('.md-input-label:first', element);
var isDisabled = input[0] && input[0].tagName == 'SPAN';
var focused = false;
var updateHasValueClass = function () {
if (isDisabled) {
element.toggleClass('md-input-has-value', input.html().length > 0);
} else {
element.toggleClass('md-input-has-value', focused || input.val().length > 0);
}
};
updateHasValueClass();
onContentLoaded(function () {
updateHasValueClass();
setZeroTimeout(function () {
element.addClass('md-input-animated');
});
});
if (!isDisabled) {
input.on('blur focus', function (e) {
focused = e.type == 'focus';
element.toggleClass('md-input-focused', focused);
updateHasValueClass();
});
}
};
})

2
app/js/lib/config.js

File diff suppressed because one or more lines are too long

1
app/js/lib/schema.tl.txt

@ -491,6 +491,7 @@ updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference; @@ -491,6 +491,7 @@ updates.getDifference#a041495 pts:int date:int qts:int = updates.Difference;
photos.updateProfilePhoto#eef579a0 id:InputPhoto crop:InputPhotoCrop = UserProfilePhoto;
photos.uploadProfilePhoto#d50f9c88 file:InputFile caption:string geo_point:InputGeoPoint crop:InputPhotoCrop = photos.Photo;
photos.deletePhotos#87cf7f2f id:Vector<InputPhoto> = Vector<long>;
upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool;
upload.getFile#e3a6cfb5 location:InputFileLocation offset:int limit:int = upload.File;

26
app/js/lib/utils.js

@ -151,3 +151,29 @@ function calcImageInBox(imageW, imageH, boxW, boxH, noZooom) { @@ -151,3 +151,29 @@ function calcImageInBox(imageW, imageH, boxW, boxH, noZooom) {
return {w: boxedImageW, h: boxedImageH};
}
function versionCompare (ver1, ver2) {
if (typeof ver1 !== 'string') {
ver1 = '';
}
if (typeof ver2 !== 'string') {
ver2 = '';
}
ver1 = ver1.replace(/^\s+|\s+$/g, '').split('.');
ver2 = ver2.replace(/^\s+|\s+$/g, '').split('.');
var a = Math.max(ver1.length, ver2.length), i;
for (i = 0; i < a; i++) {
if (ver1[i] == ver2[i]) {
continue;
}
if (ver1[i] > ver2[i]) {
return 1;
} else {
return -1;
}
}
return 0;
}

17
app/js/locales/en-us.json

@ -1,6 +1,9 @@ @@ -1,6 +1,9 @@
{
"modal_search": "Search",
"modal_close": "Close",
"modal_edit": "Edit",
"modal_cancel": "Cancel",
"modal_more": "More...",
"modal_next": "Next",
"modal_ok": "OK",
"modal_done": "Done",
@ -14,13 +17,12 @@ @@ -14,13 +17,12 @@
"group_modal_menu_more": "More",
"group_modal_menu_delete_photo": "Delete photo",
"group_modal_menu_edit_group": "Edit group",
"group_modal_menu_leave_group": "Leave group",
"group_modal_menu_leave": "Leave",
"group_modal_menu_delete_chat": "Delete chat",
"group_modal_settings": "Settings",
"group_modal_notifications": "Notifications",
"group_modal_members": "Members",
"group_modal_members_kick": "Kick",
"group_modal_members_unavailable": "Group members list is unavailable.",
"country_select_modal_title": "Country",
@ -130,6 +132,7 @@ @@ -130,6 +132,7 @@
"confirm_modal_clipboard_file_send": "Are you sure to send file(s) from clipboard?",
"confirm_modal_clipboard_X_files_send": "{'one': 'Are you sure to send file from clipboard?', 'other': 'Are you sure to send {} files from clipboard?'}",
"confirm_modal_message_delete": "Are you sure you want to delete the message?",
"confirm_modal_photo_delete": "Are you sure you want to delete the photo?",
"confirm_modal_contacts_import": "Telegram will now sync your contacts in order to find your friends.",
"confirm_modal_login_phone_correct": "Is this phone number correct?",
"confirm_modal_forward_to_peer": "Forward to {peer}?",
@ -146,6 +149,7 @@ @@ -146,6 +149,7 @@
"confirm_modal_clipboard_files_send_submit": "Send",
"confirm_modal_clipboard_file_send_submit": "Send",
"confirm_modal_message_delete_submit": "Delete",
"confirm_modal_photo_delete_submit": "Delete",
"confirm_modal_forward_message_submit": "Forward message",
"confirm_modal_share_photo_submit": "Forward photo",
"confirm_modal_share_video_submit": "Forward video",
@ -160,6 +164,12 @@ @@ -160,6 +164,12 @@
"contacts_modal_new_contact": "New Contact",
"contacts_modal_empty_list": "Your contacts list is empty. You can {import-link: add new contact} by phone number.",
"conversations_modal_forward_title": "Forward",
"conversations_modal_forward_submit": "Forward",
"conversations_modal_select_recipients": "Select recipients",
"conversations_modal_recipients": "Recipients:",
"contact_edit_modal_first_name": "First name",
"contact_edit_modal_last_name": "Last name",
"contact_edit_modal_title": "Edit contact",
@ -353,6 +363,9 @@ @@ -353,6 +363,9 @@
"conversation_select_modal_title": "Select conversation",
"conversation_select_modal_contacts": "Contacts",
"conversation_one_selected": "{name1}",
"conversation_two_selected": "{name1} and {name2}",
"conversation_many_selected": "{name1}, {name2} and {count} more",
"phonebook_modal_title": "Phonebook",
"phonebook_modal_deselect_all": "Deselect all",

143
app/js/services.js

@ -96,7 +96,14 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -96,7 +96,14 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
apiUser.rFirstName = RichTextProcessor.wrapRichText(apiUser.last_name, {noLinks: true, noLinebreaks: true}) || apiUser.rPhone || _('user_first_name_deleted');
apiUser.rFullName = RichTextProcessor.wrapRichText(apiUser.last_name, {noLinks: true, noLinebreaks: true}) || apiUser.rPhone || _('user_name_deleted');
}
apiUser.sortName = SearchIndexManager.cleanSearchText(apiUser.first_name + ' ' + (apiUser.last_name || ''));
var nameWords = apiUser.sortName.split(' ');
var firstWord = nameWords.shift();
var lastWord = nameWords.pop();
apiUser.initials = firstWord.charAt(0) + (lastWord ? lastWord.charAt(0) : firstWord.charAt(1));
apiUser.sortStatus = getUserStatusForSort(apiUser.status);
@ -323,7 +330,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -323,7 +330,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return $modal.open({
templateUrl: templateUrl('import_contact_modal'),
controller: 'ImportContactModalController',
windowClass: 'import_contact_modal_window mobile_modal'
windowClass: 'md_simple_modal_window mobile_modal'
}).result.then(function (foundUserID) {
if (!foundUserID) {
return $q.reject();
@ -474,7 +481,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -474,7 +481,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
})
.service('AppChatsManager', function ($rootScope, $modal, _, MtpApiFileManager, MtpApiManager, AppUsersManager, RichTextProcessor) {
.service('AppChatsManager', function ($rootScope, $modal, _, MtpApiFileManager, MtpApiManager, AppUsersManager, RichTextProcessor, SearchIndexManager) {
var chats = {},
cachedPhotoLocations = {};
@ -487,10 +494,19 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -487,10 +494,19 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return;
}
apiChat.rTitle = RichTextProcessor.wrapRichText(apiChat.title, {noLinks: true, noLinebreaks: true}) || _('chat_title_deleted');
var titleWords = SearchIndexManager.cleanSearchText(apiChat.title || '').split(' ');
var firstWord = titleWords.shift();
var lastWord = titleWords.pop();
apiChat.initials = firstWord.charAt(0) + (lastWord ? lastWord.charAt(0) : firstWord.charAt(1));
apiChat.num = (Math.abs(apiChat.id) % 4) + 1;
if (chats[apiChat.id] === undefined) {
chats[apiChat.id] = apiChat;
} else {
safeReplaceObject(chats[apiChat.id], apiChat);
$rootScope.$broadcast('chat_update', apiChat.id);
}
if (cachedPhotoLocations[apiChat.id] !== undefined) {
@ -514,7 +530,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -514,7 +530,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
}
return {
placeholder: 'img/placeholders/' + placeholder + 'Avatar'+((Math.abs(id) % 4) + 1)+'@2x.png',
placeholder: 'img/placeholders/' + placeholder + 'Avatar' + chat.num + '@2x.png',
location: cachedPhotoLocations[id]
};
}
@ -533,8 +549,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -533,8 +549,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
MtpApiManager.getUserID().then(function (myID) {
angular.forEach(chatFull.participants.participants, function(participant){
participant.user = AppUsersManager.getUser(participant.user_id);
participant.inviter = AppUsersManager.getUser(participant.inviter_id);
participant.canKick = myID != participant.user_id && (myID == chatFull.participants.admin_id || myID == participant.inviter_id);
participant.canLeave = myID == participant.user_id;
participant.canKick = !participant.canLeave && (myID == chatFull.participants.admin_id || myID == participant.inviter_id);
});
});
}
@ -542,8 +558,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -542,8 +558,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
chatFull.thumb = {
placeholder: 'img/placeholders/GroupAvatar'+((Math.abs(id) % 4) + 1)+'@2x.png',
location: chat && chat.photo && chat.photo.photo_small,
width: 120,
height: 120,
width: 72,
height: 72,
size: 0
};
chatFull.peerString = getChatString(id);
@ -1654,6 +1670,20 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1654,6 +1670,20 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return false;
}
function onStatedMessage (statedMessage) {
ApiUpdatesManager.processUpdateMessage({
_: 'updates',
users: statedMessage.users,
chats: statedMessage.chats,
seq: statedMessage.seq,
updates: [{
_: 'updateNewMessage',
message: statedMessage.message,
pts: statedMessage.pts
}]
});
}
function getMessagePeer (message) {
var toID = message.to_id && AppPeersManager.getPeerID(message.to_id) || 0;
@ -1939,12 +1969,16 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -1939,12 +1969,16 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
console.log(dT(), 'Received activity', source.name, source.data);
if (source.name === 'share' && source.data.blobs.length > 0) {
PeersSelectService.selectPeer({confirm_type: 'EXT_SHARE_PEER'}).then(function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
angular.forEach(source.data.blobs, function (blob) {
sendFile(peerID, blob, {isMedia: true});
});
$rootScope.$broadcast('history_focus', {peerString: peerString});
PeersSelectService.selectPeers({confirm_type: 'EXT_SHARE_PEER'}).then(function (peerStrings) {
angular.forEach(peerStrings, function (peerString) {
var peerID = AppPeersManager.getPeerID(peerString);
angular.forEach(source.data.blobs, function (blob) {
sendFile(peerID, blob, {isMedia: true});
});
})
if (peerStrings.length == 1) {
$rootScope.$broadcast('history_focus', {peerString: peerStrings[0]});
}
});
}
});
@ -2171,6 +2205,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2171,6 +2205,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
sendFile: sendFile,
sendOther: sendOther,
forwardMessages: forwardMessages,
onStatedMessage: onStatedMessage,
getMessagePeer: getMessagePeer,
wrapForDialog: wrapForDialog,
wrapForHistory: wrapForHistory,
@ -2338,7 +2373,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2338,7 +2373,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return photo;
}
function openPhoto (photoID, peerListID) {
function openPhoto (photoID, list) {
if (!photoID || photoID === '0') {
return false;
}
@ -2346,16 +2381,24 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2346,16 +2381,24 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var scope = $rootScope.$new(true);
scope.photoID = photoID;
if (peerListID < 0) {
scope.userID = -peerListID;
} else{
scope.messageID = peerListID;
var controller = 'PhotoModalController';
if (list && list.p > 0) {
controller = 'UserpicModalController';
scope.userID = list.p;
}
else if (list && list.p < 0) {
controller = 'ChatpicModalController';
scope.chatID = -list.p;
}
else if (list && list.m > 0) {
scope.messageID = list.m;
}
var modalInstance = $modal.open({
templateUrl: templateUrl('photo_modal'),
windowTemplateUrl: templateUrl('media_modal_layout'),
controller: scope.userID ? 'UserpicModalController' : 'PhotoModalController',
controller: controller,
scope: scope,
windowClass: 'photo_modal_window'
});
@ -2406,6 +2449,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -2406,6 +2449,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
preloadPhoto: preloadPhoto,
getUserPhotos: getUserPhotos,
getPhoto: getPhoto,
choosePhotoSize: choosePhotoSize,
wrapForHistory: wrapForHistory,
wrapForFull: wrapForFull,
openPhoto: openPhoto,
@ -3756,7 +3800,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3756,7 +3800,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var shownBoxes = 0;
function show (params, options) {
if (shownBoxes >= 2) {
if (shownBoxes >= 1) {
console.log('Skip error box, too many open', shownBoxes, params, options);
return false;
}
@ -3824,6 +3868,28 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3824,6 +3868,28 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function selectPeer (options) {
var scope = $rootScope.$new();
scope.multiSelect = false;
if (options) {
angular.extend(scope, options);
}
return $modal.open({
templateUrl: templateUrl('peer_select'),
controller: 'PeerSelectController',
scope: scope,
windowClass: 'peer_select_window mobile_modal'
}).result;
}
function selectPeers (options) {
if (Config.Mobile) {
return selectPeer(options).then(function (peerString) {
return [peerString];
});
}
var scope = $rootScope.$new();
scope.multiSelect = true;
if (options) {
angular.extend(scope, options);
}
@ -3838,7 +3904,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3838,7 +3904,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return {
selectPeer: selectPeer
selectPeer: selectPeer,
selectPeers: selectPeers
}
})
@ -3877,32 +3944,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3877,32 +3944,6 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
.service('ChangelogNotifyService', function (Storage, $rootScope, $modal) {
function versionCompare (ver1, ver2) {
if (typeof ver1 !== 'string') {
ver1 = '';
}
if (typeof ver2 !== 'string') {
ver2 = '';
}
ver1 = ver1.replace(/^\s+|\s+$/g, '').split('.');
ver2 = ver2.replace(/^\s+|\s+$/g, '').split('.');
var a = Math.max(ver1.length, ver2.length), i;
for (i = 0; i < a; i++) {
if (ver1[i] == ver2[i]) {
continue;
}
if (ver1[i] > ver2[i]) {
return 1;
} else {
return -1;
}
}
return 0;
}
function checkUpdate () {
Storage.get('last_version').then(function (lastVersion) {
if (lastVersion != Config.App.version) {
@ -3916,15 +3957,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils']) @@ -3916,15 +3957,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function showChangelog (lastVersion) {
var $scope = $rootScope.$new();
$scope.lastVersion = lastVersion;
$scope.canShowVersion = function (curVersion) {
if ($scope.lastVersion === false || $scope.lastVersion === undefined) {
return true;
}
return versionCompare(curVersion, lastVersion) >= 0;
};
$modal.open({
controller: 'ChangelogModalController',

256
app/partials/desktop/changelog_modal.html

@ -1,28 +1,39 @@ @@ -1,28 +1,39 @@
<div class="changelog_modal_wrap" my-modal-position>
<div class="changelog_modal_wrap md_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$close()"><i></i></a>
<div class="modal-body">
<div class="md_modal_head">
<div class="md_modal_title_wrap">
<div class="md_modal_actions_wrap clearfix">
<a class="md_modal_action md_modal_action_close" ng-click="$close()" my-i18n="modal_close"></a>
</div>
<div class="md_modal_title" my-i18n="head_about"></div>
</div>
<div class="changelog_card_wrap" ng-switch="lastVersion === false">
<div ng-switch-when="true">
<div class="changelog_card"></div>
<h2 class="changelog_header" my-i18n="changelog_modal_header_recent_updates_md"></h2>
<div class="peer_modal_profile_wrap clearfix">
<div class="peer_modal_photo_wrap pull-left">
<div class="peer_modal_photo telegram_modal_logo"></div>
</div>
<div ng-switch-default>
<div class="changelog_card"></div>
<h2 class="changelog_header" my-i18n="changelog_modal_header_new_updates_md"></h2>
<div class="peer_modal_profile">
<div class="peer_modal_profile_name">Telegram Web</div>
<div class="peer_modal_profile_description">Version {{currentVersion}}</div>
</div>
</div>
</div>
<div class="changelog_versions_wrap">
<div class="md_modal_split_actions_wrap">
<div class="md_modal_split_actions">
<a href="https://twitter.com/telegram_web" target="_blank" class="md_modal_split_action">
<i class="md_modal_split_action_twitter"></i>
</a>
</div>
</div>
<div class="md_modal_body">
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.3.6
<span class="pull-right" my-i18n="changelog_modal_title_current_version"></span>
</h3>
<div class="modal_section_body changelog_version_changes">
<div class="md_modal_sections">
<div class="md_modal_versioned_section_wrap" ng-if="canShowVersion('0.3.6')">
<div class="md_modal_section_version">0.3.6</div>
<div class="md_modal_section_description changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>New viewer for photos, videos, documents.</li>
<li>[FirefoxOS] Improved media downloads.</li>
@ -30,11 +41,9 @@ @@ -30,11 +41,9 @@
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.3.5
</h3>
<div class="modal_section_body changelog_version_changes">
<div class="md_modal_versioned_section_wrap" ng-if="canShowVersion('0.3.5')">
<div class="md_modal_section_version">0.3.5</div>
<div class="md_modal_section_description changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Added embedded Soundcloud tracks and playlists.</li>
<li>Added global user search to contacts list.</li>
@ -45,11 +54,9 @@ @@ -45,11 +54,9 @@
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.3.4
</h3>
<div class="modal_section_body changelog_version_changes">
<div class="md_modal_versioned_section_wrap" ng-if="canShowVersion('0.3.4')">
<div class="md_modal_section_version">0.3.4</div>
<div class="md_modal_section_description changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Added embedded Facebook posts and Vimeo videos.</li>
<li>Improved IE10+ support: downloading files and style fixes.</li>
@ -59,11 +66,9 @@ @@ -59,11 +66,9 @@
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.3.3
</h3>
<div class="modal_section_body changelog_version_changes">
<div class="md_modal_versioned_section_wrap" ng-if="canShowVersion('0.3.3')">
<div class="md_modal_section_version">0.3.3</div>
<div class="md_modal_section_description changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Added Native Client module: dramatically improved encryption speed; Download and upload speed is now as high as in native applications.</li>
<li>HTTPS. We recommend you to use <a href="https://web.telegram.org" target="_blank">https://web.telegram.org</a>.</li>
@ -75,11 +80,9 @@ @@ -75,11 +80,9 @@
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.3.2
</h3>
<div class="modal_section_body changelog_version_changes">
<div class="md_modal_versioned_section_wrap" ng-if="canShowVersion('0.3.2')">
<div class="md_modal_section_version">0.3.2</div>
<div class="md_modal_section_description changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Usernames support: <a href="" ng-click="changeUsername()">Choose a username right now!</a></li>
<li>Search can now find public users by username.</li>
@ -90,11 +93,9 @@ @@ -90,11 +93,9 @@
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.3.1
</h3>
<div class="modal_section_body changelog_version_changes">
<div class="md_modal_versioned_section_wrap" ng-if="canShowVersion('0.3.1')">
<div class="md_modal_section_version">0.3.1</div>
<div class="md_modal_section_description changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>New languages: Spanish, German and Italian are now available </li>
<li>New custom-made audio player</li>
@ -104,11 +105,9 @@ @@ -104,11 +105,9 @@
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.3.0
</h3>
<div class="modal_section_body changelog_version_changes">
<div class="md_modal_versioned_section_wrap" ng-if="canShowVersion('0.3.0')">
<div class="md_modal_section_version">0.3.0</div>
<div class="md_modal_section_description changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Log in codes may be received in other Telegram apps</li>
<li>Partner's online status updates automatically</li>
@ -123,164 +122,15 @@ @@ -123,164 +122,15 @@
</ul>
</div>
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.2.9
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Updated mobile layout</li>
<li>Bugfixes</li>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.2.5
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Updated mobile layout</li>
<li>Improved performance</li>
<li>Improved messages grouping</li>
<li>[FirefoxOS] Fixed notifications for &lt;= 1.1</li>
<li>[FirefoxOS] Fixed phonebook import</li>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.2.1
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Improved key generation performance on slow devices</li>
<li>Added network sleep for mobile devices</li>
<li>[FirefoxOS] Added support of PUSH notifications</li>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap">
<h3 class="modal_section_header changelog_version_title">
Version 0.2
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Updated contacts list, added edit mode</li>
<li>First Firefox OS release. See <a href="https://marketplace.firefox.com/app/telegram" target="_blank">Firefox Marketplace</a></li>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap" ng-show="canShowVersion('0.1.9')">
<h3 class="modal_section_header changelog_version_title">
Version 0.1.9
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Improvements of performance</li>
<li>Bugfixes</li>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap" ng-show="canShowVersion('0.1.8')">
<h3 class="modal_section_header changelog_version_title">
Version 0.1.8
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Improved mobile layout</li>
<li>Bugfixes</li>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap" ng-show="canShowVersion('0.1.7')">
<h3 class="modal_section_header changelog_version_title">
Version 0.1.7
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Improved mobile layout</li>
<li>Added file cache for Firefox and Android</li>
<li>New design for forwarded messages</li>
<li>Hash-tags support</li>
<li>Messaging bugfixes</li>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap" ng-show="canShowVersion('0.1.6')">
<h3 class="modal_section_header changelog_version_title">
Version 0.1.6
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Added search of messages</li>
<li>Improved performance of chats with lots of unread messages</li>
<li>Bugfixes</li>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap" ng-show="canShowVersion('0.1.5')">
<h3 class="modal_section_header changelog_version_title">
Version 0.1.5
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Added registration</li>
<li>Improved experience for newly registered users</li>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap" ng-show="canShowVersion('0.1.4')">
<h3 class="modal_section_header changelog_version_title">
Version 0.1.4
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Browse userpic history (click on the photo in user info)</li>
<li>New <a href="https://github.com/zhukov/webogram" target="_blank" title="Source code on GitHub">GitHub</a>, <a href="https://twitter.com/telegram_web" target="_blank" title="Follow us on Twitter!">Twitter</a> buttons in Settings</li>
<li>Updated keyboard shortcuts:</li>
<ul>
<li><strong>Alt+Home</strong> - switch to first (most recent) conversation</li>
<li>Removed <strong>Alt+1, 2, 3..</strong> shortcuts due to conflicts in different browsers</li>
</ul>
</ul>
</div>
</div>
<div class="modal_section changelog_version_wrap" ng-show="canShowVersion('0.1.3')">
<h3 class="modal_section_header changelog_version_title">
Version 0.1.3
</h3>
<div class="modal_section_body changelog_version_changes">
<ul class="list-unstyled changelog_version_changes_list">
<li>Added version history to welcome screen</li>
<li>Added keyboard shortcuts:</li>
<ul>
<li><strong>Tab</strong> - set focus to message field</li>
<li><strong>Esc</strong> or <strong>Shift+Tab</strong> - set focus to search field</li>
<li><strong>Up/Down</strong> (while in search field) - move between conversations</li>
<li><strong>Enter</strong> (while in search field) - open selected or first conversation</li>
<li><strong>Alt+Up/Down</strong> - move to previous/next conversation</li>
</ul>
<li>Improved grouping for messages</li>
<li>Fixed video modal positioning bug</li>
<li>Fixed focusing issues on mobile</li>
</ul>
</div>
</div>
<div class="changelog_footer_wrap clearfix">
<a class="changelog_github_link" href="https://github.com/zhukov/webogram" target="_blank">GitHub</a>
<a ng-show="changelogHidden" class="changelog_more_link" href="" ng-click="showAllVersions()">View Previous Updates</a>
</div>
</div>
</div>
</div>

21
app/partials/desktop/chat_create_modal.html

@ -1,24 +1,23 @@ @@ -1,24 +1,23 @@
<div class="contacts_modal_wrap" my-modal-position>
<div class="md_simple_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$dismiss()"><i></i></a>
<div class="md_simple_modal_body">
<div class="modal-body">
<form class="modal_simple_form" ng-submit="createGroup()">
<form class="modal_simple_form" ng-submit="updateGroup()">
<h4 my-i18n="group_create_modal_title"></h4>
<div class="form-group">
<input class="form-control input-sm" my-focused type="text" placeholder="{{'group_create_name' | i18n}}" ng-model="group.name"/>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="group_create_name"></label>
<input class="md-input" my-focused type="text" ng-model="group.name" />
</div>
</form>
</div>
<div class="modal-footer">
<a class="btn btn-link" ng-click="$dismiss()" my-i18n="modal_cancel"></a>
<button class="btn btn-primary" ng-class="{disabled: group.creating}" ng-click="createGroup()" ng-bind="group.creating ? 'group_create_submit_active' : 'group_create_submit' | i18n" ng-disabled="group.creating"></button>
<div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md" ng-class="{disabled: group.creating}" ng-click="createGroup()" ng-bind="group.creating ? 'group_create_submit_active' : 'group_create_submit' | i18n" ng-disabled="group.creating"></button>
</div>
</div>
</div>

19
app/partials/desktop/chat_edit_modal.html

@ -1,24 +1,23 @@ @@ -1,24 +1,23 @@
<div class="contacts_modal_wrap" my-modal-position>
<div class="md_simple_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$dismiss()"><i></i></a>
<div class="modal-body">
<div class="md_simple_modal_body">
<form class="modal_simple_form" ng-submit="updateGroup()">
<h4 my-i18n="group_edit_modal_title"></h4>
<div class="form-group">
<input class="form-control input-sm" my-focused type="text" placeholder="{{'group_edit_name' | i18n}}" ng-model="group.name"/>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="group_edit_name"></label>
<input class="md-input" my-focused type="text" ng-model="group.name" />
</div>
</form>
</div>
<div class="modal-footer">
<a class="btn btn-link" ng-click="$dismiss()" my-i18n="modal_cancel"></a>
<button class="btn btn-primary" ng-class="{disabled: group.updating}" ng-click="updateGroup()" ng-bind="group.updating ? 'group_edit_submit_active' : 'group_edit_submit' | i18n" ng-disabled="group.updating"></button>
<div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md" ng-class="{disabled: group.updating}" ng-click="updateGroup()" ng-bind="group.updating ? 'group_edit_submit_active' : 'group_edit_submit' | i18n" ng-disabled="group.updating"></button>
</div>
</div>
</div>

153
app/partials/desktop/chat_modal.html

@ -1,106 +1,105 @@ @@ -1,106 +1,105 @@
<div class="chat_modal_wrap" my-modal-position>
<div class="chat_modal_wrap md_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$close()"><i></i></a>
<div class="modal-body">
<div class="user_modal_photo_profile_wrap">
<div class="user_modal_image_wrap pull-left">
<img
class="user_modal_image"
my-load-thumb
watch="true"
thumb="chatFull.thumb"
/>
<div class="md_modal_head">
<div class="md_modal_title_wrap">
<div class="md_modal_actions_wrap clearfix">
<a class="md_modal_action md_modal_action_close" ng-click="$close()" my-i18n="modal_close"></a>
<a class="md_modal_action" ng-if="chatFull.chat._ != 'chatForbidden' &amp;&amp; !chatFull.chat.left" ng-click="editTitle()" my-i18n="modal_edit"></a>
</div>
<div class="md_modal_title" my-i18n="group_modal_info"></div>
</div>
<div class="chat_modal_info_wrap clearfix">
<h4 class="chat_modal_header" ng-bind-html="chatFull.chat.rTitle"></h4>
<p class="chat_modal_members_count" ng-if="chatFull.chat.participants_count > 0">
<div class="peer_modal_profile_wrap clearfix">
<div class="peer_modal_photo_wrap pull-left" ng-switch="photo.updating">
<div ng-switch-when="true" class="peer_modal_photo md_photo_loading loading_dots">
<i></i><i></i><i></i>
</div>
<a ng-switch-default ng-click="openPhoto(chatFull.chat_photo.id, {p: -chatFull.chat.id})" class="peer_modal_photo" my-peer-photolink="::-chatFull.chat.id" img-class="peer_modal_photo" no-open="true" watch="true" ng-class="{disabled: !chatFull.chat.photo.photo_small}" ng-disabled="!chatFull.chat.photo.photo_small"></a>
</div>
<div class="peer_modal_profile">
<div class="peer_modal_profile_name" ng-bind-html="chatFull.chat.rTitle"></div>
<div class="peer_modal_profile_description" ng-if="chatFull.chat.participants_count > 0">
<ng-pluralize count="chatFull.chat.participants_count"
when="group_modal_pluralize_participants">
when="group_modal_pluralize_participants">
</ng-pluralize>
</p>
<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()" my-i18n="group_modal_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()" my-i18n="group_modal_return"></button>
<button ng-if="chatFull.chat._ == 'chatForbidden' || chatFull.chat.left" class="btn btn-danger chat_modal_delete_btn" ng-click="flushHistory()" my-i18n="group_modal_menu_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" />
<my-i18n msgid="group_modal_update_photo"></my-i18n>
</span>
<span ng-if="photo.updating" class="btn btn-primary chat_modal_main_btn disabled" disabled>
<my-i18n msgid="group_modal_update_active"></my-i18n><span my-loading-dots></span>
</span>
<div class="dropdown chat_modal_other_btn" ng-if="chatFull.chat._ != 'chatForbidden' &amp;&amp; !chatFull.chat.left" dropdown>
<button class="btn btn-link dropdown-toggle" dropdown-toggle>
<my-i18n msgid="group_modal_menu_more"></my-i18n>
<i class="icon icon-caret"></i>
</button>
<ul class="dropdown-menu">
<li ng-if="chatFull.thumb.location">
<a ng-click="deletePhoto()" my-i18n="group_modal_menu_delete_photo"></a>
</li>
<li>
<a ng-click="editTitle()" my-i18n="group_modal_menu_edit_group"></a>
</li>
<li>
<a ng-click="leaveGroup()" my-i18n="group_modal_menu_leave_group"></a>
</li>
<li>
<a ng-click="flushHistory()" my-i18n="group_modal_menu_delete_chat"></a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="md_modal_split_actions_wrap">
<div class="md_modal_split_actions">
<div class="md_modal_split_action">
<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" title="{{'group_modal_update_photo' | i18n}}" />
<i class="md_modal_split_action_camera"></i>
</div>
</div>
</div>
<div class="md_modal_body">
<div class="md_modal_sections">
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_link" ng-if="chatFull.chat._ != 'chatForbidden'">
<i class="md_modal_section_icon md_modal_section_icon_person"></i>
<div class="md_modal_section_link_wrap" ng-switch="chatFull.chat.left">
<div class="modal_section">
<h3 class="modal_section_header" my-i18n="group_modal_settings"></h3>
<div class="modal_section_body">
<a ng-switch-when="true" class="md_modal_section_link" ng-click="returnToGroup()" my-i18n="group_modal_return"></a>
<a ng-switch-default class="md_modal_section_link" ng-click="inviteToGroup()" my-i18n="group_modal_add_member"></a>
</div>
</div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_toggle">
<i class="md_modal_section_icon md_modal_section_icon_notification"></i>
<a class="md_modal_section_toggle_wrap tg_checkbox" ng-click="settings.notifications = !settings.notifications" ng-class="settings.notifications ? 'tg_checkbox_on' : ''">
<span class="icon icon-checkbox-outer"><i class="icon-checkbox-inner"></i></span>
<span class="tg_checkbox_label" my-i18n="group_modal_notifications"></span>
</a>
</div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_link">
<i class="md_modal_section_icon md_modal_section_icon_more"></i>
<div class="tg_form_group">
<a class="tg_checkbox" ng-click="settings.notifications = !settings.notifications" ng-class="settings.notifications ? 'tg_checkbox_on' : ''">
<span class="icon icon-checkbox-outer"><i class="icon-checkbox-inner"></i></span>
<span class="tg_checkbox_label" my-i18n="group_modal_notifications"></span>
</a>
<div class="md_modal_section_link_wrap">
<a class="md_modal_section_link" ng-click="flushHistory()" my-i18n="group_modal_menu_delete_chat"></a>
</div>
</div>
</div>
<div class="modal_section">
<h3 class="modal_section_header" my-i18n="group_modal_members"></h3>
<div class="modal_section_body">
<div ng-if="chatFull.chat._ != 'chatForbidden' &amp;&amp; !chatFull.chat.left">
<div class="md_modal_section_splitter" ng-if="chatFull.participants.participants.length > 0"></div>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_peers">
<i class="md_modal_section_icon md_modal_section_icon_people"></i>
<div class="md_modal_section_peers_wrap">
<div class="chat_modal_members_list">
<div class="md_modal_list_peer_wrap clearfix" ng-repeat="participant in chatFull.participants.participants | orderBy:'-user.sortStatus'">
<div class="chat_modal_participant_wrap clearfix" ng-repeat="participant in chatFull.participants.participants | orderBy:'-user.sortStatus'">
<a ng-if="participant.canKick" ng-click="kickFromGroup(participant.user_id)" class="chat_modal_participant_kick pull-right" my-i18n="group_modal_members_kick"></a>
<a ng-if="participant.canLeave" ng-click="leaveGroup()" class="md_modal_list_peer_action pull-right" my-i18n="group_modal_menu_leave"></a>
<a ng-if="participant.canKick" ng-click="kickFromGroup(participant.user_id)" class="md_modal_list_peer_action pull-right" my-i18n="group_modal_members_kick"></a>
<a class="chat_modal_participant_photo pull-left" my-user-photolink="participant.user_id" img-class="chat_modal_participant_photo" status="true"></a>
<a class="md_modal_list_peer_photo pull-left" my-peer-photolink="::participant.user_id" img-class="md_modal_list_peer_photo"></a>
<div class="chat_modal_participant_name">
<a my-user-link="participant.user_id"></a>
<div class="md_modal_list_peer_name">
<a class="md_modal_list_peer_name" my-user-link="participant.user_id"></a>
</div>
<div class="chat_modal_participant_status" my-user-status="::participant.user_id"></div>
<div class="md_modal_list_peer_description" my-user-status="::participant.user_id"></div>
</div>
</div>
<div class="chat_modal_members_forbidden" ng-if="chatFull.chat._ == 'chatForbidden' || chatFull.chat.left" my-i18n="group_modal_members_unavailable"></div>
</div>
</div>
</div>
</div>
</div>

18
app/partials/desktop/confirm_modal.html

@ -1,8 +1,6 @@ @@ -1,8 +1,6 @@
<div class="confirm_modal_wrap" my-modal-position>
<div class="confirm_modal_wrap md_simple_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$dismiss()"><i></i></a>
<div class="modal-body">
<div class="md_simple_modal_body">
<div class="confirm_modal_description" ng-switch="type">
<span ng-switch-when="LOGOUT" my-i18n="confirm_modal_logout"></span>
@ -17,6 +15,7 @@ @@ -17,6 +15,7 @@
</span>
<span ng-switch-when="FILE_CLIPBOARD_PASTE" my-i18n="confirm_modal_clipboard_file_send"></span>
<span ng-switch-when="MESSAGE_DELETE" my-i18n="confirm_modal_message_delete"></span>
<span ng-switch-when="PHOTO_DELETE" my-i18n="confirm_modal_photo_delete"></span>
<span ng-switch-when="CONTACTS_IMPORT_PERFORM" my-i18n="confirm_modal_contacts_import"></span>
<div ng-switch-when="LOGIN_PHONE_CORRECT">
<my-i18n msgid="confirm_modal_login_phone_correct"></my-i18n>
@ -47,16 +46,17 @@ @@ -47,16 +46,17 @@
</div>
<div class="modal-footer">
<a class="btn btn-link" ng-click="$dismiss()" ng-switch="type">
<span ng-switch-default my-i18n="modal_cancel"></span>
</a>
<button type="button" class="btn btn-primary" ng-switch="type" ng-click="$close()" my-focused>
<div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()">
<span my-i18n="modal_cancel"></span>
</button>
<button class="btn btn-md" ng-switch="type" ng-click="$close()" my-focused >
<span ng-switch-when="LOGOUT" my-i18n="confirm_modal_logout_submit"></span>
<span ng-switch-when="HISTORY_FLUSH" my-i18n="confirm_modal_history_flush_submit"></span>
<span ng-switch-when="FILES_CLIPBOARD_PASTE" my-i18n="confirm_modal_clipboard_files_send_submit"></span>
<span ng-switch-when="FILE_CLIPBOARD_PASTE" my-i18n="confirm_modal_clipboard_file_send_submit"></span>
<span ng-switch-when="MESSAGE_DELETE" my-i18n="confirm_modal_message_delete_submit"></span>
<span ng-switch-when="PHOTO_DELETE" my-i18n="confirm_modal_photo_delete_submit"></span>
<span ng-switch-when="FORWARD_PEER" my-i18n="confirm_modal_forward_message_submit"></span>
<span ng-switch-when="PHOTO_SHARE_PEER" my-i18n="confirm_modal_share_photo_submit"></span>
<span ng-switch-when="VIDEO_SHARE_PEER" my-i18n="confirm_modal_share_video_submit"></span>

71
app/partials/desktop/contacts_modal.html

@ -1,33 +1,34 @@ @@ -1,33 +1,34 @@
<div class="contacts_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$dismiss()"><i></i></a>
<div class="modal-body">
<div class="contacts_modal_header">
<div class="contacts_modal_edit_wrap" ng-if="!action || action == 'edit'" ng-switch="action">
<a ng-switch-when="edit" class="contacts_modal_edit_link" ng-click="toggleEdit(false)" my-i18n="contacts_modal_edit_cancel"></a>
<a ng-switch-default class="contacts_modal_edit_link" ng-click="toggleEdit(true)" my-i18n="contacts_modal_edit_list"></a>
<div class="contacts_modal_wrap md_modal_wrap" my-modal-position>
<div class="md_modal_head md_modal_head_simple">
<div class="md_modal_title_wrap">
<div class="md_modal_actions_wrap clearfix">
<a class="md_modal_action md_modal_action_close" ng-if="action != 'edit'" ng-click="$dismiss()" my-i18n="modal_close"></a>
<a class="md_modal_action" ng-if="action == 'edit'" class="contacts_modal_edit_link" ng-click="toggleEdit(false)" my-i18n="contacts_modal_edit_cancel"></a>
<a class="md_modal_action" ng-if="!action" ng-click="toggleEdit(true)" my-i18n="contacts_modal_edit_list"></a>
</div>
<h4 class="contacts_modal_title" ng-switch="action">
<div ng-switch-when="new_group" ng-switch="selectedCount > 0">
<span ng-switch-when="true">
<ng-pluralize count="selectedCount" when="contacts_modal_pluralize_new_group_members">
</ng-pluralize>
</span>
<span ng-switch-default my-i18n="group_create_contacts_modal_title"></span>
</div>
<span ng-switch-default my-i18n="contacts_modal_title"></span>
</h4>
</div>
<div class="md_modal_title" ng-switch="action">
<div ng-switch-when="new_group" ng-switch="selectedCount > 0">
<span ng-switch-when="true">
<ng-pluralize count="selectedCount" when="contacts_modal_pluralize_new_group_members">
</ng-pluralize>
</span>
<span ng-switch-default my-i18n="group_create_contacts_modal_title"></span>
</div>
<span ng-switch-default my-i18n="contacts_modal_title"></span>
</div>
</div>
<div class="md_modal_body">
<div class="contacts_modal_search">
<input class="form-control contacts_modal_search_field no_outline" my-focused type="search" placeholder="{{'modal_search' | i18n}}" ng-model="search.query"/>
<a class="contacts_modal_search_clear" ng-click="search.query = ''" ng-show="search.query.length"></a>
<a class="im_dialogs_search_clear" ng-click="search.query = ''" ng-show="search.query.length">
<i class="im_dialogs_search_clear"></i>
</a>
</div>
<div my-contacts-list class="contacts_modal_col">
<div class="contacts_wrap nano" my-infinite-scroller>
@ -42,11 +43,9 @@ @@ -42,11 +43,9 @@
<li class="contacts_modal_contact_wrap clearfix" ng-repeat="contact in contacts | orderBy:'user.sortName' | limitTo: slice.limit track by contact.userID" ng-class="{active: selectedContacts[contact.userID], disabled: disabledContacts[contact.userID]}">
<a class="contacts_modal_contact" ng-click="contactSelect(contact.userID)">
<i ng-if="multiSelect" class="icon icon-contact-tick"></i>
<div class="contacts_modal_contact_photo pull-left" my-user-photolink="contact.userID" status="true" img-class="contacts_modal_contact_photo"></div>
<div class="contacts_modal_contact_name" ng-bind-html="contact.user.rFullName"></div>
<div class="contacts_modal_contact_status" ng-switch="contact.found">
<div class="md_modal_list_peer_photo pull-left" my-peer-photolink="::contact.userID" img-class="md_modal_list_peer_photo"></div>
<div class="md_modal_list_peer_name" ng-bind-html="contact.user.rFullName"></div>
<div class="md_modal_list_peer_description" ng-switch="contact.found">
<span ng-switch-when="true" ng-bind="'@' + contact.user.username"></span>
<span ng-switch-default my-user-status="::contact.userID"></span>
</div>
@ -63,18 +62,24 @@ @@ -63,18 +62,24 @@
</div>
<div class="modal-footer contacts_modal_panel" ng-switch="action">
<div class="md_modal_footer clearfix" ng-switch="action">
<div ng-switch-when="new_group" class="pull-right">
<button class="btn btn-link" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-primary" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" ng-click="submitSelected()" type="submit" my-i18n="modal_next"></button>
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" ng-click="submitSelected()" type="submit" my-i18n="modal_next"></button>
</div>
<button ng-switch-when="select" class="btn btn-primary" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" ng-click="submitSelected()" type="submit" my-i18n="modal_next"></button>
<button ng-switch-when="edit" class="btn btn-danger" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" ng-click="deleteSelected()">
<button ng-switch-when="select" class="btn btn-md pull-right" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" ng-click="submitSelected()" type="submit" my-i18n="modal_next"></button>
<button ng-switch-when="edit" class="btn btn-md btn-md-danger pull-right" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" ng-click="deleteSelected()">
<my-i18n msgid="contacts_modal_edit_delete"></my-i18n>
<strong ng-bind="selectedCount"></strong>
</button>
<button ng-switch-default class="btn btn-link" ng-click="importContact()" my-i18n="contacts_modal_new_contact"></button>
<div ng-switch-default class="text-center">
<button class="btn btn-md" ng-click="importContact()" my-i18n="contacts_modal_new_contact"></button>
</div>
</div>
</div>

9
app/partials/desktop/dialog.html

@ -13,14 +13,7 @@ @@ -13,14 +13,7 @@
></i>
</div>
<div class="im_dialog_photo pull-left">
<img
class="im_dialog_photo"
my-load-thumb
watch="true"
thumb="dialogMessage.peerPhoto"
/>
</div>
<div class="im_dialog_photo pull-left" my-peer-photolink="::dialogMessage.peerID" img-class="im_dialog_photo" watch="true"></div>
<div class="im_dialog_message_wrap">

12
app/partials/desktop/document_modal.html

@ -16,9 +16,15 @@ @@ -16,9 +16,15 @@
</a>
</div>
<div class="media_modal_info_wrap pull-left">
<a class="media_modal_author" my-user-link="document.user_id" user-watch="true"></a>
<span class="media_modal_date" ng-bind="document.date | dateOrTime :true"></span>
<div class="media_modal_info_wrap pull-left" ng-switch="messageID > 0">
<a class="media_modal_author_photo pull-left" my-peer-photolink="document.user_id" img-class="media_modal_author_photo" watch="true"></a>
<div class="media_modal_author_name">
<a class="media_modal_author" my-user-link="document.user_id" user-watch="true"></a>
</div>
<div class="media_modal_date">
<a ng-switch-when="true" class="media_modal_date" ng-click="goToMessage()" ng-bind="document.date | dateOrTime :true"></a>
<span ng-switch-default ng-bind="document.date | dateOrTime :true"></span>
</div>
</div>
<div class="media_modal_title_wrap" ng-bind="document.file_name"></div>

31
app/partials/desktop/edit_contact_modal.html

@ -1,30 +1,33 @@ @@ -1,30 +1,33 @@
<div class="import_modal_wrap" my-modal-position>
<div class="md_simple_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$dismiss()"><i></i></a>
<div class="modal-body">
<div class="md_simple_modal_body">
<form class="modal_simple_form" ng-submit="doImport()">
<h4 my-i18n="contact_edit_modal_title"></h4>
<div class="form-group">
<span class="form-control uneditable-input input-sm disabled" disabled ng-bind="importContact.phone | phoneNumber"></span>
<div class="md-input-group md-input-disabled" my-labeled-input>
<label class="md-input-label" my-i18n="contact_import_modal_phone"></label>
<span class="md-input" ng-bind="importContact.phone | phoneNumber"></span>
</div>
<div class="form-group">
<input class="form-control input-sm" my-focused type="text" placeholder="{{'contact_edit_modal_first_name' | i18n}}" ng-model="importContact.first_name"/>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="contact_edit_modal_first_name"></label>
<input class="md-input" my-focused type="text" ng-model="importContact.first_name" />
</div>
<div class="form-group">
<input class="form-control input-sm" type="text" placeholder="{{'contact_edit_modal_last_name' | i18n}}" ng-model="importContact.last_name"/>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="contact_edit_modal_last_name"></label>
<input class="md-input" type="text" ng-model="importContact.last_name" />
</div>
</form>
</div>
<div class="modal-footer">
<a class="btn btn-link" ng-click="$dismiss()" my-i18n="modal_cancel"></a>
<button class="btn btn-primary" ng-class="{disabled: progress.enabled}" ng-click="doImport()" ng-bind="progress.enabled ? 'contact_edit_modal_submit_active' : 'contact_edit_modal_submit'| i18n" ng-disabled="progress.enabled"></button>
<div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md" ng-class="{disabled: progress.enabled}" ng-click="doImport()" ng-bind="progress.enabled ? 'contact_edit_modal_submit_active' : 'contact_edit_modal_submit'| i18n" ng-disabled="progress.enabled"></button>
</div>
</div>
</div>

18
app/partials/desktop/error_modal.html

@ -1,10 +1,8 @@ @@ -1,10 +1,8 @@
<div class="error_modal_wrap" my-modal-position>
<div class="error_modal_wrap md_simple_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$close()"><i></i></a>
<div class="md_simple_modal_body">
<div class="modal-body">
<h4 ng-if="error" class="modal_simple_header" ng-switch="error.type">
<h4 ng-if="error" class="md_simple_header" ng-switch="error.type">
<span ng-switch-when="MEDIA_TYPE_NOT_SUPPORTED" my-i18n="error_modal_media_not_supported_title"></span>
<span ng-switch-default ng-switch="error.code">
<span ng-switch-when="400" my-i18n="error_modal_bad_request_title"></span>
@ -16,7 +14,7 @@ @@ -16,7 +14,7 @@
<span ng-switch-default my-i18n="error_modal_internal_title"></span>
</span>
</h4>
<h4 ng-if="!error" class="modal_simple_header" ng-switch="title.length > 0">
<h4 ng-if="!error" class="md_simple_header" ng-switch="title.length > 0">
<span ng-switch-when="true" ng-bind="title"></span>
<span ng-switch-default my-i18n="error_modal_alert"></span>
</h4>
@ -57,7 +55,7 @@ @@ -57,7 +55,7 @@
Result: {{error.originalError ? error.originalError : (error.stack ? (error.name || '') + ' ' + (error.description || error.message) : error)}}
Stack: {{error.originalError.stack || error.stack}}</textarea>
<div ng-switch-default>
<a href="" ng-click="error.detailsShown = true" my-i18n="error_modal_tech_details"></a>
<a class="error_modal_details_link" href="" ng-click="error.detailsShown = true" my-i18n="error_modal_tech_details"></a>
</div>
</div>
@ -65,4 +63,10 @@ Stack: {{error.originalError.stack || error.stack}}</textarea> @@ -65,4 +63,10 @@ Stack: {{error.originalError.stack || error.stack}}</textarea>
</div>
<div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()">
<span my-i18n="modal_ok"></span>
</button>
</div>
</div>

30
app/partials/desktop/im.html

@ -21,7 +21,9 @@ @@ -21,7 +21,9 @@
</div>
<div class="im_dialogs_search">
<input class="form-control im_dialogs_search_field no_outline" type="search" placeholder="{{'modal_search' | i18n}}" ng-model="search.query"/>
<a class="im_dialogs_search_clear" ng-click="searchClear()" ng-show="search.query.length"></a>
<a class="im_dialogs_search_clear" ng-click="searchClear()" ng-show="search.query.length">
<i class="im_dialogs_search_clear"></i>
</a>
</div>
<div class="im_dialogs_tabs_wrap">
@ -57,7 +59,8 @@ @@ -57,7 +59,8 @@
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" ng-repeat="contact in contacts | orderBy:'user.sortName' track by contact.userID" ng-class="{active: curDialog.peerID == contact.userID}">
<a class="im_dialog" ng-mousedown="dialogSelect(contact.peerString)">
<div class="im_dialog_photo pull-left" my-user-photolink="contact.userID" img-class="im_dialog_photo"></div>
<div class="im_dialog_photo pull-left" my-peer-photolink="contact.userID" img-class="im_dialog_photo" watch="true"></div>
<div class="im_dialog_message_wrap">
<div class="im_dialog_peer">
<span class="im_dialog_user" my-user-link="contact.userID"></span>
@ -76,7 +79,7 @@ @@ -76,7 +79,7 @@
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" ng-repeat="foundUser in foundUsers track by foundUser.userID" ng-class="{active: curDialog.peerID == foundUser.userID}">
<a class="im_dialog" ng-mousedown="dialogSelect(foundUser.peerString)">
<div class="im_dialog_photo pull-left" my-user-photolink="foundUser.userID" img-class="im_dialog_photo"></div>
<div class="im_dialog_photo pull-left" my-peer-photolink="foundUser.userID" img-class="im_dialog_photo" watch="true"></div>
<div class="im_dialog_message_wrap">
<div class="im_dialog_peer">
<span class="im_dialog_user" my-user-link="foundUser.userID"></span>
@ -226,23 +229,12 @@ @@ -226,23 +229,12 @@
<div class="im_send_form_wrap1">
<div class="im_send_form_wrap clearfix" ng-controller="AppImSendController">
<div class="pull-right im_panel_peer_photo" ng-click="showPeerInfo()">
<img
class="im_panel_peer_photo"
my-load-thumb
watch="true"
thumb="historyPeer.photo"
/>
<a class="pull-right im_panel_peer_photo" my-peer-photolink="historyPeer.id" img-class="im_panel_peer_photo" watch="true">
<i class="icon im_panel_peer_online" ng-show="historyPeer.id > 0 &amp;&amp; historyPeer.data.status._ == 'userStatusOnline'"></i>
</div>
<div class="pull-left im_panel_own_photo">
<img
class="im_panel_own_photo"
my-load-thumb
watch="true"
thumb="ownPhoto"
/>
</div>
</a>
<div class="pull-left im_panel_own_photo" my-peer-photolink="ownID" img-class="im_panel_own_photo" watch="true"></div>
<form my-send-form draft-message="draftMessage" class="im_send_form" ng-class="{im_send_form_empty: !draftMessage.text.length}">
<div class="im_send_field_wrap">

32
app/partials/desktop/import_contact_modal.html

@ -1,31 +1,33 @@ @@ -1,31 +1,33 @@
<div class="import_modal_wrap" my-modal-position>
<div class="md_simple_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$dismiss()"><i></i></a>
<div class="modal-body">
<div class="md_simple_modal_body">
<form class="modal_simple_form" ng-submit="doImport()">
<h4 my-i18n="contact_import_modal_title"></h4>
<div class="form-group">
<input class="form-control input-sm" my-focused type="text" placeholder="{{'contact_import_modal_phone' | i18n}}" ng-model="importContact.phone"/>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="contact_import_modal_phone"></label>
<input class="md-input" my-focused type="text" ng-model="importContact.phone" />
</div>
<div class="form-group">
<input class="form-control input-sm" type="text" placeholder="{{'contact_edit_modal_first_name' | i18n}}" ng-model="importContact.first_name"/>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="contact_edit_modal_first_name"></label>
<input class="md-input" type="text" ng-model="importContact.first_name" />
</div>
<div class="form-group">
<input class="form-control input-sm" type="text" placeholder="{{'contact_edit_modal_last_name' | i18n}}" ng-model="importContact.last_name"/>
<div class="md-input-group" my-labeled-input>
<label class="md-input-label" my-i18n="contact_edit_modal_last_name"></label>
<input class="md-input" type="text" ng-model="importContact.last_name" />
</div>
</form>
</div>
<div class="modal-footer">
<a class="btn btn-link pull-left" ng-if="phonebookAvailable" ng-click="importPhonebook()" my-i18n="contact_import_modal_phonebook"></a>
<a class="btn btn-link" ng-click="$dismiss()" my-i18n="modal_cancel"></a>
<button class="btn btn-primary" ng-class="{disabled: progress.enabled}" ng-click="doImport()" ng-bind="progress.enabled ? 'contact_import_modal_submit_active' : 'contact_import_modal_submit' | i18n" ng-disabled="progress.enabled"></button>
<div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md" ng-class="{disabled: progress.enabled}" ng-click="doImport()" ng-bind="progress.enabled ? 'contact_import_modal_submit_active' : 'contact_import_modal_submit' | i18n" ng-disabled="progress.enabled"></button>
</div>
</div>
</div>

2
app/partials/desktop/message.html

@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
<i ng-if="::historyMessage.unread || historyMessage.pending || false" class="icon-message-status" ng-class="{'icon-message-status-unread': historyMessage.unread, 'icon-message-status-pending': historyMessage.pending}" ng-show="!historyMessage.error"></i>
<a class="im_message_from_photo pull-left" my-user-photolink="historyMessage.from_id" img-class="im_message_from_photo"></a>
<a class="im_message_from_photo pull-left" my-peer-photolink="::historyMessage.from_id" img-class="im_message_from_photo"></a>
<div class="im_message_meta pull-right text-right">
<i class="icon-message-status-tick"></i>

2
app/partials/desktop/message_attach_contact.html

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<div>
<a ng-if="historyMessage.media.user_id > 0" class="im_message_contact_photo pull-left" my-user-photolink="historyMessage.media.user_id" img-class="im_message_contact_photo" user-override="historyMessage.media"></a>
<a ng-if="historyMessage.media.user_id > 0" class="im_message_contact_photo pull-left" my-peer-photolink="historyMessage.media.user_id" img-class="im_message_contact_photo" user-override="historyMessage.media"></a>
<div class="im_message_contact_name" ng-switch="historyMessage.media.user_id > 0">
<a ng-switch-when="true" my-user-link="historyMessage.media.user_id" user-override="historyMessage.media"></a>
<span ng-switch-default ng-bind-html="::historyMessage.media.rFullName"></span>

2
app/partials/desktop/message_attach_photo.html

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<a class="im_message_photo_thumb" href="" ng-click="openPhoto(historyMessage.media.photo.id, historyMessage.id)" ng-style="::{width: historyMessage.media.photo.thumb.width + 'px'}" ng-mouseover="preloadPhoto(historyMessage.media.photo.id)">
<a class="im_message_photo_thumb" ng-click="openPhoto(historyMessage.media.photo.id, {m: historyMessage.id})" ng-style="::{width: historyMessage.media.photo.thumb.width + 'px'}" ng-mouseover="preloadPhoto(historyMessage.media.photo.id)">
<img
class="im_message_photo_thumb"
my-load-thumb

2
app/partials/desktop/message_attach_video.html

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<div class="im_message_video im_message_document_thumbed">
<a class="im_message_video_thumb" href="" ng-click="videoOpen()" ng-style="::{width: video.thumb.width + 'px'}">
<a class="im_message_video_thumb" ng-click="videoOpen()" ng-style="::{width: video.thumb.width + 'px'}">
<span class="im_message_video_duration" ng-bind="::video.duration | duration"></span>
<i class="icon icon-videoplay"></i>
<img

50
app/partials/desktop/peer_select.html

@ -1,34 +1,37 @@ @@ -1,34 +1,37 @@
<div class="peer_select_modal_wrap" my-modal-position>
<div class="peer_select_modal_wrap md_modal_wrap" my-modal-position>
<a class="modal-close-button visible-xs" ng-click="$dismiss()"><i></i></a>
<div class="md_modal_head md_modal_head_simple">
<div class="md_modal_title_wrap">
<div class="md_modal_actions_wrap clearfix">
<a class="md_modal_action md_modal_action_close" ng-click="$dismiss()" my-i18n="modal_close"></a>
</div>
</div>
<div class="md_modal_title" my-i18n="conversations_modal_forward_title"></div>
</div>
<div class="modal-body">
<div class="md_modal_body">
<div class="im_dialogs_modal_col_wrap" ng-controller="AppImDialogsController" my-dialogs>
<div class="im_dialogs_panel">
<div class="im_dialogs_search">
<input my-focused class="form-control im_dialogs_search_field no_outline" type="search" placeholder="{{'modal_search' | i18n}}" ng-model="search.query"/>
<a class="im_dialogs_search_clear" ng-click="search.query = ''" ng-show="search.query.length"></a>
<a class="im_dialogs_search_clear" ng-click="search.query = ''" ng-show="search.query.length">
<i class="im_dialogs_search_clear"></i>
</a>
</div>
</div>
<div my-dialogs-list modal="true" class="im_dialogs_modal_col">
<div class="im_dialogs_wrap nano">
<div class="im_dialogs_scrollable_wrap nano-content">
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in dialogs track by dialogMessage.peerID"></li>
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in dialogs track by dialogMessage.peerID" ng-class="{active: selectedPeers[dialogMessage.peerID] !== undefined}"></li>
</ul>
<div class="im_dialogs_contacts_wrap" ng-show="contacts.length > 0">
<h5 my-i18n="conversation_select_modal_contacts"></h5>
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" ng-repeat="contact in contacts | orderBy:'user.sortName' track by contact.userID" ng-class="{active: curDialog.peerID == contact.userID}">
<li class="im_dialog_wrap" ng-repeat="contact in contacts | orderBy:'user.sortName' track by contact.userID" ng-class="{active: selectedPeers[contact.userID] !== undefined}">
<a class="im_dialog" ng-click="dialogSelect(contact.peerString)">
<div class="im_dialog_photo pull-left">
<img
class="im_dialog_photo"
my-load-thumb
thumb="contact.userPhoto"
/>
</div>
<div class="im_dialog_photo pull-left" my-peer-photolink="::contact.userID" img-class="im_dialog_photo"></div>
<div class="im_dialog_message_wrap">
<div class="im_dialog_peer">
<span class="im_dialog_user" ng-bind-html="contact.user.rFullName"></span>
@ -48,4 +51,25 @@ @@ -48,4 +51,25 @@
</div>
<div class="md_modal_footer peer_select_modal_footer clearfix" ng-if="multiSelect">
<button class="btn btn-md pull-right" ng-click="submitSelected()" ng-class="{disabled: !selectedCount}" ng-disabled="!selectedCount" my-i18n="conversations_modal_forward_submit"></button>
<div class="peer_select_modal_recipients_wrap" ng-switch="!selectedCount">
<span class="peer_select_modal_recipients_empty" ng-switch-when="true" my-i18n="conversations_modal_select_recipients"></span>
<span ng-switch-default>
<span class="peer_select_modal_recipients_name" my-i18n="conversations_modal_recipients"></span>
<span class="peer_select_modal_recipients_list" ng-switch="selectedCount" my-i18n>
<span ng-switch-when="1" my-i18n-format="conversation_one_selected"></span>
<span ng-switch-when="2" my-i18n-format="conversation_two_selected"></span>
<span ng-switch-default my-i18n-format="conversation_many_selected"></span>
<my-i18n-param name="name1"><span class="peer_select_modal_recipient" ng-bind-html="selectedPeers[selectedPeerIDs[0]][selectedPeerIDs[0] > 0 ? 'rFullName' : 'rTitle']"></span></my-i18n-param>
<my-i18n-param name="name2"><span class="peer_select_modal_recipient" ng-bind-html="selectedPeers[selectedPeerIDs[1]][selectedPeerIDs[1] > 0 ? 'rFullName' : 'rTitle']"></span></my-i18n-param>
<my-i18n-param name="count">{{selectedCount - 2}}</my-i18n-param>
</span>
</span>
</div>
</div>
</div>

13
app/partials/desktop/photo_modal.html

@ -22,10 +22,15 @@ @@ -22,10 +22,15 @@
</a>
</div>
<div class="media_modal_info_wrap" ng-switch="messageID > 0">
<a class="media_modal_author" my-user-link="photo.user_id" user-watch="true"></a>
<a ng-switch-when="true" ng-click="goToMessage()" class="media_modal_date" ng-bind="photo.date | dateOrTime :true"></a>
<span ng-switch-default class="media_modal_date" ng-bind="photo.date | dateOrTime :true"></span>
<div class="media_modal_info_wrap pull-left" ng-switch="messageID > 0">
<a class="media_modal_author_photo pull-left" my-peer-photolink="photo.user_id" img-class="media_modal_author_photo" watch="true"></a>
<div class="media_modal_author_name">
<a class="media_modal_author" my-user-link="photo.user_id" user-watch="true"></a>
</div>
<div class="media_modal_date">
<a ng-switch-when="true" class="media_modal_date" ng-click="goToMessage()" ng-bind="photo.date | dateOrTime :true"></a>
<span ng-switch-default ng-bind="photo.date | dateOrTime :true"></span>
</div>
</div>

23
app/partials/desktop/profile_edit_modal.html

@ -1,27 +1,28 @@ @@ -1,27 +1,28 @@
<div class="profile_edit_modal_wrap" my-modal-position>
<div class="md_simple_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$dismiss()"><i></i></a>
<div class="modal-body">
<div class="md_simple_modal_body">
<form class="modal_simple_form" ng-submit="updateProfile()">
<h4 my-i18n="profile_edit_modal_title"></h4>
<div class="form-group import_modal_field_wrap" ng-class="{'has-error': error.field == 'first_name'}">
<input class="form-control input-sm" my-focused type="text" placeholder="{{'profile_edit_first_name' | i18n}}" ng-model="profile.first_name" name="first_name"/>
<div class="md-input-group" ng-class="{'has-error': error.field == 'first_name'}" my-labeled-input>
<label class="md-input-label" my-i18n="profile_edit_first_name"></label>
<input class="md-input" my-focused type="text" ng-model="profile.first_name" />
</div>
<div class="form-group import_modal_field_wrap" ng-class="{'has-error': error.field == 'last_name'}">
<input class="form-control input-sm" type="text" placeholder="{{'profile_edit_last_name' | i18n}}" ng-model="profile.last_name"/>
<div class="md-input-group" ng-class="{'has-error': error.field == 'last_name'}" my-labeled-input>
<label class="md-input-label" my-i18n="profile_edit_last_name"></label>
<input class="md-input" type="text" ng-model="profile.last_name" />
</div>
</form>
</div>
<div class="modal-footer">
<a class="btn btn-link" ng-click="$dismiss()" my-i18n="modal_cancel"></a>
<button class="btn btn-primary" ng-class="{disabled: profile.updating}" ng-click="updateProfile()" ng-bind="profile.updating ? 'profile_edit_submit_active' : 'profile_edit_submit' | i18n" ng-disabled="profile.updating"></button>
<div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md" ng-class="{disabled: profile.updating}" ng-click="updateProfile()" ng-bind="profile.updating ? 'profile_edit_submit_active' : 'profile_edit_submit' | i18n" ng-disabled="profile.updating"></button>
</div>
</div>

212
app/partials/desktop/settings_modal.html

@ -1,144 +1,118 @@ @@ -1,144 +1,118 @@
<div class="settings_modal_wrap modal_content_wrap" my-modal-position>
<div class="settings_modal_wrap md_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$close()"><i></i></a>
<div class="md_modal_head">
<div class="md_modal_title_wrap">
<div class="md_modal_actions_wrap clearfix">
<a class="md_modal_action md_modal_action_close" ng-click="$close()" my-i18n="modal_close"></a>
<a class="md_modal_action" ng-click="editProfile()" my-i18n="modal_edit"></a>
</div>
<div class="md_modal_title" my-i18n="settings_modal_title"></div>
</div>
<div class="modal-body">
<div class="peer_modal_profile_wrap clearfix">
<div class="peer_modal_photo_wrap pull-left" ng-switch="photo.updating">
<div ng-switch-when="true" class="peer_modal_photo md_photo_loading loading_dots">
<i></i><i></i><i></i>
</div>
<a ng-switch-default ng-click="openPhoto(profile.photo.photo_id, {p: profile.id})" class="peer_modal_photo" my-peer-photolink="::profile.id" img-class="peer_modal_photo" watch="true" no-open="true" ng-class="{disabled: !profile.photo.photo_id}" ng-disabled="!profile.photo.photo_id"></a>
</div>
<div class="peer_modal_profile">
<div class="peer_modal_profile_name" ng-bind-html="profile.rFullName"></div>
<div class="peer_modal_profile_description" my-user-status="::profile.id"></div>
</div>
</div>
</div>
<div class="user_modal_photo_profile_wrap">
<div class="md_modal_split_actions_wrap">
<div class="md_modal_split_actions">
<div class="md_modal_split_action">
<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" title="{{'settings_modal_set_photo' | i18n}}" />
<i class="md_modal_split_action_camera"></i>
</div>
</div>
</div>
<a href="" ng-click="openPhoto(photo.id, -profile.id)" class="user_modal_image_wrap pull-left" ng-class="{disabled: !photo.id}">
<img
class="user_modal_image"
my-load-thumb
watch="true"
thumb="photo"
/>
</a>
<div class="md_modal_body">
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_number">
<i class="md_modal_section_icon md_modal_section_icon_phone"></i>
<div class="user_modal_info_wrap clearfix">
<h4 class="user_modal_header" ng-bind-html="profile.rFullName"></h4>
<p class="user_modal_status" my-user-status="::profile.id"></p>
<div class="user_modal_actions_wrap clearfix">
<span class="btn btn-primary user_modal_main_btn" ng-if="!photo.updating">
<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" />
<my-i18n msgid="settings_modal_set_photo"></my-i18n>
</span>
<span class="btn btn-primary user_modal_main_btn disabled" disabled ng-if="photo.updating">
<my-i18n msgid="settings_modal_photo_updating"></my-i18n>
<span my-loading-dots></span>
</span>
<div class="dropdown user_modal_other_btn" dropdown>
<button class="btn btn-link dropdown-toggle" dropdown-toggle>
<my-i18n msgid="settings_modal_menu_more"></my-i18n>
<i class="icon icon-caret"></i>
</button>
<ul class="dropdown-menu">
<li ng-if="photo.location">
<a ng-click="deletePhoto()" my-i18n="settings_modal_delete_photo"></a>
</li>
<li>
<a ng-click="editProfile()" my-i18n="settings_modal_edit_profile"></a>
</li>
<li>
<a ng-click="changeUsername()" my-i18n="settings_modal_edit_username"></a>
</li>
<li>
<a ng-click="terminateSessions()" my-i18n="settings_modal_terminate_sessions"></a>
</li>
</ul>
</div>
<div class="md_modal_section_param_wrap">
<div class="md_modal_section_param_value" ng-bind="profile.phone | phoneNumber"></div>
<div class="md_modal_section_param_name" my-i18n="user_modal_phone"></div>
</div>
<div class="md_modal_section_param_wrap">
<div class="md_modal_section_param_value" ng-switch="profile.username.length > 0">
<a ng-switch-when="true" class="settings_modal_username_link" ng-click="changeUsername()" ng-bind="'@' + profile.username"></a>
<a ng-switch-default ng-click="changeUsername()" my-i18n="settings_modal_empty_username_set"></a>
</div>
<div class="md_modal_section_param_name" my-i18n="user_modal_username"></div>
</div>
</div>
<div class="modal_section">
<h3 class="modal_section_header" my-i18n="user_modal_info"></h3>
<div class="modal_section_body">
<dl ng-if="profile.phone">
<dt><my-i18n msgid="user_modal_phone"></my-i18n>:</dt>
<dd ng-bind="profile.phone | phoneNumber"></dd>
</dl>
<dl>
<dt><my-i18n msgid="user_modal_username"></my-i18n>:</dt>
<dd ng-switch="profile.username.length > 0">
<a class="settings_modal_username_link" ng-switch-when="true" href="" ng-click="changeUsername()" ng-bind="'@' + profile.username"></a>
<a ng-switch-default href="" ng-click="changeUsername()" my-i18n="settings_modal_empty_username_set"></a>
</dd>
</dl>
<dl class="settings_modal_language" ng-controller="AppLangSelectController">
<dt><my-i18n msgid="settings_modal_language"></my-i18n>:</dt>
<dd>
<select class="form-control settings_modal_language_select" ng-change="localeSelect()" ng-model="form.locale">
<option ng-repeat="locale in ::supportedLocales" value="{{locale}}" ng-bind="langNames[locale]" ng-selected="locale == curLocale"></option>
</select>
</dd>
</dl>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_toggle">
<i class="md_modal_section_icon md_modal_section_icon_notification"></i>
<a class="md_modal_section_toggle_wrap tg_checkbox" ng-click="toggleDesktop()" ng-class="notify.desktop ? 'tg_checkbox_on' : ''">
<span class="icon icon-checkbox-outer"><i class="icon-checkbox-inner"></i></span>
<span class="tg_checkbox_label" my-i18n="settings_modal_notifications"></span>
</a>
<a class="md_modal_section_toggle_wrap tg_checkbox" ng-click="toggleSound()" ng-class="notify.volume ? 'tg_checkbox_on' : ''">
<span class="icon icon-checkbox-outer"><i class="icon-checkbox-inner"></i></span>
<span class="tg_checkbox_label" my-i18n="settings_modal_sound"></span>
</a>
<div class="md_modal_section_range_wrap tg_range_wrap" ng-show="notify.volume > 0">
<div my-slider slider-model="notify.volume"></div>
</div>
</div>
<div class="modal_section">
<h3 class="modal_section_header" my-i18n="settings_modal_settings"></h3>
<div class="modal_section_body">
<div class="tg_form_group">
<a class="tg_checkbox" ng-click="toggleDesktop()" ng-class="notify.desktop ? 'tg_checkbox_on' : ''">
<span class="icon icon-checkbox-outer"><i class="icon-checkbox-inner"></i></span>
<span class="tg_checkbox_label" my-i18n="settings_modal_notifications"></span>
</a>
<a class="tg_checkbox" ng-click="toggleSound()" ng-class="notify.volume ? 'tg_checkbox_on' : ''">
<span class="icon icon-checkbox-outer"><i class="icon-checkbox-inner"></i></span>
<span class="tg_checkbox_label" my-i18n="settings_modal_sound"></span>
</a>
<div class="tg_range_wrap" ng-show="notify.volume > 0">
<span class="icon icon-volume-outer" ng-class="'icon-volume-outer' + notify.volumeOf4()">
<i class="icon-volume-inner icon-volume-inner1"></i>
<i class="icon-volume-inner icon-volume-inner2"></i>
<i class="icon-volume-inner icon-volume-inner3"></i>
<i class="icon-volume-inner icon-volume-inner4"></i>
</span>
<div class="settings_volume_slider" my-slider slider-model="notify.volume"></div>
</div>
</div>
</div>
<div class="tg_form_group">
<a class="tg_radio" ng-click="toggleCtrlEnter(1)" ng-class="send.enter == 1 ? 'tg_radio_on' : ''">
<i class="icon icon-radio"></i>
<span my-i18n="settings_modal_enter_send_description_md"></span>
</a>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_radio">
<i class="md_modal_section_icon md_modal_section_icon_keyboard"></i>
<a class="tg_radio" ng-click="toggleCtrlEnter(0)" ng-class="send.enter == 0 ? 'tg_radio_on' : ''">
<i class="icon icon-radio"></i>
<span my-i18n="settings_modal_ctrl_enter_send_description_md"></span>
</a>
</div>
<div class="tg_radios_wrap">
<a class="md_modal_section_radio_wrap tg_radio" ng-click="toggleCtrlEnter(1)" ng-class="send.enter == 1 ? 'tg_radio_on' : ''">
<span class="icon icon-radio-outer"><i class="icon-radio"></i></span>
<span my-i18n="settings_modal_enter_send_description_md"></span>
</a>
<a class="md_modal_section_radio_wrap tg_radio" ng-click="toggleCtrlEnter(0)" ng-class="send.enter == 0 ? 'tg_radio_on' : ''">
<span class="icon icon-radio-outer"><i class="icon-radio"></i></span>
<span my-i18n="settings_modal_ctrl_enter_send_description_md"></span>
</a>
</div>
</div>
<div class="modal_section">
<h3 class="modal_section_header" my-i18n="settings_modal_about"></h3>
<div class="modal_section_body settings_about_section_body">
<div class="settings_external_services pull-right">
<a href="https://github.com/zhukov/webogram" target="_blank" title="{{'settings_modal_source_code_github' | i18n}}" class="settings_external_service"><i class="icon icon-github"></i></a>
<a href="https://twitter.com/telegram_web" target="_blank" title="{{'settings_modal_follow_us_twitter' | i18n}}" class="settings_external_service"><i class="icon icon-twitter"></i></a>
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_link">
<i class="md_modal_section_icon md_modal_section_icon_more"></i>
<div class="md_modal_section_select_wrap" ng-controller="AppLangSelectController">
<div class="dropdown md_modal_section_select" dropdown>
<button class="btn btn-link dropdown-toggle" dropdown-toggle ng-bind="langNames[curLocale]"></button>
<ul class="dropdown-menu dropdown-menu-to-up">
<li ng-repeat="locale in ::supportedLocales">
<a ng-click="localeSelect(locale)" ng-bind="langNames[locale]"></a>
</li>
</ul>
</div>
<p>
<a ng-click="openChangelog()" my-i18n="settings_modal_recent_updates">
<my-i18n-param name="version" ng-bind="version"></my-i18n-param>
</a>
</p>
<div class="md_modal_section_param_name" my-i18n="settings_modal_language"></div>
</div>
<div class="md_modal_section_link_wrap">
<a class="md_modal_section_link" ng-click="terminateSessions()" my-i18n="settings_modal_terminate_sessions"></a>
</div>
<div class="md_modal_section_link_wrap">
<a class="md_modal_section_link" ng-click="openChangelog()" my-i18n="settings_modal_about"></a>
</div>
</div>
</div>
</div>

146
app/partials/desktop/user_modal.html

@ -1,90 +1,100 @@ @@ -1,90 +1,100 @@
<div class="user_modal_wrap" my-modal-position>
<div class="user_modal_wrap md_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$close()"><i></i></a>
<div class="modal-body">
<div class="md_modal_head">
<div class="md_modal_title_wrap">
<div class="md_modal_actions_wrap clearfix">
<a class="md_modal_action md_modal_action_close" ng-click="$close()" my-i18n="modal_close"></a>
<a class="md_modal_action" ng-if="user._ == 'userContact'" ng-click="importContact(true)" my-i18n="modal_edit"></a>
</div>
<div class="md_modal_title" my-i18n="user_modal_contact_info"></div>
</div>
<div class="user_modal_photo_profile_wrap">
<div class="peer_modal_profile_wrap clearfix">
<div class="peer_modal_photo_wrap pull-left">
<a ng-click="openPhoto(user.photo.photo_id, {p: user.id})" class="peer_modal_photo" ng-class="{disabled: !user.photo.photo_id}" ng-disabled="!user.photo.photo_id" my-peer-photolink="::user.id" img-class="peer_modal_photo" no-open="true"></a>
</div>
<div class="peer_modal_profile">
<div class="peer_modal_profile_name" ng-bind-html="user.rFullName"></div>
<div class="peer_modal_profile_description" my-user-status="::user.id"></div>
</div>
</div>
</div>
<a href="" ng-click="openPhoto(userPhoto.id, -user.id)" class="user_modal_image_wrap pull-left" ng-class="{disabled: !userPhoto.id}">
<img
class="user_modal_image"
my-load-thumb
thumb="userPhoto"
/>
<div class="md_modal_split_actions_wrap">
<div class="md_modal_split_actions">
<a class="md_modal_split_action" href="" ng-click="goToHistory()" title="{{'user_modal_send_message' | i18n}}">
<i class="md_modal_split_action_msg"></i>
</a>
</div>
</div>
<div class="user_modal_info_wrap clearfix">
<h4 class="user_modal_header" ng-bind="user | userName"></h4>
<p class="user_modal_status" ng-if="user.status" my-user-status="::user.id"></p>
<div class="user_modal_actions_wrap clearfix">
<button class="btn btn-primary user_modal_main_btn" ng-click="goToHistory()" my-i18n="user_modal_send_message"></button>
<div class="dropdown user_modal_other_btn" dropdown>
<button class="btn btn-link dropdown-toggle" dropdown-toggle>
<my-i18n msgid="user_modal_menu_more"></my-i18n>
<i class="icon icon-caret"></i>
</button>
<ul class="dropdown-menu">
<li ng-if="user._ == 'userContact'">
<a ng-click="importContact(true)" my-i18n="user_modal_edit_contact"></a>
</li>
<li ng-if="user._ == 'userContact'">
<a ng-click="deleteContact()" my-i18n="user_modal_delete_contact"></a>
</li>
<li ng-if="user.phone.length > 0 &amp;&amp; user._ != 'userContact'">
<a ng-click="importContact()" my-i18n="user_modal_add_contact"></a>
</li>
<li ng-if="user.phone.length > 0">
<a ng-click="shareContact()" my-i18n="user_modal_share_contact"></a>
</li>
<li ng-if="user._ != 'userSelf'">
<a ng-click="toggleBlock(!blocked)" ng-switch="blocked">
<my-i18n ng-switch-when="true" msgid="user_modal_unblock_user"></my-i18n>
<my-i18n ng-switch-default msgid="user_modal_block_user"></my-i18n>
</a>
</li>
<li>
<a ng-click="flushHistory()" my-i18n="user_modal_delete_chat"></a>
</li>
</ul>
</div>
<div class="md_modal_body">
<div class="md_modal_sections">
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_number" ng-if="user.phone || user.username">
<i class="md_modal_section_icon md_modal_section_icon_phone"></i>
<div class="md_modal_section_param_wrap" ng-if="user.phone">
<div class="md_modal_section_param_value" ng-bind="user.phone | phoneNumber"></div>
<div class="md_modal_section_param_name" my-i18n="user_modal_phone"></div>
</div>
</div>
</div>
<div class="md_modal_section_param_wrap" ng-if="user.username">
<div class="md_modal_section_param_value">
<a class="user_modal_username_link" ng-click="changeUsername()" ng-bind="'@' + user.username"></a>
</div>
<div class="md_modal_section_param_name" my-i18n="user_modal_username"></div>
</div>
</div>
<div class="modal_section" ng-if="user.phone || user.username">
<h3 class="modal_section_header" my-i18n="user_modal_info"></h3>
<div class="modal_section_body">
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_toggle">
<i class="md_modal_section_icon md_modal_section_icon_notification"></i>
<dl ng-if="user.phone">
<dt><my-i18n msgid="user_modal_phone"></my-i18n>:</dt>
<dd ng-bind="user.phone | phoneNumber"></dd>
</dl>
<dl ng-if="user.username">
<dt><my-i18n msgid="user_modal_username"></my-i18n>:</dt>
<dd ng-bind="'@' + user.username"></dd>
</dl>
<a class="md_modal_section_toggle_wrap tg_checkbox" ng-click="settings.notifications = !settings.notifications" ng-class="settings.notifications ? 'tg_checkbox_on' : ''">
<span class="icon icon-checkbox-outer"><i class="icon-checkbox-inner"></i></span>
<span class="tg_checkbox_label" my-i18n="user_modal_notifications"></span>
</a>
</div>
</div>
<div class="modal_section">
<h3 class="modal_section_header" my-i18n="user_modal_settings"></h3>
<div class="modal_section_body">
<div class="md_modal_iconed_section_wrap md_modal_iconed_section_link" ng-init="f.showMoreActions = !user.phone.length">
<i class="md_modal_section_icon md_modal_section_icon_more"></i>
<div class="md_modal_section_link_wrap" ng-if="user.phone.length > 0 &amp;&amp; user._ != 'userContact'">
<a class="md_modal_section_link" ng-click="importContact()" my-i18n="user_modal_add_contact"></a>
</div>
<div class="md_modal_section_link_wrap" ng-if="user.phone.length > 0">
<a class="md_modal_section_link" ng-click="shareContact()" my-i18n="user_modal_share_contact"></a>
</div>
<div class="md_modal_section_link_wrap" ng-if="f.showMoreActions &amp;&amp; user._ == 'userContact'">
<a class="md_modal_section_link" ng-click="deleteContact()" my-i18n="user_modal_delete_contact"></a>
</div>
<div class="tg_form_group">
<a class="tg_checkbox" ng-click="settings.notifications = !settings.notifications" ng-class="settings.notifications ? 'tg_checkbox_on' : ''">
<span class="icon icon-checkbox-outer"><i class="icon-checkbox-inner"></i></span>
<span class="tg_checkbox_label" my-i18n="user_modal_notifications"></span>
<div class="md_modal_section_link_wrap" ng-if="f.showMoreActions &amp;&amp; user._ != 'userSelf'">
<a class="md_modal_section_link" ng-click="toggleBlock(!blocked)" ng-switch="blocked">
<my-i18n ng-switch-when="true" msgid="user_modal_unblock_user"></my-i18n>
<my-i18n ng-switch-default msgid="user_modal_block_user"></my-i18n>
</a>
</div>
<div class="md_modal_section_link_wrap" ng-if="f.showMoreActions">
<a class="md_modal_section_link" ng-click="flushHistory()" my-i18n="user_modal_delete_chat"></a>
</div>
<div class="md_modal_section_link_wrap" ng-if="!f.showMoreActions">
<a class="md_modal_section_link" ng-click="f.showMoreActions = true" my-i18n="modal_more"></a>
</div>
</div>
</div>
</div>
</div>

24
app/partials/desktop/username_edit_modal.html

@ -1,27 +1,27 @@ @@ -1,27 +1,27 @@
<div class="username_edit_modal_wrap" my-modal-position>
<div class="md_simple_modal_wrap" my-modal-position>
<a class="modal-close-button" ng-click="$dismiss()"><i></i></a>
<div class="modal-body">
<div class="md_simple_modal_body">
<form class="modal_simple_form" ng-submit="updateUsername()">
<h4 my-i18n="username_edit_modal_title"></h4>
<div class="form-group import_modal_field_wrap" ng-class="{'has-error': checked.error, 'has-feedback': checked.feedback.length > 0}">
<input class="form-control input-md" my-focused type="text" placeholder="{{'username_edit_placeholder' | i18n}}" ng-model="profile.username" name="username" ng-model-options="{updateOn: 'default blur', debounce: {default: 600, blur: 0}}"/>
<span ng-if="checked.error" class="glyphicon form-control-feedback" ng-class="{'glyphicon-remove': checked.error}"></span>
<div class="md-input-group" ng-class="{'md-input-error': checked.error}" my-labeled-input>
<label class="md-input-label" my-i18n="username_edit_placeholder"></label>
<input class="md-input" my-focused type="text" ng-model="profile.username" name="username" ng-model-options="{updateOn: 'default blur', debounce: {default: 600, blur: 0}}" />
</div>
<div class="modal_simple_form_description" my-i18n="username_edit_description_md"></div>
<div class="md_simple_form_description" my-i18n="username_edit_description_md"></div>
</form>
</div>
<div class="modal-footer">
<a class="btn btn-link" ng-click="$dismiss()" my-i18n="modal_cancel"></a>
<button class="btn btn-primary" ng-class="{disabled: profile.updating}" ng-click="updateUsername()" ng-bind="profile.updating ? 'username_edit_submit_active' : 'username_edit_submit' | i18n" ng-disabled="profile.updating"></button>
<div class="md_simple_modal_footer">
<button class="btn btn-md" ng-click="$dismiss()" my-i18n="modal_cancel"></button>
<button class="btn btn-md" ng-class="{disabled: profile.updating}" ng-click="updateUsername()" ng-bind="profile.updating ? 'username_edit_submit_active' : 'username_edit_submit' | i18n" ng-disabled="profile.updating"></button>
</div>
</div>
</div>

12
app/partials/desktop/video_modal.html

@ -16,9 +16,15 @@ @@ -16,9 +16,15 @@
</a>
</div>
<div class="media_modal_info_wrap pull-left">
<a class="media_modal_author" my-user-link="video.user_id" user-watch="true"></a>
<span class="media_modal_date" ng-bind="video.date | dateOrTime :true"></span>
<div class="media_modal_info_wrap pull-left" ng-switch="messageID > 0">
<a class="media_modal_author_photo pull-left" my-peer-photolink="video.user_id" img-class="media_modal_author_photo" watch="true"></a>
<div class="media_modal_author_name">
<a class="media_modal_author" my-user-link="video.user_id" user-watch="true"></a>
</div>
<div class="media_modal_date">
<a ng-switch-when="true" class="media_modal_date" ng-click="goToMessage()" ng-bind="video.date | dateOrTime :true"></a>
<span ng-switch-default ng-bind="video.date | dateOrTime :true"></span>
</div>
</div>
<div class="media_modal_title_wrap" my-i18n="media_modal_video"></div>

2
app/partials/mobile/message.html

@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
<a class="im_message_from_photo pull-left" my-user-photolink="historyMessage.from_id" img-class="im_message_from_photo"></a>
<div class="im_message_meta pull-right text-right">
<div class="im_message_meta">
<i class="icon-message-status-tick"></i>
<span class="im_message_date" ng-bind="::historyMessage.date | time"></span>
</div>

2
app/partials/mobile/message_attach_photo.html

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<a class="im_message_photo_thumb" href="" ng-click="openPhoto(historyMessage.media.photo.id, historyMessage.id)" ng-style="::{width: historyMessage.media.photo.thumb.width + 'px'}" ng-mouseover="preloadPhoto(historyMessage.media.photo.id)">
<a class="im_message_photo_thumb" href="" ng-click="openPhoto(historyMessage.media.photo.id, {m: historyMessage.id})" ng-style="::{width: historyMessage.media.photo.thumb.width + 'px'}" ng-mouseover="preloadPhoto(historyMessage.media.photo.id)">
<img
class="im_message_photo_thumb"
my-load-thumb

4
app/partials/mobile/settings_modal.html

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<div class="settings_modal_wrap modal_content_wrap">
<div class="settings_modal_wrap">
<div class="tg_page_head tg_modal_head">
<div class="navbar navbar-static-top navbar-inverse">
@ -49,7 +49,7 @@ @@ -49,7 +49,7 @@
<div class="mobile_user_modal_photo_profile_wrap">
<a href="" ng-click="openPhoto(photo.id, -profile.id)" class="mobile_user_modal_image_wrap pull-left" ng-class="{disabled: !photo.id}">
<a href="" ng-click="openPhoto(user.photo.photo_id, {u: profile.id})" class="mobile_user_modal_image_wrap pull-left" ng-class="{disabled: !user.photo.id}">
<img
class="mobile_user_modal_image"
my-load-thumb

2
app/partials/mobile/user_modal.html

@ -49,7 +49,7 @@ @@ -49,7 +49,7 @@
<div class="mobile_user_modal_photo_profile_wrap">
<a href="" ng-click="openPhoto(userPhoto.id, -user.id)" class="mobile_user_modal_image_wrap pull-left" ng-class="{disabled: !userPhoto.id}">
<a href="" ng-click="openPhoto(user.photo.photo_id, {u: user.id})" class="mobile_user_modal_image_wrap pull-left" ng-class="{disabled: !user.photo.photo_id}">
<img
class="mobile_user_modal_image"
my-load-thumb

Loading…
Cancel
Save