diff --git a/app/css/app.css b/app/css/app.css
index 7ac9490c..0b5b43f2 100644
--- a/app/css/app.css
+++ b/app/css/app.css
@@ -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"] {
.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"] {
.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 {
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 {
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 {
}
.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 {
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 {
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 {
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 {
.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 {
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 {
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 {
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 {
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 {
.icon-online {
- background: #6DBF69;
+ background: #6ec26d;
border: 1px solid #FFF;
display: block;
width: 11px;
@@ -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 {
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 {
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 {
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 {
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 {
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 {
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
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
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 {
diff --git a/app/css/desktop.css b/app/css/desktop.css
index ffbcddac..4833179a 100644
--- a/app/css/desktop.css
+++ b/app/css/desktop.css
@@ -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 {
.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 {
}
.icon-message-status {
- background: #43A4DB;
+ background: #6ba2cb;
border: 0;
display: block;
width: 10px;
@@ -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 {
.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 {
}
.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 {
margin-top: -7px;
margin-left: 43px;
}
+.emoji-wysiwyg-editor,
+.im_message_field {
+ border-radius: 0;
+}
/* Peer modals */
.user_modal_window .modal-dialog {
diff --git a/app/css/mobile.css b/app/css/mobile.css
index f77916b1..c02539ac 100644
--- a/app/css/mobile.css
+++ b/app/css/mobile.css
@@ -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;
}
diff --git a/app/img/icons/IconsetW.png b/app/img/icons/IconsetW.png
index 3b2b0cd4..39e592bf 100644
Binary files a/app/img/icons/IconsetW.png and b/app/img/icons/IconsetW.png differ
diff --git a/app/img/icons/IconsetW_1x.png b/app/img/icons/IconsetW_1x.png
index f1fa3182..92d5ec04 100644
Binary files a/app/img/icons/IconsetW_1x.png and b/app/img/icons/IconsetW_1x.png differ
diff --git a/app/js/controllers.js b/app/js/controllers.js
index 47ab1d5e..7420b0c7 100644
--- a/app/js/controllers.js
+++ b/app/js/controllers.js
@@ -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'])
});
})
+ .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);
diff --git a/app/js/directives.js b/app/js/directives.js
index 6ded1e2f..09e9235c 100644
--- a/app/js/directives.js
+++ b/app/js/directives.js
@@ -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'])
})
- .directive('myLoadGif', function($rootScope, MtpApiFileManager) {
+ .directive('myLoadGif', function($rootScope, MtpApiFileManager, AppDocsManager) {
return {
link: link,
@@ -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'])
}
})
+ .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'])
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'])
prevMargin = margin;
};
+ $($window).on('resize', updateMargin);
+
onContentLoaded(updateMargin);
- $($window).on('resize', updateMargin);
$scope.$on('ui_height', function () {
onContentLoaded(updateMargin);
diff --git a/app/js/i18n.js b/app/js/i18n.js
index 4e02f554..197fc73a 100644
--- a/app/js/i18n.js
+++ b/app/js/i18n.js
@@ -21,16 +21,6 @@ angular.module('myApp.i18n', ['izhukov.utils'])
});
}
- function encodeEntities(value) {
- return value.
- replace(/&/g, '&').
- replace(/([^\#-~| |!\n\*])/g, function (value) { // non-alphanumeric
- return '' + value.charCodeAt(0) + ';';
- }).
- replace(//g, '>');
- }
-
function parseMarkdownString(msgstr, msgid) {
msgstr = msgstr.replace(/\*\*(.+?)\*\*/g, "$1")
.replace(/\n/g, "
");
diff --git a/app/js/lib/mtproto_wrapper.js b/app/js/lib/mtproto_wrapper.js
index bf6ca356..951e8185 100644
--- a/app/js/lib/mtproto_wrapper.js
+++ b/app/js/lib/mtproto_wrapper.js
@@ -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'])
return {
getCachedFile: getCachedFile,
+ getDownloadedFile: getDownloadedFile,
downloadFile: downloadFile,
downloadSmallFile: downloadSmallFile,
saveSmallFile: saveSmallFile,
diff --git a/app/js/lib/ng_utils.js b/app/js/lib/ng_utils.js
index 5e7c81a9..61e17733 100644
--- a/app/js/lib/ng_utils.js
+++ b/app/js/lib/ng_utils.js
@@ -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', [])
};
})
+.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 {
diff --git a/app/js/lib/utils.js b/app/js/lib/utils.js
index 46cf9624..a86851bc 100644
--- a/app/js/lib/utils.js
+++ b/app/js/lib/utils.js
@@ -114,3 +114,35 @@ function templateUrl (tplName) {
return 'partials/' + (Config.Mobile ? 'mobile' : 'desktop') + '/' + tplName + '.html';
}
+function encodeEntities(value) {
+ return value.
+ replace(/&/g, '&').
+ replace(/([^\#-~| |!])/g, function (value) { // non-alphanumeric
+ return '' + value.charCodeAt(0) + ';';
+ }).
+ replace(//g, '>');
+}
+
+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};
+}
diff --git a/app/js/locales/en-us.json b/app/js/locales/en-us.json
index 64c0ca8d..b8dbef04 100644
--- a/app/js/locales/en-us.json
+++ b/app/js/locales/en-us.json
@@ -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",
diff --git a/app/js/services.js b/app/js/services.js
index 8a6b6602..fc3de5fd 100644
--- a/app/js/services.js
+++ b/app/js/services.js
@@ -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'])
}
})
-.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'])
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'])
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'])
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'])
}
})
-.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'])
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'])
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'])
}
})
-.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'])
wrapPlainText: wrapPlainText
};
- function encodeEntities(value) {
- return value.
- replace(/&/g, '&').
- replace(/([^\#-~| |!])/g, function (value) { // non-alphanumeric
- return '' + value.charCodeAt(0) + ';';
- }).
- replace(//g, '>');
- }
-
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'])
})
-
-.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;
diff --git a/app/partials/desktop/document_modal.html b/app/partials/desktop/document_modal.html
new file mode 100644
index 00000000..0a0e494f
--- /dev/null
+++ b/app/partials/desktop/document_modal.html
@@ -0,0 +1,21 @@
+