diff --git a/NEWS b/NEWS index cfef0ec6b..a444225db 100644 --- a/NEWS +++ b/NEWS @@ -2,7 +2,7 @@ ------------------ New features - - + - [web] new images viewer in Mail module Enhancements - [core] now possible to {un}subscribe to folders using sogo-tool diff --git a/UI/Templates/MailPartViewers/UIxMailPartLinkViewer.wox b/UI/Templates/MailPartViewers/UIxMailPartLinkViewer.wox index 37e5d6cef..d4206b069 100644 --- a/UI/Templates/MailPartViewers/UIxMailPartLinkViewer.wox +++ b/UI/Templates/MailPartViewers/UIxMailPartLinkViewer.wox @@ -6,7 +6,7 @@ xmlns:label="OGo:label"> -

+

diff --git a/UI/Templates/MailerUI/UIxMailViewTemplate.wox b/UI/Templates/MailerUI/UIxMailViewTemplate.wox index 8950cb90b..c4957d1ca 100644 --- a/UI/Templates/MailerUI/UIxMailViewTemplate.wox +++ b/UI/Templates/MailerUI/UIxMailViewTemplate.wox @@ -267,7 +267,7 @@
+ sg-zoomable-image="$index"> diff --git a/UI/WebServerResources/js/Mailer/MessageController.js b/UI/WebServerResources/js/Mailer/MessageController.js index e58e3a790..ea4f08b65 100644 --- a/UI/WebServerResources/js/Mailer/MessageController.js +++ b/UI/WebServerResources/js/Mailer/MessageController.js @@ -6,13 +6,16 @@ /** * @ngInject */ - MessageController.$inject = ['$window', '$scope', '$state', '$mdMedia', '$mdDialog', 'sgConstant', 'stateAccounts', 'stateAccount', 'stateMailbox', 'stateMessage', 'sgHotkeys', 'encodeUriFilter', 'sgSettings', '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) { + 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, ImageGallery, focus, Dialog, Calendar, Component, Account, Mailbox, Message) { var vm = this, popupWindow = null, hotkeys = []; // Expose controller $window.$messageController = vm; + // Initialize image gallery service + ImageGallery.setMessage(stateMessage); + vm.$state = $state; vm.accounts = stateAccounts; vm.account = stateAccount; @@ -424,8 +427,8 @@ }); } } - + angular - .module('SOGo.MailerUI') - .controller('MessageController', MessageController); + .module('SOGo.MailerUI') + .controller('MessageController', MessageController); })(); diff --git a/UI/WebServerResources/js/Mailer/sgZoomableImage.directive.js b/UI/WebServerResources/js/Mailer/sgZoomableImage.directive.js index 56c533779..4ac8cece5 100644 --- a/UI/WebServerResources/js/Mailer/sgZoomableImage.directive.js +++ b/UI/WebServerResources/js/Mailer/sgZoomableImage.directive.js @@ -1,16 +1,17 @@ /* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ (function() { + /* jshint validthis: true */ '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 * @restrict attribute * @ngInject * @example: -
+
@@ -19,22 +20,53 @@ function sgZoomableImage() { return { restrict: 'A', - link: link + bindToController: { + partIndex: '=sgZoomableImage' + }, + controller: sgZoomableImageController }; function link(scope, iElement, attrs, ctrl) { var parentNode = iElement.parent(), - toggleClass; + imgElement, showImage, toggleClass; + + imgElement = iElement.find('img'); toggleClass = function(event) { if (event.target.tagName == 'IMG') 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 .module('SOGo.MailerUI') .directive('sgZoomableImage', sgZoomableImage); diff --git a/UI/WebServerResources/scss/components/imagegallery/imagegallery.scss b/UI/WebServerResources/scss/components/imagegallery/imagegallery.scss new file mode 100644 index 000000000..0f92e9000 --- /dev/null +++ b/UI/WebServerResources/scss/components/imagegallery/imagegallery.scss @@ -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; + } + } + } +} diff --git a/UI/WebServerResources/scss/core/angular.scss b/UI/WebServerResources/scss/core/angular.scss index c8d7e53c7..e6334bcb3 100644 --- a/UI/WebServerResources/scss/core/angular.scss +++ b/UI/WebServerResources/scss/core/angular.scss @@ -3,4 +3,8 @@ // ngCloak directive [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; -} \ No newline at end of file +} + +.sg-hide { + opacity: 0; +} diff --git a/UI/WebServerResources/scss/styles.scss b/UI/WebServerResources/scss/styles.scss index 0d2533c51..87992865f 100755 --- a/UI/WebServerResources/scss/styles.scss +++ b/UI/WebServerResources/scss/styles.scss @@ -69,6 +69,7 @@ @import 'components/draggable-droppable/draggable'; @import 'components/draggable-droppable/droppable'; @import 'components/hotkeys/hotkeys'; +@import 'components/imagegallery/imagegallery'; @import 'components/ripple/ripple'; @import 'components/timepicker/timepicker'; @import 'components/pseudo-input/pseudo-input'; diff --git a/UI/WebServerResources/scss/views/MailerUI.scss b/UI/WebServerResources/scss/views/MailerUI.scss index 8e559d8f8..3ef56f1d2 100644 --- a/UI/WebServerResources/scss/views/MailerUI.scss +++ b/UI/WebServerResources/scss/views/MailerUI.scss @@ -211,6 +211,10 @@ md-sidenav { max-width: 100%; } +.sg-attachment-name { + word-break: break-word; +} + .sg-attachment-size { @extend .md-caption; padding-left: $baseline-grid;