Basic Safari, Mozilla support, perfomance improvements, bugfixes
* Added data:image/jpeg;base64, mode for small images on browsers, which dont support LocalFileSystem. Please use Chrome for full experience * Speed-up chat modal window, by making getFullChat request asynchronous * Added basic error handling for photo/video modal windows * Improved dateOrTime filter perfomance by caching its values * Added sentMessages cleanup * Guest DCs networkers now dont perform http_wait if no sentMessages pending * Added favicon blinking on new message
This commit is contained in:
parent
deae4717a6
commit
ca781f6c86
@ -226,6 +226,7 @@ fieldset[disabled] .btn-tg.active {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.img_fullsize_with_progress_wrap {
|
.img_fullsize_with_progress_wrap {
|
||||||
position: relative;
|
position: relative;
|
||||||
/*margin: 0 auto 20px;*/
|
/*margin: 0 auto 20px;*/
|
||||||
@ -286,7 +287,8 @@ fieldset[disabled] .btn-tg.active {
|
|||||||
|
|
||||||
.im_page_wrap {
|
.im_page_wrap {
|
||||||
background: #FFF;
|
background: #FFF;
|
||||||
max-width: 1000px;
|
/*max-width: 1000px;*/
|
||||||
|
width: 1000px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
-webkit-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1);
|
-webkit-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
@ -328,11 +330,13 @@ fieldset[disabled] .btn-tg.active {
|
|||||||
|
|
||||||
|
|
||||||
/* Dialogs list */
|
/* Dialogs list */
|
||||||
|
.im_dialogs_col {
|
||||||
|
width: 315px;
|
||||||
|
}
|
||||||
.im_dialogs_col .nano > .pane {
|
.im_dialogs_col .nano > .pane {
|
||||||
background : rgba(0,0,0,.0);
|
background : rgba(0,0,0,.0);
|
||||||
width : 12px;
|
width : 12px;
|
||||||
right: -7px;
|
right: 0px;
|
||||||
-webkit-transition : .2s;
|
-webkit-transition : .2s;
|
||||||
-moz-transition : .2s;
|
-moz-transition : .2s;
|
||||||
-o-transition : .2s;
|
-o-transition : .2s;
|
||||||
@ -372,15 +376,10 @@ fieldset[disabled] .btn-tg.active {
|
|||||||
|
|
||||||
|
|
||||||
.im_dialogs_wrap {
|
.im_dialogs_wrap {
|
||||||
overflow: visible;
|
|
||||||
overflow-x: visible !important;
|
|
||||||
overflow-y: visible;
|
|
||||||
}
|
}
|
||||||
.im_dialogs_scrollable_wrap {
|
.im_dialogs_scrollable_wrap {
|
||||||
/*border-right: 2px solid #E9EBED;*/
|
padding: 0 19px 0 12px;
|
||||||
padding: 0 12px;
|
|
||||||
outline: none ! important;
|
outline: none ! important;
|
||||||
overflow-x: visible;
|
|
||||||
}
|
}
|
||||||
.im_dialogs_scrollable_wrap .nav-stacked > li + li {
|
.im_dialogs_scrollable_wrap .nav-stacked > li + li {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
@ -538,6 +537,9 @@ a.im_dialog:hover .im_dialog_message_text {
|
|||||||
-moz-box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.12);
|
-moz-box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.12);
|
||||||
box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.12);
|
box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.12);
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
.im_history_panel {
|
.im_history_panel {
|
||||||
padding: 10px 4px 0;
|
padding: 10px 4px 0;
|
||||||
@ -1104,7 +1106,6 @@ img.img_fullsize {
|
|||||||
.chat_modal_window .modal-dialog {
|
.chat_modal_window .modal-dialog {
|
||||||
max-width: 506px;
|
max-width: 506px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat_modal_wrap .modal-body {
|
.chat_modal_wrap .modal-body {
|
||||||
padding: 23px 25px 15px;
|
padding: 23px 25px 15px;
|
||||||
}
|
}
|
||||||
@ -1253,4 +1254,32 @@ img.img_fullsize {
|
|||||||
.error_modal_description {
|
.error_modal_description {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 40px 20px;
|
padding: 40px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.photo_modal_error {
|
||||||
|
color: #999;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -20px;
|
||||||
|
padding: 0 20px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.4em;
|
||||||
|
line-height: 160%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video_full_error {
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: rgba(0,0,0,0.6);
|
||||||
|
color: #FFF;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
margin: -40px 10px 0;
|
||||||
|
padding: 10px 10px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.4em;
|
||||||
|
line-height: 160%;
|
||||||
}
|
}
|
BIN
app/favicon_unread.ico
Normal file
BIN
app/favicon_unread.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 738 B |
BIN
app/img/placeholders/PhotoThumbConversation.gif
Normal file
BIN
app/img/placeholders/PhotoThumbConversation.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 B |
BIN
app/img/placeholders/PhotoThumbModal.gif
Normal file
BIN
app/img/placeholders/PhotoThumbModal.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 B |
BIN
app/img/placeholders/VideoThumbConversation.gif
Normal file
BIN
app/img/placeholders/VideoThumbConversation.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 B |
BIN
app/img/placeholders/VideoThumbModal.gif
Normal file
BIN
app/img/placeholders/VideoThumbModal.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 B |
@ -7,7 +7,7 @@
|
|||||||
<link rel="stylesheet" href="vendor/angular/angular-csp.css"/>
|
<link rel="stylesheet" href="vendor/angular/angular-csp.css"/>
|
||||||
<link rel="stylesheet" href="vendor/bootstrap/css/bootstrap.css"/>
|
<link rel="stylesheet" href="vendor/bootstrap/css/bootstrap.css"/>
|
||||||
<link rel="stylesheet" href="vendor/jquery.nanoscroller/nanoscroller.css"/>
|
<link rel="stylesheet" href="vendor/jquery.nanoscroller/nanoscroller.css"/>
|
||||||
<link rel="stylesheet" href="css/app.css?3"/>
|
<link rel="stylesheet" href="css/app.css?4"/>
|
||||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -33,14 +33,14 @@
|
|||||||
|
|
||||||
|
|
||||||
<script type="text/javascript" src="js/lib/config.js"></script>
|
<script type="text/javascript" src="js/lib/config.js"></script>
|
||||||
<script type="text/javascript" src="js/lib/mtproto.js?1"></script>
|
<script type="text/javascript" src="js/lib/mtproto.js?2"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/util.js"></script>
|
<script type="text/javascript" src="js/util.js"></script>
|
||||||
<script type="text/javascript" src="js/app.js?2"></script>
|
<script type="text/javascript" src="js/app.js?3"></script>
|
||||||
<script type="text/javascript" src="js/services.js?5"></script>
|
<script type="text/javascript" src="js/services.js?6"></script>
|
||||||
<script type="text/javascript" src="js/controllers.js?4"></script>
|
<script type="text/javascript" src="js/controllers.js?5"></script>
|
||||||
<script type="text/javascript" src="js/filters.js?2"></script>
|
<script type="text/javascript" src="js/filters.js?3"></script>
|
||||||
<script type="text/javascript" src="js/directives.js?4"></script>
|
<script type="text/javascript" src="js/directives.js?5"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -25,7 +25,7 @@ angular.module('myApp', [
|
|||||||
config(['$locationProvider', '$routeProvider', '$compileProvider', function($locationProvider, $routeProvider, $compileProvider) {
|
config(['$locationProvider', '$routeProvider', '$compileProvider', function($locationProvider, $routeProvider, $compileProvider) {
|
||||||
|
|
||||||
var icons = {}, reverseIcons = {}, i, j, hex, name, dataItem,
|
var icons = {}, reverseIcons = {}, i, j, hex, name, dataItem,
|
||||||
ranges = [[0x1f600, 0x1f637], [0x270a, 0x270c], [0x1f446, 0x1f450]];
|
ranges = [[0x1f600, 0x1f637], [0x261d, 0x263f], [0x270a, 0x270c], [0x1f446, 0x1f450]];
|
||||||
|
|
||||||
for (j in ranges) {
|
for (j in ranges) {
|
||||||
for (i = ranges[j][0]; i <= ranges[j][1]; i++) {
|
for (i = ranges[j][0]; i <= ranges[j][1]; i++) {
|
||||||
|
@ -121,7 +121,8 @@ angular.module('myApp.controllers', [])
|
|||||||
$scope.isLoggedIn = true;
|
$scope.isLoggedIn = true;
|
||||||
$scope.logOut = function () {
|
$scope.logOut = function () {
|
||||||
MtpApiManager.logOut().then(function () {
|
MtpApiManager.logOut().then(function () {
|
||||||
location.href = 'login';
|
location.hash = '/login';
|
||||||
|
location.reload();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,8 +488,17 @@ angular.module('myApp.controllers', [])
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
.controller('ChatModalController', function ($scope, AppUsersManager, AppChatsManager, fullChat) {
|
.controller('ChatModalController', function ($scope, $timeout, AppUsersManager, AppChatsManager, MtpApiManager) {
|
||||||
$scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, fullChat);
|
$scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, {});
|
||||||
|
|
||||||
|
MtpApiManager.invokeApi('messages.getFullChat', {
|
||||||
|
chat_id: $scope.chatID
|
||||||
|
}).then(function (result) {
|
||||||
|
AppChatsManager.saveApiChats(result.chats);
|
||||||
|
AppUsersManager.saveApiUsers(result.users);
|
||||||
|
|
||||||
|
$scope.chatFull = AppChatsManager.wrapForFull($scope.chatID, result.full_chat);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
|||||||
restrict: 'AE',
|
restrict: 'AE',
|
||||||
scope: true,
|
scope: true,
|
||||||
translude: false,
|
translude: false,
|
||||||
templateUrl: 'partials/dialog.html?1'
|
templateUrl: 'partials/dialog.html?2'
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
|||||||
restrict: 'AE',
|
restrict: 'AE',
|
||||||
scope: true,
|
scope: true,
|
||||||
translude: false,
|
translude: false,
|
||||||
templateUrl: 'partials/message.html?2'
|
templateUrl: 'partials/message.html?3'
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -399,6 +399,10 @@ angular.module('myApp.directives', ['myApp.filters'])
|
|||||||
<img class="photo_modal_image" width="{{fullPhoto.width}}" height="{{fullPhoto.height}}" />\
|
<img class="photo_modal_image" width="{{fullPhoto.width}}" height="{{fullPhoto.height}}" />\
|
||||||
</a>\
|
</a>\
|
||||||
</div>\
|
</div>\
|
||||||
|
<div class="photo_modal_error_wrap" ng-if="error">\
|
||||||
|
<div class="photo_modal_error" ng-if="error.html" ng-bind-html="error.html"></div>\
|
||||||
|
<div class="photo_modal_error" ng-if="error.text">{{error.text}}</div>\
|
||||||
|
</div>\
|
||||||
</div>',
|
</div>',
|
||||||
scope: {
|
scope: {
|
||||||
fullPhoto: '=',
|
fullPhoto: '=',
|
||||||
@ -411,8 +415,9 @@ angular.module('myApp.directives', ['myApp.filters'])
|
|||||||
fullLoaded = false;
|
fullLoaded = false;
|
||||||
|
|
||||||
|
|
||||||
|
imgElement.attr('src', scope.fullPhoto.placeholder || 'img/blank.gif');
|
||||||
|
|
||||||
if (!scope.fullPhoto.location) {
|
if (!scope.fullPhoto.location) {
|
||||||
imgElement.attr('src', scope.fullPhoto.placeholder || '');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,10 +455,12 @@ angular.module('myApp.directives', ['myApp.filters'])
|
|||||||
}, function (e) {
|
}, function (e) {
|
||||||
dLog('Download image failed', e, scope.fullPhoto.location);
|
dLog('Download image failed', e, scope.fullPhoto.location);
|
||||||
scope.progress.enabled = false;
|
scope.progress.enabled = false;
|
||||||
imgElement
|
|
||||||
.attr('src', scope.fullPhoto.placeholder || '')
|
|
||||||
.removeClass('thumb_blurred');
|
|
||||||
|
|
||||||
|
if (e && e.type == 'FS_BROWSER_UNSUPPORTED') {
|
||||||
|
scope.error = {html: 'Your browser doesn\'t support <a href="https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem" target="_blank">LocalFileSystem</a> feature which is needed to display this image.<br/>Please, install <a href="http://google.com/chrome" target="_blank">Google Chrome</a> or use <a href="https://telegram.org/" target="_blank">mobile app</a> instead.'};
|
||||||
|
} else {
|
||||||
|
scope.error = {text: 'Download failed', error: e};
|
||||||
|
}
|
||||||
}, function (progress) {
|
}, function (progress) {
|
||||||
scope.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
|
scope.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
|
||||||
});
|
});
|
||||||
@ -487,6 +494,10 @@ angular.module('myApp.directives', ['myApp.filters'])
|
|||||||
<source ng-src="{{player.src}}" type="video/mp4">\
|
<source ng-src="{{player.src}}" type="video/mp4">\
|
||||||
</video>\
|
</video>\
|
||||||
</div>\
|
</div>\
|
||||||
|
<div class="video_full_error_wrap" ng-if="error">\
|
||||||
|
<div class="video_full_error" ng-if="error.html" ng-bind-html="error.html"></div>\
|
||||||
|
<div class="video_full_error" ng-if="error.text">{{error.text}}</div>\
|
||||||
|
</div>\
|
||||||
</div>',
|
</div>',
|
||||||
scope: {
|
scope: {
|
||||||
video: '='
|
video: '='
|
||||||
@ -519,9 +530,16 @@ angular.module('myApp.directives', ['myApp.filters'])
|
|||||||
scope.player.quicktime = hasQt;
|
scope.player.quicktime = hasQt;
|
||||||
scope.player.src = $sce.trustAsResourceUrl(url);
|
scope.player.src = $sce.trustAsResourceUrl(url);
|
||||||
}, function (e) {
|
}, function (e) {
|
||||||
dLog('Download image failed', e, scope.fullPhoto.location);
|
dLog('Download video failed', e, scope.video);
|
||||||
scope.progress.enabled = false;
|
scope.progress.enabled = false;
|
||||||
scope.player.src = '';
|
scope.player.src = '';
|
||||||
|
|
||||||
|
if (e && e.type == 'FS_BROWSER_UNSUPPORTED') {
|
||||||
|
scope.error = {html: 'Your browser doesn\'t support <a href="https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem" target="_blank">LocalFileSystem</a> feature which is needed to play this video.<br/>Please, install <a href="http://google.com/chrome" target="_blank">Google Chrome</a> or use <a href="https://telegram.org/" target="_blank">mobile app</a> instead.'};
|
||||||
|
} else {
|
||||||
|
scope.error = {text: 'Video download failed', error: e};
|
||||||
|
}
|
||||||
|
|
||||||
}, function (progress) {
|
}, function (progress) {
|
||||||
scope.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
|
scope.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
|
||||||
});
|
});
|
||||||
|
@ -52,7 +52,14 @@ angular.module('myApp.filters', [])
|
|||||||
}])
|
}])
|
||||||
|
|
||||||
.filter('dateOrTime', ['$filter', function($filter) {
|
.filter('dateOrTime', ['$filter', function($filter) {
|
||||||
|
var cachedDates = {};
|
||||||
|
|
||||||
return function (timestamp) {
|
return function (timestamp) {
|
||||||
|
|
||||||
|
if (cachedDates[timestamp]) {
|
||||||
|
return cachedDates[timestamp];
|
||||||
|
}
|
||||||
|
|
||||||
var ticks = timestamp * 1000,
|
var ticks = timestamp * 1000,
|
||||||
diff = Math.abs(+new Date() - ticks),
|
diff = Math.abs(+new Date() - ticks),
|
||||||
format = 'HH:mm';
|
format = 'HH:mm';
|
||||||
@ -63,7 +70,7 @@ angular.module('myApp.filters', [])
|
|||||||
else if (diff > 43200000) { // 12 hours
|
else if (diff > 43200000) { // 12 hours
|
||||||
format = 'EEE';
|
format = 'EEE';
|
||||||
}
|
}
|
||||||
return $filter('date')(ticks, format);
|
return cachedDates[timestamp] = $filter('date')(ticks, format);
|
||||||
}
|
}
|
||||||
}])
|
}])
|
||||||
|
|
||||||
|
@ -61,6 +61,40 @@ function bytesFromHex (hexString) {
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bytesToBase64 (bytes) {
|
||||||
|
var mod3, result = '';
|
||||||
|
|
||||||
|
for (var nLen = bytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
|
||||||
|
mod3 = nIdx % 3;
|
||||||
|
nUint24 |= bytes[nIdx] << (16 >>> mod3 & 24);
|
||||||
|
if (mod3 === 2 || nLen - nIdx === 1) {
|
||||||
|
result += String.fromCharCode(
|
||||||
|
uint6ToBase64(nUint24 >>> 18 & 63),
|
||||||
|
uint6ToBase64(nUint24 >>> 12 & 63),
|
||||||
|
uint6ToBase64(nUint24 >>> 6 & 63),
|
||||||
|
uint6ToBase64(nUint24 & 63)
|
||||||
|
);
|
||||||
|
nUint24 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.replace(/A(?=A$|$)/g, '=');
|
||||||
|
}
|
||||||
|
|
||||||
|
function uint6ToBase64 (nUint6) {
|
||||||
|
return nUint6 < 26
|
||||||
|
? nUint6 + 65
|
||||||
|
: nUint6 < 52
|
||||||
|
? nUint6 + 71
|
||||||
|
: nUint6 < 62
|
||||||
|
? nUint6 - 4
|
||||||
|
: nUint6 === 62
|
||||||
|
? 43
|
||||||
|
: nUint6 === 63
|
||||||
|
? 47
|
||||||
|
: 65;
|
||||||
|
}
|
||||||
|
|
||||||
function bytesCmp (bytes1, bytes2) {
|
function bytesCmp (bytes1, bytes2) {
|
||||||
var len = bytes1.length;
|
var len = bytes1.length;
|
||||||
if (len != bytes2.length) {
|
if (len != bytes2.length) {
|
||||||
@ -120,14 +154,7 @@ function bytesFromBigInt (bigInt, len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function bytesToArrayBuffer (b) {
|
function bytesToArrayBuffer (b) {
|
||||||
var len = b.length,
|
return (new Uint8Array(b)).buffer;
|
||||||
array = new Uint8Array(len);
|
|
||||||
|
|
||||||
for (var i = 0; i < len; ++i) {
|
|
||||||
array[i] = b[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return array.buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function bytesFromArrayBuffer (buffer) {
|
function bytesFromArrayBuffer (buffer) {
|
||||||
@ -1482,14 +1509,21 @@ factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerato
|
|||||||
|
|
||||||
this.serverSalt = serverSalt;
|
this.serverSalt = serverSalt;
|
||||||
|
|
||||||
|
// if (1 == dcID) {
|
||||||
|
// var self = this;
|
||||||
|
// (function () {
|
||||||
|
// dLog('update server salt');
|
||||||
|
// self.serverSalt = [0,0,0,0,0,0,0,0];
|
||||||
|
// setTimeout(arguments.callee, nextRandomInt(2000, 12345));
|
||||||
|
// })();
|
||||||
|
// }
|
||||||
|
|
||||||
this.sessionID = new Array(8);
|
this.sessionID = new Array(8);
|
||||||
MtpSecureRandom.nextBytes(this.sessionID);
|
MtpSecureRandom.nextBytes(this.sessionID);
|
||||||
|
|
||||||
if (true) {
|
if (false) {
|
||||||
this.sessionID[0] = 0xA;
|
this.sessionID[0] = 0xAB;
|
||||||
this.sessionID[1] = 0xB;
|
this.sessionID[1] = 0xCD;
|
||||||
this.sessionID[3] = 0xC;
|
|
||||||
this.sessionID[4] = 0xD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.seqNo = 0;
|
this.seqNo = 0;
|
||||||
@ -1594,7 +1628,14 @@ factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerato
|
|||||||
if (this.longPollPending && (new Date().getTime()) < this.longPollPending) {
|
if (this.longPollPending && (new Date().getTime()) < this.longPollPending) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.sendLongPoll();
|
var self = this;
|
||||||
|
AppConfigManager.get('dc').then(function (baseDcID) {
|
||||||
|
if (baseDcID != self.dcID && self.cleanupSent()) {
|
||||||
|
// console.warn('send long-poll for guest DC is delayed', self.dcID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.sendLongPoll();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
MtpNetworker.prototype.sendLongPoll = function() {
|
MtpNetworker.prototype.sendLongPoll = function() {
|
||||||
@ -1741,22 +1782,24 @@ factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerato
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.pendingAcks = [];
|
this.pendingAcks = [];
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this.sendEncryptedRequest(message).then(function (result) {
|
this.sendEncryptedRequest(message).then(function (result) {
|
||||||
self.parseResponse(result.data);
|
self.parseResponse(result.data).then(function (response) {
|
||||||
|
// dLog('Server response', self.dcID, response);
|
||||||
|
|
||||||
if (noResponseMsgs.length) {
|
self.processMessage(response.response, response.messageID, response.sessionID);
|
||||||
$timeout(function () {
|
|
||||||
angular.forEach(noResponseMsgs, function (msgID) {
|
angular.forEach(noResponseMsgs, function (msgID) {
|
||||||
if (self.sentMessages[msgID]) {
|
if (self.sentMessages[msgID]) {
|
||||||
var deferred = self.sentMessages[msgID].deferred;
|
var deferred = self.sentMessages[msgID].deferred;
|
||||||
delete self.sentMessages[msgID];
|
delete self.sentMessages[msgID];
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, 200);
|
|
||||||
}
|
self.cleanupSent();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1833,7 +1876,7 @@ factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerato
|
|||||||
var dataLength = responseBuffer.byteLength - deserializer.getOffset();
|
var dataLength = responseBuffer.byteLength - deserializer.getOffset();
|
||||||
var encryptedData = deserializer.fetchRawBytes(dataLength, 'encrypted_data');
|
var encryptedData = deserializer.fetchRawBytes(dataLength, 'encrypted_data');
|
||||||
|
|
||||||
this.getDecryptedMessage(msgKey, encryptedData).then(function (dataWithPadding) {
|
return this.getDecryptedMessage(msgKey, encryptedData).then(function (dataWithPadding) {
|
||||||
var buffer = bytesToArrayBuffer(dataWithPadding);
|
var buffer = bytesToArrayBuffer(dataWithPadding);
|
||||||
|
|
||||||
var deserializer = new TLDeserialization(buffer, {mtproto: true});
|
var deserializer = new TLDeserialization(buffer, {mtproto: true});
|
||||||
@ -1848,7 +1891,7 @@ factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerato
|
|||||||
|
|
||||||
var offset = deserializer.getOffset();
|
var offset = deserializer.getOffset();
|
||||||
|
|
||||||
MtpSha1Service.hash(dataWithPadding.slice(0, offset)).then(function (dataHashed) {
|
return MtpSha1Service.hash(dataWithPadding.slice(0, offset)).then(function (dataHashed) {
|
||||||
if (!bytesCmp(msgKey, dataHashed.slice(-16))) {
|
if (!bytesCmp(msgKey, dataHashed.slice(-16))) {
|
||||||
throw new Error('server msgKey mismatch');
|
throw new Error('server msgKey mismatch');
|
||||||
}
|
}
|
||||||
@ -1858,9 +1901,12 @@ factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerato
|
|||||||
|
|
||||||
var response = deserializer.fetchObject('', 'INPUT');
|
var response = deserializer.fetchObject('', 'INPUT');
|
||||||
|
|
||||||
// dLog('Server response', response);
|
return {
|
||||||
|
response: response,
|
||||||
self.processResponse(response, messageID, sessionID, seqNo);
|
messageID: messageID,
|
||||||
|
sessionID: sessionID,
|
||||||
|
seqNo: seqNo
|
||||||
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -1908,10 +1954,35 @@ factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerato
|
|||||||
this.sheduleRequest(100);
|
this.sheduleRequest(100);
|
||||||
};
|
};
|
||||||
|
|
||||||
MtpNetworker.prototype.processResponse = function (response, messageID, sessionID, seqNo) {
|
MtpNetworker.prototype.cleanupSent = function () {
|
||||||
return this.processMessage(response, messageID, sessionID);
|
var self = this;
|
||||||
|
var notEmpty = false;
|
||||||
|
// dLog('clean start', this.dcID/*, this.sentMessages*/);
|
||||||
|
angular.forEach(this.sentMessages, function(message, msgID) {
|
||||||
|
// dLog('clean iter', msgID, message);
|
||||||
|
if (message.notContentRelated && self.pendingMessages[msgID] === undefined) {
|
||||||
|
// dLog('clean notContentRelated', msgID);
|
||||||
|
delete self.sentMessages[msgID];
|
||||||
|
}
|
||||||
|
else if (message.container) {
|
||||||
|
for (var i = 0; i < message.inner.length; i++) {
|
||||||
|
if (self.sentMessages[message.inner[i]] !== undefined) {
|
||||||
|
// dLog('clean failed, found', msgID, message.inner[i], self.sentMessages[message.inner[i]].seq_no);
|
||||||
|
notEmpty = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// dLog('clean container', msgID);
|
||||||
|
delete self.sentMessages[msgID];
|
||||||
|
} else {
|
||||||
|
notEmpty = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return !notEmpty;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MtpNetworker.prototype.processMessageAck = function (messageID) {
|
MtpNetworker.prototype.processMessageAck = function (messageID) {
|
||||||
var sentMessage = this.sentMessages[messageID];
|
var sentMessage = this.sentMessages[messageID];
|
||||||
if (sentMessage && !sentMessage.acked) {
|
if (sentMessage && !sentMessage.acked) {
|
||||||
@ -1948,6 +2019,7 @@ factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerato
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'bad_server_salt':
|
case 'bad_server_salt':
|
||||||
|
dLog('bad server salt', message);
|
||||||
var sentMsg = this.sentMessages[message.bad_msg_id];
|
var sentMsg = this.sentMessages[message.bad_msg_id];
|
||||||
if (!sentMsg || sentMsg.seq_no != message.bad_msg_seqno) {
|
if (!sentMsg || sentMsg.seq_no != message.bad_msg_seqno) {
|
||||||
dLog(message.bad_msg_id, message.bad_msg_seqno);
|
dLog(message.bad_msg_id, message.bad_msg_seqno);
|
||||||
@ -2005,7 +2077,7 @@ factory('MtpNetworkerFactory', function (MtpDcConfigurator, MtpMessageIdGenerato
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (deferred) {
|
if (deferred) {
|
||||||
dLog('rpc response', message.result);
|
dLog('rpc response', message.result._);
|
||||||
sentMessage.deferred.resolve(message.result);
|
sentMessage.deferred.resolve(message.result);
|
||||||
}
|
}
|
||||||
if (sentMessage.isAPI) {
|
if (sentMessage.isAPI) {
|
||||||
@ -2077,14 +2149,13 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker
|
|||||||
return $q.when(cachedNetworkers[dcID]);
|
return $q.when(cachedNetworkers[dcID]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var deferred = $q.defer(),
|
var akk = 'dc' + dcID + '_auth_key',
|
||||||
ak = 'dc' + dcID + '_auth_key',
|
|
||||||
ssk = 'dc' + dcID + '_server_salt';
|
ssk = 'dc' + dcID + '_server_salt';
|
||||||
|
|
||||||
AppConfigManager.get(ak, ssk).then(function (result) {
|
return AppConfigManager.get(akk, ssk).then(function (result) {
|
||||||
|
|
||||||
if (cachedNetworkers[dcID] !== undefined) {
|
if (cachedNetworkers[dcID] !== undefined) {
|
||||||
return deferred.resolve(cachedNetworkers[dcID]);
|
return cachedNetworkers[dcID];
|
||||||
}
|
}
|
||||||
|
|
||||||
var authKeyHex = result[0],
|
var authKeyHex = result[0],
|
||||||
@ -2094,26 +2165,21 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker
|
|||||||
var authKey = bytesFromHex(authKeyHex);
|
var authKey = bytesFromHex(authKeyHex);
|
||||||
var serverSalt = bytesFromHex(serverSaltHex);
|
var serverSalt = bytesFromHex(serverSaltHex);
|
||||||
|
|
||||||
return deferred.resolve(cachedNetworkers[dcID] = MtpNetworkerFactory.getNetworker(dcID, authKey, serverSalt));
|
return cachedNetworkers[dcID] = MtpNetworkerFactory.getNetworker(dcID, authKey, serverSalt);
|
||||||
}
|
}
|
||||||
|
|
||||||
MtpAuthorizer.auth(dcID).then(function (auth) {
|
return MtpAuthorizer.auth(dcID).then(function (auth) {
|
||||||
var storeObj = {};
|
var storeObj = {};
|
||||||
storeObj[ak] = bytesToHex(auth.authKey);
|
storeObj[akk] = bytesToHex(auth.authKey);
|
||||||
storeObj[ssk] = bytesToHex(auth.serverSalt);
|
storeObj[ssk] = bytesToHex(auth.serverSalt);
|
||||||
AppConfigManager.set(storeObj);
|
AppConfigManager.set(storeObj);
|
||||||
|
|
||||||
deferred.resolve(
|
return cachedNetworkers[dcID] = MtpNetworkerFactory.getNetworker(dcID, auth.authKey, auth.serverSalt);
|
||||||
cachedNetworkers[dcID] = MtpNetworkerFactory.getNetworker(dcID, auth.authKey, auth.serverSalt)
|
|
||||||
);
|
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
dLog('Get networker error', error, error.stack);
|
dLog('Get networker error', error, error.stack);
|
||||||
deferred.reject(error);
|
return error;
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function mtpInvokeApi (method, params, options) {
|
function mtpInvokeApi (method, params, options) {
|
||||||
@ -2189,7 +2255,12 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getBaseDcID () {
|
||||||
|
return baseDcID || false;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
getBaseDcID: getBaseDcID,
|
||||||
getUserID: mtpGetUserID,
|
getUserID: mtpGetUserID,
|
||||||
invokeApi: mtpInvokeApi,
|
invokeApi: mtpInvokeApi,
|
||||||
setUserAuth: mtpSetUserAuth,
|
setUserAuth: mtpSetUserAuth,
|
||||||
@ -2205,22 +2276,28 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
|
|||||||
var cachedSavePromises = {};
|
var cachedSavePromises = {};
|
||||||
var cachedDownloadPromises = {};
|
var cachedDownloadPromises = {};
|
||||||
|
|
||||||
var downloadPull = [];
|
var downloadPulls = {};
|
||||||
var downloadActive = 0;
|
var downloadActive = 0;
|
||||||
var downloadLimit = 5;
|
var downloadLimit = 5;
|
||||||
|
|
||||||
function downloadRequest(cb, activeDelta) {
|
function downloadRequest(dcID, cb, activeDelta) {
|
||||||
|
if (downloadPulls[dcID] === undefined) {
|
||||||
|
downloadPulls[dcID] = [];
|
||||||
|
}
|
||||||
|
var downloadPull = downloadPulls[dcID];
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
downloadPull.push({cb: cb, deferred: deferred, activeDelta: activeDelta});
|
downloadPull.push({cb: cb, deferred: deferred, activeDelta: activeDelta});
|
||||||
downloadCheck();
|
downloadCheck(dcID);
|
||||||
|
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
|
||||||
function downloadCheck() {
|
function downloadCheck(dcID) {
|
||||||
if (downloadActive >= downloadLimit || !downloadPull.length) {
|
var downloadPull = downloadPulls[dcID];
|
||||||
|
|
||||||
|
if (downloadActive >= downloadLimit || !downloadPull || !downloadPull.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2233,13 +2310,13 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
|
|||||||
data.cb()
|
data.cb()
|
||||||
.then(function (result) {
|
.then(function (result) {
|
||||||
downloadActive -= activeDelta;
|
downloadActive -= activeDelta;
|
||||||
downloadCheck();
|
downloadCheck(dcID);
|
||||||
|
|
||||||
data.deferred.resolve(result);
|
data.deferred.resolve(result);
|
||||||
|
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
downloadActive -= activeDelta;
|
downloadActive -= activeDelta;
|
||||||
downloadCheck();
|
downloadCheck(dcID);
|
||||||
|
|
||||||
data.deferred.reject(error);
|
data.deferred.reject(error);
|
||||||
})
|
})
|
||||||
@ -2250,10 +2327,14 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
|
|||||||
return $q.when(cachedFS);
|
return $q.when(cachedFS);
|
||||||
}
|
}
|
||||||
|
|
||||||
var deferred = $q.defer();
|
|
||||||
|
|
||||||
$window.requestFileSystem = $window.requestFileSystem || $window.webkitRequestFileSystem;
|
$window.requestFileSystem = $window.requestFileSystem || $window.webkitRequestFileSystem;
|
||||||
|
|
||||||
|
if (!$window.requestFileSystem) {
|
||||||
|
return $q.reject({type: 'FS_BROWSER_UNSUPPORTED', description: 'requestFileSystem not present'});
|
||||||
|
}
|
||||||
|
|
||||||
|
var deferred = $q.defer();
|
||||||
|
|
||||||
$window.requestFileSystem($window.TEMPORARY, 5*1024*1024, function (fs) {
|
$window.requestFileSystem($window.TEMPORARY, 5*1024*1024, function (fs) {
|
||||||
cachedFS = fs;
|
cachedFS = fs;
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
@ -2368,7 +2449,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
|
|||||||
},
|
},
|
||||||
doDownload = function () {
|
doDownload = function () {
|
||||||
cachedFS.root.getFile(fileName, {create: true}, function(fileEntry) {
|
cachedFS.root.getFile(fileName, {create: true}, function(fileEntry) {
|
||||||
var downloadPromise = downloadRequest(function () {
|
var downloadPromise = downloadRequest(location.dc_id, function () {
|
||||||
// dLog('next small promise');
|
// dLog('next small promise');
|
||||||
return MtpApiManager.invokeApi('upload.getFile', {
|
return MtpApiManager.invokeApi('upload.getFile', {
|
||||||
location: angular.extend({}, location, {_: 'inputFileLocation'}),
|
location: angular.extend({}, location, {_: 'inputFileLocation'}),
|
||||||
@ -2400,7 +2481,19 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
|
|||||||
}
|
}
|
||||||
}, errorHandler);
|
}, errorHandler);
|
||||||
}, doDownload);
|
}, doDownload);
|
||||||
}, errorHandler);
|
}, function (error) {
|
||||||
|
|
||||||
|
downloadRequest(location.dc_id, function () {
|
||||||
|
// dLog('next small promise');
|
||||||
|
return MtpApiManager.invokeApi('upload.getFile', {
|
||||||
|
location: angular.extend({}, location, {_: 'inputFileLocation'}),
|
||||||
|
offset: 0,
|
||||||
|
limit: 0
|
||||||
|
}, {dcID: location.dc_id});
|
||||||
|
}).then(function (result) {
|
||||||
|
deferred.resolve('data:image/jpeg;base64,' + bytesToBase64(result.bytes))
|
||||||
|
}, errorHandler);
|
||||||
|
});
|
||||||
|
|
||||||
return cachedDownloadPromises[fileName] = deferred.promise;
|
return cachedDownloadPromises[fileName] = deferred.promise;
|
||||||
}
|
}
|
||||||
@ -2415,6 +2508,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var deferred = $q.defer(),
|
var deferred = $q.defer(),
|
||||||
|
cacheFileWriter,
|
||||||
errorHandler = function (error) {
|
errorHandler = function (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
// dLog('fail');
|
// dLog('fail');
|
||||||
@ -2433,7 +2527,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
|
|||||||
for (var offset = 0; offset < size; offset += limit) {
|
for (var offset = 0; offset < size; offset += limit) {
|
||||||
writeFileDeferred = $q.defer();
|
writeFileDeferred = $q.defer();
|
||||||
(function (isFinal, offset, writeFileDeferred, writeFilePromise) {
|
(function (isFinal, offset, writeFileDeferred, writeFilePromise) {
|
||||||
return downloadRequest(function () {
|
return downloadRequest(dcID, function () {
|
||||||
// dLog('next big promise');
|
// dLog('next big promise');
|
||||||
return MtpApiManager.invokeApi('upload.getFile', {
|
return MtpApiManager.invokeApi('upload.getFile', {
|
||||||
location: location,
|
location: location,
|
||||||
|
@ -309,7 +309,7 @@ angular.module('myApp.services', [])
|
|||||||
var chatFull = angular.copy(fullChat),
|
var chatFull = angular.copy(fullChat),
|
||||||
chat = getChat(id);
|
chat = getChat(id);
|
||||||
|
|
||||||
if (chatFull.participants._ == 'chatParticipants') {
|
if (chatFull.participants && chatFull.participants._ == 'chatParticipants') {
|
||||||
angular.forEach(chatFull.participants.participants, function(participant){
|
angular.forEach(chatFull.participants.participants, function(participant){
|
||||||
participant.user = AppUsersManager.getUser(participant.user_id);
|
participant.user = AppUsersManager.getUser(participant.user_id);
|
||||||
participant.userPhoto = AppUsersManager.getUserPhoto(participant.user_id, 'User');
|
participant.userPhoto = AppUsersManager.getUserPhoto(participant.user_id, 'User');
|
||||||
@ -335,21 +335,10 @@ angular.module('myApp.services', [])
|
|||||||
scope.chatID = chatID;
|
scope.chatID = chatID;
|
||||||
|
|
||||||
var modalInstance = $modal.open({
|
var modalInstance = $modal.open({
|
||||||
templateUrl: 'partials/chat_modal.html?1',
|
templateUrl: 'partials/chat_modal.html?2',
|
||||||
controller: 'ChatModalController',
|
controller: 'ChatModalController',
|
||||||
windowClass: 'chat_modal_window',
|
windowClass: 'chat_modal_window',
|
||||||
scope: scope,
|
scope: scope
|
||||||
resolve: {
|
|
||||||
fullChat: function () {
|
|
||||||
return MtpApiManager.invokeApi('messages.getFullChat', {
|
|
||||||
chat_id: chatID
|
|
||||||
}).then(function (result) {
|
|
||||||
saveApiChats(result.chats);
|
|
||||||
AppUsersManager.saveApiUsers(result.users);
|
|
||||||
return result.full_chat;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1172,7 +1161,7 @@ angular.module('myApp.services', [])
|
|||||||
height = 100,
|
height = 100,
|
||||||
thumbPhotoSize = choosePhotoSize(photo, width, height),
|
thumbPhotoSize = choosePhotoSize(photo, width, height),
|
||||||
thumb = {
|
thumb = {
|
||||||
placeholder: 'img/placeholders/PhotoThumbConversation.jpg',
|
placeholder: 'img/placeholders/PhotoThumbConversation.gif',
|
||||||
width: width,
|
width: width,
|
||||||
height: height
|
height: height
|
||||||
};
|
};
|
||||||
@ -1200,7 +1189,7 @@ angular.module('myApp.services', [])
|
|||||||
fullHeight = $($window).height() - 150,
|
fullHeight = $($window).height() - 150,
|
||||||
fullPhotoSize = choosePhotoSize(photo, fullWidth, fullHeight),
|
fullPhotoSize = choosePhotoSize(photo, fullWidth, fullHeight),
|
||||||
full = {
|
full = {
|
||||||
placeholder: 'img/placeholders/PhotoThumbModal.jpg',
|
placeholder: 'img/placeholders/PhotoThumbModal.gif',
|
||||||
width: fullWidth,
|
width: fullWidth,
|
||||||
height: fullHeight
|
height: fullHeight
|
||||||
};
|
};
|
||||||
@ -1272,7 +1261,7 @@ angular.module('myApp.services', [])
|
|||||||
height = 100,
|
height = 100,
|
||||||
thumbPhotoSize = video.thumb,
|
thumbPhotoSize = video.thumb,
|
||||||
thumb = {
|
thumb = {
|
||||||
placeholder: 'img/placeholders/VideoThumbConversation.jpg',
|
placeholder: 'img/placeholders/VideoThumbConversation.gif',
|
||||||
width: width,
|
width: width,
|
||||||
height: height
|
height: height
|
||||||
};
|
};
|
||||||
@ -1299,7 +1288,7 @@ angular.module('myApp.services', [])
|
|||||||
fullHeight = $($window).height() - 150,
|
fullHeight = $($window).height() - 150,
|
||||||
fullPhotoSize = video,
|
fullPhotoSize = video,
|
||||||
full = {
|
full = {
|
||||||
placeholder: 'img/placeholders/VideoThumbModal.jpg',
|
placeholder: 'img/placeholders/VideoThumbModal.gif',
|
||||||
width: fullWidth,
|
width: fullWidth,
|
||||||
height: fullHeight,
|
height: fullHeight,
|
||||||
};
|
};
|
||||||
@ -1865,7 +1854,10 @@ angular.module('myApp.services', [])
|
|||||||
var notificationsShown = [];
|
var notificationsShown = [];
|
||||||
var notificationsCount = 0;
|
var notificationsCount = 0;
|
||||||
var peerSettings = {};
|
var peerSettings = {};
|
||||||
|
var faviconEl = $('link[rel="icon"]');
|
||||||
|
|
||||||
var titleBackup = document.title,
|
var titleBackup = document.title,
|
||||||
|
faviconBackup = faviconEl.attr('href'),
|
||||||
titlePromise;
|
titlePromise;
|
||||||
|
|
||||||
$rootScope.$watch('idle.isIDLE', function (newVal) {
|
$rootScope.$watch('idle.isIDLE', function (newVal) {
|
||||||
@ -1875,6 +1867,7 @@ angular.module('myApp.services', [])
|
|||||||
if (!newVal) {
|
if (!newVal) {
|
||||||
notificationsCount = 0;
|
notificationsCount = 0;
|
||||||
document.title = titleBackup;
|
document.title = titleBackup;
|
||||||
|
faviconEl.attr('href', faviconBackup);
|
||||||
notificationsClear();
|
notificationsClear();
|
||||||
} else {
|
} else {
|
||||||
titleBackup = document.title;
|
titleBackup = document.title;
|
||||||
@ -1884,8 +1877,10 @@ angular.module('myApp.services', [])
|
|||||||
// dLog('check title', notificationsCount, time % 2000 > 1000);
|
// dLog('check title', notificationsCount, time % 2000 > 1000);
|
||||||
if (!notificationsCount || time % 2000 > 1000) {
|
if (!notificationsCount || time % 2000 > 1000) {
|
||||||
document.title = titleBackup;
|
document.title = titleBackup;
|
||||||
|
faviconEl.attr('href', faviconBackup);
|
||||||
} else {
|
} else {
|
||||||
document.title = notificationsCount + ' notifications';
|
document.title = notificationsCount + ' notifications';
|
||||||
|
faviconEl.attr('href', 'favicon_unread.ico');
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,13 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|
||||||
<div class="chat_modal_image_wrap pull-left">
|
<div class="chat_modal_image_wrap pull-left">
|
||||||
<img class="chat_modal_image" my-load-thumb thumb="chatFull.thumb"/>
|
<img class="chat_modal_image" src="img/blank.gif" my-load-thumb thumb="chatFull.thumb"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chat_modal_info_wrap clearfix">
|
<div class="chat_modal_info_wrap clearfix">
|
||||||
<h4 class="chat_modal_header">{{chatFull.chat | chatTitle}}</h4>
|
<h4 class="chat_modal_header" ng-bind-html="chatFull.chat.rTitle"></h4>
|
||||||
<p class="chat_modal_members_count" ng-if="chatFull.participants._ == 'chatParticipants'">
|
<p class="chat_modal_members_count" ng-if="chatFull.chat.participants_count > 0">
|
||||||
<ng-pluralize count="chatFull.participants.participants.length"
|
<ng-pluralize count="chatFull.chat.participants_count"
|
||||||
when="{'0': 'No members', 'one': '1 member', 'other': '{} members'}">
|
when="{'0': 'No members', 'one': '1 member', 'other': '{} members'}">
|
||||||
</ng-pluralize>
|
</ng-pluralize>
|
||||||
</p>
|
</p>
|
||||||
|
@ -4,13 +4,11 @@
|
|||||||
<div class="im_dialog_date">
|
<div class="im_dialog_date">
|
||||||
{{dialogMessage.date | dateOrTime}}
|
{{dialogMessage.date | dateOrTime}}
|
||||||
</div>
|
</div>
|
||||||
<span class="im_dialog_badge badge" ng-show="dialogMessage.unreadCount > 0">
|
<span class="im_dialog_badge badge" ng-show="dialogMessage.unreadCount > 0" ng-bind="dialogMessage.unreadCount"></span>
|
||||||
{{dialogMessage.unreadCount}}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="im_dialog_photo pull-left">
|
<div class="im_dialog_photo pull-left">
|
||||||
<img class="im_dialog_photo" src="img/blank.gif" my-load-thumb thumb="dialogMessage.peerPhoto" aaa="{{dialogMessage.peerPhoto.location}}" />
|
<img class="im_dialog_photo" src="img/blank.gif" my-load-thumb thumb="dialogMessage.peerPhoto" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="im_dialog_message_wrap">
|
<div class="im_dialog_message_wrap">
|
||||||
|
@ -86,7 +86,9 @@
|
|||||||
<i class="icon icon-document"></i>
|
<i class="icon icon-document"></i>
|
||||||
<div class="im_message_document_info">
|
<div class="im_message_document_info">
|
||||||
<div class="im_message_document_name_wrap">
|
<div class="im_message_document_name_wrap">
|
||||||
<span class="im_message_document_name">{{historyMessage.media.document.file_name}}</span>
|
<span class="im_message_document_name">
|
||||||
|
{{historyMessage.media.document.file_name}}
|
||||||
|
</span>
|
||||||
<span class="im_message_document_size" ng-if="!historyMessage.media.document.progress.enabled">
|
<span class="im_message_document_size" ng-if="!historyMessage.media.document.progress.enabled">
|
||||||
{{historyMessage.media.document.size | formatSize}}
|
{{historyMessage.media.document.size | formatSize}}
|
||||||
</span>
|
</span>
|
||||||
@ -100,7 +102,9 @@
|
|||||||
<div class="im_message_download_progress_wrap" ng-if="historyMessage.media.document.progress.enabled">
|
<div class="im_message_download_progress_wrap" ng-if="historyMessage.media.document.progress.enabled">
|
||||||
<div class="progress tg_down_progress">
|
<div class="progress tg_down_progress">
|
||||||
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.document.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.document.progress.percent}}%">
|
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.document.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.document.progress.percent}}%">
|
||||||
<span class="sr-only">{{historyMessage.media.document.progress.percent}}% Complete (success)</span>
|
<span class="sr-only">
|
||||||
|
{{historyMessage.media.document.progress.percent}}% Complete (success)
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -115,15 +119,21 @@
|
|||||||
<a ng-click="openUser(historyMessage.media.user.id)" class="im_message_contact_photo pull-left" ng-if="historyMessage.media.user">
|
<a ng-click="openUser(historyMessage.media.user.id)" class="im_message_contact_photo pull-left" ng-if="historyMessage.media.user">
|
||||||
<img class="im_message_contact_photo" src="img/blank.gif" my-load-thumb thumb="historyMessage.media.userPhoto"/>
|
<img class="im_message_contact_photo" src="img/blank.gif" my-load-thumb thumb="historyMessage.media.userPhoto"/>
|
||||||
</a>
|
</a>
|
||||||
<div class="im_message_contact_name"><span class="glyphicon glyphicon-user"></span> {{historyMessage.media.first_name}} {{historyMessage.media.last_name}}</div>
|
<div class="im_message_contact_name"><span class="glyphicon glyphicon-user"></span>
|
||||||
<div class="im_message_contact_phone">{{historyMessage.media.phone_number}}</div>
|
{{historyMessage.media.first_name}} {{historyMessage.media.last_name}}
|
||||||
|
</div>
|
||||||
|
<div class="im_message_contact_phone">
|
||||||
|
{{historyMessage.media.phone_number}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-switch-when="messageMediaPending" class="im_message_upload_file im_message_upload_{{historyMessage.media.type}}">
|
<div ng-switch-when="messageMediaPending" class="im_message_upload_file im_message_upload_{{historyMessage.media.type}}">
|
||||||
<i class="icon icon-document"></i>
|
<i class="icon icon-document"></i>
|
||||||
<div class="im_message_document_info">
|
<div class="im_message_document_info">
|
||||||
<div class="im_message_document_name_wrap">
|
<div class="im_message_document_name_wrap">
|
||||||
<span class="im_message_document_name">{{historyMessage.media.file_name}}</span>
|
<span class="im_message_document_name">
|
||||||
|
{{historyMessage.media.file_name}}
|
||||||
|
</span>
|
||||||
<span class="im_message_document_size" ng-if="historyMessage.media.progress">
|
<span class="im_message_document_size" ng-if="historyMessage.media.progress">
|
||||||
{{historyMessage.media.progress | formatSizeProgress}}
|
{{historyMessage.media.progress | formatSizeProgress}}
|
||||||
</span>
|
</span>
|
||||||
@ -131,7 +141,9 @@
|
|||||||
<div class="im_message_download_progress_wrap">
|
<div class="im_message_download_progress_wrap">
|
||||||
<div class="progress tg_down_progress">
|
<div class="progress tg_down_progress">
|
||||||
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.progress.percent}}%">
|
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.progress.percent}}%">
|
||||||
<span class="sr-only">{{historyMessage.media.progress.percent}}% Complete (success)</span>
|
<span class="sr-only">
|
||||||
|
{{historyMessage.media.progress.percent}}% Complete (success)
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
1
app/vendor/jquery/jquery.min.map
vendored
Normal file
1
app/vendor/jquery/jquery.min.map
vendored
Normal file
File diff suppressed because one or more lines are too long
8
app/vendor/zlib/gunzip.min.js.map
vendored
Normal file
8
app/vendor/zlib/gunzip.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
8
app/vendor/zlib/gzip.min.js.map
vendored
Normal file
8
app/vendor/zlib/gzip.min.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user