Download videos, attach tooltips

This commit is contained in:
Igor Zhukov 2014-03-21 16:05:40 +04:00
parent a4db65e21b
commit 37cebdb237
7 changed files with 212 additions and 65 deletions

View File

@ -256,7 +256,7 @@ input[type="number"]::-webkit-inner-spin-button {
vertical-align: text-top; vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -15px -419px no-repeat; background: url(../img/icons/IconsetW.png) -15px -419px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
opacity: 0.6; opacity: 0.6;
} }
.is_1x .icon-back { .is_1x .icon-back {
@ -518,7 +518,7 @@ input[type="number"]::-webkit-inner-spin-button {
font-size: 12px; font-size: 12px;
line-height: normal; line-height: normal;
background: #F2F2F2 url(../img/icons/IconsetW.png) -6px -205px no-repeat; background: #F2F2F2 url(../img/icons/IconsetW.png) -6px -205px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
border: 1px solid #F2F2F2; border: 1px solid #F2F2F2;
border-radius: 3px; border-radius: 3px;
padding: 6px 20px 6px 30px; padding: 6px 20px 6px 30px;
@ -542,7 +542,7 @@ input[type="number"]::-webkit-inner-spin-button {
height: 13px; height: 13px;
vertical-align: text-top; vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -15px -192px no-repeat; background: url(../img/icons/IconsetW.png) -15px -192px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
opacity: 0.6; opacity: 0.6;
} }
.is_1x .im_dialogs_search_clear { .is_1x .im_dialogs_search_clear {
@ -795,7 +795,7 @@ a.im_dialog:hover .im_dialog_date {
margin-left: 6px; margin-left: 6px;
background: url(../img/icons/IconsetW.png) -17px -444px no-repeat; background: url(../img/icons/IconsetW.png) -17px -444px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
} }
.is_1x .icon-caret { .is_1x .icon-caret {
background-image: url(../img/icons/IconsetW_1x.png); background-image: url(../img/icons/IconsetW_1x.png);
@ -961,7 +961,6 @@ a.im_message_contact_photo {
a.im_message_photo_thumb, a.im_message_photo_thumb,
a.im_message_video_thumb { a.im_message_video_thumb {
display: block; display: block;
margin-top: 5px;
overflow: hidden; overflow: hidden;
border-radius: 2px; border-radius: 2px;
} }
@ -970,6 +969,15 @@ img.im_message_video_thumb {
overflow: hidden; overflow: hidden;
border-radius: 2px; border-radius: 2px;
} }
.im_message_video,
a.im_message_photo_thumb {
margin-top: 5px;
}
a.im_message_video_thumb {
float: left;
margin-right: 15px;
position: relative;
}
img.im_message_video_thumb { img.im_message_video_thumb {
-webkit-filter: blur(2px); -webkit-filter: blur(2px);
@ -983,21 +991,36 @@ img.im_message_video_thumb {
div.im_message_video_thumb { div.im_message_video_thumb {
position: relative; position: relative;
} }
.im_message_video_duration_wrap { .im_message_video_duration {
background: rgba(0, 0, 0, 0.5); background: rgba(0, 0, 0, 0.4);
color: #FFF; color: #FFF;
position: absolute; position: absolute;
margin-top: -15px; bottom: 4px;
height: 15px; right: 4px;
padding: 0 3px; padding: 2px 6px;
font-size: 11px; font-size: 11px;
line-height: 15px; line-height: 15px;
border-radius: 2px;
border-radius: 0 0 2px 2px;
overflow: hidden; overflow: hidden;
z-index: 1;
} }
.im_message_video_duration {
.icon-videoplay {
position: absolute;
display: inline-block;
top: 50%;
left: 50%;
margin-left: -21px;
margin-top: -21px;
width: 42px;
height: 42px;
background: url(../img/icons/IconsetW.png) 0 -590px no-repeat;
background-size: 42px 680px;
z-index: 1;
}
.is_1x .icon-videoplay {
background-image: url(../img/icons/IconsetW_1x.png);
} }
.im_message_geopoint { .im_message_geopoint {
@ -1020,7 +1043,7 @@ div.im_message_video_thumb {
height: 19px; height: 19px;
background: url(../img/icons/IconsetW.png) -14px -389px no-repeat; background: url(../img/icons/IconsetW.png) -14px -389px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
} }
.is_1x .icon-geo-point { .is_1x .icon-geo-point {
background-image: url(../img/icons/IconsetW_1x.png); background-image: url(../img/icons/IconsetW_1x.png);
@ -1048,7 +1071,7 @@ div.im_message_video_thumb {
vertical-align: text-top; vertical-align: text-top;
background: #F2F2F2 url(../img/icons/IconsetW.png) -2px -229px no-repeat; background: #F2F2F2 url(../img/icons/IconsetW.png) -2px -229px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
border-radius: 3px; border-radius: 3px;
margin-right: 10px; margin-right: 10px;
} }
@ -1135,7 +1158,7 @@ img.im_message_document_thumb {
vertical-align: text-top; vertical-align: text-top;
background: #F2F2F2 url(../img/icons/IconsetW.png) -2px -277px no-repeat; background: #F2F2F2 url(../img/icons/IconsetW.png) -2px -277px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
border-radius: 3px; border-radius: 3px;
margin-right: 10px; margin-right: 10px;
} }
@ -1189,6 +1212,13 @@ img.im_message_document_thumb {
.im_message_document_thumbed .im_message_document_name { .im_message_document_thumbed .im_message_document_name {
max-width: 150px; max-width: 150px;
} }
.im_message_video .im_message_document_name_wrap,
.im_message_video .im_message_download_progress_wrap {
width: 150px;
}
.im_message_video .im_message_document_name_wrap {
margin-top: 5px;
}
.tg_up_progress, .tg_up_progress,
.tg_down_progress { .tg_down_progress {
@ -1404,7 +1434,7 @@ textarea.im_message_field {
height: 23px; height: 23px;
vertical-align: text-top; vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -12px -68px no-repeat; background: url(../img/icons/IconsetW.png) -12px -68px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
opacity: 0.8; opacity: 0.8;
} }
.is_1x .icon-paperclip { .is_1x .icon-paperclip {
@ -1432,7 +1462,7 @@ textarea.im_message_field {
height: 23px; height: 23px;
vertical-align: text-top; vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -10px -4px no-repeat; background: url(../img/icons/IconsetW.png) -10px -4px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
opacity: 0.8; opacity: 0.8;
} }
.is_1x .icon-emoji { .is_1x .icon-emoji {
@ -1482,7 +1512,7 @@ textarea.im_message_field {
height: 21px; height: 21px;
vertical-align: text-top; vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -9px -132px no-repeat; background: url(../img/icons/IconsetW.png) -9px -132px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
opacity: 0.8; opacity: 0.8;
} }
.is_1x .icon-camera { .is_1x .icon-camera {
@ -1905,7 +1935,7 @@ img.img_fullsize {
.emoji-menu-tail { .emoji-menu-tail {
display: none; display: none;
background: url(../img/icons/IconsetW.png) -14px -268px no-repeat; background: url(../img/icons/IconsetW.png) -14px -268px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
width: 14px; width: 14px;
height: 7px; height: 7px;
margin: 0 83px; margin: 0 83px;
@ -2050,7 +2080,7 @@ img.img_fullsize {
font-size: 12px; font-size: 12px;
line-height: normal; line-height: normal;
background: #F2F2F2 url(../img/icons/IconsetW.png) -6px -205px no-repeat; background: #F2F2F2 url(../img/icons/IconsetW.png) -6px -205px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
border: 1px solid #F2F2F2; border: 1px solid #F2F2F2;
border-radius: 3px; border-radius: 3px;
padding: 6px 20px 6px 30px; padding: 6px 20px 6px 30px;
@ -2074,7 +2104,7 @@ img.img_fullsize {
height: 13px; height: 13px;
vertical-align: text-top; vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -15px -192px no-repeat; background: url(../img/icons/IconsetW.png) -15px -192px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
opacity: 0.6; opacity: 0.6;
} }
.is_1x .contacts_modal_search_clear { .is_1x .contacts_modal_search_clear {
@ -2151,7 +2181,7 @@ a.contacts_modal_contact:hover .contacts_modal_contact_status {
width: 17px; width: 17px;
height: 15px; height: 15px;
background: url(../img/icons/IconsetW.png) -13px -366px no-repeat; background: url(../img/icons/IconsetW.png) -13px -366px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
opacity: 0.5; opacity: 0.5;
} }
.is_1x .icon-contact-tick { .is_1x .icon-contact-tick {
@ -2249,7 +2279,7 @@ a.contacts_modal_contact:hover .contacts_modal_contact_status {
height: 15px; height: 15px;
background: url(../img/icons/IconsetW.png) -15px -319px no-repeat; background: url(../img/icons/IconsetW.png) -15px -319px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
} }
.is_1x .icon-delete { .is_1x .icon-delete {
background-image: url(../img/icons/IconsetW_1x.png); background-image: url(../img/icons/IconsetW_1x.png);
@ -2296,7 +2326,7 @@ a.contacts_modal_contact:hover .contacts_modal_contact_status {
height: 26px; height: 26px;
margin: 13px 0 0 40px; margin: 13px 0 0 40px;
background: url(../img/icons/IconsetW.png) -9px -516px no-repeat; background: url(../img/icons/IconsetW.png) -9px -516px no-repeat;
background-size: 42px 620px; background-size: 42px 680px;
} }
.is_1x .icon-select-tick { .is_1x .icon-select-tick {
background-image: url(../img/icons/IconsetW_1x.png); background-image: url(../img/icons/IconsetW_1x.png);
@ -2531,4 +2561,4 @@ ce671b orange
color: #999; color: #999;
font-size: 13px; font-size: 13px;
margin-left: 8px; margin-left: 8px;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -623,7 +623,11 @@ angular.module('myApp.controllers', [])
$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) {
if ($scope.mediaType) { if ($scope.mediaType) {
$scope.missedCount++; if (addedMessage.my) {
toggleMedia();
} else {
$scope.missedCount++;
}
return; return;
} }
// console.log('append', addedMessage); // console.log('append', addedMessage);
@ -665,6 +669,12 @@ angular.module('myApp.controllers', [])
} }
}); });
$scope.$on('history_focus', function (e, peerData) {
if ($scope.mediaType) {
toggleMedia();
}
});
$scope.$on('apiUpdate', function (e, update) { $scope.$on('apiUpdate', function (e, update) {
// console.log('on apiUpdate inline', update); // console.log('on apiUpdate inline', update);
switch (update._) { switch (update._) {

View File

@ -1827,8 +1827,9 @@ angular.module('myApp.services', [])
}) })
.service('AppVideoManager', function ($rootScope, $modal, $window, MtpApiFileManager, AppUsersManager) { .service('AppVideoManager', function ($rootScope, $modal, $window, $timeout, MtpApiFileManager, AppUsersManager) {
var videos = {}; var videos = {};
var videosForHistory = {};
function saveVideo (apiVideo) { function saveVideo (apiVideo) {
videos[apiVideo.id] = apiVideo; videos[apiVideo.id] = apiVideo;
@ -1844,6 +1845,10 @@ angular.module('myApp.services', [])
}; };
function wrapForHistory (videoID) { function wrapForHistory (videoID) {
if (videosForHistory[videoID] !== undefined) {
return videosForHistory[videoID];
}
var video = angular.copy(videos[videoID]), var video = angular.copy(videos[videoID]),
width = 200, width = 200,
height = 200, height = 200,
@ -1867,7 +1872,7 @@ angular.module('myApp.services', [])
video.thumb = thumb; video.thumb = thumb;
return video; return videosForHistory[videoID] = video;
} }
function wrapForFull (videoID) { function wrapForFull (videoID) {
@ -1915,7 +1920,76 @@ angular.module('myApp.services', [])
}); });
} }
function downloadVideo (videoID, accessHash, popup) {
var video = videos[videoID],
historyVideo = videosForHistory[videoID] || video || {},
inputFileLocation = {
_: 'inputVideoFileLocation',
id: videoID,
access_hash: accessHash || video.access_hash
};
historyVideo.progress = {enabled: true, percent: 1, total: video.size};
function updateDownloadProgress (progress) {
console.log('dl progress', progress);
historyVideo.progress.done = progress.done;
historyVideo.progress.percent = Math.max(1, Math.floor(100 * progress.done / progress.total));
$rootScope.$broadcast('history_update');
}
var ext = 'mp4',
mimeType = 'video/mpeg4',
fileName = 'video' + videoID + '.' + ext;
if (window.chrome && chrome.fileSystem && chrome.fileSystem.chooseEntry) {
chrome.fileSystem.chooseEntry({
type: 'saveFile',
suggestedName: fileName,
accepts: [{
mimeTypes: [mimeType],
extensions: [ext]
}]
}, function (writableFileEntry) {
MtpApiFileManager.downloadFile(video.dc_id, inputFileLocation, video.size, writableFileEntry, {mime: mimeType}).then(function (url) {
delete historyVideo.progress;
console.log('file save done');
}, function (e) {
console.log('video download failed', e);
historyVideo.progress.enabled = false;
}, updateDownloadProgress);
});
} else {
MtpApiFileManager.downloadFile(video.dc_id, inputFileLocation, video.size, null, {mime: mimeType}).then(function (url) {
delete historyVideo.progress;
if (popup) {
window.open(url, '_blank');
return
}
var a = $('<a>Download</a>')
.css({position: 'absolute', top: 1, left: 1})
.attr('href', url)
.attr('target', '_blank')
.attr('download', fileName)
.appendTo('body');
a[0].dataset.downloadurl = [mimeType, fileName, url].join(':');
a[0].click();
$timeout(function () {
a.remove();
}, 100);
}, function (e) {
console.log('video download failed', e);
historyVideo.progress.enabled = false;
}, updateDownloadProgress);
}
};
$rootScope.openVideo = openVideo; $rootScope.openVideo = openVideo;
$rootScope.downloadVideo = downloadVideo;
return { return {
saveVideo: saveVideo, saveVideo: saveVideo,
@ -1977,7 +2051,7 @@ angular.module('myApp.services', [])
return docsForHistory[docID] = doc; return docsForHistory[docID] = doc;
} }
function openDoc (docID, accessHash, popup) { function downloadDoc (docID, accessHash, popup) {
var doc = docs[docID], var doc = docs[docID],
historyDoc = docsForHistory[docID] || doc || {}, historyDoc = docsForHistory[docID] || doc || {},
inputFileLocation = { inputFileLocation = {
@ -2024,8 +2098,14 @@ angular.module('myApp.services', [])
return return
} }
var a = $('<a>Download</a>').css({position: 'absolute', top: 1, left: 1}).attr('href', url).attr('target', '_blank').attr('download', doc.file_name).appendTo('body'); var a = $('<a>Download</a>')
a[0].dataset.downloadurl = ['png', doc.file_name, url].join(':'); .css({position: 'absolute', top: 1, left: 1})
.attr('href', url)
.attr('target', '_blank')
.attr('download', doc.file_name)
.appendTo('body');
a[0].dataset.downloadurl = [doc.mime_type, doc.file_name, url].join(':');
a[0].click(); a[0].click();
$timeout(function () { $timeout(function () {
a.remove(); a.remove();
@ -2037,12 +2117,12 @@ angular.module('myApp.services', [])
} }
} }
$rootScope.openDoc = openDoc; $rootScope.downloadDoc = downloadDoc;
return { return {
saveDoc: saveDoc, saveDoc: saveDoc,
wrapForHistory: wrapForHistory, wrapForHistory: wrapForHistory,
openDoc: openDoc downloadDoc: downloadDoc
} }
}) })

View File

@ -118,7 +118,7 @@
</div> </div>
<div class="im_history_typing_wrap"> <div class="im_history_typing_wrap">
<div class="im_history_typing" ng-show="typing.user"> <div class="im_history_typing" ng-show="typing.user &amp;&amp; !mediaType">
<strong class="im_history_typing_author" ng-bind-html="typing.user.rFullName"></strong> is typing<span my-typing-dots></span> <strong class="im_history_typing_author" ng-bind-html="typing.user.rFullName"></strong> is typing<span my-typing-dots></span>
</div> </div>
</div> </div>
@ -175,22 +175,24 @@
<div class="im_send_dropbox_wrap"> Drop photos here to send </div> <div class="im_send_dropbox_wrap"> Drop photos here to send </div>
<textarea ng-model="draftMessage.text" placeholder="Write a message..." class="form-control im_message_field"></textarea> <textarea ng-model="draftMessage.text" placeholder="Write a message..." class="form-control im_message_field"></textarea>
<div class="im_media_attach pull-right"> <div class="" style="position: relative;">
<input type="file" class="im_media_attach_input" size="28" multiple="true" accept="image/*, video/*, audio/*" /> <div class="im_media_attach pull-right" tooltip="Send media" tooltip-append-to-body="true">
<i class="icon icon-camera"></i> <input type="file" class="im_media_attach_input" size="28" multiple="true" accept="image/*, video/*, audio/*" />
<i class="icon icon-camera"></i>
</div>
<div class="im_attach pull-right" tooltip="Send file" tooltip-append-to-body="true">
<input type="file" class="im_attach_input" size="28" multiple="true" />
<i class="icon icon-paperclip"></i>
</div>
<div class="im_emoji_btn pull-right">
<i class="icon icon-emoji"></i>
</div>
<button type="submit" class="btn btn-success im_submit">Send</button>
</div> </div>
<div class="im_attach pull-right">
<input type="file" class="im_attach_input" size="28" multiple="true" />
<i class="icon icon-paperclip"></i>
</div>
<div class="im_emoji_btn pull-right">
<i class="icon icon-emoji"></i>
</div>
<button type="submit" class="btn btn-success im_submit">Send</button>
</form> </form>
</div> </div>

View File

@ -106,22 +106,47 @@
/> />
</a> </a>
<a ng-switch-when="messageMediaVideo" class="im_message_video_thumb" href="" ng-click="openVideo(historyMessage.media.video.id)" style="width: {{historyMessage.media.video.thumb.width}}px;"> <div ng-switch-when="messageMediaVideo" class="im_message_video im_message_document_thumbed">
<img <a class="im_message_video_thumb" href="" ng-click="openVideo(historyMessage.media.video.id)" style="width: {{historyMessage.media.video.thumb.width}}px;">
class="im_message_video_thumb" <span class="im_message_video_duration">{{historyMessage.media.video.duration | duration}}</span>
my-load-thumb <i class="icon icon-videoplay"></i>
thumb="historyMessage.media.video.thumb" <img
width="{{historyMessage.media.video.thumb.width}}" class="im_message_video_thumb"
height="{{historyMessage.media.video.thumb.height}}" my-load-thumb
/> thumb="historyMessage.media.video.thumb"
<div class="im_message_video_duration_wrap" style="width: {{historyMessage.media.video.thumb.width}}px;"> width="{{historyMessage.media.video.thumb.width}}"
<span class="im_message_video_duration pull-right">{{historyMessage.media.video.duration | duration}}</span> height="{{historyMessage.media.video.thumb.height}}"
<span class="glyphicon glyphicon-facetime-video"></span> />
</a>
<div class="im_message_document_info">
<div class="im_message_document_name_wrap">
<span class="im_message_document_name">Video</span>
<span class="im_message_document_size" ng-if="!historyMessage.media.video.progress.enabled">
{{historyMessage.media.video.size | formatSize}}
</span>
<span class="im_message_document_size" ng-if="historyMessage.media.video.progress.enabled">
{{historyMessage.media.video.progress | formatSizeProgress}}
</span>
</div>
<div class="im_message_document_actions" ng-if="!historyMessage.media.video.progress.enabled">
<a href="" ng-click="downloadVideo(historyMessage.media.video.id)">Download</a>
<a href="" ng-click="openVideo(historyMessage.media.video.id)">Play video</a>
</div>
<div class="im_message_download_progress_wrap" ng-if="historyMessage.media.video.progress.enabled">
<div class="progress tg_down_progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{historyMessage.media.video.progress.percent}}" aria-valuemin="0" aria-valuemax="100" style="width: {{historyMessage.media.video.progress.percent}}%">
<span class="sr-only">
{{historyMessage.media.video.progress.percent}}% Complete (success)
</span>
</div>
</div>
</div>
</div> </div>
</a> </div>
<div ng-switch-when="messageMediaDocument" class="im_message_document" ng-class="{im_message_document_thumbed: !!historyMessage.media.document.thumb}"> <div ng-switch-when="messageMediaDocument" class="im_message_document" ng-class="{im_message_document_thumbed: !!historyMessage.media.document.thumb}">
<a href="" ng-click="openDoc(historyMessage.media.document.id, false, historyMessage.media.document.withPreview)" ng-class="{im_message_document_link_disabled: historyMessage.media.document.progress.enabled}"> <a href="" ng-click="downloadDoc(historyMessage.media.document.id, false, historyMessage.media.document.withPreview)" ng-class="{im_message_document_link_disabled: historyMessage.media.document.progress.enabled}">
<i class="icon icon-document" ng-if="!historyMessage.media.document.thumb"></i> <i class="icon icon-document" ng-if="!historyMessage.media.document.thumb"></i>
<div class="im_message_document_thumb_wrap" ng-if="historyMessage.media.document.thumb"> <div class="im_message_document_thumb_wrap" ng-if="historyMessage.media.document.thumb">
<img <img
@ -147,8 +172,8 @@
</span> </span>
</div> </div>
<div class="im_message_document_actions" ng-if="!historyMessage.media.document.progress.enabled"> <div class="im_message_document_actions" ng-if="!historyMessage.media.document.progress.enabled">
<a href="" ng-click="openDoc(historyMessage.media.document.id)">Download</a> <a href="" ng-click="downloadDoc(historyMessage.media.document.id)">Download</a>
<a href="" ng-click="openDoc(historyMessage.media.document.id, false, true)" ng-if="historyMessage.media.document.withPreview">Open</a> <a href="" ng-click="downloadDoc(historyMessage.media.document.id, false, true)" ng-if="historyMessage.media.document.withPreview">Open</a>
</div> </div>
<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">