Browse Source

Add Mediabox directive

Danilo Bargen 8 years ago
parent
commit
50c9bf56a0

+ 3 - 0
index.html

@@ -67,6 +67,9 @@
             </h1>
             </h1>
         </header>
         </header>
 
 
+        <!-- The overlay box that shows up if media is previewed -->
+        <mediabox></mediabox>
+
         <div id="main">
         <div id="main">
             <div id="status-bar">
             <div id="status-bar">
                 <status-bar active="ctrl.expandStatusBar"></status-bar>
                 <status-bar active="ctrl.expandStatusBar"></status-bar>

+ 2 - 0
src/directives.ts

@@ -30,6 +30,7 @@ import includeReplace from './directives/include_replace';
 import latestMessage from './directives/latest_message';
 import latestMessage from './directives/latest_message';
 import latestMessageState from './directives/latest_message_state';
 import latestMessageState from './directives/latest_message_state';
 import location from './directives/location';
 import location from './directives/location';
+import mediabox from './directives/mediabox';
 import memberListEditor from './directives/member_list_editor';
 import memberListEditor from './directives/member_list_editor';
 import message from './directives/message';
 import message from './directives/message';
 import messageContact from './directives/message_contact';
 import messageContact from './directives/message_contact';
@@ -70,6 +71,7 @@ angular.module('3ema.directives').directive('eeeVerificationLevel', verification
 angular.module('3ema.directives').directive('includeReplace', includeReplace);
 angular.module('3ema.directives').directive('includeReplace', includeReplace);
 angular.module('3ema.directives').directive('location', location);
 angular.module('3ema.directives').directive('location', location);
 angular.module('3ema.directives').directive('memberListEditor', memberListEditor);
 angular.module('3ema.directives').directive('memberListEditor', memberListEditor);
+angular.module('3ema.directives').directive('mediabox', mediabox);
 angular.module('3ema.directives').directive('searchbox', searchbox);
 angular.module('3ema.directives').directive('searchbox', searchbox);
 angular.module('3ema.directives').directive('statusBar', statusBar);
 angular.module('3ema.directives').directive('statusBar', statusBar);
 angular.module('3ema.directives').directive('threemaAction', threemaAction);
 angular.module('3ema.directives').directive('threemaAction', threemaAction);

+ 60 - 0
src/directives/mediabox.ts

@@ -0,0 +1,60 @@
+/**
+ * This file is part of Threema Web.
+ *
+ * Threema Web is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Threema Web. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import {MediaboxService} from '../services/mediabox';
+
+export default [
+    '$rootScope',
+    '$filter',
+    'MediaboxService',
+    function($rootScope: ng.IRootScopeService,
+             $filter: ng.IFilterService,
+             mediaboxService: MediaboxService) {
+        return {
+            restrict: 'E',
+            scope: {},
+            bindToController: {},
+            controllerAs: 'ctrl',
+            controller: [function() {
+                this.imageDataUrl = null;
+
+                this.close = () => {
+                    this.imageDataUrl = null;
+                };
+
+                const filter = $filter('bufferToUrl') as (buffer: ArrayBuffer, mimeType: string) => string;
+                mediaboxService.evtMediaChanged.attach((dataAvailable: boolean) => {
+                    $rootScope.$apply(() => {
+                        this.imageDataUrl = filter(mediaboxService.data, 'image/jpeg');
+                    });
+                });
+            }],
+            // tslint:disable:max-line-length
+            template: `
+                <div class="box" ng-if="ctrl.imageDataUrl !== null">
+                    <md-icon class="close material-icons md-24" ng-click="ctrl.close()" aria-label="Close" translate-attr="{'aria-label': 'common.CLOSE'}">close</md-icon>
+                    <div class="inner">
+                        <img ng-src="{{ ctrl.imageDataUrl }}">
+                        <div class="caption">
+                            Image Caption
+                        </div>
+                    </div>
+                </div>
+            `,
+        };
+    },
+];

+ 12 - 6
src/directives/message_media.html

@@ -3,29 +3,35 @@
 <span class="in-view-indicator" in-view="ctrl.thumbnailInView($inview)"></span>
 <span class="in-view-indicator" in-view="ctrl.thumbnailInView($inview)"></span>
 
 
 <div ng-if="ctrl.uploading">
 <div ng-if="ctrl.uploading">
-    <! -- Loading indicator -->
+    <!-- Loading indicator -->
     <div class="circle active center">
     <div class="circle active center">
         <i class="material-icons md-24">file_upload</i>
         <i class="material-icons md-24">file_upload</i>
         <div class="loading active"></div>
         <div class="loading active"></div>
     </div>
     </div>
 </div>
 </div>
 <div ng-if="!ctrl.uploading">
 <div ng-if="!ctrl.uploading">
-    <div ng-if="ctrl.showThumbnail" class="thumbnail {{ctrl.type}}" ng-click="ctrl.download()" ng-style="ctrl.thumbnailStyle">
+    <div ng-if="ctrl.showThumbnail" class="thumbnail {{ ctrl.type }}" ng-click="ctrl.download()" ng-style="ctrl.thumbnailStyle">
 
 
+        <!-- Loading indicator -->
         <div class="loading-wrapper" ng-class="{active: ctrl.downloading || ctrl.thumbnailDownloading}">
         <div class="loading-wrapper" ng-class="{active: ctrl.downloading || ctrl.thumbnailDownloading}">
             <div class="loading"></div>
             <div class="loading"></div>
             <div class="loading-text" translate>messenger.DOWNLOADING</div>
             <div class="loading-text" translate>messenger.DOWNLOADING</div>
         </div>
         </div>
+
+        <!-- Thumbnail overlays for videos and GIFs -->
         <div class="overlay video" ng-if="ctrl.type === 'video' && !ctrl.downloading">
         <div class="overlay video" ng-if="ctrl.type === 'video' && !ctrl.downloading">
             <i class="material-icons md-light">play_circle_outline</i>
             <i class="material-icons md-light">play_circle_outline</i>
         </div>
         </div>
         <div class="overlay gif" ng-if="ctrl.type === 'file' && ctrl.message.file.type === 'image/gif' && !ctrl.downloading">
         <div class="overlay gif" ng-if="ctrl.type === 'file' && ctrl.message.file.type === 'image/gif' && !ctrl.downloading">
             <i class="material-icons md-light">play_circle_outline</i>
             <i class="material-icons md-light">play_circle_outline</i>
         </div>
         </div>
+
+        <!-- Thumbnails -->
         <img ng-if="ctrl.thumbnail !== null" ng-src="{{ctrl.thumbnail}}">
         <img ng-if="ctrl.thumbnail !== null" ng-src="{{ctrl.thumbnail}}">
         <div ng-if="ctrl.message.thumbnail != undefined" class="thumbnail-loader">
         <div ng-if="ctrl.message.thumbnail != undefined" class="thumbnail-loader">
             <img ng-src="{{ ctrl.message.thumbnail.preview | bufferToUrl: 'image/png' }}">
             <img ng-src="{{ ctrl.message.thumbnail.preview | bufferToUrl: 'image/png' }}">
         </div>
         </div>
+
     </div>
     </div>
 
 
     <!-- Location -->
     <!-- Location -->
@@ -33,14 +39,14 @@
 
 
     <!-- Audio file -->
     <!-- Audio file -->
     <div class="file-message" ng-if="ctrl.type === 'audio'">
     <div class="file-message" ng-if="ctrl.type === 'audio'">
-        <! -- Loading indicator -->
+        <!-- Loading indicator -->
         <div class="circle" ng-click="ctrl.download()"
         <div class="circle" ng-click="ctrl.download()"
              ng-class="{active: !ctrl.downloading}"
              ng-class="{active: !ctrl.downloading}"
              ng-if="!ctrl.downloaded">
              ng-if="!ctrl.downloaded">
             <i class="material-icons md-24">file_download</i>
             <i class="material-icons md-24">file_download</i>
             <div class="loading" ng-class="{active: ctrl.downloading}"></div>
             <div class="loading" ng-class="{active: ctrl.downloading}"></div>
         </div>
         </div>
-        <! -- Play Indicator -->
+        <!-- Play Indicator -->
         <div class="circle" ng-click="ctrl.download()" ng-if="ctrl.downloaded">
         <div class="circle" ng-click="ctrl.download()" ng-if="ctrl.downloaded">
             <i class="material-icons md-24">play_arrow</i>
             <i class="material-icons md-24">play_arrow</i>
         </div>
         </div>
@@ -54,7 +60,7 @@
 
 
     <!-- Other file messages -->
     <!-- Other file messages -->
     <div class="file-message" ng-if="ctrl.type === 'file' && !ctrl.isAnimGif" ng-click="ctrl.download()">
     <div class="file-message" ng-if="ctrl.type === 'file' && !ctrl.isAnimGif" ng-click="ctrl.download()">
-        <! -- Loading indicator -->
+        <!-- Loading indicator -->
         <div class="circle"
         <div class="circle"
              ng-class="{active: !ctrl.downloading}"
              ng-class="{active: !ctrl.downloading}"
              ng-if="!ctrl.downloaded"
              ng-if="!ctrl.downloaded"
@@ -62,7 +68,7 @@
             <i class="material-icons md-24">file_download</i>
             <i class="material-icons md-24">file_download</i>
             <div class="loading" ng-class="{active: ctrl.downloading}"></div>
             <div class="loading" ng-class="{active: ctrl.downloading}"></div>
         </div>
         </div>
-        <! -- Open Indicator -->
+        <!-- Open Indicator -->
         <div class="circle"
         <div class="circle"
              ng-if="ctrl.downloaded && ctrl.message.thumbnail.preview !== undefined"
              ng-if="ctrl.downloaded && ctrl.message.thumbnail.preview !== undefined"
              ng-style="{'background-image': 'url({{ctrl.message.thumbnail.preview | bufferToUrl: 'image/png'}})' }">
              ng-style="{'background-image': 'url({{ctrl.message.thumbnail.preview | bufferToUrl: 'image/png'}})' }">

+ 1 - 0
src/sass/app.scss

@@ -42,6 +42,7 @@
 @import "components/avatar_area";
 @import "components/avatar_area";
 @import "components/drag_file";
 @import "components/drag_file";
 @import "components/buttons";
 @import "components/buttons";
+@import "components/mediabox";
 
 
 // Sections: Styles specific to individual pages or sections.
 // Sections: Styles specific to individual pages or sections.
 // Nothing to see here yet!
 // Nothing to see here yet!

+ 56 - 0
src/sass/components/_mediabox.scss

@@ -0,0 +1,56 @@
+mediabox {
+    .box {
+        position: absolute;
+        left: 0;
+        top: 0;
+        right: 0;
+        bottom: 0;
+        padding: 24px;
+        z-index: 41;
+        background-color: rgba(0, 0, 0, 0.75);
+
+        .close {
+            height: 24px;
+            width: 24px;
+            display: block;
+            position: absolute;
+            top: 24px;
+            right: 24px;
+            color: rgba(255, 255, 255, 0.8);
+            background-color: rgba(0, 0, 0, 0.7);
+            border: 2px solid rgba(255, 255, 255, 0.8);
+            border-radius: 50%;
+            user-select: none;
+            @include mouse-hand;
+
+            &:focus {
+                color: rgba(255, 255, 255, 1.0);
+                border: 2px solid rgba(255, 255, 255, 1.0);
+            }
+        }
+
+        .inner {
+            width: 100%;
+            height: 100%;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+
+            img {
+                max-height: calc(100% - 28px - 28px);
+                max-width: 100%;
+                user-select: none;
+            }
+
+            .caption {
+                display: flex;
+                align-items: flex-end;
+                height: 28px;
+                margin: 4px 0 0;
+                color: rgba(255, 255, 255, 0.8);
+                font-size: 1.3em;
+            }
+        }
+    }
+}