(js) New images viewer for Mail module

pull/228/merge
Francis Lachapelle 2017-05-29 14:03:59 -04:00
parent 0a990ff66b
commit 555b7303d1
9 changed files with 121 additions and 14 deletions

2
NEWS
View File

@ -2,7 +2,7 @@
------------------ ------------------
New features New features
- - [web] new images viewer in Mail module
Enhancements Enhancements
- [core] now possible to {un}subscribe to folders using sogo-tool - [core] now possible to {un}subscribe to folders using sogo-tool

View File

@ -6,7 +6,7 @@
xmlns:label="OGo:label"> xmlns:label="OGo:label">
<md-card> <md-card>
<md-card-content> <md-card-content>
<p class="md-caption" var:title="filenameForDisplay"> <p class="md-caption sg-attachment-name" var:title="filenameForDisplay">
<var:if condition="preferredPathExtension.length"><span class="sg-label-outline"><var:string value="preferredPathExtension"/></span></var:if> <var:if condition="preferredPathExtension.length"><span class="sg-label-outline"><var:string value="preferredPathExtension"/></span></var:if>
<var:string value="filenameForDisplay"/> <var:string value="filenameForDisplay"/>
</p> </p>

View File

@ -267,7 +267,7 @@
<div class="md-flex sg-mail-part" <div class="md-flex sg-mail-part"
ng-if="::part.compile" ng-if="::part.compile"
sg-compile="part.content" sg-compile="part.content"
sg-zoomable-image="sg-zoomable-image"><!-- angular-friendly msg --></div> sg-zoomable-image="$index"><!-- angular-friendly msg --></div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,13 +6,16 @@
/** /**
* @ngInject * @ngInject
*/ */
MessageController.$inject = ['$window', '$scope', '$state', '$mdMedia', '$mdDialog', 'sgConstant', 'stateAccounts', 'stateAccount', 'stateMailbox', 'stateMessage', 'sgHotkeys', 'encodeUriFilter', 'sgSettings', 'sgFocus', 'Dialog', 'Calendar', 'Component', 'Account', 'Mailbox', 'Message']; MessageController.$inject = ['$window', '$scope', '$state', '$mdMedia', '$mdDialog', 'sgConstant', 'stateAccounts', 'stateAccount', 'stateMailbox', 'stateMessage', 'sgHotkeys', 'encodeUriFilter', 'sgSettings', 'ImageGallery', 'sgFocus', 'Dialog', 'Calendar', 'Component', 'Account', 'Mailbox', 'Message'];
function MessageController($window, $scope, $state, $mdMedia, $mdDialog, sgConstant, stateAccounts, stateAccount, stateMailbox, stateMessage, sgHotkeys, encodeUriFilter, sgSettings, focus, Dialog, Calendar, Component, Account, Mailbox, Message) { function MessageController($window, $scope, $state, $mdMedia, $mdDialog, sgConstant, stateAccounts, stateAccount, stateMailbox, stateMessage, sgHotkeys, encodeUriFilter, sgSettings, ImageGallery, focus, Dialog, Calendar, Component, Account, Mailbox, Message) {
var vm = this, popupWindow = null, hotkeys = []; var vm = this, popupWindow = null, hotkeys = [];
// Expose controller // Expose controller
$window.$messageController = vm; $window.$messageController = vm;
// Initialize image gallery service
ImageGallery.setMessage(stateMessage);
vm.$state = $state; vm.$state = $state;
vm.accounts = stateAccounts; vm.accounts = stateAccounts;
vm.account = stateAccount; vm.account = stateAccount;
@ -424,8 +427,8 @@
}); });
} }
} }
angular angular
.module('SOGo.MailerUI') .module('SOGo.MailerUI')
.controller('MessageController', MessageController); .controller('MessageController', MessageController);
})(); })();

View File

@ -1,16 +1,17 @@
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
(function() { (function() {
/* jshint validthis: true */
'use strict'; 'use strict';
/* /*
* sgZoomableImage - Toggle the 'sg-zoom' class when clicking on the image inside the container. * sgZoomableImage - Show the image fullscreen when clicking on the image inside the container.
* @memberof SOGo.MailerUI * @memberof SOGo.MailerUI
* @restrict attribute * @restrict attribute
* @ngInject * @ngInject
* @example: * @example:
<div sg-zoomable-image="sg-zoomable-image"> <div sg-zoomable-image="$index">
<md-card> <md-card>
<img src="foo.png"> <img src="foo.png">
</md-card> </md-card>
@ -19,22 +20,53 @@
function sgZoomableImage() { function sgZoomableImage() {
return { return {
restrict: 'A', restrict: 'A',
link: link bindToController: {
partIndex: '=sgZoomableImage'
},
controller: sgZoomableImageController
}; };
function link(scope, iElement, attrs, ctrl) { function link(scope, iElement, attrs, ctrl) {
var parentNode = iElement.parent(), var parentNode = iElement.parent(),
toggleClass; imgElement, showImage, toggleClass;
imgElement = iElement.find('img');
toggleClass = function(event) { toggleClass = function(event) {
if (event.target.tagName == 'IMG') if (event.target.tagName == 'IMG')
parentNode.toggleClass('sg-zoom'); parentNode.toggleClass('sg-zoom');
}; };
iElement.on('click', toggleClass); showImage = function(event) {
if (event.target.tagName == 'IMG')
ctrl.showGallery(event, imgElement[0].src);
};
if (imgElement.length)
ctrl.addImage(imgElement[0].src);
iElement.on('click', showImage);
} }
} }
/**
* @ngInject
*/
sgZoomableImageController.$inject = ['$element', 'ImageGallery'];
function sgZoomableImageController($element, ImageGallery) {
var $ctrl = this;
this.$postLink = function() {
ImageGallery.registerImage($element);
$element.on('click', this.showImage);
};
this.showImage = function($event) {
if ($event.target.tagName == 'IMG')
ImageGallery.showGallery($event, $ctrl.partIndex);
};
}
angular angular
.module('SOGo.MailerUI') .module('SOGo.MailerUI')
.directive('sgZoomableImage', sgZoomableImage); .directive('sgZoomableImage', sgZoomableImage);

View File

@ -0,0 +1,63 @@
/// imagegallery.scss -*- Mode: scss; indent-tabs-mode: nil; basic-offset: 2 -*-
$imagegallery_thumbnail_size: 100px;
body.sg-image-gallery-backdrop .md-panel._md-opaque-enter {
opacity: .88;
}
sg-image-gallery,
sg-image-gallery md-icon {
color: white;
}
sg-image-gallery {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
[role="button"] {
cursor: pointer;
}
.sg-image {
max-height: 80vh;
max-width: 90vh;
}
.sg-image-thumbnails {
align-self: center;
display: flex;
max-width: 100%;
overflow: hidden;
overflow-x: auto;
}
.sg-image-thumbnail {
position: relative;
width: $imagegallery_thumbnail_size;
height: $imagegallery_thumbnail_size;
margin: 1em 2em 1em 0;
min-width: $imagegallery_thumbnail_size;
overflow: hidden;
img {
position: absolute;
left: 50%;
opacity: 0.8;
top: 50%;
height: 100%;
width: auto;
transform: translate(-50%,-50%);
transition: opacity $material-enter-duration $material-enter-timing-function;
&:hover {
opacity: 1.0;
}
&.portrait {
height: auto;
width: 100%;
}
&.sg-hide {
opacity: 0;
transition: opacity $material-enter-duration $material-enter-timing-function;
}
}
}
}

View File

@ -3,4 +3,8 @@
// ngCloak directive // ngCloak directive
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important; display: none !important;
} }
.sg-hide {
opacity: 0;
}

View File

@ -69,6 +69,7 @@
@import 'components/draggable-droppable/draggable'; @import 'components/draggable-droppable/draggable';
@import 'components/draggable-droppable/droppable'; @import 'components/draggable-droppable/droppable';
@import 'components/hotkeys/hotkeys'; @import 'components/hotkeys/hotkeys';
@import 'components/imagegallery/imagegallery';
@import 'components/ripple/ripple'; @import 'components/ripple/ripple';
@import 'components/timepicker/timepicker'; @import 'components/timepicker/timepicker';
@import 'components/pseudo-input/pseudo-input'; @import 'components/pseudo-input/pseudo-input';

View File

@ -211,6 +211,10 @@ md-sidenav {
max-width: 100%; max-width: 100%;
} }
.sg-attachment-name {
word-break: break-word;
}
.sg-attachment-size { .sg-attachment-size {
@extend .md-caption; @extend .md-caption;
padding-left: $baseline-grid; padding-left: $baseline-grid;