Browse Source

Moved send message to async logic, added media send progress, added doc download progress

master
Igor Zhukov 11 years ago
parent
commit
a4ecd553b9
  1. 2
      README.md
  2. 48
      app/css/app.css
  3. 77
      app/js/controllers.js
  4. 43
      app/js/directives.js
  5. 4
      app/js/lib/mtproto.js
  6. 296
      app/js/services.js
  7. 2
      app/partials/head.html
  8. 2
      app/partials/im.html
  9. 37
      app/partials/message.html

2
README.md

@ -1,4 +1,4 @@
## [Webogram](http://zhukov.github.io/webogram) - Telegram UNOFFICIAL web app ## [Webogram](http://zhukov.github.io/webogram) – UNOFFICIAL Telegram Web App
Telegram offers great [apps for mobile communication](https://www.telegram.org). It is based on the [MTProto protocol](https://core.telegram.org/protocol) and has an [Open API](http://core.telegram.org/api). I personally like Telegram for its speed and cloud-support (that makes a web app possible, unlike in the case of WA and others). Telegram offers great [apps for mobile communication](https://www.telegram.org). It is based on the [MTProto protocol](https://core.telegram.org/protocol) and has an [Open API](http://core.telegram.org/api). I personally like Telegram for its speed and cloud-support (that makes a web app possible, unlike in the case of WA and others).

48
app/css/app.css

@ -709,7 +709,8 @@ div.im_message_video_thumb {
.im_message_document { .im_message_document,
.im_message_upload_file {
margin-top: 3px; margin-top: 3px;
border-radius: 3px; border-radius: 3px;
display: inline-block; display: inline-block;
@ -728,7 +729,7 @@ div.im_message_video_thumb {
.im_message_document .icon-group { .im_message_document .icon-group {
background-image: url(../img/icons/DialogListGroupChatIcon_Highlighted@2x.png); background-image: url(../img/icons/DialogListGroupChatIcon_Highlighted@2x.png);
} }
.im_message_document .im_message_document_name { .im_message_document_name {
color: #999; color: #999;
vertical-align: text-top; vertical-align: text-top;
display: inline-block; display: inline-block;
@ -756,6 +757,33 @@ div.im_message_video_thumb {
padding-right: 3px; padding-right: 3px;
} }
.im_message_upload_progress_wrap,
.im_message_download_progress_wrap {
margin-top: 5px;
}
.tg_up_progress,
.tg_down_progress {
height: 5px;
margin: 0;
padding: 0;
background: rgba(0,0,0, 0.1);
border: 0;
border-radius: 4px;
}
.tg_up_progress .progress-bar,
.tg_down_progress .progress-bar {
height: 5px;
line-height: 5px;
background: #43A4DB;
border-radius: 3px;
overflow: hidden;
}
.tg_down_progress .progress-bar {
background: #6DBF69;
}
.im_service_message_wrap { .im_service_message_wrap {
text-align: center; text-align: center;
@ -782,7 +810,7 @@ div.im_message_video_thumb {
.im_content_message_wrap { .im_content_message_wrap {
margin: 10px 0 5px; margin: 10px 0 5px;
} }
.icon-message-status-unread { .icon-message-status {
background: #43A4DB; background: #43A4DB;
border: 1px solid #FFF; border: 1px solid #FFF;
display: block; display: block;
@ -793,7 +821,21 @@ div.im_message_video_thumb {
position: absolute; position: absolute;
margin-left: -27px; margin-left: -27px;
margin-top: 14px; margin-top: 14px;
opacity: 0;
-webkit-transition: opacity ease-in-out 0.15s;
transition: opacity ease-in-out 0.15s;
} }
.icon-message-status-unread {
opacity: 1.0;
}
.icon-message-status-pending {
opacity: 0.5;
}
/*.icon-message-status-done {
opacity: 0;
}*/
.icon-message-status-tick { .icon-message-status-tick {
/*display: inline-block;*/ /*display: inline-block;*/
display: none; display: none;

77
app/js/controllers.js

@ -301,6 +301,8 @@ angular.module('myApp.controllers', [])
var typingTimeouts = {}; var typingTimeouts = {};
$scope.$on('history_update', angular.noop);
$scope.$on('history_append', function (e, addedMessage) { $scope.$on('history_append', function (e, addedMessage) {
if (addedMessage.peerID == $scope.curDialog.peerID) { if (addedMessage.peerID == $scope.curDialog.peerID) {
dLog('append', addedMessage); dLog('append', addedMessage);
@ -383,7 +385,7 @@ angular.module('myApp.controllers', [])
var text = $scope.draftMessage.text; var text = $scope.draftMessage.text;
if ($scope.draftMessage.sending || !text.length) { if (!text.length) {
return false; return false;
} }
@ -395,50 +397,16 @@ angular.module('myApp.controllers', [])
return all; return all;
}); });
$scope.draftMessage.sending = true; AppMessagesManager.sendText($scope.curDialog.peerID, text);
resetDraft();
MtpApiManager.invokeApi('messages.sendMessage', { $scope.$broadcast('ui_message_send');
peer: $scope.curDialog.inputPeer,
message: text,
random_id: $scope.draftMessage.randomID
}).then(function (result) {
if (ApiUpdatesManager.saveSeq(result.seq)) {
MtpApiManager.getUserID().then(function (fromID) {
ApiUpdatesManager.saveUpdate({
_: 'updateNewMessage',
message: {
_: 'message',
id: result.id,
from_id: fromID,
to_id: AppPeersManager.getOutputPeer($scope.curDialog.peerID),
out: true,
unread: true,
date: result.date,
message: text,
media: {_: 'messageMediaEmpty'}
},
pts: result.pts
});
});
}
$scope.$broadcast('ui_message_send'); return false;
resetDraft();
}, function () {
delete $scope.draftMessage.sending;
});
return cancelEvent(e);
} }
function resetDraft () { function resetDraft () {
$scope.draftMessage = { $scope.draftMessage = {
randomID: [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)],
text: '' text: ''
}; };
} }
@ -449,35 +417,8 @@ angular.module('myApp.controllers', [])
} }
for (var i = 0; i < newVal.length; i++) { for (var i = 0; i < newVal.length; i++) {
(function (file, randomID) { AppMessagesManager.sendFile($scope.curDialog.peerID, newVal[i]);
MtpApiFileManager.uploadFile(file).then(function (inputFile) { $scope.$broadcast('ui_message_send');
var inputMedia;
if (file.type == 'image/jpeg') {
inputMedia = {_: 'inputMediaUploadedPhoto', file: inputFile};
} else {
inputMedia = {_: 'inputMediaUploadedDocument', file: inputFile, file_name: file.name, mime_type: file.type};
}
MtpApiManager.invokeApi('messages.sendMedia', {
peer: $scope.curDialog.inputPeer,
media: inputMedia,
random_id: randomID
}).then(function (result) {
if (ApiUpdatesManager.saveSeq(result.seq)) {
ApiUpdatesManager.saveUpdate({
_: 'updateNewMessage',
message: result.message,
pts: result.pts
});
}
$scope.$broadcast('ui_message_send');
});
}, function (error) {
dLog('upload error', error);
})
})(newVal[i], [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)]);
} }
} }

43
app/js/directives.js

@ -450,7 +450,8 @@ angular.module('myApp.directives', ['myApp.filters'])
<img class="img_fullsize" my-load-thumb thumb="video.thumb" width="{{video.full.width}}" height="{{video.full.height}}" />\ <img class="img_fullsize" my-load-thumb thumb="video.thumb" width="{{video.full.width}}" height="{{video.full.height}}" />\
</div>\ </div>\
<div class="video_full_player" ng-if="player.src">\ <div class="video_full_player" ng-if="player.src">\
<video width="{{video.full.width}}" height="{{video.full.height}}" controls autoplay>\ <embed ng-src="{{player.src}}" width="{{video.full.width}}" height="{{video.full.height}}" autoplay="true" CONTROLLER="TRUE" loop="false" pluginspace="http://www.apple.com/quicktime/" ng-if="player.quicktime"/>\
<video width="{{video.full.width}}" height="{{video.full.height}}" controls autoplay ng-if="!player.quicktime">\
<source ng-src="{{player.src}}" type="video/mp4">\ <source ng-src="{{player.src}}" type="video/mp4">\
</video>\ </video>\
</div>\ </div>\
@ -471,9 +472,19 @@ angular.module('myApp.directives', ['myApp.filters'])
access_hash: scope.video.access_hash access_hash: scope.video.access_hash
}; };
var hasQt = false, i;
// if (navigator.plugins) {
// for (i = 0; i < navigator.plugins.length; i++) {
// if (navigator.plugins[i].name.indexOf('QuickTime') >= 0) {
// hasQt = true;
// }
// }
// }
MtpApiFileManager.downloadFile(scope.video.dc_id, inputLocation, scope.video.size).then(function (url) { MtpApiFileManager.downloadFile(scope.video.dc_id, inputLocation, scope.video.size).then(function (url) {
scope.progress.enabled = false; scope.progress.enabled = false;
// scope.progress = {enabled: true, percent: 50}; // scope.progress = {enabled: true, percent: 50};
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 image failed', e, scope.fullPhoto.location);
@ -510,3 +521,33 @@ angular.module('myApp.directives', ['myApp.filters'])
} }
}) })
.directive('myTypingDots', function($interval) {
return {
link: link,
};
var interval;
function link (scope, element, attrs) {
var promise = $interval(function () {
var time = +new Date(),
cnt = 3;
if (time % 1000 <= 200) {
cnt = 0;
} else if (time % 1000 <= 400) {
cnt = 1;
} else if (time % 1000 <= 600) {
cnt = 2;
}
element.html((new Array(cnt + 1)).join('.'));
}, 200);
scope.$on('$destroy', function cleanup() {
$interval.cancel(promise);
});
}
})

4
app/js/lib/mtproto.js

@ -2130,7 +2130,7 @@ factory('MtpApiManager', function (AppConfigManager, MtpAuthorizer, MtpNetworker
deferred.resolve(result); deferred.resolve(result);
// setTimeout(function () { // setTimeout(function () {
// deferred.resolve(result); // deferred.resolve(result);
// },1000); // }, 1000);
}, },
function (error) { function (error) {
dLog('error', error.code, error.type, baseDcID, dcID); dLog('error', error.code, error.type, baseDcID, dcID);
@ -2481,7 +2481,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
cachedFS.root.getFile(fileName, {create: false}, function(fileEntry) { cachedFS.root.getFile(fileName, {create: false}, function(fileEntry) {
fileEntry.file(function(file) { fileEntry.file(function(file) {
dLog('check size', file.size, size); dLog('check size', file.size, size);
if (file.size >= size && false) { if (file.size >= size) {
deferred.resolve(fileEntry.toURL()); deferred.resolve(fileEntry.toURL());
} else { } else {
dLog('File bad size', file, size); dLog('File bad size', file, size);

296
app/js/services.js

@ -405,12 +405,15 @@ angular.module('myApp.services', [])
} }
}) })
.service('AppMessagesManager', function ($q, $rootScope, $filter, $sanitize, ApiUpdatesManager, AppUsersManager, AppChatsManager, AppPeersManager, AppPhotosManager, AppVideoManager, AppDocsManager, MtpApiManager, RichTextProcessor) { .service('AppMessagesManager', function ($q, $rootScope, $filter, $sanitize, ApiUpdatesManager, AppUsersManager, AppChatsManager, AppPeersManager, AppPhotosManager, AppVideoManager, AppDocsManager, MtpApiManager, MtpApiFileManager, RichTextProcessor) {
var messagesStorage = {}; var messagesStorage = {};
var messagesForHistory = {}; var messagesForHistory = {};
var historiesStorage = {}; var historiesStorage = {};
var dialogsStorage = {count: null, dialogs: []}; var dialogsStorage = {count: null, dialogs: []};
var pendingByRandomID = {};
var pendingByMessageID = {};
var tempID = -1;
function getDialogs (offset, limit) { function getDialogs (offset, limit) {
if (dialogsStorage.count !== null && dialogsStorage.dialogs.length >= offset + limit) { if (dialogsStorage.count !== null && dialogsStorage.dialogs.length >= offset + limit) {
@ -458,10 +461,14 @@ angular.module('myApp.services', [])
var peerID = AppPeersManager.getPeerID(inputPeer), var peerID = AppPeersManager.getPeerID(inputPeer),
historyStorage = historiesStorage[peerID], historyStorage = historiesStorage[peerID],
offset = 0; offset = 0,
resultPending = [];
if (historyStorage === undefined) { if (historyStorage === undefined) {
historyStorage = historiesStorage[peerID] = {count: null, history: []}; historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
}
else if (!maxID && historyStorage.pending.length) {
resultPending = historyStorage.pending.slice();
} }
@ -477,7 +484,7 @@ angular.module('myApp.services', [])
if (historyStorage.count !== null && historyStorage.history.length >= offset + limit) { if (historyStorage.count !== null && historyStorage.history.length >= offset + limit) {
return $q.when({ return $q.when({
count: historyStorage.count, count: historyStorage.count,
history: historyStorage.history.slice(offset, offset + limit) history: resultPending.concat(historyStorage.history.slice(offset, offset + limit))
}); });
} }
@ -515,7 +522,7 @@ angular.module('myApp.services', [])
deferred.resolve({ deferred.resolve({
count: historyStorage.count, count: historyStorage.count,
history: historyStorage.history.slice(offset, offset + limit) history: resultPending.concat(historyStorage.history.slice(offset, offset + limit))
}); });
}, function (error) { }, function (error) {
deferred.reject(error); deferred.reject(error);
@ -619,6 +626,205 @@ angular.module('myApp.services', [])
}); });
} }
function sendText(peerID, text) {
var messageID = tempID--,
randomID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)],
randomIDS = bigint(randomID[0]).shiftLeft(32).add(bigint(randomID[1])).toString(),
historyStorage = historiesStorage[peerID],
inputPeer = AppPeersManager.getInputPeerByID(peerID),
message;
if (historyStorage === undefined) {
historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
}
MtpApiManager.getUserID().then(function (fromID) {
message = {
_: 'message',
id: messageID,
from_id: fromID,
to_id: AppPeersManager.getOutputPeer(peerID),
out: true,
unread: true,
date: (+new Date()) / 1000,
message: text,
media: {_: 'messageMediaEmpty'},
random_id: randomIDS,
pending: true
};
message.send = function () {
MtpApiManager.invokeApi('messages.sendMessage', {
peer: inputPeer,
message: text,
random_id: randomID
}).then(function (result) {
if (ApiUpdatesManager.saveSeq(result.seq)) {
ApiUpdatesManager.saveUpdate({
_: 'updateMessageID',
random_id: randomIDS,
id: result.id
});
message.date = result.date;
message.id = result.id;
ApiUpdatesManager.saveUpdate({
_: 'updateNewMessage',
message: message,
pts: result.pts
});
}
});
};
saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID});
// setTimeout(function () {
message.send();
// }, 5000);
});
pendingByRandomID[randomIDS] = [peerID, messageID];
};
function sendFile(peerID, file, options) {
var messageID = tempID--,
randomID = [nextRandomInt(0xFFFFFFFF), nextRandomInt(0xFFFFFFFF)],
randomIDS = bigint(randomID[0]).shiftLeft(32).add(bigint(randomID[1])).toString(),
historyStorage = historiesStorage[peerID],
inputPeer = AppPeersManager.getInputPeerByID(peerID),
isPhoto = file.type == 'image/jpeg' && file.size <= 5242880; // 5Mb
if (historyStorage === undefined) {
historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
}
MtpApiManager.getUserID().then(function (fromID) {
var media = {
_: 'messageMediaPending',
type: isPhoto ? 'photo' : 'doc',
file_name: file.name,
size: file.size,
progress: {percent: 1}
};
var message = {
_: 'message',
id: messageID,
from_id: fromID,
to_id: AppPeersManager.getOutputPeer(peerID),
out: true,
unread: true,
date: (+new Date()) / 1000,
message: '',
media: media,
random_id: randomIDS,
pending: true
};
message.send = function () {
MtpApiFileManager.uploadFile(file).then(function (inputFile) {
var inputMedia;
if (isPhoto) {
inputMedia = {_: 'inputMediaUploadedPhoto', file: inputFile};
} else {
inputMedia = {_: 'inputMediaUploadedDocument', file: inputFile, file_name: file.name, mime_type: file.type};
}
MtpApiManager.invokeApi('messages.sendMedia', {
peer: inputPeer,
media: inputMedia,
random_id: randomID
}).then(function (result) {
if (ApiUpdatesManager.saveSeq(result.seq)) {
ApiUpdatesManager.saveUpdate({
_: 'updateMessageID',
random_id: randomIDS,
id: result.message.id
});
message.date = result.message.date;
message.id = result.message.id;
message.media = result.message.media;
ApiUpdatesManager.saveUpdate({
_: 'updateNewMessage',
message: message,
pts: result.pts
});
}
});
}, null, function (progress) {
// dLog('upload progress', progress);
var historyMessage = messagesForHistory[messageID],
percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
media.progress.percent = percent;
if (historyMessage) {
historyMessage.media.progress.percent = percent;
$rootScope.$broadcast('history_update', {peerID: peerID});
}
});
};
saveMessages([message]);
historyStorage.pending.unshift(messageID);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: messageID});
// setTimeout(function () {
message.send();
// }, 5000);
});
pendingByRandomID[randomIDS] = [peerID, messageID];
}
function finalizePendingMessage(randomID, finalMessage) {
var pendingData = pendingByRandomID[randomID];
// dLog('pdata', randomID, pendingData);
if (pendingData) {
var peerID = pendingData[0],
tempID = pendingData[1],
historyStorage = historiesStorage[peerID],
index = false,
message = false,
historyMessage = false,
i;
// dLog('pending', randomID, historyStorage.pending);
for (i = 0; i < historyStorage.pending.length; i++) {
if (historyStorage.pending[i] == tempID) {
historyStorage.pending.splice(i, 1);
break;
}
}
if (message = messagesStorage[tempID]) {
delete message.pending;
delete message.random_id;
delete message.send;
}
if (historyMessage = messagesForHistory[tempID]) {
messagesForHistory[finalMessage.id] = angular.extend(historyMessage, wrapForHistory(finalMessage.id));
delete historyMessage.pending;
delete historyMessage.random_id;
delete historyMessage.send;
}
delete messagesForHistory[tempID];
delete messagesStorage[tempID];
return message;
}
return false;
}
function getMessagePeer (message) { function getMessagePeer (message) {
var toID = message.to_id && AppPeersManager.getPeerID(message.to_id) || 0; var toID = message.to_id && AppPeersManager.getPeerID(message.to_id) || 0;
@ -660,8 +866,8 @@ angular.module('myApp.services', [])
return message; return message;
} }
function wrapForHistory (msgID) { function wrapForHistory (msgID, force) {
if (messagesForHistory[msgID] !== undefined) { if (!force && messagesForHistory[msgID] !== undefined) {
return messagesForHistory[msgID]; return messagesForHistory[msgID];
} }
@ -679,6 +885,10 @@ angular.module('myApp.services', [])
case 'messageMediaVideo': case 'messageMediaVideo':
message.media.video = AppVideoManager.wrapForHistory(message.media.video.id); message.media.video = AppVideoManager.wrapForHistory(message.media.video.id);
break; break;
case 'messageMediaDocument':
message.media.document = AppDocsManager.wrapForHistory(message.media.document.id);
break;
} }
if (message.media.user_id) { if (message.media.user_id) {
@ -714,10 +924,13 @@ angular.module('myApp.services', [])
return []; return [];
} }
$rootScope.$on('apiUpdate', function (e, update) { $rootScope.$on('apiUpdate', function (e, update) {
dLog('on apiUpdate', update); dLog('on apiUpdate', update);
switch (update._) { switch (update._) {
case 'updateMessageID':
pendingByMessageID[update.id] = update.random_id;
break;
case 'updateNewMessage': case 'updateNewMessage':
var message = update.message, var message = update.message,
peerID = getMessagePeer(message), peerID = getMessagePeer(message),
@ -729,7 +942,7 @@ angular.module('myApp.services', [])
return false; return false;
} }
} else { } else {
historyStorage = historiesStorage[peerID] = {count: null, history: []}; historyStorage = historiesStorage[peerID] = {count: null, history: [], pending: []};
} }
saveMessages([message]); saveMessages([message]);
@ -737,8 +950,23 @@ angular.module('myApp.services', [])
if (historyStorage.count !== null) { if (historyStorage.count !== null) {
historyStorage.count++; historyStorage.count++;
} }
historyStorage.history.unshift(message.id); historyStorage.history.unshift(message.id);
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: message.id}); var randomID = pendingByMessageID[message.id],
pendingMessage;
if (randomID) {
if (pendingMessage = finalizePendingMessage(randomID, message)) {
$rootScope.$broadcast('history_update', {peerID: peerID});
}
delete pendingByMessageID[message.id];
}
// dLog(11, randomID, pendingMessage);
if (!pendingMessage) {
$rootScope.$broadcast('history_append', {peerID: peerID, messageID: message.id});
}
var foundDialog = getDialogByPeerID(peerID), var foundDialog = getDialogByPeerID(peerID),
dialog; dialog;
@ -767,6 +995,7 @@ angular.module('myApp.services', [])
if (message) { if (message) {
message.unread = false; message.unread = false;
if (messagesForHistory[messageID]) { if (messagesForHistory[messageID]) {
// dLog(222, messagesForHistory[messageID]);
messagesForHistory[messageID].unread = false; messagesForHistory[messageID].unread = false;
} }
peerID = getMessagePeer(message); peerID = getMessagePeer(message);
@ -782,6 +1011,7 @@ angular.module('myApp.services', [])
angular.forEach(dialogsUpdated, function(count, peerID) { angular.forEach(dialogsUpdated, function(count, peerID) {
$rootScope.$broadcast('dialog_unread', {peerID: peerID, count: count}); $rootScope.$broadcast('dialog_unread', {peerID: peerID, count: count});
}); });
// $rootScope.$broadcast('history_update');
break; break;
} }
}); });
@ -791,6 +1021,8 @@ angular.module('myApp.services', [])
getHistory: getHistory, getHistory: getHistory,
readHistory: readHistory, readHistory: readHistory,
saveMessages: saveMessages, saveMessages: saveMessages,
sendText: sendText,
sendFile: sendFile,
getMessagePeer: getMessagePeer, getMessagePeer: getMessagePeer,
wrapForDialog: wrapForDialog, wrapForDialog: wrapForDialog,
wrapForHistory: wrapForHistory wrapForHistory: wrapForHistory
@ -1011,6 +1243,7 @@ angular.module('myApp.services', [])
.service('AppDocsManager', function ($rootScope, $modal, $window, $timeout, MtpApiFileManager, AppUsersManager) { .service('AppDocsManager', function ($rootScope, $modal, $window, $timeout, MtpApiFileManager, AppUsersManager) {
var docs = {}; var docs = {};
var docsForHistory = {};
function saveDoc (apiDoc) { function saveDoc (apiDoc) {
docs[apiDoc.id] = apiDoc; docs[apiDoc.id] = apiDoc;
@ -1026,6 +1259,10 @@ angular.module('myApp.services', [])
}; };
function wrapForHistory (docID) { function wrapForHistory (docID) {
if (docsForHistory[docID] !== undefined) {
return docsForHistory[docID];
}
var doc = angular.copy(docs[docID]), var doc = angular.copy(docs[docID]),
width = 100, width = 100,
height = 100, height = 100,
@ -1045,23 +1282,31 @@ angular.module('myApp.services', [])
thumb.location = thumbPhotoSize.location; thumb.location = thumbPhotoSize.location;
thumb.size = thumbPhotoSize.size; thumb.size = thumbPhotoSize.size;
} else {
thumb = false;
} }
doc.thumb = thumb; doc.thumb = thumb;
return doc; return docsForHistory[docID] = doc;
} }
function openDoc (docID, accessHash) { function openDoc (docID, accessHash) {
var doc = docs[docID], var doc = docs[docID],
historyDoc = docsForHistory[docID] || doc || {},
inputFileLocation = { inputFileLocation = {
_: 'inputDocumentFileLocation', _: 'inputDocumentFileLocation',
id: docID, id: docID,
access_hash: accessHash || doc.access_hash access_hash: accessHash || doc.access_hash
}, };
scope = {};
historyDoc.progress = {enabled: true, percent: 1};
scope.progress = {enabled: true, percent: 1}; function updateDownloadProgress (progress) {
dLog('dl progress', progress);
historyDoc.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
$rootScope.$broadcast('history_update');
}
if (window.chrome && chrome.fileSystem && chrome.fileSystem.chooseEntry) { if (window.chrome && chrome.fileSystem && chrome.fileSystem.chooseEntry) {
@ -1076,13 +1321,16 @@ angular.module('myApp.services', [])
}] }]
}, function (writableFileEntry) { }, function (writableFileEntry) {
MtpApiFileManager.downloadFile(doc.dc_id, inputFileLocation, doc.size, writableFileEntry).then(function (url) { MtpApiFileManager.downloadFile(doc.dc_id, inputFileLocation, doc.size, writableFileEntry).then(function (url) {
delete historyDoc.progress;
dLog('file save done'); dLog('file save done');
}); }, function (e) {
dLog('document download failed', e);
historyDoc.progress.enabled = false;
}, updateDownloadProgress);
}); });
} else { } else {
MtpApiFileManager.downloadFile(doc.dc_id, inputFileLocation, doc.size).then(function (url) { MtpApiFileManager.downloadFile(doc.dc_id, inputFileLocation, doc.size).then(function (url) {
scope.progress.enabled = false; delete historyDoc.progress;
var a = $('<a>Download</a>').attr('href', url).attr('target', '_blank').attr('download', doc.file_name).appendTo('body'); var a = $('<a>Download</a>').attr('href', url).attr('target', '_blank').attr('download', doc.file_name).appendTo('body');
a[0].dataset.downloadurl = ['png', doc.file_name, url].join(':'); a[0].dataset.downloadurl = ['png', doc.file_name, url].join(':');
@ -1092,9 +1340,8 @@ angular.module('myApp.services', [])
}, 100); }, 100);
}, function (e) { }, function (e) {
dLog('document download failed', e); dLog('document download failed', e);
}, function (progress) { historyDoc.progress.enabled = false;
scope.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total)); }, updateDownloadProgress);
});
} }
} }
@ -1240,6 +1487,11 @@ angular.module('myApp.services', [])
AppUsersManager.saveApiUsers(differenceResult.users); AppUsersManager.saveApiUsers(differenceResult.users);
AppChatsManager.saveApiChats(differenceResult.chats); AppChatsManager.saveApiChats(differenceResult.chats);
// Should be first because of updateMessageID
angular.forEach(differenceResult.other_updates, function(update){
saveUpdate(update, true);
});
angular.forEach(differenceResult.new_messages, function (apiMessage) { angular.forEach(differenceResult.new_messages, function (apiMessage) {
saveUpdate({ saveUpdate({
_: 'updateNewMessage', _: 'updateNewMessage',
@ -1248,10 +1500,6 @@ angular.module('myApp.services', [])
}, true); }, true);
}); });
angular.forEach(differenceResult.other_updates, function(update){
saveUpdate(update, true);
});
var nextState = differenceResult.intermediate_state || differenceResult.state; var nextState = differenceResult.intermediate_state || differenceResult.state;
curState.seq = nextState.seq; curState.seq = nextState.seq;
curState.pts = nextState.pts; curState.pts = nextState.pts;

2
app/partials/head.html

@ -2,7 +2,7 @@
<div class="navbar navbar-static-top navbar-inverse" role="navigation"> <div class="navbar navbar-static-top navbar-inverse" role="navigation">
<div class="container"> <div class="container">
<div class="navbar-header"> <div class="navbar-header">
<a class="navbar-brand" href="https://zhukov.github.io/webogram"><img src="img/Logo_2x.png" class="tg_head_logo" alt="Telegram logo" width="110" height="31" /> <span class="navbar-brand-alpha font-light">alpha</span></a> <a class="navbar-brand" href="http://zhukov.github.io/webogram"><img src="img/Logo_2x.png" class="tg_head_logo" alt="Telegram logo" width="110" height="31" /> <span class="navbar-brand-alpha font-light">alpha</span></a>
</div> </div>
<div class="navbar-collapse collapse"> <div class="navbar-collapse collapse">

2
app/partials/im.html

@ -68,7 +68,7 @@
<div class="im_history_typing_wrap"> <div class="im_history_typing_wrap">
<div class="im_history_typing" ng-animate="{enter:'animate-show', leave:'animate-hide'}" ng-if="typing.user"> <div class="im_history_typing" ng-animate="{enter:'animate-show', leave:'animate-hide'}" ng-if="typing.user">
<strong class="im_history_typing_author" ng-bind-html="typing.user.rFullName"></strong> is typing.. <strong class="im_history_typing_author" ng-bind-html="typing.user.rFullName"></strong> is typing<span my-typing-dots></span>
</div> </div>
</div> </div>

37
app/partials/message.html

@ -39,7 +39,9 @@
</div> </div>
<div class="im_content_message_wrap" ng-if="historyMessage._ != 'messageService'"> <div class="im_content_message_wrap" ng-if="historyMessage._ != 'messageService'">
<i ng-if="historyMessage.unread" class="icon icon-message-status-unread"></i> {{historyMessage}}
<i class="icon-message-status" ng-class="{'icon-message-status-unread': historyMessage.unread, 'icon-message-status-pending': historyMessage.pending}"></i>
<a ng-click="openUser(historyMessage.from_id)" class="im_message_from_photo pull-left"> <a ng-click="openUser(historyMessage.from_id)" class="im_message_from_photo pull-left">
<img class="im_message_from_photo" my-load-thumb thumb="historyMessage.fromPhoto"/> <img class="im_message_from_photo" my-load-thumb thumb="historyMessage.fromPhoto"/>
</a> </a>
@ -66,10 +68,20 @@
</div> </div>
</a> </a>
<a ng-switch-when="messageMediaDocument" class="im_message_document" href="" ng-click="openDoc(historyMessage.media.document.id)"> <div ng-switch-when="messageMediaDocument">
<i class="icon icon-document"></i> <a class="im_message_document" href="" ng-click="openDoc(historyMessage.media.document.id)">
<div class="im_message_document_name"><strong>{{historyMessage.media.document.file_name}}</strong> {{historyMessage.media.document.size | formatSize}}</div> <i class="icon icon-document"></i>
</a> <div class="im_message_document_name"><strong>{{historyMessage.media.document.file_name}}</strong> {{historyMessage.media.document.size | formatSize}}</div>
</a>
<div class="im_message_download_progress_wrap" ng-if="historyMessage.media.document.progress.enabled">
<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}}%">
<span class="sr-only">{{historyMessage.media.document.progress.percent}}% Complete (success)</span>
</div>
</div>
</div>
</div>
<a ng-switch-when="messageMediaGeo" my-map-point point="historyMessage.media.geo" class="im_message_geopoint"> <a ng-switch-when="messageMediaGeo" my-map-point point="historyMessage.media.geo" class="im_message_geopoint">
<i class="icon icon-geo-point"></i> <i class="icon icon-geo-point"></i>
@ -82,6 +94,21 @@
<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> {{historyMessage.media.first_name}} {{historyMessage.media.last_name}}</div>
<div class="im_message_contact_phone">{{historyMessage.media.phone_number}}</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}}">
<i class="icon icon-document"></i>
<div class="im_message_document_name"><strong>{{historyMessage.media.file_name}}</strong> {{historyMessage.media.size | formatSize}}</div>
<div class="im_message_upload_progress_wrap">
<div class="progress tg_up_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}}%">
<span class="sr-only">{{historyMessage.media.progress.percent}}% Complete (success)</span>
</div>
</div>
</div>
</div>
</div> </div>
<div class="im_message_text" ng-if="historyMessage.message" ng-bind-html="historyMessage.richMessage"></div> <div class="im_message_text" ng-if="historyMessage.message" ng-bind-html="historyMessage.richMessage"></div>

Loading…
Cancel
Save