Browse Source

Added mobile-friendly photo/video viewer

Closes #479
master
Igor Zhukov 10 years ago
parent
commit
bf3e0ab630
  1. 126
      app/css/mobile.css
  2. 7
      app/js/controllers.js
  3. 4
      app/js/locales/en-us.json
  4. 19
      app/js/services.js
  5. 10
      app/partials/desktop/photo_modal.html
  6. 5
      app/partials/desktop/video_modal.html
  7. 1
      app/partials/mobile/media_modal_layout.html
  8. 66
      app/partials/mobile/photo_modal.html
  9. 60
      app/partials/mobile/video_modal.html

126
app/css/mobile.css

@ -1128,3 +1128,129 @@ a.mobile_modal_action .tg_checkbox_label {
margin-top: 40px; margin-top: 40px;
text-align: center; text-align: center;
} }
.media_modal_bottom_panel_wrap {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 46px;
background: rgba(0,0,0,0.6);
z-index: 1030;
}
.media_modal_bottom_panel {
color: #FFF;
}
.media_modal_top_panel_wrap {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 46px;
background: rgba(0,0,0,0.6);
z-index: 1030;
}
.media_modal_top_panel {
color: #FFF;
}
.media_modal_top_actions .navbar-quick-media-back {
color: inherit;
position: relative;
display: block;
padding-left: 16px;
padding: 6px 10px 2px 28px;
font-size: 13px;
height: 46px;
}
.media_modal_top_actions .navbar-quick-media-back .icon-back {
position: absolute;
margin-left: -18px;
margin-top: 8px;
}
h4.media_modal_title_wrap {
color: inherit;
margin: 8px 0 11px 0;
}
.media_modal_info_wrap {
line-height: 16px;
padding: 7px 20px;
text-align: center;
max-width: 150px;
margin: 0 auto;
}
.media_modal_author {
display: inline-block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 150px;
font-size: 14px;
}
.media_modal_date,
a.media_modal_date:hover {
font-size: 12px;
color: #999;
}
.photo_modal_window,
.video_modal_window,
.document_modal_window {
padding: 0;
background: #000;
}
.photo_modal_window .modal-content,
.video_modal_window .modal-content,
.document_modal_window .modal-content {
background: none;
box-shadow: none;
}
.video_modal_window .modal-body {
padding: 0;
}
.media_modal_action_btn {
float: left;
display: block;
width: 46px;
height: 46px;
}
.tg_page_head .navbar-inverse .navbar-quick-nav > .navbar-quick-right > a.media_modal_action_btn,
.tg_page_head .navbar-inverse .navbar-quick-nav > .navbar-quick-left > a.media_modal_action_btn {
padding: 0;
}
.media_modal_action_btn i {
background: url(../img/icons/PhotoIcons.png) 0 0 no-repeat;
background-size: 40px 200px;
display: block;
opacity: 0.8;
}
.media_modal_action_btn:active i {
opacity: 1;
}
.is_1x .media_modal_action_btn i {
background-image: url(../img/icons/PhotoIcons_1x.png);
}
.media_modal_action_btn i.media_modal_action_btn_download {
background-position: -12px -163px;
width: 16px;
height: 20px;
margin: 14px 15px;
}
.media_modal_action_btn i.media_modal_action_btn_forward {
background-position: -9px -109px;
width: 23px;
height: 15px;
margin: 14px 13px;
}
.media_modal_action_btn i.media_modal_action_btn_delete {
background-position: -13px -135px;
width: 14px;
height: 18px;
margin: 13px 17px;
}

7
app/js/controllers.js

@ -1533,13 +1533,6 @@ angular.module('myApp.controllers', ['myApp.i18n'])
$rootScope.$broadcast('history_focus', {peerString: peerString, messageID: messageID}); $rootScope.$broadcast('history_focus', {peerString: peerString, messageID: messageID});
}; };
if (Config.Mobile) {
$scope.canForward = true;
$scope.canDelete = true;
return;
}
$scope['delete'] = function () { $scope['delete'] = function () {
var messageID = $scope.messageID; var messageID = $scope.messageID;
ErrorService.confirm({type: 'MESSAGE_DELETE'}).then(function () { ErrorService.confirm({type: 'MESSAGE_DELETE'}).then(function () {

4
app/js/locales/en-us.json

@ -79,7 +79,9 @@
"user_modal_notifications": "Notifications", "user_modal_notifications": "Notifications",
"user_modal_contact_info": "Contact info", "user_modal_contact_info": "Contact info",
"media_modal_photo": "Photo {pos} of {count}", "media_modal_photo": "Photo",
"media_modal_photo_index": "Photo {pos} of {count}",
"media_modal_video": "Video",
"media_modal_forward": "Forward", "media_modal_forward": "Forward",
"media_modal_download": "Download", "media_modal_download": "Download",
"media_modal_delete": "Delete", "media_modal_delete": "Delete",

19
app/js/services.js

@ -2309,9 +2309,9 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function wrapForFull (photoID) { function wrapForFull (photoID) {
var photo = wrapForHistory(photoID); var photo = wrapForHistory(photoID);
var fullWidth = $(window).width() - (Config.Mobile ? 20 : 32); var fullWidth = $(window).width() - (Config.Mobile ? 0 : 32);
var fullHeight = $($window).height() - (Config.Mobile ? 150 : 116); var fullHeight = $($window).height() - (Config.Mobile ? 0 : 116);
if (fullWidth > 800) { if (!Config.Mobile && fullWidth > 800) {
fullWidth -= 208; fullWidth -= 208;
} }
var fullPhotoSize = choosePhotoSize(photo, fullWidth, fullHeight); var fullPhotoSize = choosePhotoSize(photo, fullWidth, fullHeight);
@ -2354,7 +2354,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var modalInstance = $modal.open({ var modalInstance = $modal.open({
templateUrl: templateUrl('photo_modal'), templateUrl: templateUrl('photo_modal'),
windowTemplateUrl: !Config.Mobile && templateUrl('media_modal_layout') || undefined, windowTemplateUrl: templateUrl('media_modal_layout'),
controller: scope.userID ? 'UserpicModalController' : 'PhotoModalController', controller: scope.userID ? 'UserpicModalController' : 'PhotoModalController',
scope: scope, scope: scope,
windowClass: 'photo_modal_window' windowClass: 'photo_modal_window'
@ -2471,8 +2471,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
function wrapForFull (videoID) { function wrapForFull (videoID) {
var video = wrapForHistory(videoID), var video = wrapForHistory(videoID),
fullWidth = Math.min($(window).width() - 60, 542), fullWidth = Math.min($(window).width() - (Config.Mobile ? 0 : 60), 542),
fullHeight = $($window).height() - 150, fullHeight = $($window).height() - (Config.Mobile ? 92 : 150),
fullPhotoSize = video, fullPhotoSize = video,
full = { full = {
placeholder: 'img/placeholders/VideoThumbModal.gif', placeholder: 'img/placeholders/VideoThumbModal.gif',
@ -2503,7 +2503,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
return $modal.open({ return $modal.open({
templateUrl: templateUrl('video_modal'), templateUrl: templateUrl('video_modal'),
windowTemplateUrl: !Config.Mobile && templateUrl('media_modal_layout') || undefined, windowTemplateUrl: templateUrl('media_modal_layout'),
controller: 'VideoModalController', controller: 'VideoModalController',
scope: scope, scope: scope,
windowClass: 'video_modal_window' windowClass: 'video_modal_window'
@ -2655,8 +2655,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
} }
doc.thumb = thumb; doc.thumb = thumb;
doc.canDownload = !(window.chrome && chrome.fileSystem && chrome.fileSystem.chooseEntry); doc.withPreview = !Config.Mobile && doc.mime_type.match(/^(image\/)/) ? 1 : 0;
doc.withPreview = doc.canDownload && doc.mime_type.match(/^(image\/)/) ? 1 : 0;
if (isGif && doc.thumb) { if (isGif && doc.thumb) {
doc.isSpecial = 'gif'; doc.isSpecial = 'gif';
@ -2734,7 +2733,7 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
var modalInstance = $modal.open({ var modalInstance = $modal.open({
templateUrl: templateUrl('document_modal'), templateUrl: templateUrl('document_modal'),
windowTemplateUrl: !Config.Mobile && templateUrl('media_modal_layout') || undefined, windowTemplateUrl: templateUrl('media_modal_layout'),
controller: 'DocumentModalController', controller: 'DocumentModalController',
scope: scope, scope: scope,
windowClass: 'document_modal_window' windowClass: 'document_modal_window'

10
app/partials/desktop/photo_modal.html

@ -28,9 +28,13 @@
<span ng-switch-default class="media_modal_date" ng-bind="photo.date | dateOrTime :true"></span> <span ng-switch-default class="media_modal_date" ng-bind="photo.date | dateOrTime :true"></span>
</div> </div>
<div class="media_modal_title_wrap" ng-if="count > 1 &amp;&amp; pos > 0" my-i18n="media_modal_photo">
<my-i18n-param name="pos" ng-bind="pos"></my-i18n-param> <div class="media_modal_title_wrap" ng-switch="count > 1 &amp;&amp; pos > 0">
<my-i18n-param name="count" ng-bind="count"></my-i18n-param> <my-i18n ng-switch-when="true" msgid="media_modal_photo_index">
<my-i18n-param name="pos" ng-bind="pos"></my-i18n-param>
<my-i18n-param name="count" ng-bind="count"></my-i18n-param>
</my-i18n>
<my-i18n ng-switch-default msgid="media_modal_photo">
</div> </div>
</div> </div>
</div> </div>

5
app/partials/desktop/video_modal.html

@ -21,10 +21,7 @@
<span class="media_modal_date" ng-bind="video.date | dateOrTime :true"></span> <span class="media_modal_date" ng-bind="video.date | dateOrTime :true"></span>
</div> </div>
<div class="media_modal_title_wrap" ng-if="count > 1 &amp;&amp; pos > 0" my-i18n="media_modal_photo"> <div class="media_modal_title_wrap" my-i18n="media_modal_video"></div>
<my-i18n-param name="pos" ng-bind="pos"></my-i18n-param>
<my-i18n-param name="count" ng-bind="count"></my-i18n-param>
</div>
</div> </div>
</div> </div>

1
app/partials/mobile/media_modal_layout.html

@ -0,0 +1 @@
../desktop/media_modal_layout.html

66
app/partials/mobile/photo_modal.html

@ -1,22 +1,62 @@
<div my-modal-width="{{photo.full.modalWidth}}" class="media_modal_wrap photo_modal_wrap" my-modal-position animation="no" my-modal-nav next="nav.next()" prev="nav.prev()"> <div class="media_modal_bottom_panel_wrap" ng-show="!hideToolbars">
<div class="media_modal_bottom_panel">
<div class="media_modal_bottom_actions pull-right">
<a class="media_modal_action_btn" ng-if="canDelete" ng-click="delete()" title="{{'media_modal_delete' | i18n}}">
<i class="media_modal_action_btn_delete"></i>
</a>
</div>
<div class="modal-body"> <div class="media_modal_bottom_actions pull-left">
<a class="media_modal_action_btn" ng-if="canForward" ng-click="forward()" title="{{'media_modal_forward' | i18n}}">
<i class="media_modal_action_btn_forward"></i>
</a>
</div>
<div class="photo_modal_image_wrap" my-load-full-photo full-photo="photo.full" thumb-location="photo.thumb.location" ng-click="nav.next()"> </div> <div class="media_modal_info_wrap">
<a class="media_modal_author" my-user-link="photo.user_id" user-watch="true"></a>
<br/>
<span class="media_modal_date" ng-bind="photo.date | dateOrTime :true"></span>
</div>
<div class="media_meta_wrap clearfix"> </div>
<div class="media_modal_actions pull-right"> </div>
<a href="" class="media_modal_action_link" ng-click="download()" my-i18n="media_modal_download"></a>
<a href="" class="media_modal_action_link" ng-if="canForward" ng-click="forward()" my-i18n="media_modal_forward"></a>
<a href="" class="media_modal_action_link" ng-if="canDelete" ng-click="delete()" my-i18n="media_modal_delete"></a>
</div>
<p class="media_modal_info"> <div class="media_modal_top_panel_wrap" ng-show="!hideToolbars">
<a class="media_modal_author" my-user-link="photo.user_id"></a>, <span ng-bind="photo.date | dateOrTime"></span> <div class="media_modal_top_panel">
</p> <div class="media_modal_top_actions pull-right">
<a class="media_modal_action_btn" ng-click="download()" title="{{'media_modal_download' | i18n}}">
<i class="media_modal_action_btn_download"></i>
</a>
</div> </div>
<div class="media_modal_top_actions pull-left">
<a ng-click="$close()" class="navbar-quick-media-back">
<i class="icon icon-back"></i>
<div class="navbar-quick-back-title">
<h4 class="media_modal_title_wrap" ng-switch="count > 1 &amp;&amp; pos > 0">
<my-i18n ng-switch-when="true" msgid="media_modal_photo_index">
<my-i18n-param name="pos" ng-bind="pos"></my-i18n-param>
<my-i18n-param name="count" ng-bind="count"></my-i18n-param>
</my-i18n>
<my-i18n ng-switch-default msgid="media_modal_photo">
</h4>
</div>
</a>
</div>
</div> </div>
</div>
<div class="modal-dialog" ng-swipe-right="nav.prev()" ng-swipe-left="nav.next()" ng-click="hideToolbars = !hideToolbars">
<div class="modal-content">
<div my-modal-width="{{photo.full.modalWidth}}" class="media_modal_wrap photo_modal_wrap" my-vertical-position="0.5">
<div class="modal-body">
<div class="photo_modal_image_wrap" my-load-full-photo full-photo="photo.full" thumb-location="photo.thumb.location"></div>
</div>
</div>
</div>
</div> </div>

60
app/partials/mobile/video_modal.html

@ -1,21 +1,55 @@
<div class="media_modal_wrap video_modal_wrap" my-modal-position> <div class="media_modal_bottom_panel_wrap">
<div class="media_modal_bottom_panel">
<div class="media_modal_bottom_actions pull-right">
<a class="media_modal_action_btn" ng-if="messageID" ng-click="delete()" title="{{'media_modal_delete' | i18n}}">
<i class="media_modal_action_btn_delete"></i>
</a>
</div>
<div class="modal-body"> <div class="media_modal_bottom_actions pull-left">
<a class="media_modal_action_btn" ng-if="messageID" ng-click="forward()" title="{{'media_modal_forward' | i18n}}">
<i class="media_modal_action_btn_forward"></i>
</a>
</div>
<div class="video_modal_image_wrap" my-load-video video="video"></div> <div class="media_modal_info_wrap">
<a class="media_modal_author" my-user-link="video.user_id" user-watch="true"></a>
<br/>
<span class="media_modal_date" ng-bind="video.date | dateOrTime :true"></span>
</div>
<div class="media_meta_wrap clearfix"> </div>
<div class="media_modal_actions pull-right"> </div>
<a href="" class="media_modal_action_link" ng-click="download()" my-i18n="media_modal_download"></a>
<a ng-if="messageID" href="" class="media_modal_action_link" ng-click="forward()" my-i18n="media_modal_forward"></a>
<a ng-if="messageID" href="" class="media_modal_action_link" ng-click="delete()" my-i18n="media_modal_delete"></a>
</div>
<p class="media_modal_info"> <div class="media_modal_top_panel_wrap">
<a class="media_modal_author" my-user-link="video.user_id"></a>, <span ng-bind="video.date | dateOrTime"></span> <div class="media_modal_top_panel">
</p> <div class="media_modal_top_actions pull-right">
<a class="media_modal_action_btn" ng-click="download()" title="{{'media_modal_download' | i18n}}">
<i class="media_modal_action_btn_download"></i>
</a>
</div>
<div class="media_modal_top_actions pull-left">
<a ng-click="$close()" class="navbar-quick-media-back">
<i class="icon icon-back"></i>
<div class="navbar-quick-back-title">
<h4 class="media_modal_title_wrap" my-i18n="media_modal_video"></h4>
</div>
</a>
</div> </div>
</div> </div>
</div>
<div class="modal-dialog">
<div class="modal-content">
<div my-modal-width="{{video.full.width}}" class="media_modal_wrap video_modal_wrap" my-vertical-position="0.5">
<div class="modal-body">
<div class="video_modal_image_wrap" my-load-video video="video"></div>
</div>
</div>
</div>
</div> </div>

Loading…
Cancel
Save