Browse Source

File download improvements

Added some opengraph meta tags
Fixed multiDC file download problems
Added fallback blob mode for downloads (for Safari & Firefox)
master
Igor Zhukov 11 years ago
parent
commit
e999975808
  1. 13
      app/index.html
  2. 2
      app/js/app.js
  3. 50
      app/js/directives.js
  4. 115
      app/js/lib/mtproto.js
  5. 4
      app/js/services.js
  6. 11
      app/partials/chat_modal.html
  7. 21
      app/partials/dialog.html
  8. 18
      app/partials/im.html
  9. 36
      app/partials/message.html
  10. 6
      app/partials/user_modal.html

13
app/index.html

@ -9,6 +9,13 @@ @@ -9,6 +9,13 @@
<link rel="stylesheet" href="vendor/jquery.nanoscroller/nanoscroller.css"/>
<link rel="stylesheet" href="css/app.css?4"/>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<meta property="og:title" content="Webogram">
<meta property="og:url" content="http://zhukov.github.io/webogram">
<meta property="og:image" content="http://zhukov.github.io/webogram/img/Logo_2x.png">
<meta property="og:site_name" content="Webogram">
<meta property="og:description" content="Welcome to an experimental web-client of Telegram messenger. See https://github.com/zhukov/webogram for more info.">
</head>
<body>
@ -30,14 +37,14 @@ @@ -30,14 +37,14 @@
<script type="text/javascript" src="js/lib/config.js"></script>
<script type="text/javascript" src="js/lib/mtproto.js?7"></script>
<script type="text/javascript" src="js/lib/mtproto.js?8"></script>
<script type="text/javascript" src="js/util.js"></script>
<script type="text/javascript" src="js/app.js?3"></script>
<script type="text/javascript" src="js/app.js?4"></script>
<script type="text/javascript" src="js/services.js?6"></script>
<script type="text/javascript" src="js/controllers.js?8"></script>
<script type="text/javascript" src="js/filters.js?3"></script>
<script type="text/javascript" src="js/directives.js?5"></script>
<script type="text/javascript" src="js/directives.js?6"></script>
</body>
</html>

2
app/js/app.js

@ -49,7 +49,7 @@ config(['$locationProvider', '$routeProvider', '$compileProvider', function($loc @@ -49,7 +49,7 @@ config(['$locationProvider', '$routeProvider', '$compileProvider', function($loc
// $locationProvider.html5Mode(true);
$routeProvider.when('/', {templateUrl: 'partials/welcome.html', controller: 'AppWelcomeController'});
$routeProvider.when('/login', {templateUrl: 'partials/login.html?1', controller: 'AppLoginController'});
$routeProvider.when('/im', {templateUrl: 'partials/im.html?2', controller: 'AppIMController', reloadOnSearch: false});
$routeProvider.when('/im', {templateUrl: 'partials/im.html?3', controller: 'AppIMController', reloadOnSearch: false});
$routeProvider.otherwise({redirectTo: '/'});
}]);

50
app/js/directives.js

@ -16,7 +16,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -16,7 +16,7 @@ angular.module('myApp.directives', ['myApp.filters'])
restrict: 'AE',
scope: true,
translude: false,
templateUrl: 'partials/dialog.html?2'
templateUrl: 'partials/dialog.html?3'
};
})
@ -25,7 +25,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -25,7 +25,7 @@ angular.module('myApp.directives', ['myApp.filters'])
restrict: 'AE',
scope: true,
translude: false,
templateUrl: 'partials/message.html?3'
templateUrl: 'partials/message.html?4'
};
})
@ -359,18 +359,31 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -359,18 +359,31 @@ angular.module('myApp.directives', ['myApp.filters'])
};
function link (scope, element, attrs) {
element.src = 'img/blank.gif';
var counter = 0;
scope.$watch('thumb.location', function (newVal) {
var counterSaved = ++counter;
if (!scope.thumb || !scope.thumb.location) {
element.attr('src', scope.thumb && scope.thumb.placeholder || '');
element.attr('src', scope.thumb && scope.thumb.placeholder || 'img/blank.gif');
return;
}
var cachedSrc = MtpApiFileManager.getCachedFile(location);
if (cachedSrc) {
element.attr('src', cachedSrc);
return;
}
element.attr('src', scope.thumb.placeholder || 'img/blank.gif');
MtpApiFileManager.downloadSmallFile(scope.thumb.location, scope.thumb.size).then(function (url) {
element.attr('src', url);
if (counterSaved == counter) {
element.attr('src', url);
}
}, function (e) {
dLog('Download image failed', e, scope.thumb.location);
element.attr('src', scope.thumb.placeholder || '');
if (counterSaved == counter) {
element.attr('src', scope.thumb.placeholder || 'img/blank.gif');
}
});
})
@ -411,24 +424,18 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -411,24 +424,18 @@ angular.module('myApp.directives', ['myApp.filters'])
};
function link (scope, element, attrs) {
var imgElement = $('img', element),
fullLoaded = false;
var imgElement = $('img', element);
imgElement.attr('src', scope.fullPhoto.placeholder || 'img/blank.gif');
imgElement
.attr('src', MtpApiFileManager.getCachedFile(scope.thumbLocation) || 'img/blank.gif')
.addClass('thumb_blurred')
.addClass('thumb_blur_animation');
if (!scope.fullPhoto.location) {
return;
}
MtpApiFileManager.getCachedFile(scope.thumbLocation).then(function (url) {
if (!fullLoaded) {
imgElement
.attr('src', url)
.addClass('thumb_blurred')
.addClass('thumb_blur_animation');
}
});
var apiPromise;
if (scope.fullPhoto.size) {
@ -446,7 +453,6 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -446,7 +453,6 @@ angular.module('myApp.directives', ['myApp.filters'])
scope.progress = {enabled: true, percent: 1};
apiPromise.then(function (url) {
fullLoaded = true;
scope.progress.enabled = false;
imgElement
.attr('src', url)
@ -486,7 +492,13 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -486,7 +492,13 @@ angular.module('myApp.directives', ['myApp.filters'])
</div>\
</div>\
<div class="img_fullsize_wrap" ng-if="!player.src">\
<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 class="video_full_player" ng-if="player.src">\
<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"/>\

115
app/js/lib/mtproto.js

@ -2297,14 +2297,16 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2297,14 +2297,16 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
var apiUploadPromise = $q.when();
var cachedSavePromises = {};
var cachedDownloadPromises = {};
var cachedDownloads = {};
var downloadPulls = {};
var downloadActive = 0;
var downloadActives = {};
var downloadLimit = 5;
function downloadRequest(dcID, cb, activeDelta) {
if (downloadPulls[dcID] === undefined) {
downloadPulls[dcID] = [];
downloadActives[dcID] = 0
}
var downloadPull = downloadPulls[dcID];
var deferred = $q.defer();
@ -2319,25 +2321,25 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2319,25 +2321,25 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
function downloadCheck(dcID) {
var downloadPull = downloadPulls[dcID];
if (downloadActive >= downloadLimit || !downloadPull || !downloadPull.length) {
if (downloadActives[dcID] >= downloadLimit || !downloadPull || !downloadPull.length) {
return false;
}
var data = downloadPull.shift(),
activeDelta = data.activeDelta || 1;
downloadActive += activeDelta;
downloadActives[dcID] += activeDelta;
var a = index++;
data.cb()
.then(function (result) {
downloadActive -= activeDelta;
downloadActives[dcID] -= activeDelta;
downloadCheck(dcID);
data.deferred.resolve(result);
}, function (error) {
downloadActive -= activeDelta;
downloadActives[dcID] -= activeDelta;
downloadCheck(dcID);
data.deferred.reject(error);
@ -2351,7 +2353,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2351,7 +2353,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
$window.requestFileSystem = $window.requestFileSystem || $window.webkitRequestFileSystem;
if (!$window.requestFileSystem) {
if (!$window.requestFileSystem/* || true*/) {
return $q.reject({type: 'FS_BROWSER_UNSUPPORTED', description: 'requestFileSystem not present'});
}
@ -2404,23 +2406,12 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2404,23 +2406,12 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
};
function getCachedFile (location) {
var fileName = getFileName(location);
if (cachedSavePromises[fileName]) {
return cachedSavePromises[fileName];
if (!location) {
return false;
}
var deferred = $q.defer(),
errorHandler = function (error) {
deferred.reject();
};
requestFS().then(function () {
cachedFS.root.getFile(fileName, {create: false}, function(fileEntry) {
deferred.resolve(fileEntry.toURL());
}, errorHandler);
}, errorHandler);
var fileName = getFileName(location);
return deferred.promise;
return cachedDownloads[fileName] || false;
}
function saveSmallFile (location, bytes) {
@ -2434,17 +2425,18 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2434,17 +2425,18 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
errorHandler = function (error) {
deferred.reject(error);
if (cacheFileWriter) cacheFileWriter.truncate();
errorHandler = angular.noop;
};
requestFS().then(function () {
cachedFS.root.getFile(fileName, {create: false}, function(fileEntry) {
deferred.resolve(fileEntry.toURL());
deferred.resolve(cachedDownloads[fileName] = fileEntry.toURL());
}, function () {
cachedFS.root.getFile(fileName, {create: true}, function(fileEntry) {
fileEntry.createWriter(function (fileWriter) {
cacheFileWriter = fileWriter;
fileWriteBytes(fileWriter, bytes).then(function () {
deferred.resolve(fileEntry.toURL());
deferred.resolve(cachedDownloads[fileName] = fileEntry.toURL());
}, errorHandler);
}, errorHandler);
}, errorHandler);
@ -2468,6 +2460,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2468,6 +2460,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
errorHandler = function (error) {
deferred.reject(error);
if (cacheFileWriter) cacheFileWriter.truncate();
errorHandler = angular.noop;
},
doDownload = function () {
cachedFS.root.getFile(fileName, {create: true}, function(fileEntry) {
@ -2485,7 +2478,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2485,7 +2478,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
downloadPromise.then(function (result) {
fileWriteBytes(fileWriter, result.bytes).then(function () {
// dLog('Success', location, fileEntry.toURL());
deferred.resolve(fileEntry.toURL());
deferred.resolve(cachedDownloads[fileName] = fileEntry.toURL());
}, errorHandler);
}, errorHandler);
}, errorHandler);
@ -2496,7 +2489,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2496,7 +2489,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
cachedFS.root.getFile(fileName, {create: false}, function(fileEntry) {
fileEntry.file(function(file) {
if (file.size) {
deferred.resolve(fileEntry.toURL());
deferred.resolve(cachedDownloads[fileName] = fileEntry.toURL());
} else {
dLog('Small file empty', file);
doDownload();
@ -2513,7 +2506,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2513,7 +2506,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
limit: 0
}, {dcID: location.dc_id});
}).then(function (result) {
deferred.resolve('data:image/jpeg;base64,' + bytesToBase64(result.bytes))
deferred.resolve(cachedDownloads[fileName] = 'data:image/jpeg;base64,' + bytesToBase64(result.bytes))
}, errorHandler);
});
@ -2536,6 +2529,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2536,6 +2529,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
// dLog('fail');
deferred.reject(error);
if (cacheFileWriter) cacheFileWriter.truncate();
errorHandler = angular.noop;
},
saveToFileEntry = function (fileEntry) {
fileEntry.createWriter(function (fileWriter) {
@ -2571,7 +2565,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2571,7 +2565,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
}, errorHandler).then(function () {
if (isFinal) {
deferred.resolve(fileEntry.toURL('image/jpeg'));
deferred.resolve(cachedDownloads[fileName] = fileEntry.toURL('image/jpeg'));
} else {
// dLog('notify', {done: offset + limit, total: size});
deferred.notify({done: offset + limit, total: size});
@ -2590,9 +2584,6 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2590,9 +2584,6 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
}
}, errorHandler);
},
doDownload = function () {
cachedFS.root.getFile(fileName, {create: true}, saveToFileEntry, errorHandler);
};
if (fileEntry) {
@ -2603,14 +2594,68 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2603,14 +2594,68 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
fileEntry.file(function(file) {
dLog('check size', file.size, size);
if (file.size >= size) {
deferred.resolve(fileEntry.toURL());
deferred.resolve(cachedDownloads[fileName] = fileEntry.toURL());
} else {
dLog('File bad size', file, size);
doDownload();
cachedFS.root.getFile(fileName, {create: true}, saveToFileEntry, errorHandler)
}
}, errorHandler);
}, doDownload);
}, errorHandler);
}, function () {
cachedFS.root.getFile(fileName, {create: true}, saveToFileEntry, errorHandler)
});
}, function () {
var blobParts = [];
var limit = size > 30400 ? 524288 : 4096;
var writeBlobPromise = $q.when(),
writeBlobDeferred;
for (var offset = 0; offset < size; offset += limit) {
writeBlobDeferred = $q.defer();
(function (isFinal, offset, writeBlobDeferred, writeBlobPromise) {
return downloadRequest(dcID, function () {
return MtpApiManager.invokeApi('upload.getFile', {
location: location,
offset: offset,
limit: limit
}, {dcID: dcID});
}, 6).then(function (result) {
writeBlobPromise.then(function () {
try {
blobParts.push(bytesToArrayBuffer(result.bytes));
writeBlobDeferred.resolve();
if (isFinal) {
try {
var blob = new Blob(blobParts, {type: 'image/jpeg'});
} catch (e) {
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
var bb = new BlobBuilder;
angular.forEach(blobParts, function(blobPart) {
bb.append(blobPart);
});
var blob = bb.getBlob('image/jpeg');
}
window.URL = window.URL || window.webkitURL;
deferred.resolve(cachedDownloads[fileName] = URL.createObjectURL(blob));
} else {
deferred.notify({done: offset + limit, total: size});
};
} catch (e) {
errorHandler(e);
}
}, errorHandler);
});
})(offset + limit >= size, offset, writeBlobDeferred, writeBlobPromise);
writeBlobPromise = writeBlobDeferred.promise;
}
});
}
return cachedDownloadPromises[fileName] = deferred.promise;
@ -2626,6 +2671,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2626,6 +2671,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
dLog('fail');
deferred.reject(error);
if (cacheFileWriter) cacheFileWriter.truncate();
errorHandler = angular.noop;
};
requestFS().then(function () {
@ -2660,6 +2706,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) { @@ -2660,6 +2706,7 @@ factory('MtpApiFileManager', function (MtpApiManager, $q, $window) {
errorHandler = function (error) {
dLog('error', error);
deferred.reject(error);
errorHandler = angular.noop;
},
part = 0,
offset,

4
app/js/services.js

@ -213,7 +213,7 @@ angular.module('myApp.services', []) @@ -213,7 +213,7 @@ angular.module('myApp.services', [])
scope.userID = userID;
var modalInstance = $modal.open({
templateUrl: 'partials/user_modal.html',
templateUrl: 'partials/user_modal.html?1',
controller: 'UserModalController',
scope: scope,
windowClass: 'user_modal_window',
@ -335,7 +335,7 @@ angular.module('myApp.services', []) @@ -335,7 +335,7 @@ angular.module('myApp.services', [])
scope.chatID = chatID;
var modalInstance = $modal.open({
templateUrl: 'partials/chat_modal.html?2',
templateUrl: 'partials/chat_modal.html?3',
controller: 'ChatModalController',
windowClass: 'chat_modal_window',
scope: scope

11
app/partials/chat_modal.html

@ -8,7 +8,10 @@ @@ -8,7 +8,10 @@
<div class="modal-body">
<div class="chat_modal_image_wrap pull-left">
<img class="chat_modal_image" src="img/blank.gif" my-load-thumb thumb="chatFull.thumb"/>
<img
class="chat_modal_image"
my-load-thumb
thumb="chatFull.thumb"/>
</div>
<div class="chat_modal_info_wrap clearfix">
@ -27,7 +30,11 @@ @@ -27,7 +30,11 @@
<div class="chat_modal_participant_wrap clearfix" ng-repeat="participant in chatFull.participants.participants">
<a ng-click="openUser(participant.user_id)" class="chat_modal_participant_photo pull-left">
<img class="chat_modal_participant_photo" my-load-thumb thumb="participant.userPhoto"/>
<img
class="chat_modal_participant_photo"
my-load-thumb
thumb="participant.userPhoto"
/>
<i class="icon modal_participant_online" ng-show="participant.user.status._ == 'userStatusOnline'"></i>
</a>
<div class="chat_modal_participant_name">

21
app/partials/dialog.html

@ -4,11 +4,19 @@ @@ -4,11 +4,19 @@
<div class="im_dialog_date">
{{dialogMessage.date | dateOrTime}}
</div>
<span class="im_dialog_badge badge" ng-show="dialogMessage.unreadCount > 0" ng-bind="dialogMessage.unreadCount"></span>
<span
class="im_dialog_badge badge"
ng-show="dialogMessage.unreadCount > 0"
ng-bind="dialogMessage.unreadCount"
></span>
</div>
<div class="im_dialog_photo pull-left">
<img class="im_dialog_photo" src="img/blank.gif" my-load-thumb thumb="dialogMessage.peerPhoto" />
<img
class="im_dialog_photo"
my-load-thumb
thumb="dialogMessage.peerPhoto"
/>
</div>
<div class="im_dialog_message_wrap">
@ -22,7 +30,14 @@ @@ -22,7 +30,14 @@
<div class="im_dialog_message">
<span class="im_dialog_chat_from_wrap">
<span class="im_dialog_chat_from" ng-if="!dialogMessage.out &amp;&amp; dialogMessage.chatID" ng-bind-html="dialogMessage.fromUser.rFirstName"></span><span class="im_dialog_chat_from" ng-if="dialogMessage.out">You</span>{{((dialogMessage.out || dialogMessage.peerID &lt; 0) &amp;&amp; (dialogMessage.message.length || dialogMessage.media &amp;&amp; dialogMessage.media._ != 'messageMediaEmpty')) ? ':' : ''}}
<span
class="im_dialog_chat_from"
ng-if="!dialogMessage.out &amp;&amp; dialogMessage.chatID"
ng-bind-html="dialogMessage.fromUser.rFirstName"
></span><span
class="im_dialog_chat_from"
ng-if="dialogMessage.out"
>You</span>{{((dialogMessage.out || dialogMessage.peerID &lt; 0) &amp;&amp; (dialogMessage.message.length || dialogMessage.media &amp;&amp; dialogMessage.media._ != 'messageMediaEmpty')) ? ':' : ''}}
</span>
<span class="im_dialog_message_media" ng-if="dialogMessage.media &amp;&amp; dialogMessage.media._ != 'messageMediaEmpty'" ng-switch="dialogMessage.media._">

18
app/partials/im.html

@ -80,14 +80,26 @@ @@ -80,14 +80,26 @@
<div class="im_send_form_wrap clearfix" ng-controller="AppImSendController">
<div class="pull-right im_panel_peer_photo" ng-click="openUser(historyPeer.id)" ng-if="historyPeer.id > 0">
<img class="im_panel_peer_photo" src="img/blank.gif" my-load-thumb thumb="historyPeer.photo" />
<img
class="im_panel_peer_photo"
my-load-thumb
thumb="historyPeer.photo"
/>
<i class="icon im_panel_peer_online" ng-show="historyPeer.data.status._ == 'userStatusOnline'"></i>
</div>
<div class="pull-right im_panel_peer_photo" ng-click="openChat(-historyPeer.id)" ng-if="historyPeer.id < 0">
<img class="im_panel_peer_photo" src="img/blank.gif" my-load-thumb thumb="historyPeer.photo" />
<img
class="im_panel_peer_photo"
my-load-thumb
thumb="historyPeer.photo"
/>
</div>
<div class="pull-left im_panel_own_photo">
<img class="im_panel_own_photo" src="img/blank.gif" my-load-thumb thumb="ownPhoto" />
<img
class="im_panel_own_photo"
my-load-thumb
thumb="ownPhoto"
/>
</div>
<form my-send-form draft-message="draftMessage" class="im_send_form" ng-submit="sendMessage($event)">
<div class="im_send_dropbox_wrap"> Drop photos here to send </div>

36
app/partials/message.html

@ -43,7 +43,13 @@ @@ -43,7 +43,13 @@
</div>
<a ng-if="historyMessage.action._ == 'messageActionChatEditPhoto'" class="im_service_message_photo_thumb" href="" ng-click="openPhoto(historyMessage.action.photo.id)">
<img class="im_service_message_photo_thumb" src="img/blank.gif" my-load-thumb thumb="historyMessage.action.photo.thumb" width="{{historyMessage.action.photo.thumb.width}}" height="{{historyMessage.action.photo.thumb.height}}" />
<img
class="im_service_message_photo_thumb"
my-load-thumb
thumb="historyMessage.action.photo.thumb"
width="{{historyMessage.action.photo.thumb.width}}"
height="{{historyMessage.action.photo.thumb.height}}"
/>
</a>
</div>
@ -52,7 +58,11 @@ @@ -52,7 +58,11 @@
<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">
<img class="im_message_from_photo" src="img/blank.gif" my-load-thumb thumb="historyMessage.fromPhoto"/>
<img
class="im_message_from_photo"
my-load-thumb
thumb="historyMessage.fromPhoto"
/>
</a>
<div class="im_message_meta pull-right text-right">
<i ng-if="historyMessage.out" class="icon icon-message-status-tick" ng-class="{'message-status-delivered-tick': true, 'message-status-unread-tick': historyMessage.unread}"></i>
@ -71,11 +81,23 @@ @@ -71,11 +81,23 @@
<div class="im_message_media" ng-if="historyMessage.media &amp;&amp; historyMessage.media._ != 'messageMediaEmpty'" ng-switch="historyMessage.media._">
<a ng-switch-when="messageMediaPhoto" class="im_message_photo_thumb" href="" ng-click="openPhoto(historyMessage.media.photo.id)" >
<img class="im_message_photo_thumb" src="img/blank.gif" my-load-thumb thumb="historyMessage.media.photo.thumb" width="{{historyMessage.media.photo.thumb.width}}" height="{{historyMessage.media.photo.thumb.height}}" />
<img
class="im_message_photo_thumb"
my-load-thumb
thumb="historyMessage.media.photo.thumb"
width="{{historyMessage.media.photo.thumb.width}}"
height="{{historyMessage.media.photo.thumb.height}}"
/>
</a>
<a ng-switch-when="messageMediaVideo" class="im_message_video_thumb" href="" ng-click="openVideo(historyMessage.media.video.id)">
<img class="im_message_video_thumb" src="img/blank.gif" my-load-thumb thumb="historyMessage.media.video.thumb" width="{{historyMessage.media.video.thumb.width}}" height="{{historyMessage.media.video.thumb.height}}" />
<img
class="im_message_video_thumb"
my-load-thumb
thumb="historyMessage.media.video.thumb"
width="{{historyMessage.media.video.thumb.width}}"
height="{{historyMessage.media.video.thumb.height}}"
/>
<div class="im_message_video_duration_wrap" style="width: {{historyMessage.media.video.thumb.width}}px;">
<span class="im_message_video_duration pull-right">{{historyMessage.media.video.duration | duration}}</span>
<span class="glyphicon glyphicon-facetime-video"></span>
@ -117,7 +139,11 @@ @@ -117,7 +139,11 @@
<div ng-switch-when="messageMediaContact">
<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"
my-load-thumb
thumb="historyMessage.media.userPhoto"
/>
</a>
<div class="im_message_contact_name"><span class="glyphicon glyphicon-user"></span>
{{historyMessage.media.first_name}} {{historyMessage.media.last_name}}

6
app/partials/user_modal.html

@ -9,7 +9,11 @@ @@ -9,7 +9,11 @@
<div class="modal-body">
<div class="user_modal_image_wrap pull-left">
<img class="user_modal_image" my-load-thumb thumb="user.thumb"/>
<img
class="user_modal_image"
my-load-thumb
thumb="user.thumb"
/>
</div>
<div class="user_modal_info_wrap clearfix">

Loading…
Cancel
Save