Browse Source

UI improvements

Updates some styles and colours
Updated document button
Added new document state: downloaded
Added modal document preview
master
Igor Zhukov 10 years ago
parent
commit
6e9dc004c1
  1. 123
      app/css/app.css
  2. 15
      app/css/desktop.css
  3. 4
      app/css/mobile.css
  4. BIN
      app/img/icons/IconsetW.png
  5. BIN
      app/img/icons/IconsetW_1x.png
  6. 33
      app/js/controllers.js
  7. 127
      app/js/directives.js
  8. 10
      app/js/i18n.js
  9. 8
      app/js/lib/mtproto_wrapper.js
  10. 182
      app/js/lib/ng_utils.js
  11. 32
      app/js/lib/utils.js
  12. 1
      app/js/locales/en-us.json
  13. 342
      app/js/services.js
  14. 21
      app/partials/desktop/document_modal.html
  15. 21
      app/partials/desktop/full_document.html
  16. 2
      app/partials/desktop/message.html
  17. 37
      app/partials/desktop/message_attach_document.html
  18. 2
      app/partials/desktop/photo_modal.html
  19. 2
      app/partials/desktop/video_modal.html

123
app/css/app.css

@ -79,7 +79,7 @@ input[type="number"] { @@ -79,7 +79,7 @@ input[type="number"] {
}
.btn-success {
color: #ffffff;
background-color: #6AC065;
background-color: #6ec26d;
}
.btn-success:hover,
@ -94,7 +94,7 @@ input[type="number"] { @@ -94,7 +94,7 @@ input[type="number"] {
.btn-success:active,
.btn-success.active,
.open .dropdown-toggle.btn-success {
background: #5aaf54;
background: #66b864;
background-image: none;
}
@ -425,7 +425,7 @@ input[type="number"] { @@ -425,7 +425,7 @@ input[type="number"] {
.modal-close-button i {
display: inline-block;
background: url(../img/icons/IconsetW.png) -15px -320px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
width: 12px;
height: 12px;
margin: 21px;
@ -910,7 +910,7 @@ img.welcome_logo { @@ -910,7 +910,7 @@ img.welcome_logo {
font-size: 12px;
line-height: normal;
background: #F2F2F2 url(../img/icons/IconsetW.png) -6px -205px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
border: 1px solid #F2F2F2;
border-radius: 3px;
padding: 6px 20px 6px 30px;
@ -938,7 +938,7 @@ img.welcome_logo { @@ -938,7 +938,7 @@ img.welcome_logo {
height: 13px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -15px -192px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
opacity: 0.6;
}
.is_1x .im_dialogs_search_clear {
@ -1070,7 +1070,7 @@ a.im_dialog_selected .im_dialog_message_text { @@ -1070,7 +1070,7 @@ a.im_dialog_selected .im_dialog_message_text {
}
.im_dialog_badge {
background: #75BB72;
background: #6ec26d;
border-radius: 2px;
font-size: 10px;
padding: 3px 4px;
@ -1144,7 +1144,7 @@ a.im_dialog_selected .im_dialog_date { @@ -1144,7 +1144,7 @@ a.im_dialog_selected .im_dialog_date {
margin-left: 6px;
background: url(../img/icons/IconsetW.png) -17px -444px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
}
.is_1x .icon-caret {
background-image: url(../img/icons/IconsetW_1x.png);
@ -1302,7 +1302,7 @@ div.im_message_video_thumb { @@ -1302,7 +1302,7 @@ div.im_message_video_thumb {
height: 42px;
background: url(../img/icons/IconsetW.png) 0 -590px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
z-index: 1;
}
.is_1x .icon-videoplay {
@ -1329,7 +1329,7 @@ div.im_message_video_thumb { @@ -1329,7 +1329,7 @@ div.im_message_video_thumb {
height: 19px;
background: url(../img/icons/IconsetW.png) -14px -389px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
}
.is_1x .icon-geo-point {
background-image: url(../img/icons/IconsetW_1x.png);
@ -1373,39 +1373,44 @@ div.im_message_video_thumb { @@ -1373,39 +1373,44 @@ div.im_message_video_thumb {
.im_message_document,
.im_message_upload_file {
margin-top: 3px;
border-radius: 3px;
display: inline-block;
width: 340px;
/*border-radius: 3px;*/
/*display: inline-block;*/
width: 342px;
}
.im_message_audio {
margin-top: 3px;
}
.icon-document,
.icon-photo,
.icon-video {
.im_message_file_button {
display: block;
background: rgba(218,228,234,0.50);
float: left;
width: 38px;
height: 38px;
vertical-align: text-top;
background: #F2F2F2 url(../img/icons/IconsetW.png) -2px -229px no-repeat;
background-size: 42px 971px;
border-radius: 3px;
width: 42px;
height: 42px;
border-radius: 0;
margin-right: 10px;
}
.is_1x .icon-document,
.is_1x .icon-photo,
.is_1x .icon-video {
.im_message_file_button_icon {
display: inline-block;
line-height: 0;
/*#dae4ea 50%*/
background: url(../img/icons/IconsetW.png) -15px -953px no-repeat;
background-size: 42px 1171px;
width: 12px;
height: 20px;
margin: 11px 15px;
}
.is_1x .im_message_file_button_icon {
background-image: url(../img/icons/IconsetW_1x.png);
}
.im_message_file_button_dl_doc .im_message_file_button_icon {
background-position: -13px -983px;
width: 16px;
height: 18px;
margin: 12px 13px;
}
.im_message_selected .icon-document,
.im_message_selected .icon-photo,
.im_message_selected .icon-video,
.im_history_selectable .im_message_outer_wrap:hover .icon-document,
.im_history_selectable .im_message_outer_wrap:hover .icon-photo,
.im_history_selectable .im_message_outer_wrap:hover .icon-video {
.im_history_selectable .im_message_outer_wrap:hover .icon-document {
background-color: #dae6f0;
background-position: -2px -542px;
}
@ -1479,7 +1484,7 @@ img.im_message_document_thumb { @@ -1479,7 +1484,7 @@ img.im_message_document_thumb {
width: 14px;
height: 17px;
background: url(../img/icons/IconsetW.png) -15px -897px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
}
.is_1x .audio_player_btn_icon {
background-image: url(../img/icons/IconsetW_1x.png);
@ -1759,7 +1764,7 @@ textarea.im_message_field { @@ -1759,7 +1764,7 @@ textarea.im_message_field {
height: 23px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -12px -68px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
opacity: 0.8;
}
.is_1x .icon-paperclip {
@ -1787,7 +1792,7 @@ textarea.im_message_field { @@ -1787,7 +1792,7 @@ textarea.im_message_field {
height: 23px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -10px -4px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
opacity: 0.8;
}
.is_1x .icon-emoji {
@ -1836,7 +1841,7 @@ textarea.im_message_field { @@ -1836,7 +1841,7 @@ textarea.im_message_field {
height: 21px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -9px -132px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
opacity: 0.8;
}
.is_1x .icon-camera {
@ -1852,7 +1857,7 @@ textarea.im_message_field { @@ -1852,7 +1857,7 @@ textarea.im_message_field {
.icon-online {
background: #6DBF69;
background: #6ec26d;
border: 1px solid #FFF;
display: block;
width: 11px;
@ -1868,13 +1873,41 @@ textarea.im_message_field { @@ -1868,13 +1873,41 @@ textarea.im_message_field {
.media_modal_wrap .modal-body {
padding: 19px 18px 17px;
}
a.img_fullsize {
a.img_fullsize,
.img_fullsize_wrap {
display: block;
text-align: center;
}
img.img_fullsize {
margin: 0 auto;
}
.document_modal_image_wrap {
overflow: auto;
}
.document_fullsize_wrap {
display: none;
cursor: zoom-in;
text-align: center;
}
.document_fullsize_zoomed {
cursor: zoom-out;
}
.document_fullsize_img {
/*max-width: 100%;*/
-webkit-user-select: none;
}
.document_fullsize_zoomed .document_fullsize_img {
/*min-width: 100%;*/
-webkit-user-select: none;
image-rendering: optimizeSpeed; /* FUCK SMOOTHING, GIVE ME SPEED */
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Chrome (and eventually Safari) */
image-rendering: optimize-contrast; /* CSS3 Proposed */
-ms-interpolation-mode: nearest-neighbor; /* IE8+ */
}
.media_modal_info {
color: #999;
margin: 20px 0 0;
@ -1886,8 +1919,12 @@ img.img_fullsize { @@ -1886,8 +1919,12 @@ img.img_fullsize {
margin-left: 15px;
}
.media_modal_author {
color: inherit;
font-weight: bold;
}
.media_modal_author:hover {
color: inherit;
}
.non_osx .media_modal_author {
font-size: 12px;
}
@ -1914,7 +1951,7 @@ img.img_fullsize { @@ -1914,7 +1951,7 @@ img.img_fullsize {
overflow: auto;
line-height: 17px;
border: 1px solid #d9dbde;
border: 1px solid #d2dbe3;
border-radius: 2px;
-webkit-box-shadow: none;
box-shadow: none;
@ -2179,7 +2216,7 @@ a:hover .icon-twitter { @@ -2179,7 +2216,7 @@ a:hover .icon-twitter {
font-size: 12px;
line-height: normal;
background: url(../img/icons/IconsetW.png) -6px -205px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
border: 1px solid #d9dbde;
border-radius: 3px;
padding: 6px 15px 6px 30px;
@ -2198,7 +2235,7 @@ a:hover .icon-twitter { @@ -2198,7 +2235,7 @@ a:hover .icon-twitter {
height: 13px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -15px -192px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
opacity: 0.6;
}
.is_1x .contacts_modal_search_clear {
@ -2314,7 +2351,7 @@ img.chat_modal_participant_photo { @@ -2314,7 +2351,7 @@ img.chat_modal_participant_photo {
width: 25px;
height: 25px;
background: url(../img/icons/IconsetW.png) -9px -516px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
opacity: 0.5;
}
.is_1x .icon-contact-tick {
@ -2395,7 +2432,7 @@ img.chat_modal_participant_photo { @@ -2395,7 +2432,7 @@ img.chat_modal_participant_photo {
height: 26px;
margin: 13px 0 0 40px;
background: url(../img/icons/IconsetW.png) -9px -516px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
}
.is_1x .icon-select-tick {
background-image: url(../img/icons/IconsetW_1x.png);
@ -2514,7 +2551,7 @@ ce671b orange @@ -2514,7 +2551,7 @@ ce671b orange
font-size: 12px;
line-height: normal;
background: #F2F2F2 url(../img/icons/IconsetW.png) -6px -205px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
border: 1px solid #F2F2F2;
border-radius: 3px;
padding: 6px 20px 6px 30px;
@ -2537,7 +2574,7 @@ ce671b orange @@ -2537,7 +2574,7 @@ ce671b orange
height: 13px;
vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -15px -192px no-repeat;
background-size: 42px 971px;
background-size: 42px 1171px;
opacity: 0.6;
}
.is_1x .countries_modal_search_clear {

15
app/css/desktop.css

@ -179,7 +179,7 @@ a.footer_lang_link.active:active { @@ -179,7 +179,7 @@ a.footer_lang_link.active:active {
.im_history_col .nano > .nano-pane,
.contacts_modal_col .nano > .nano-pane,
.im_dialogs_modal_col .nano > .nano-pane {
background : rgba(3,36,64,0.08);
background : rgba(216,223,225,0.45); /*45% d8dfe5*/
width : 9px;
right: 0;
top: 0;
@ -218,7 +218,7 @@ a.footer_lang_link.active:active { @@ -218,7 +218,7 @@ a.footer_lang_link.active:active {
.im_history_col .nano > .nano-pane > .nano-slider,
.contacts_modal_col .nano > .nano-pane > .nano-slider,
.im_dialogs_modal_col .nano > .nano-pane > .nano-slider {
background : rgba(3,46,79,0.22);
background : rgba(137,160,179,0.50); /*50% 89a0b3*/
margin: 0;
-moz-border-radius : 2px;
-webkit-border-radius : 2px;
@ -324,7 +324,7 @@ a.footer_lang_link.active:active { @@ -324,7 +324,7 @@ a.footer_lang_link.active:active {
}
.icon-message-status {
background: #43A4DB;
background: #6ba2cb;
border: 0;
display: block;
width: 10px;
@ -381,6 +381,7 @@ a.footer_lang_link.active:active { @@ -381,6 +381,7 @@ a.footer_lang_link.active:active {
font-size: 13px;
line-height: 17px;
min-width: 60px;
border-radius: 2px;
}
.im_message_selected .im_message_date,
@ -492,7 +493,7 @@ a.footer_lang_link.active:active { @@ -492,7 +493,7 @@ a.footer_lang_link.active:active {
.im_panel_own_photo {
width: 50px;
height: 50px;
border-radius: 3px;
border-radius: 0;
overflow: hidden;
}
div.im_panel_peer_photo {
@ -505,7 +506,7 @@ div.im_panel_own_photo { @@ -505,7 +506,7 @@ div.im_panel_own_photo {
}
.im_panel_peer_online {
background: #6DBF69;
background: #6ec26d;
border: 1px solid #FFF;
display: block;
width: 11px;
@ -516,6 +517,10 @@ div.im_panel_own_photo { @@ -516,6 +517,10 @@ div.im_panel_own_photo {
margin-top: -7px;
margin-left: 43px;
}
.emoji-wysiwyg-editor,
.im_message_field {
border-radius: 0;
}
/* Peer modals */
.user_modal_window .modal-dialog {

4
app/css/mobile.css

@ -535,9 +535,7 @@ img.im_message_video_thumb, @@ -535,9 +535,7 @@ img.im_message_video_thumb,
color: #93a2ae;
}
.im_message_out .icon-document,
.im_message_out .icon-photo,
.im_message_out .icon-video {
.im_message_out .icon-document {
background-color: #dae6f0;
background-position: -2px -542px;
}

BIN
app/img/icons/IconsetW.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

BIN
app/img/icons/IconsetW_1x.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

33
app/js/controllers.js

@ -1765,6 +1765,7 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1765,6 +1765,7 @@ angular.module('myApp.controllers', ['myApp.i18n'])
})
.controller('VideoModalController', function ($scope, $rootScope, $modalInstance, PeersSelectService, AppMessagesManager, AppVideoManager, AppPeersManager, ErrorService) {
$scope.video = AppVideoManager.wrapForFull($scope.videoID);
$scope.progress = {enabled: false};
@ -1799,6 +1800,38 @@ angular.module('myApp.controllers', ['myApp.i18n']) @@ -1799,6 +1800,38 @@ angular.module('myApp.controllers', ['myApp.i18n'])
});
})
.controller('DocumentModalController', function ($scope, $rootScope, $modalInstance, PeersSelectService, AppMessagesManager, AppDocsManager, AppPeersManager, ErrorService) {
$scope.document = AppDocsManager.wrapForHistory($scope.docID);
$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});
});
});
};
$scope['delete'] = function () {
var messageID = $scope.messageID;
ErrorService.confirm({type: 'MESSAGE_DELETE'}).then(function () {
AppMessagesManager.deleteMessages([messageID]);
});
};
$scope.download = function () {
AppDocsManager.saveDocFile($scope.docID);
};
$scope.$on('history_delete', function (e, historyUpdate) {
if (historyUpdate.msgs[$scope.messageID]) {
$modalInstance.dismiss();
}
});
})
.controller('UserModalController', function ($scope, $location, $rootScope, $modal, AppUsersManager, MtpApiManager, NotificationsManager, AppPhotosManager, AppMessagesManager, AppPeersManager, PeersSelectService, ErrorService) {
var peerString = AppUsersManager.getUserString($scope.userID);

127
app/js/directives.js

@ -182,9 +182,25 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -182,9 +182,25 @@ angular.module('myApp.directives', ['myApp.filters'])
templateUrl: templateUrl('message_attach_video')
};
})
.directive('myMessageDocument', function() {
.directive('myMessageDocument', function(AppDocsManager) {
return {
templateUrl: templateUrl('message_attach_document')
scope: {
'document': '=myMessageDocument',
'messageId': '=messageId'
},
templateUrl: templateUrl('message_attach_document'),
link: function ($scope, element, attrs) {
AppDocsManager.updateDocDownloaded($scope.document.id);
$scope.docSave = function () {
AppDocsManager.saveDocFile($scope.document.id);
};
$scope.docOpen = function () {
if (!$scope.document.withPreview) {
return $scope.download();
}
AppDocsManager.openDoc($scope.document.id, $scope.messageId);
};
}
};
})
.directive('myMessageAudio', function() {
@ -1395,7 +1411,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1395,7 +1411,7 @@ angular.module('myApp.directives', ['myApp.filters'])
})
.directive('myLoadGif', function($rootScope, MtpApiFileManager) {
.directive('myLoadGif', function($rootScope, MtpApiFileManager, AppDocsManager) {
return {
link: link,
@ -1417,11 +1433,9 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1417,11 +1433,9 @@ angular.module('myApp.directives', ['myApp.filters'])
$scope.isActive = false;
$scope.document.url = MtpApiFileManager.getCachedFile(inputFileLocation);
/*return $scope.document.progress = {enabled: true, percent: 30, total: $scope.document.size};*/
$scope.toggle = function (e) {
if (checkClick(e, true)) {
$rootScope.downloadDoc($scope.document.id);
AppDocsManager.saveDocFile($scope.document.id);
return false;
}
@ -1464,6 +1478,102 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1464,6 +1478,102 @@ angular.module('myApp.directives', ['myApp.filters'])
}
})
.directive('myLoadDocument', function($rootScope, MtpApiFileManager, AppDocsManager) {
return {
link: link,
templateUrl: templateUrl('full_document'),
scope: {
document: '=myLoadDocument'
}
};
function updateModalWidth(element, width) {
while (element && !$(element).hasClass('modal-dialog')) {
element = element.parentNode;
}
if (element) {
$(element).width(width + (Config.Mobile ? 0 : 36));
}
}
function link ($scope, element, attrs) {
var loaderWrap = $('.document_fullsize_with_progress_wrap', element);
var fullSizeWrap = $('.document_fullsize_wrap', element);
var fullSizeImage = $('.document_fullsize_img', element);
var fullWidth = $(window).width() - (Config.Mobile ? 20 : 36);
var fullHeight = $(window).height() - 150;
$scope.imageWidth = fullWidth;
$scope.imageHeight = fullHeight;
var thumbPhotoSize = $scope.document.thumb;
if (thumbPhotoSize && thumbPhotoSize._ != 'photoSizeEmpty') {
var wh = calcImageInBox(thumbPhotoSize.width, thumbPhotoSize.height, fullWidth, fullHeight);
$scope.imageWidth = wh.w;
$scope.imageHeight = wh.h;
$scope.thumbSrc = MtpApiFileManager.getCachedFile(thumbPhotoSize.location);
}
$scope.frameWidth = Math.max($scope.imageWidth, Math.min(600, fullWidth))
$scope.frameHeight = $scope.imageHeight;
onContentLoaded(function () {
$scope.$emit('ui_height');
});
updateModalWidth(element[0], $scope.frameWidth);
var checkSizesInt;
var realImageWidth, realImageHeight;
AppDocsManager.downloadDoc($scope.document.id).then(function (url) {
var image = new Image();
var checkSizes = function (e) {
if (!image.height || !image.width) {
return;
}
realImageWidth = image.width;
realImageHeight = image.height;
clearInterval(checkSizesInt);
var defaultWh = calcImageInBox(image.width, image.height, fullWidth, fullHeight, true);
var zoomedWh = {w: realImageWidth, h: realImageHeight};
if (defaultWh.w >= zoomedWh.w && defaultWh.h >= zoomedWh.h) {
zoomedWh.w *= 4;
zoomedWh.h *= 4;
}
var zoomed = true;
$scope.toggleZoom = function () {
zoomed = !zoomed;
var imageWidth = (zoomed ? zoomedWh : defaultWh).w;
var imageHeight = (zoomed ? zoomedWh : defaultWh).h;
fullSizeImage.css({
width: imageWidth,
height: imageHeight,
marginTop: $scope.frameHeight > imageHeight ? Math.floor(($scope.frameHeight - imageHeight) / 2) : 0
});
fullSizeWrap.toggleClass('document_fullsize_zoomed', zoomed);
};
$scope.toggleZoom(false);
fullSizeImage.attr('src', url);
loaderWrap.hide();
fullSizeWrap.css({width: $scope.frameWidth, height: $scope.frameHeight}).show();
};
checkSizesInt = setInterval(checkSizes, 20);
image.onload = checkSizes;
image.src = url;
setZeroTimeout(checkSizes);
});
}
})
.directive('myMapPoint', function(ExternalResourcesManager) {
return {
@ -1730,8 +1840,8 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1730,8 +1840,8 @@ angular.module('myApp.directives', ['myApp.filters'])
var updateMargin = function () {
var height = element[0].offsetHeight,
fullHeight = height - (height && usePadding ? 2 * prevMargin : 0),
contHeight = $($window).height(),
ratio = attrs.myVerticalPosition && parseFloat(attrs.myVerticalPosition) || 0.5,
contHeight = attrs.contHeight ? $scope.$eval(attrs.contHeight) : $($window).height(),
margin = fullHeight < contHeight ? parseInt((contHeight - fullHeight) * ratio) : '',
styles = usePadding
? {paddingTop: margin, paddingBottom: margin}
@ -1747,9 +1857,10 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1747,9 +1857,10 @@ angular.module('myApp.directives', ['myApp.filters'])
prevMargin = margin;
};
$($window).on('resize', updateMargin);
onContentLoaded(updateMargin);
$($window).on('resize', updateMargin);
$scope.$on('ui_height', function () {
onContentLoaded(updateMargin);

10
app/js/i18n.js

@ -21,16 +21,6 @@ angular.module('myApp.i18n', ['izhukov.utils']) @@ -21,16 +21,6 @@ angular.module('myApp.i18n', ['izhukov.utils'])
});
}
function encodeEntities(value) {
return value.
replace(/&/g, '&amp;').
replace(/([^\#-~| |!\n\*])/g, function (value) { // non-alphanumeric
return '&#' + value.charCodeAt(0) + ';';
}).
replace(/</g, '&lt;').
replace(/>/g, '&gt;');
}
function parseMarkdownString(msgstr, msgid) {
msgstr = msgstr.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
.replace(/\n/g, "<br/>");

8
app/js/lib/mtproto_wrapper.js

@ -383,6 +383,13 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto']) @@ -383,6 +383,13 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
});
}
function getDownloadedFile(location, size) {
var fileStorage = getFileStorage(),
fileName = getFileName(location);
return fileStorage.getFile(fileName, size);
}
function downloadFile (dcID, location, size, options) {
if (!FileManager.isAvailable()) {
return $q.reject({type: 'BROWSER_BLOB_NOT_SUPPORTED'});
@ -598,6 +605,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto']) @@ -598,6 +605,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
return {
getCachedFile: getCachedFile,
getDownloadedFile: getDownloadedFile,
downloadFile: downloadFile,
downloadSmallFile: downloadSmallFile,
saveSmallFile: saveSmallFile,

182
app/js/lib/ng_utils.js

@ -33,7 +33,7 @@ angular.module('izhukov.utils', []) @@ -33,7 +33,7 @@ angular.module('izhukov.utils', [])
})
.service('FileManager', function ($window, $q) {
.service('FileManager', function ($window, $q, $timeout) {
$window.URL = $window.URL || $window.webkitURL;
$window.BlobBuilder = $window.BlobBuilder || $window.WebKitBlobBuilder || $window.MozBlobBuilder;
@ -610,6 +610,186 @@ angular.module('izhukov.utils', []) @@ -610,6 +610,186 @@ angular.module('izhukov.utils', [])
};
})
.service('SearchIndexManager', function () {
var badCharsRe = /[`~!@#$%^&*()\-_=+\[\]\\|{}'";:\/?.>,<\s]+/g,
trimRe = /^\s+|\s$/g,
accentsReplace = {
a: /[åáâäà]/g,
e: /[éêëè]/g,
i: /[íîïì]/g,
o: /[óôöò]/g,
u: /[úûüù]/g,
c: /ç/g,
ss: /ß/g
}
return {
createIndex: createIndex,
indexObject: indexObject,
cleanSearchText: cleanSearchText,
search: search
};
function createIndex () {
return {
shortIndexes: {},
fullTexts: {}
}
}
function cleanSearchText (text) {
text = text.replace(badCharsRe, ' ').replace(trimRe, '').toLowerCase();
for (var key in accentsReplace) {
if (accentsReplace.hasOwnProperty(key)) {
text = text.replace(accentsReplace[key], key);
}
}
return text;
}
function indexObject (id, searchText, searchIndex) {
if (searchIndex.fullTexts[id] !== undefined) {
return false;
}
searchText = cleanSearchText(searchText);
if (!searchText.length) {
return false;
}
var shortIndexes = searchIndex.shortIndexes;
searchIndex.fullTexts[id] = searchText;
angular.forEach(searchText.split(' '), function(searchWord) {
var len = Math.min(searchWord.length, 3),
wordPart, i;
for (i = 1; i <= len; i++) {
wordPart = searchWord.substr(0, i);
if (shortIndexes[wordPart] === undefined) {
shortIndexes[wordPart] = [id];
} else {
shortIndexes[wordPart].push(id);
}
}
});
}
function search (query, searchIndex) {
var shortIndexes = searchIndex.shortIndexes,
fullTexts = searchIndex.fullTexts;
query = cleanSearchText(query);
var queryWords = query.split(' '),
foundObjs = false,
newFoundObjs, i, j, searchText, found;
for (i = 0; i < queryWords.length; i++) {
newFoundObjs = shortIndexes[queryWords[i].substr(0, 3)];
if (!newFoundObjs) {
foundObjs = [];
break;
}
if (foundObjs === false || foundObjs.length > newFoundObjs.length) {
foundObjs = newFoundObjs;
}
}
newFoundObjs = {};
for (j = 0; j < foundObjs.length; j++) {
found = true;
searchText = fullTexts[foundObjs[j]];
for (i = 0; i < queryWords.length; i++) {
if (searchText.indexOf(queryWords[i]) == -1) {
found = false;
break;
}
}
if (found) {
newFoundObjs[foundObjs[j]] = true;
}
}
return newFoundObjs;
}
})
.service('ExternalResourcesManager', function ($q, $http) {
var urlPromises = {};
function downloadImage (url) {
if (urlPromises[url] !== undefined) {
return urlPromises[url];
}
return urlPromises[url] = $http.get(url, {responseType: 'blob', transformRequest: null})
.then(function (response) {
window.URL = window.URL || window.webkitURL;
return window.URL.createObjectURL(response.data);
});
}
return {
downloadImage: downloadImage
}
})
.service('IdleManager', function ($rootScope, $window, $timeout) {
$rootScope.idle = {isIDLE: false};
var toPromise, started = false;
return {
start: start
};
function start () {
if (!started) {
started = true;
$($window).on('blur focus keydown mousedown touchstart', onEvent);
setTimeout(function () {
onEvent({type: 'blur'});
}, 0);
}
}
function onEvent (e) {
// console.log('event', e.type);
if (e.type == 'mousemove') {
$($window).off('mousemove', onEvent);
}
var isIDLE = e.type == 'blur' || e.type == 'timeout' ? true : false;
$timeout.cancel(toPromise);
if (!isIDLE) {
// console.log('update timeout');
toPromise = $timeout(function () {
onEvent({type: 'timeout'});
}, 30000);
}
if ($rootScope.idle.isIDLE == isIDLE) {
return;
}
// console.log('IDLE changed', isIDLE);
$rootScope.$apply(function () {
$rootScope.idle.isIDLE = isIDLE;
});
if (isIDLE && e.type == 'timeout') {
$($window).on('mousemove', onEvent);
}
}
})
.service('AppRuntimeManager', function ($window) {
return {

32
app/js/lib/utils.js

@ -114,3 +114,35 @@ function templateUrl (tplName) { @@ -114,3 +114,35 @@ function templateUrl (tplName) {
return 'partials/' + (Config.Mobile ? 'mobile' : 'desktop') + '/' + tplName + '.html';
}
function encodeEntities(value) {
return value.
replace(/&/g, '&amp;').
replace(/([^\#-~| |!])/g, function (value) { // non-alphanumeric
return '&#' + value.charCodeAt(0) + ';';
}).
replace(/</g, '&lt;').
replace(/>/g, '&gt;');
}
function calcImageInBox(imageW, imageH, boxW, boxH, noZooom) {
var boxedImageW = boxW;
var boxedImageH = boxH;
if ((imageW / imageH) > (boxW / boxH)) {
boxedImageH = parseInt(imageH * boxW / imageW);
}
else {
boxedImageW = parseInt(imageW * boxH / imageH);
if (boxedImageW > boxW) {
boxedImageH = parseInt(boxedImageH * boxW / boxedImageW);
boxedImageW = boxW;
}
}
if (noZooom && boxedImageW >= imageW && boxedImageH >= imageH) {
boxedImageW = imageW;
boxedImageH = imageH;
}
return {w: boxedImageW, h: boxedImageH};
}

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

@ -325,6 +325,7 @@ @@ -325,6 +325,7 @@
"message_attach_document_open": "Open",
"message_attach_document_download": "Download",
"message_attach_document_save": "Save File",
"message_attach_video_video": "Video",
"message_attach_video_download": "Download",

342
app/js/services.js

@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
/* Services */
angular.module('myApp.services', ['myApp.i18n'])
angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
.service('AppUsersManager', function ($rootScope, $modal, $modalStack, $filter, $q, MtpApiFileManager, MtpApiManager, RichTextProcessor, SearchIndexManager, ErrorService, Storage, _) {
var users = {},
@ -606,115 +606,6 @@ angular.module('myApp.services', ['myApp.i18n']) @@ -606,115 +606,6 @@ angular.module('myApp.services', ['myApp.i18n'])
}
})
.service('SearchIndexManager', function () {
var badCharsRe = /[`~!@#$%^&*()\-_=+\[\]\\|{}'";:\/?.>,<\s]+/g,
trimRe = /^\s+|\s$/g,
accentsReplace = {
a: /[åáâäà]/g,
e: /[éêëè]/g,
i: /[íîïì]/g,
o: /[óôöò]/g,
u: /[úûüù]/g,
c: /ç/g,
ss: /ß/g
}
return {
createIndex: createIndex,
indexObject: indexObject,
cleanSearchText: cleanSearchText,
search: search
};
function createIndex () {
return {
shortIndexes: {},
fullTexts: {}
}
}
function cleanSearchText (text) {
text = text.replace(badCharsRe, ' ').replace(trimRe, '').toLowerCase();
for (var key in accentsReplace) {
if (accentsReplace.hasOwnProperty(key)) {
text = text.replace(accentsReplace[key], key);
}
}
return text;
}
function indexObject (id, searchText, searchIndex) {
if (searchIndex.fullTexts[id] !== undefined) {
return false;
}
searchText = cleanSearchText(searchText);
if (!searchText.length) {
return false;
}
var shortIndexes = searchIndex.shortIndexes;
searchIndex.fullTexts[id] = searchText;
angular.forEach(searchText.split(' '), function(searchWord) {
var len = Math.min(searchWord.length, 3),
wordPart, i;
for (i = 1; i <= len; i++) {
wordPart = searchWord.substr(0, i);
if (shortIndexes[wordPart] === undefined) {
shortIndexes[wordPart] = [id];
} else {
shortIndexes[wordPart].push(id);
}
}
});
}
function search (query, searchIndex) {
var shortIndexes = searchIndex.shortIndexes,
fullTexts = searchIndex.fullTexts;
query = cleanSearchText(query);
var queryWords = query.split(' '),
foundObjs = false,
newFoundObjs, i, j, searchText, found;
for (i = 0; i < queryWords.length; i++) {
newFoundObjs = shortIndexes[queryWords[i].substr(0, 3)];
if (!newFoundObjs) {
foundObjs = [];
break;
}
if (foundObjs === false || foundObjs.length > newFoundObjs.length) {
foundObjs = newFoundObjs;
}
}
newFoundObjs = {};
for (j = 0; j < foundObjs.length; j++) {
found = true;
searchText = fullTexts[foundObjs[j]];
for (i = 0; i < queryWords.length; i++) {
if (searchText.indexOf(queryWords[i]) == -1) {
found = false;
break;
}
}
if (found) {
newFoundObjs[foundObjs[j]] = true;
}
}
return newFoundObjs;
}
})
.service('AppMessagesManager', function ($q, $rootScope, $location, $filter, ApiUpdatesManager, AppUsersManager, AppChatsManager, AppPeersManager, AppPhotosManager, AppVideoManager, AppDocsManager, AppAudioManager, MtpApiManager, MtpApiFileManager, RichTextProcessor, NotificationsManager, SearchIndexManager, PeersSelectService,Storage, _) {
var messagesStorage = {};
@ -2389,21 +2280,9 @@ angular.module('myApp.services', ['myApp.i18n']) @@ -2389,21 +2280,9 @@ angular.module('myApp.services', ['myApp.i18n'])
full.height = fullHeight;
if (fullPhotoSize && fullPhotoSize._ != 'photoSizeEmpty') {
if ((fullPhotoSize.w / fullPhotoSize.h) > (fullWidth / fullHeight)) {
full.height = parseInt(fullPhotoSize.h * fullWidth / fullPhotoSize.w);
}
else {
full.width = parseInt(fullPhotoSize.w * fullHeight / fullPhotoSize.h);
if (full.width > fullWidth) {
full.height = parseInt(full.height * fullWidth / full.width);
full.width = fullWidth;
}
}
if (!Config.Mobile && full.width >= fullPhotoSize.w && full.height >= fullPhotoSize.h) {
full.width = fullPhotoSize.w;
full.height = fullPhotoSize.h;
}
var wh = calcImageInBox(fullPhotoSize.w, fullPhotoSize.h, fullWidth, fullHeight, Config.Mobile);
full.width = wh.w;
full.height = wh.h;
full.modalWidth = Math.max(full.width, Math.min(400, fullWidth));
@ -2464,7 +2343,7 @@ angular.module('myApp.services', ['myApp.i18n']) @@ -2464,7 +2343,7 @@ angular.module('myApp.services', ['myApp.i18n'])
mime: mimeType,
toFileEntry: writableFileEntry
}).then(function (url) {
console.log('file save done');
// console.log('file save done');
}, function (e) {
console.log('photo download failed', e);
});
@ -2563,16 +2442,10 @@ angular.module('myApp.services', ['myApp.i18n']) @@ -2563,16 +2442,10 @@ angular.module('myApp.services', ['myApp.i18n'])
if (!video.w || !video.h) {
full.height = full.width = Math.min(fullWidth, fullHeight);
}
else if (video.w > video.h) {
full.height = parseInt(video.h * fullWidth / video.w);
}
else {
full.width = parseInt(video.w * fullHeight / video.h);
if (full.width > fullWidth) {
full.height = parseInt(full.height * fullWidth / full.width);
full.width = fullWidth;
}
} else {
var wh = calcImageInBox(video.w, video.h, fullWidth, fullHeight);
full.width = wh.w;
full.height = wh.h;
}
video.full = full;
@ -2669,7 +2542,7 @@ angular.module('myApp.services', ['myApp.i18n']) @@ -2669,7 +2542,7 @@ angular.module('myApp.services', ['myApp.i18n'])
}
})
.service('AppDocsManager', function ($rootScope, $modal, $window, $timeout, MtpApiFileManager, FileManager) {
.service('AppDocsManager', function ($rootScope, $modal, $window, $timeout, $q, MtpApiFileManager, FileManager) {
var docs = {},
docsForHistory = {},
windowW = $(window).width(),
@ -2737,7 +2610,7 @@ angular.module('myApp.services', ['myApp.i18n']) @@ -2737,7 +2610,7 @@ angular.module('myApp.services', ['myApp.i18n'])
return docsForHistory[docID] = doc;
}
function downloadDoc (docID, action) {
function updateDocDownloaded (docID) {
var doc = docs[docID],
historyDoc = docsForHistory[docID] || doc || {},
inputFileLocation = {
@ -2746,68 +2619,90 @@ angular.module('myApp.services', ['myApp.i18n']) @@ -2746,68 +2619,90 @@ angular.module('myApp.services', ['myApp.i18n'])
access_hash: doc.access_hash
};
function updateDownloadProgress (progress) {
if (historyDoc.downloaded === undefined) {
MtpApiFileManager.getDownloadedFile(inputFileLocation, doc.size).then(function () {
historyDoc.downloaded = true;
}, function () {
historyDoc.downloaded = false;
});
}
}
function downloadDoc (docID, toFileEntry) {
var doc = docs[docID],
historyDoc = docsForHistory[docID] || doc || {},
inputFileLocation = {
_: 'inputDocumentFileLocation',
id: docID,
access_hash: doc.access_hash
};
historyDoc.progress = {enabled: true, percent: 1, total: doc.size};
var downloadPromise = MtpApiFileManager.downloadFile(doc.dc_id, inputFileLocation, doc.size, {
mime: doc.mime_type,
toFileEntry: toFileEntry
});
downloadPromise.then(function (url) {
delete historyDoc.progress;
historyDoc.url = url;
historyDoc.downloaded = true;
console.log('file save done');
}, function (e) {
console.log('document download failed', e);
historyDoc.progress.enabled = false;
}, function (progress) {
console.log('dl progress', progress);
historyDoc.progress.done = progress.done;
historyDoc.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
$rootScope.$broadcast('history_update');
}
});
historyDoc.progress.cancel = downloadPromise.cancel;
return downloadPromise;
}
function openDoc (docID, messageID) {
var scope = $rootScope.$new(true);
scope.docID = docID;
scope.messageID = messageID;
var modalInstance = $modal.open({
templateUrl: templateUrl('document_modal'),
controller: 'DocumentModalController',
scope: scope,
windowClass: 'document_modal_window'
});
}
function saveDocFile (docID) {
var doc = docs[docID],
historyDoc = docsForHistory[docID] || doc || {};
var ext = (doc.file_name.split('.', 2) || [])[1] || '';
FileManager.chooseSave(doc.file_name, ext, doc.mime_type).then(function (writableFileEntry) {
if (!writableFileEntry) {
return;
}
historyDoc.progress = {enabled: true, percent: 1, total: doc.size};
var downloadPromise = MtpApiFileManager.downloadFile(doc.dc_id, inputFileLocation, doc.size, {
mime: doc.mime_type,
toFileEntry: writableFileEntry
});
downloadPromise.then(function (url) {
delete historyDoc.progress;
downloadDoc(docID, writableFileEntry).then(function () {
console.log('file save done');
}, function (e) {
console.log('document download failed', e);
historyDoc.progress.enabled = false;
}, updateDownloadProgress);
historyDoc.progress.cancel = downloadPromise.cancel;
});
}, function () {
historyDoc.progress = {enabled: true, percent: 1, total: doc.size};
var downloadPromise = MtpApiFileManager.downloadFile(doc.dc_id, inputFileLocation, doc.size, {mime: doc.mime_type});
downloadPromise.then(function (url) {
delete historyDoc.progress;
historyDoc.url = url;
switch (action) {
case 1:
window.open(url, '_blank');
break;
default:
FileManager.download(url, doc.mime_type, doc.file_name);
}
}, function (e) {
console.log('document download failed', e);
historyDoc.progress.enabled = false;
}, updateDownloadProgress);
historyDoc.progress.cancel = downloadPromise.cancel;
downloadDoc(docID).then(function (url) {
FileManager.download(url, doc.mime_type, doc.file_name);
});
});
}
$rootScope.downloadDoc = downloadDoc;
return {
saveDoc: saveDoc,
wrapForHistory: wrapForHistory,
downloadDoc: downloadDoc
updateDocDownloaded: updateDocDownloaded,
downloadDoc: downloadDoc,
openDoc: openDoc,
saveDocFile: saveDocFile
}
})
@ -2877,27 +2772,6 @@ angular.module('myApp.services', ['myApp.i18n']) @@ -2877,27 +2772,6 @@ angular.module('myApp.services', ['myApp.i18n'])
}
})
.service('ExternalResourcesManager', function ($q, $http) {
var urlPromises = {};
function downloadImage (url) {
if (urlPromises[url] !== undefined) {
return urlPromises[url];
}
return urlPromises[url] = $http.get(url, {responseType: 'blob', transformRequest: null})
.then(function (response) {
window.URL = window.URL || window.webkitURL;
return window.URL.createObjectURL(response.data);
});
}
return {
downloadImage: downloadImage
}
})
.service('ApiUpdatesManager', function ($rootScope, MtpNetworkerFactory, AppUsersManager, AppChatsManager, AppPeersManager, MtpApiManager) {
var isSynchronizing = true,
@ -3193,16 +3067,6 @@ angular.module('myApp.services', ['myApp.i18n']) @@ -3193,16 +3067,6 @@ angular.module('myApp.services', ['myApp.i18n'])
wrapPlainText: wrapPlainText
};
function encodeEntities(value) {
return value.
replace(/&/g, '&amp;').
replace(/([^\#-~| |!])/g, function (value) { // non-alphanumeric
return '&#' + value.charCodeAt(0) + ';';
}).
replace(/</g, '&lt;').
replace(/>/g, '&gt;');
}
function getEmojiSpritesheetCoords(emojiCode) {
var i, row, column, totalColumns;
for (var cat = 0; cat < Config.EmojiCategories.length; cat++) {
@ -3377,58 +3241,6 @@ angular.module('myApp.services', ['myApp.i18n']) @@ -3377,58 +3241,6 @@ angular.module('myApp.services', ['myApp.i18n'])
})
.service('IdleManager', function ($rootScope, $window, $timeout) {
$rootScope.idle = {isIDLE: false};
var toPromise, started = false;
return {
start: start
};
function start () {
if (!started) {
started = true;
$($window).on('blur focus keydown mousedown touchstart', onEvent);
setTimeout(function () {
onEvent({type: 'blur'});
}, 0);
}
}
function onEvent (e) {
// console.log('event', e.type);
if (e.type == 'mousemove') {
$($window).off('mousemove', onEvent);
}
var isIDLE = e.type == 'blur' || e.type == 'timeout' ? true : false;
$timeout.cancel(toPromise);
if (!isIDLE) {
// console.log('update timeout');
toPromise = $timeout(function () {
onEvent({type: 'timeout'});
}, 30000);
}
if ($rootScope.idle.isIDLE == isIDLE) {
return;
}
// console.log('IDLE changed', isIDLE);
$rootScope.$apply(function () {
$rootScope.idle.isIDLE = isIDLE;
});
if (isIDLE && e.type == 'timeout') {
$($window).on('mousemove', onEvent);
}
}
})
.service('StatusManager', function ($timeout, $rootScope, MtpApiManager, IdleManager) {
var toPromise, lastOnlineUpdated = 0, started = false;

21
app/partials/desktop/document_modal.html

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
<div class="media_modal_wrap document_modal_wrap" my-modal-position>
<div class="modal-body">
<div my-load-document="document"></div>
<div class="media_meta_wrap clearfix">
<div class="media_modal_actions pull-right">
<a href="" class="media_modal_action_link" ng-click="download()" my-i18n="media_modal_download"></a>
<a ng-if="messageID" href="" class="media_modal_action_link" ng-click="forward()" my-i18n="media_modal_forward"></a>
<a ng-if="messageID" href="" class="media_modal_action_link" ng-click="delete()" my-i18n="media_modal_delete"></a>
</div>
<p class="media_modal_info">
<a class="media_modal_author" my-user-link="document.user_id"></a>, <span ng-bind="document.date | dateOrTime"></span>
</p>
</div>
</div>
</div>

21
app/partials/desktop/full_document.html

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
<div class="document_modal_image_wrap">
<div class="img_fullsize_with_progress_wrap document_fullsize_with_progress_wrap" ng-style="{width: frameWidth + 'px', height: frameHeight + 'px'}">
<div class="img_fullsize_progress_overlay">
<div class="img_fullsize_progress_wrap" ng-style="{width: frameWidth + 'px', height: frameHeight + 'px'}">
<div class="img_fullsize_progress progress tg_progress">
<div class="progress-bar progress-bar-success" style="width: {{document.progress.percent}}%"></div>
</div>
</div>
</div>
<div class="img_fullsize_wrap" ng-if="thumbSrc.length > 0">
<img
class="img_fullsize"
ng-src="{{thumbSrc}}"
ng-style="{width: imageWidth + 'px', height: imageHeight + 'px'}"
/>
</div>
</div>
<div class="document_fullsize_wrap" ng-click="toggleZoom(!zoomed)">
<img class="document_fullsize_img" />
</div>
</div>

2
app/partials/desktop/message.html

@ -52,7 +52,7 @@ @@ -52,7 +52,7 @@
<div ng-switch-when="messageMediaPhoto" my-message-photo></div>
<div ng-switch-when="messageMediaVideo" my-message-video></div>
<div ng-switch-when="messageMediaDocument" my-message-document></div>
<div ng-switch-when="messageMediaDocument" my-message-document="historyMessage.media.document" message-id="historyMessage.id"></div>
<div ng-switch-when="messageMediaAudio" my-message-audio></div>
<div ng-switch-when="messageMediaGeo" my-message-map></div>
<div ng-switch-when="messageMediaContact" my-message-contact></div>

37
app/partials/desktop/message_attach_document.html

@ -1,39 +1,42 @@ @@ -1,39 +1,42 @@
<div ng-switch="::historyMessage.media.document.isSpecial">
<div ng-switch="::document.isSpecial">
<div ng-switch-when="gif" my-load-gif document="historyMessage.media.document"></div>
<div ng-switch-when="gif" my-load-gif document="document"></div>
<div ng-switch-when="audio" class="im_message_audio">
<div my-audio-player audio="historyMessage.media.document"></div>
<div my-audio-player audio="document"></div>
</div>
<div ng-switch-default class="im_message_document" ng-class="{im_message_document_thumbed: !!historyMessage.media.document.thumb, im_message_document_progress: historyMessage.media.document.progress.enabled}">
<div ng-switch-default class="im_message_document clearfix" ng-class="{im_message_document_thumbed: !!document.thumb, im_message_document_progress: document.progress.enabled}">
<a href="" ng-click="downloadDoc(historyMessage.media.document.id, historyMessage.media.document.withPreview)" ng-class="{im_message_document_link_disabled: historyMessage.media.document.progress.enabled}">
<i class="icon icon-document" ng-if="::!historyMessage.media.document.thumb"></i>
<div class="im_message_document_thumb_wrap" ng-if="::historyMessage.media.document.thumb">
<a ng-if="::!document.thumb" class="im_message_file_button" ng-click="docOpen()" ng-class="{im_message_file_button_dl_doc: document.downloaded}">
<i class="im_message_file_button_icon"></i>
</a>
<a ng-if="::document.thumb" ng-click="docOpen()">
<div class="im_message_document_thumb_wrap">
<img
class="im_message_document_thumb"
my-load-thumb
thumb="historyMessage.media.document.thumb"
thumb="document.thumb"
/>
</div>
</a>
<div class="im_message_document_info">
<div class="im_message_document_name_wrap">
<span class="im_message_document_name" ng-bind="::historyMessage.media.document.file_name"></span>
<span class="im_message_document_size" ng-if="!historyMessage.media.document.progress.enabled" ng-bind="::historyMessage.media.document.size | formatSize"></span>
<span class="im_message_document_size" ng-if="historyMessage.media.document.progress.enabled" ng-bind="historyMessage.media.document.progress | formatSizeProgress"></span>
<span class="im_message_document_name" ng-bind="::document.file_name"></span>
<span class="im_message_document_size" ng-if="!document.progress.enabled" ng-bind="::document.size | formatSize"></span>
<span class="im_message_document_size" ng-if="document.progress.enabled" ng-bind="document.progress | formatSizeProgress"></span>
</div>
<div class="im_message_document_actions" ng-if="!historyMessage.media.document.progress.enabled">
<a href="" ng-click="downloadDoc(historyMessage.media.document.id)" my-i18n="message_attach_document_download"></a>
<a href="" ng-click="downloadDoc(historyMessage.media.document.id, 1)" ng-if="::historyMessage.media.document.withPreview" my-i18n="message_attach_document_open"></a>
<div class="im_message_document_actions" ng-if="!document.progress.enabled" ng-switch="document.downloaded">
<a ng-switch-when="true" href="" ng-click="docSave()" my-i18n="message_attach_document_save"></a>
<a ng-switch-default href="" ng-click="docSave()" my-i18n="message_attach_document_download"></a>
<a ng-if="::document.withPreview" href="" ng-click="docOpen()" my-i18n="message_attach_document_open"></a>
</div>
<div class="clearfix cancelable_progress_wrap" ng-if="historyMessage.media.document.progress.enabled">
<a class="im_message_media_progress_cancel pull-right" ng-click="historyMessage.media.document.progress.cancel()" my-i18n="modal_cancel"></a>
<div class="clearfix cancelable_progress_wrap" ng-if="document.progress.enabled">
<a class="im_message_media_progress_cancel pull-right" ng-click="document.progress.cancel()" my-i18n="modal_cancel"></a>
<div class="im_message_download_progress_wrap">
<div class="progress tg_down_progress">
<div class="progress-bar progress-bar-success" ng-style="{width: historyMessage.media.document.progress.percent + '%'}"></div>
<div class="progress-bar progress-bar-success" ng-style="{width: document.progress.percent + '%'}"></div>
</div>
</div>
</div>

2
app/partials/desktop/photo_modal.html

@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
</div>
<p class="media_modal_info">
<span class="media_modal_author" ng-bind-html="::photo.fromUser.rFullName"></span>, <span ng-bind="photo.date | dateOrTime"></span>
<a class="media_modal_author" my-user-link="photo.user_id"></a>, <span ng-bind="photo.date | dateOrTime"></span>
</p>
</div>

2
app/partials/desktop/video_modal.html

@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
</div>
<p class="media_modal_info">
<span class="media_modal_author" ng-bind-html="video.fromUser.rFullName"></span>, <span ng-bind="video.date | dateOrTime"></span>
<a class="media_modal_author" my-user-link="video.user_id"></a>, <span ng-bind="video.date | dateOrTime"></span>
</p>
</div>

Loading…
Cancel
Save