From c1965f0f400fa22dac77ebe283ee39f14b8a48e0 Mon Sep 17 00:00:00 2001
From: Olivia Madrid <oliviajmadrid@gmail.com>
Date: Sun, 11 Aug 2019 23:48:35 -0600
Subject: [PATCH] (WIP): Media modal - handle video and more

---
 .../marketing/marketing.component.scss        |   2 +-
 .../components/cards/activity/activity.html   |   7 +-
 .../components/cards/activity/activity.ts     |  18 +-
 .../video/players/direct-http.component.ts    |  38 +--
 .../video/players/torrent.component.ts        |  29 +-
 .../components/video/video.component.html     |  19 +-
 .../components/video/video.component.scss     |  15 +-
 .../media/components/video/video.component.ts |  54 +++-
 .../volume-slider.component.html              |   1 +
 .../volume-slider.component.scss              |  11 +
 .../modules/media/modal/modal.component.html  |  24 +-
 .../modules/media/modal/modal.component.scss  |  72 +++--
 .../modules/media/modal/modal.component.ts    | 263 +++++++++++-------
 13 files changed, 356 insertions(+), 197 deletions(-)

diff --git a/src/app/modules/blockchain/marketing/marketing.component.scss b/src/app/modules/blockchain/marketing/marketing.component.scss
index 2f70958536..e0bc9f29d7 100644
--- a/src/app/modules/blockchain/marketing/marketing.component.scss
+++ b/src/app/modules/blockchain/marketing/marketing.component.scss
@@ -155,7 +155,7 @@ m-blockchain--marketing {
 
   m-video .minds-video-play-icon {
     @include m-theme(){
-      text-shadow: 0 0 3px themed($m-grey-900);
+      text-shadow: 0 0 3px rgba(themed($m-black-always), 0.6);
     }
   }
 
diff --git a/src/app/modules/legacy/components/cards/activity/activity.html b/src/app/modules/legacy/components/cards/activity/activity.html
index 91aaedd653..afc1607ec1 100644
--- a/src/app/modules/legacy/components/cards/activity/activity.html
+++ b/src/app/modules/legacy/components/cards/activity/activity.html
@@ -173,7 +173,8 @@
           [guid]="activity.custom_data.guid"
           [playCount]="activity['play:count']"
           [torrent]="[{ res: '360', key: activity.custom_data.guid + '/360.mp4' }]"
-          (triggerMediaModal)="showMediaModal('video')"
+          (requestedMediaModal)="showMediaModal()"
+          (videoMetadataLoaded)="setVideoDimensions($event)"
           #player>
           <video-ads [player]="player" *ngIf="activity.monetized"></video-ads>
       </m-video>
@@ -190,7 +191,7 @@
       </span>
     </div>
 
-    <a class="m-activity--image-link" (click)="showMediaModal('image')">
+    <a class="m-activity--image-link">
       <img [src]="activity.thumbnail_src" (error)="activity.thumbnail_src = null">
     </a>
   </div>
@@ -205,7 +206,7 @@
         <span i18n="@@M__COMMON__CONFIRM_18">Click to confirm your are 18+</span>
       </span>
     </div>
-    <a class="m-activity--image-link" (click)="showMediaModal('image')">
+    <a class="m-activity--image-link" (click)="showMediaModal()">
       <img [src]="activity.custom_data[0].src" style="width:100%"
       (error)="activity.custom_data[0].src = minds.cdn_assets_url + 'assets/logos/placeholder-bulb.jpg'"
         *ngIf="activity.custom_data"
diff --git a/src/app/modules/legacy/components/cards/activity/activity.ts b/src/app/modules/legacy/components/cards/activity/activity.ts
index 19d514da1d..c3a8505a50 100644
--- a/src/app/modules/legacy/components/cards/activity/activity.ts
+++ b/src/app/modules/legacy/components/cards/activity/activity.ts
@@ -11,7 +11,6 @@ import {
   Injector,
 } from '@angular/core';
 
-import { Location } from '@angular/common';
 import { Client } from '../../../../../services/api';
 import { Session } from '../../../../../services/session';
 import { AttachmentService } from '../../../../../services/attachment';
@@ -113,7 +112,6 @@ export class Activity implements OnInit {
     private cd: ChangeDetectorRef,
     private entitiesService: EntitiesService,
     private router: Router,
-    private location: Location,
     protected blockListService: BlockListService,
     protected activityAnalyticsOnViewService: ActivityAnalyticsOnViewService,
     protected newsfeedService: NewsfeedService,
@@ -436,12 +434,11 @@ export class Activity implements OnInit {
     this.activity.mature_visibility = !this.activity.mature_visibility;
   }
 
-  detectChanges() {
-    this.cd.markForCheck();
-    this.cd.detectChanges();
+  setVideoDimensions($event) {
+    this.activity.custom_data.dimensions = $event.dimensions;
   }
 
-  showMediaModal(subtype: string) {
+  showMediaModal() {
     // Mobile users go to media page instead of modal
     if (isMobile()) {
       this.router.navigate([`/media/${this.activity.entity_guid}`]);
@@ -449,11 +446,14 @@ export class Activity implements OnInit {
 
     this.activity.modal_source_url = this.router.url;
 
-    // 'image' or 'video'
-    this.activity.modal_subtype = subtype;
-
     this.overlayModal.create(MediaModalComponent, this.activity, {
       class: 'm-overlayModal--media'
     }).present();
+
+  }
+
+  detectChanges() {
+    this.cd.markForCheck();
+    this.cd.detectChanges();
   }
 }
diff --git a/src/app/modules/media/components/video/players/direct-http.component.ts b/src/app/modules/media/components/video/players/direct-http.component.ts
index 83fb773833..87e7780afe 100644
--- a/src/app/modules/media/components/video/players/direct-http.component.ts
+++ b/src/app/modules/media/components/video/players/direct-http.component.ts
@@ -2,9 +2,7 @@ import {
   ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output,
   ViewChild
 } from '@angular/core';
-import { Router } from '@angular/router';
 import { MindsPlayerInterface } from './player.interface';
-import isMobile from '../../../../../helpers/is-mobile';
 
 @Component({
   moduleId: module.id,
@@ -38,19 +36,24 @@ export class MindsVideoDirectHttpPlayer implements OnInit, OnDestroy, MindsPlaye
   @Output() onPause: EventEmitter<HTMLVideoElement> = new EventEmitter();
   @Output() onEnd: EventEmitter<HTMLVideoElement> = new EventEmitter();
   @Output() onError: EventEmitter<{ player: HTMLVideoElement, e }> = new EventEmitter();
-  @Output() triggerMediaModal: EventEmitter<any> = new EventEmitter();
+  @Output() onCanPlay: EventEmitter<any> = new EventEmitter();
+  @Output() onLoadedMetadata: EventEmitter<any> = new EventEmitter();
+  @Output() onLoadedData: EventEmitter<any> = new EventEmitter();
+  @Output() requestedMediaModal: EventEmitter<any> = new EventEmitter();
 
   loading: boolean = false;
-  isModal: boolean = false;
 
   constructor(
     protected cd: ChangeDetectorRef,
-    private router: Router,
   ) { }
+
   protected _emitPlay = () => this.onPlay.emit(this.getPlayer());
   protected _emitPause = () => this.onPause.emit(this.getPlayer());
   protected _emitEnd = () => this.onEnd.emit(this.getPlayer());
   protected _emitError = e => this.onError.emit({ player: this.getPlayer(), e });
+  protected _emitCanPlay = () => this.onCanPlay.emit(this.getPlayer());
+  protected _emitLoadedMetadata = () => this.onLoadedMetadata.emit(this.getPlayer());
+  protected _emitLoadedData = () => this.onLoadedData.emit(this.getPlayer());
 
   protected _canPlayThrough = () => {
     this.loading = false;
@@ -58,7 +61,7 @@ export class MindsVideoDirectHttpPlayer implements OnInit, OnDestroy, MindsPlaye
   };
 
   protected _dblClick = () => {
-    this.requestFullScreen();
+    this.requestedMediaModal.emit();
   };
 
   protected _onPlayerError = e => {
@@ -81,9 +84,11 @@ export class MindsVideoDirectHttpPlayer implements OnInit, OnDestroy, MindsPlaye
     player.addEventListener('ended', this._emitEnd);
     player.addEventListener('error', this._onPlayerError);
     player.addEventListener('canplaythrough', this._canPlayThrough);
+    player.addEventListener('canplay', this._emitCanPlay);
+    player.addEventListener('loadedmetadata', this._emitLoadedMetadata);
+    player.addEventListener('loadeddata', this._emitLoadedData);
 
     this.loading = true;
-    this.isModal = document.body.classList.contains('m-overlay-modal--shown');
   }
 
   ngOnDestroy() {
@@ -96,6 +101,9 @@ export class MindsVideoDirectHttpPlayer implements OnInit, OnDestroy, MindsPlaye
       player.removeEventListener('ended', this._emitEnd);
       player.removeEventListener('error', this._onPlayerError);
       player.removeEventListener('canplaythrough', this._canPlayThrough);
+      player.removeEventListener('canplay', this._emitCanPlay);
+      player.removeEventListener('loadedmetadata', this._emitLoadedMetadata);
+      player.removeEventListener('loadeddata', this._emitLoadedData);
     }
   }
 
@@ -172,21 +180,13 @@ export class MindsVideoDirectHttpPlayer implements OnInit, OnDestroy, MindsPlaye
     return {};
   }
 
+  requestMediaModal() {
+    this.requestedMediaModal.emit();
+  }
+
   detectChanges() {
     this.cd.markForCheck();
     this.cd.detectChanges();
   }
 
-  requestMediaModal() {
-    // Don't reopen modal if you're already on it
-    if ( this.isModal ) {
-      this.toggle();
-    }
-
-    // Mobile users go to media page instead of modal
-    if (isMobile()) {
-      this.router.navigate([`/media/${this.guid}`]);
-    }
-    this.triggerMediaModal.emit();
-  }
 }
diff --git a/src/app/modules/media/components/video/players/torrent.component.ts b/src/app/modules/media/components/video/players/torrent.component.ts
index 10600aa56e..0b2d7313ab 100644
--- a/src/app/modules/media/components/video/players/torrent.component.ts
+++ b/src/app/modules/media/components/video/players/torrent.component.ts
@@ -3,12 +3,10 @@ import {
   ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output,
   ViewChild
 } from '@angular/core';
-import { Router } from '@angular/router';
 import { MindsPlayerInterface } from './player.interface';
 import { WebtorrentService } from '../../../../webtorrent/webtorrent.service';
 import { Client } from '../../../../../services/api/client';
 import base64ToBlob from '../../../../../helpers/base64-to-blob';
-import isMobile from '../../../../../helpers/is-mobile';
 
 @Component({
   moduleId: module.id,
@@ -41,7 +39,10 @@ export class MindsVideoTorrentPlayer implements OnInit, AfterViewInit, OnDestroy
   @Output() onPause: EventEmitter<HTMLVideoElement> = new EventEmitter();
   @Output() onEnd: EventEmitter<HTMLVideoElement> = new EventEmitter();
   @Output() onError: EventEmitter<{ player, e }> = new EventEmitter();
-  @Output() triggerMediaModal: EventEmitter<any> = new EventEmitter();
+  @Output() onCanPlay: EventEmitter<any> = new EventEmitter();
+  @Output() onLoadedMetadata: EventEmitter<any> = new EventEmitter();
+  @Output() onLoadedData: EventEmitter<any> = new EventEmitter();
+  @Output() requestedMediaModal: EventEmitter<any> = new EventEmitter();
 
   initialized: boolean = false;
   loading: boolean = false;
@@ -66,13 +67,15 @@ export class MindsVideoTorrentPlayer implements OnInit, AfterViewInit, OnDestroy
     protected cd: ChangeDetectorRef,
     protected client: Client,
     protected webtorrent: WebtorrentService,
-    private router: Router,
   ) { }
 
   protected _emitPlay = () => this.onPlay.emit(this.getPlayer());
   protected _emitPause = () => this.onPause.emit(this.getPlayer());
   protected _emitEnd = () => this.onEnd.emit(this.getPlayer());
   protected _emitError = e => this.onError.emit({ player: this.getPlayer(), e});
+  protected _emitCanPlay = () => this.onCanPlay.emit(this.getPlayer());
+  protected _emitLoadedMetadata = () => this.onLoadedMetadata.emit(this.getPlayer());
+  protected _emitLoadedData = () => this.onLoadedData.emit(this.getPlayer());
 
   protected _canPlayThrough = () => {
     this.loading = false;
@@ -136,6 +139,9 @@ export class MindsVideoTorrentPlayer implements OnInit, AfterViewInit, OnDestroy
     player.addEventListener('ended', this._emitEnd);
     player.addEventListener('error', this._onPlayerError);
     player.addEventListener('canplaythrough', this._canPlayThrough);
+    player.addEventListener('canplay', this._emitCanPlay);
+    player.addEventListener('loadedmetadata', this._emitLoadedMetadata);
+    player.addEventListener('loadeddata', this._emitLoadedData);
 
     this.infoTimer$ = setInterval(this._refreshInfo, 1000);
     this.isModal = document.body.classList.contains('m-overlay-modal--shown');
@@ -165,6 +171,9 @@ export class MindsVideoTorrentPlayer implements OnInit, AfterViewInit, OnDestroy
       player.removeEventListener('ended', this._emitEnd);
       player.removeEventListener('error', this._onPlayerError);
       player.removeEventListener('canplaythrough', this._canPlayThrough);
+      player.removeEventListener('canplay', this._emitCanPlay);
+      player.removeEventListener('loadedmetadata', this._emitLoadedMetadata);
+      player.removeEventListener('loadeddata', this._emitLoadedData);
     }
   }
 
@@ -360,16 +369,8 @@ export class MindsVideoTorrentPlayer implements OnInit, AfterViewInit, OnDestroy
       this.torrentReady = false;
     }
   }
-  requestMediaModal() {
-    // Don't reopen modal if you're already on it
-    if ( this.isModal ) {
-      this.toggle();
-    }
 
-    // Mobile users go to media page instead of modal
-    if (isMobile()) {
-      this.router.navigate([`/media/${this.guid}`]);
-    }
-    this.triggerMediaModal.emit();
+  requestMediaModal() {
+    this.requestedMediaModal.emit();
   }
 }
diff --git a/src/app/modules/media/components/video/video.component.html b/src/app/modules/media/components/video/video.component.html
index 61e415fa49..4ef2bd8cbc 100644
--- a/src/app/modules/media/components/video/video.component.html
+++ b/src/app/modules/media/components/video/video.component.html
@@ -10,6 +10,10 @@
     (onPause)="onPause()"
     (onEnd)="onEnd()"
     (onError)="onError()"
+    (onCanPlay)="onCanPlay()"
+    (onLoadedMetadata)="loadedMetadata()"
+    (onLoadedData)="loadedData()"
+    (requestedMediaModal)="requestMediaModal()"
     #player
   ></m-video--direct-http-player>
 
@@ -24,15 +28,18 @@
     (onPause)="onPause()"
     (onEnd)="onEnd()"
     (onError)="onError()"
+    (onCanPlay)="onCanPlay()"
+    (onLoadedMetadata)="loadedMetadata()"
+    (onLoadedData)="loadedData()"
+    (requestedMediaModal)="requestMediaModal()"
     #player
   ></m-video--torrent-player>
 
   <ng-container *ngIf="playerRef">
     <i *ngIf="!playerRef.isPlaying() && !playerRef.isLoading()"
       class="material-icons minds-video-play-icon"
-      (click)="playerRef.play()"
+      (click)="requestMediaModal()"
     >play_circle_outline</i>
-
     <ng-content></ng-content>
 
     <div *ngIf="transcoding" class="minds-video-bar-top">
@@ -44,9 +51,9 @@
     </div>
 
     <div class="minds-video-bar-full">
-      <i class="material-icons" *ngIf="!playerRef.isLoading(); else loadingSpinner"
+      <i class="material-icons"
         (click)="playerRef.toggle()"
-      >{{ playerRef.isPlaying() ? 'pause' : 'play_arrow' }}</i>
+      >{{ playerRef.isPlaying() || playerRef.isLoading() ? 'pause' : 'play_arrow' }}</i>
       <ng-template #loadingSpinner>
         <div class="mdl-spinner mdl-js-spinner is-active" [mdl]></div>
       </ng-template>
@@ -55,7 +62,7 @@
       <m-video--volume-slider #volumeSlider [player]="playerRef"></m-video--volume-slider>
 
       <a class="material-icons m-video-full-page minds-video--open-new"
-        *ngIf="guid"
+        *ngIf="guid && !isModal"
         [routerLink]="['/media', guid]"
         target="_blank"
         (click)="playerRef.pause()">
@@ -92,7 +99,7 @@
         (select)="selectedQuality($event)"
       ></m-video--quality-selector>
 
-      <i class="material-icons" (click)="playerRef.requestFullScreen()">tv</i>
+      <i *ngIf="!isModal" class="material-icons" (click)="playerRef.requestFullScreen()">tv</i>
     </div>
 
     <div class="m-video--torrent-info" *ngIf="torrentInfo && current.type === 'torrent'">
diff --git a/src/app/modules/media/components/video/video.component.scss b/src/app/modules/media/components/video/video.component.scss
index f22ec9e4dd..49c3292744 100644
--- a/src/app/modules/media/components/video/video.component.scss
+++ b/src/app/modules/media/components/video/video.component.scss
@@ -5,6 +5,12 @@
  m-video{
   position: relative;
   display:block;
+  cursor:pointer;
+  &:hover {
+    .minds-video-play-icon {
+      opacity: 1;
+    }
+  }
 
   video{
     width:100%;
@@ -43,6 +49,7 @@
     }
   }
   .minds-video-play-icon{
+    opacity: 0.8;
     display: block;
     text-align: center;
     top: 50%;
@@ -51,8 +58,10 @@
     position: absolute;
     cursor: pointer;
     width: 100%;
+    transition: opacity 0.3s cubic-bezier(.23, 1, .32, 1);
     @include m-theme(){
       color: themed($m-white-always);
+      text-shadow: 0 0 3px rgba(themed($m-black-always), 0.6);
     }
   }
   .minds-video-bar-full{
@@ -62,7 +71,6 @@
     left: 0;
     width: 100%;
     box-sizing: border-box;
-    //padding: $minds-padding;
     text-align: center;
     align-items: center;
     @include m-theme(){
@@ -75,7 +83,7 @@
         color:themed($m-white-always);
       }
     }
-    
+
     .mdl-spinner {
       margin: 0 8px;
     }
@@ -91,9 +99,6 @@
     .minds-video-bar-min{
       display: none;
     }
-    .minds-video-bar-full{
-      display: flex;
-    }
   }
 
   .m-video--torrent-info {
diff --git a/src/app/modules/media/components/video/video.component.ts b/src/app/modules/media/components/video/video.component.ts
index 4e946284de..5859c2774b 100644
--- a/src/app/modules/media/components/video/video.component.ts
+++ b/src/app/modules/media/components/video/video.component.ts
@@ -1,5 +1,5 @@
 import { Component, ElementRef, Input, Output, EventEmitter, ViewChild, ChangeDetectorRef } from '@angular/core';
-// import { Router } from '@angular/router';
+import { Router } from '@angular/router';
 import { MindsVideoProgressBar } from './progress-bar/progress-bar.component';
 import { MindsVideoVolumeSlider } from './volume-slider/volume-slider.component';
 
@@ -8,7 +8,7 @@ import { ScrollService } from '../../../../services/ux/scroll';
 import { MindsPlayerInterface } from './players/player.interface';
 import { WebtorrentService } from '../../../webtorrent/webtorrent.service';
 import { SOURCE_CANDIDATE_PICK_ZIGZAG, SourceCandidates } from './source-candidates';
-// import isMobile from '../../../../helpers/is-mobile';
+import isMobile from '../../../../helpers/is-mobile';
 
 @Component({
   selector: 'm-video',
@@ -24,9 +24,14 @@ export class MindsVideoComponent {
   @Input() log: string | number;
   @Input() muted: boolean = false;
   @Input() poster: string = '';
+  @Input() isModal: boolean = false;
 
   @Output('finished') finished: EventEmitter<any> = new EventEmitter();
-  // @Output() triggerMediaModal: EventEmitter<any> = new EventEmitter();
+
+  @Output() videoMetadataLoaded: EventEmitter<any> = new EventEmitter();
+  @Output() videoLoaded: EventEmitter<any> = new EventEmitter();
+  @Output() videoCanPlay: EventEmitter<any> = new EventEmitter();
+  @Output() requestedMediaModal: EventEmitter<any> = new EventEmitter();
 
   @ViewChild('progressBar', { static: false }) progressBar: MindsVideoProgressBar;
   @ViewChild('volumeSlider', { static: false }) volumeSlider: MindsVideoVolumeSlider;
@@ -55,6 +60,7 @@ export class MindsVideoComponent {
   playedOnce: boolean = false;
   playCount: number = -1;
   playCountDisabled: boolean = false;
+  modalHover: boolean = false;
 
   current: { type: 'torrent' | 'direct-http', src: string };
   protected candidates: SourceCandidates = new SourceCandidates();
@@ -73,7 +79,7 @@ export class MindsVideoComponent {
     public client: Client,
     protected webtorrent: WebtorrentService,
     protected cd: ChangeDetectorRef,
-    // private router: Router,
+    private router: Router,
   ) { }
 
   ngOnInit() {
@@ -163,6 +169,9 @@ export class MindsVideoComponent {
   }
 
   onMouseLeave() {
+    if (this.modalHover) {
+      return;
+    }
     this.progressBar.stopSeeker();
     this.progressBar.disableKeyControls();
   }
@@ -228,6 +237,23 @@ export class MindsVideoComponent {
     this.playerRef.toggle();
   }
 
+  loadedMetadata() {
+    const dimensions = {
+      'width' : this.playerRef.getPlayer().videoWidth,
+      'height' : this.playerRef.getPlayer().videoHeight
+    };
+
+    this.videoMetadataLoaded.emit({dimensions: dimensions});
+  }
+
+  loadedData() {
+    this.videoLoaded.emit();
+  }
+
+  onCanPlay() {
+    this.videoCanPlay.emit();
+  }
+
   // Sources
 
   async fallback() {
@@ -327,21 +353,23 @@ export class MindsVideoComponent {
     }
   }
 
-  // requestMediaModal() {
-  //   // this.playerRef.pause(); //no need anymore
-  //   // Mobile users go to media page instead of modal
-  //   if (isMobile()) {
-  //     this.router.navigate([`/media/${this.guid}`]);
-  //   }
+  requestMediaModal() {
+    // Don't reopen modal if you're already on it
+    if (this.isModal) {
+      this.toggle();
+    }
+    //  Mobile users go to media page instead of modal
+    if (isMobile()) {
+      this.router.navigate([`/media/${this.guid}`]);
+    }
 
-  //   this.triggerMediaModal.emit();
-  // }
+    this.requestedMediaModal.emit();
+  }
 
   detectChanges() {
     this.cd.markForCheck();
     this.cd.detectChanges();
   }
-
 }
 
 export { VideoAds } from './ads.component';
diff --git a/src/app/modules/media/components/video/volume-slider/volume-slider.component.html b/src/app/modules/media/components/video/volume-slider/volume-slider.component.html
index e02d9aec99..cbf99b8979 100644
--- a/src/app/modules/media/components/video/volume-slider/volume-slider.component.html
+++ b/src/app/modules/media/components/video/volume-slider/volume-slider.component.html
@@ -5,6 +5,7 @@
   <i class="material-icons" *ngIf="element.volume >= 0.9 && !element.muted" (click)="element.muted = true">volume_up</i>
 
   <div class="m-video--volume-control">
+    <div class="m-video--volume-control--background"></div>
     <input type="range" [(ngModel)]="element.volume" class="m-video--volume-control-selector" min="0" max="1" step="0.05" />
   </div>
 </div>
diff --git a/src/app/modules/media/components/video/volume-slider/volume-slider.component.scss b/src/app/modules/media/components/video/volume-slider/volume-slider.component.scss
index e79ab7ccb3..84c21c189b 100644
--- a/src/app/modules/media/components/video/volume-slider/volume-slider.component.scss
+++ b/src/app/modules/media/components/video/volume-slider/volume-slider.component.scss
@@ -61,6 +61,9 @@ m-video--volume-slider{
     position: absolute;
     top: 35px;
     right: -18px;
+    @include m-theme(){
+      background-color: themed($m-white-always);
+    }
   }
 
   .m-video--volume-control{
@@ -72,6 +75,14 @@ m-video--volume-slider{
     height: 80px;
     position: absolute;
     margin: 0;
+  }
+
+  .m-video--volume-control--background {
+    width:40px;
+    height:72px;
+    position: absolute;
+    left: calc(50% - 20px);
+    bottom: 16px;
     @include m-theme(){
       background-color: rgba(themed($m-black-always), 0.4);
     }
diff --git a/src/app/modules/media/modal/modal.component.html b/src/app/modules/media/modal/modal.component.html
index 4025d827bd..5bd11485f7 100644
--- a/src/app/modules/media/modal/modal.component.html
+++ b/src/app/modules/media/modal/modal.component.html
@@ -1,15 +1,17 @@
-<div class="m-mediaModal__exoWrapper">
-  <div class="m-mediaModal__wrapper"
+<div class="m-mediaModal__wrapper">
+  <div class="m-mediaModal__theater"
     (click)="clickedModal($event)"
   >
     <div class="m-mediaModal m-mediaModal__clearFix"
       [style.width]="modalWidth + 'px'"
       [style.height]="stageHeight + 'px'"
     >
-      <!-- This is the element that goes into fullscreen -->
+      <!-- The stageWrapper is the element that goes into fullscreen -->
       <div class="m-mediaModal__stageWrapper"
         [style.width]="stageWidth + 'px'"
         [style.line-height]="stageHeight + 'px'"
+        (mouseenter)="onMouseEnterStage()"
+        (mouseleave)="onMouseLeaveStage()"
       >
         <!-- LOADING PANEL -->
         <div class="m-mediaModal__loadingPanel" *ngIf="inProgress">
@@ -22,28 +24,28 @@
         >
 
           <!-- MEDIA: IMAGE -->
-          <div class="m-mediaModal__imageWrapper"
-            *ngIf="entity.modal_subtype === 'image'"
+          <div class="m-mediaModal__mediaWrapper m-mediaModal__mediaWrapper--image"
+            *ngIf="entity.custom_type === 'batch'"
             [style.width]="mediaWidth + 'px'"
             [style.height]="mediaHeight + 'px'"
           >
             <img [src]="thumbnail"
-              (load)="inProgress = !inProgress"
-
+              (load)="this.inProgress = false"
               [style.height]="entity.height + 'px'"
               [style.width]="entity.width + 'px'"
             />
           </div>
 
           <!-- MEDIA: VIDEO -->
-          <div class="m-mediaModal__videoWrapper"
-            *ngIf="entity.modal_subtype === 'video'"
+          <div class="m-mediaModal__mediaWrapper m-mediaModal__mediaWrapper--video"
+            *ngIf="entity.custom_type === 'video'"
             [style.width]="mediaWidth + 'px'"
             [style.height]="mediaHeight + 'px'"
           >
             <m-video
               [style.height]="entity.height + 'px'"
               [style.width]="entity.width + 'px'"
+              [isModal]="true"
               [autoplay]="true"
               [muted]="false"
               [poster]="entity.custom_data.thumbnail_src"
@@ -51,7 +53,7 @@
               [guid]="entity.custom_data.guid"
               [playCount]="entity['play:count']"
               [torrent]="[{ res: '360', key: entity.custom_data.guid + '/360.mp4' }]"
-              #player
+              (videoCanPlay)="this.inProgress = false"
             >
               <video-ads [player]="player" *ngIf="entity.monetized"></video-ads>
             </m-video>
@@ -67,7 +69,7 @@
               <!-- TITLE: FULLSCREEN -->
               <span class="m-mediaModal__overlayTitle m-mediaModal__overlayTitle--fullscreen" *ngIf="isFullscreen">
                 <a [routerLink]="['/', entity.ownerObj.username]">
-                  <img class="avatar" [hovercard]="entity.ownerObj.guid" [src]="minds.cdn_url + 'icon/' + entity.ownerObj.guid + '/small/' + getOwnerIconTime()" class="mdl-shadow--2dp"/>
+                  <img class="avatar" [src]="minds.cdn_url + 'icon/' + entity.ownerObj.guid + '/small/' + getOwnerIconTime()" class="mdl-shadow--2dp"/>
                   <span title={{entity.ownerObj.name}}>{{entity.ownerObj.name}}</span>
                 </a>
                 <div class="m-mediaModal__overlayTitleSeparator"></div>
diff --git a/src/app/modules/media/modal/modal.component.scss b/src/app/modules/media/modal/modal.component.scss
index 1223a0dc8b..ed1fb0d717 100644
--- a/src/app/modules/media/modal/modal.component.scss
+++ b/src/app/modules/media/modal/modal.component.scss
@@ -9,9 +9,9 @@ m-overlay-modal {
   }
 
   .m-overlay-modal.m-overlayModal--media {
-    min-width: 1060px; // ! Need to output this to parent
+    // min-width: 1060px; // should output this to parent
     min-height: 100%;
-    position: fixed; //should be absolute?
+    position: fixed; //? should be absolute?
     top: 0;
     right: 0;
     left: 0;
@@ -48,28 +48,25 @@ m-overlay-modal {
       vertical-align: middle;
       width: 100%;
 
-      .m-mediaModal__exoWrapper {
+      .m-mediaModal__wrapper {
         position: static;
         margin: 20px;
         display:inline-block;
         text-align: left;
 
-        .m-mediaModal__wrapper {
+        .m-mediaModal__theater {
           position: relative;
           @include m-theme(){
             box-shadow: 0 12px 24px rgba(themed($m-black-always), 0.3);
           }
-          // .m-mediaModal { // has inline width/height
-
-          // }
+          // .m-mediaModal {} // has inline width/height
         }
       }
     }
   }
 }
 
-.m-mediaModal__loadingPanel {
-  .mdl-spinner {
+.m-mediaModal__loadingPanel .mdl-spinner {
     position: absolute;
     top:  unquote("-webkit-calc(50% - 14px)");
     left: unquote("-webkit-calc(50% - 14px)");
@@ -77,7 +74,6 @@ m-overlay-modal {
     left:    unquote("-moz-calc(50% - 14px)");
     top:          unquote("calc(50% - 14px)");
     left:         unquote("calc(50% - 14px)");
-  }
 }
 
 .m-mediaModal__stageWrapper { // Has inline width/line-height
@@ -95,13 +91,17 @@ m-overlay-modal {
     .m-mediaModal__overlayContainer {
       opacity: 1;
     }
+    .minds-video-bar-full {
+      visibility: visible;
+      opacity: 1;
+    }
   }
 }
 
 .m-mediaModal__stage {
   display: flex;
   align-items:center;
-  font-size:0;
+  font-size: 0;
   height: 100%;
   min-height: 402px;
   position: relative;
@@ -109,27 +109,55 @@ m-overlay-modal {
   width: 100%;
 }
 
-.m-mediaModal__imageWrapper { // Has inline width/height
+.m-mediaModal__mediaWrapper { // Has inline width/height
   display: inline-block;
   margin: 0 auto;
   vertical-align: middle;
 
-  img { // Has inline width/height
+  img, m-video { // Has inline width/height
     display: inline-block;
     max-height: 100%;
     max-width: 100%;
     vertical-align: top;
   }
 
-}
+  m-video {
+    position: static;
+
+    .minds-video-bar-full  {
+      visibility: hidden;
+      display: flex;
+      opacity: 0;
+      transition: opacity .3s;
+
+      .m-video--progress-bar {
+        padding-right: 0;
+      }
+
+      .m-video--volume-control-wrapper {
+        margin-right: 16px;
+      }
+    }
+    .minds-video-play-icon {
+      transform: none;
+      width: auto;
+      top:  unquote("-webkit-calc(50% - 50px)");
+      left: unquote("-webkit-calc(50% - 50px)");
+      top:     unquote("-moz-calc(50% - 50px)");
+      left:    unquote("-moz-calc(50% - 50px)");
+      top:          unquote("calc(50% - 50px)");
+      left:         unquote("calc(50% - 50px)");
+    }
+    m-video--progress-bar {
+      .seeker-ball {
+        top: 4px;
+      }
+      .progress-bar {
+        margin-right: 8px;
+      }
+    }
+  }
 
-.m-mediaModal__videoWrapper {
-  // TODO - this was from fb
-  //  bottom: 40px;
-  // overflow: hidden;
-  // position: absolute;
-  // top: 40px;
-  // width: 100%;
 }
 
 .m-mediaModal__overlayContainer {
@@ -155,13 +183,13 @@ m-overlay-modal {
   overflow: hidden;
   text-overflow: ellipsis;
   margin-right: 36px;
-  cursor: pointer;
   @include m-theme(){
     color: themed($m-white-always);
   }
 
   .m-mediaModal__overlayTitle {
     text-decoration: none;
+    cursor: pointer;
 
     > * {
       &:not(.m-mediaModal__overlayTitleSeparator) {
diff --git a/src/app/modules/media/modal/modal.component.ts b/src/app/modules/media/modal/modal.component.ts
index 18d9ccc966..a467d98698 100644
--- a/src/app/modules/media/modal/modal.component.ts
+++ b/src/app/modules/media/modal/modal.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, OnDestroy, Input, HostListener } from '@angular/core';
+import { Component, OnInit, OnDestroy, Input, HostListener, ViewChild } from '@angular/core';
 import { Location } from '@angular/common';
 import { Router, Event, NavigationStart } from '@angular/router';
 import { trigger, state, style, animate, transition } from '@angular/animations';
@@ -6,15 +6,13 @@ import { Subscription } from 'rxjs';
 import { Session } from '../../../services/session';
 import { OverlayModalService } from '../../../services/ux/overlay-modal';
 import { AnalyticsService } from '../../../services/analytics';
-import isMobile from '../../../helpers/is-mobile';
-import isMobileOrTablet from '../../../helpers/is-mobile-or-tablet';
-
+import { MindsVideoComponent } from '../components/video/video.component';
 
 @Component({
   selector: 'm-media--modal',
   templateUrl: 'modal.component.html',
   animations: [
-    // Fade in image when it's done loading
+    // Fade in media when done loading
     trigger('simpleFadeAnimation', [
       state('in', style({opacity: 1})),
       transition(':enter', [
@@ -22,18 +20,17 @@ import isMobileOrTablet from '../../../helpers/is-mobile-or-tablet';
         animate(800)
       ])
     ])
-]
+  ]
 })
 
-
 export class MediaModalComponent implements OnInit, OnDestroy {
   minds = window.Minds;
   entity: any = {};
   inProgress: boolean = true;
+
   isFullscreen: boolean = false;
   navigatedAway: boolean = false;
   fullscreenHovering: boolean = false; // Used for fullscreen button transformation
-  isTablet: boolean = false;
 
   screenWidth: number;
   screenHeight: number;
@@ -47,48 +44,54 @@ export class MediaModalComponent implements OnInit, OnDestroy {
   maxStageWidth: number;
   maxHeight: number;
   minStageHeight: number;
+  minStageWidth: number;
 
   title: string = '';
   thumbnail: string = '';
   boosted: boolean = false;
 
-  isOpen: boolean = false; // Used for backdrop click detection hack
-  isOpenTimeout: any = null; // Used for backdrop click detection hack
+  // Used for backdrop click detection hack
+  isOpen: boolean = false;
+  isOpenTimeout: any = null;
 
   routerSubscription: Subscription;
 
   @Input('entity') set data(entity) {
     this.entity = entity;
+    this.entity.width = 0;
+    this.entity.height = 0;
   }
 
+
+  @ViewChild( MindsVideoComponent, { static: false }) videoComponent: MindsVideoComponent;
+
   constructor(
     public session: Session,
+    public analyticsService: AnalyticsService,
     private overlayModal: OverlayModalService,
     private router: Router,
     private location: Location,
-    public analyticsService: AnalyticsService
   ) {
   }
 
   ngOnInit() {
+
     // Prevent dismissal of modal when it's just been opened
     this.isOpenTimeout = setTimeout(() => this.isOpen = true, 50);
 
     this.analyticsService.send('pageview', {url: `/media/${this.entity.entity_guid}?ismodal=true`});
 
-    // this.isTablet = isMobileOrTablet() && !isMobile();
-
-    this.thumbnail = `${this.minds.cdn_url}fs/v1/thumbnail/${this.entity.entity_guid}/xlarge`;
     this.boosted = this.entity.boosted || this.entity.p2p_boosted;
 
     // Set title
     if ( !this.entity.title ) {
       if ( !this.entity.message ) {
-        // ? is there ever a case where there is a message but no title?
         this.title = `${this.entity.ownerObj.name}'s post`;
       } else {
         this.title = this.entity.message;
       }
+    } else {
+      this.title = this.entity.title;
     }
 
     // Change the url to point to media page so user can easily share link
@@ -108,119 +111,168 @@ export class MediaModalComponent implements OnInit, OnDestroy {
           // Go to the intended destination
           this.router.navigate([event.url]);
 
-          this.overlayModal.dismiss();
+          this.dismissModal();
         }
       }
 
     });
 
-    // Dimensions are in px
-    this.entity.width = this.entity.custom_data[0].width;
-    this.entity.height = this.entity.custom_data[0].height;
-    this.entity.aspectRatio = this.entity.width / this.entity.height;
-    this.entity.isPortrait = this.entity.aspectRatio < 1;
-    console.log(this.entity);
+    // TO DO? handle giant screens by setting max on screenwidth and height and window size?
 
+    // Set fixed dimensions (i.e. those that don't change when window changes)
     this.screenWidth = screen.width;
     this.screenHeight = screen.height;
-    this.contentWidth = Math.round(this.screenWidth * 0.25);
-    this.minStageHeight = Math.round((this.screenHeight * 0.6) - 20); // 520px
-    this.maxHeight = Math.round(this.screenHeight * 0.8); // ~723px
-    this.stageWidthPaddingThreshold = this.screenWidth * 0.4 + 44; // 620
+    this.contentWidth = Math.max(Math.round(this.screenWidth * 0.25), 300);
+    this.minStageHeight = Math.round((this.screenHeight * 0.6) - 20);
+    this.maxHeight = Math.round(this.screenHeight * 0.8);
+    this.stageWidthPaddingThreshold = this.screenWidth * 0.4 + 44;
+    this.minStageWidth = this.stageWidthPaddingThreshold + 40;
+
+    if (this.entity.custom_type === 'batch') {
+      // Image
+      this.entity.width = this.entity.custom_data[0].width;
+      this.entity.height = this.entity.custom_data[0].height;
+      this.thumbnail = `${this.minds.cdn_url}fs/v1/thumbnail/${this.entity.entity_guid}/xlarge`;
+    } else {
+      // Video
+      this.entity.width = this.entity.custom_data.dimensions.width;
+      this.entity.height = this.entity.custom_data.dimensions.height;
+      this.thumbnail = this.entity.custom_data.thumbnail_src; // Not currently used
+    }
 
+    this.entity.aspectRatio = this.entity.width / this.entity.height;
     this.calculateDimensions();
   }
 
-  // Change media containers' height/width on window resize
+  // Recalculate height/width when window resizes
   @HostListener('window:resize', ['$resizeEvent'])
     onResize(resizeEvent) {
       this.calculateDimensions();
     }
 
   calculateDimensions() {
-    // This can be simplified but it works
     const windowWidth: number = window.innerWidth;
     const windowHeight: number = window.innerHeight;
 
     if ( !this.isFullscreen ) {
-    // Set stageHeight as % of windowHeight
-    this.stageHeight = Math.round(windowHeight * 0.94);
-
-    // Ensure stageHeight is between min and max (max. is % of screenHeight)
-    if ( this.stageHeight > this.maxHeight ) {
-      this.stageHeight = this.maxHeight;
-    } else if ( this.stageHeight < this.minStageHeight ) {
-      // Stage height should be no lower than minimum
-      this.stageHeight = this.minStageHeight;
-    }
-
 
-    // Set image height as hight as stageHeight but no larger than intrinsic height
-    if (this.entity.height >= this.stageHeight) {
-      this.mediaHeight = this.stageHeight;
-    } else {
-      this.mediaHeight = this.entity.height;
-      this.stageHeight = this.minStageHeight;
-    }
-    this.mediaWidth = Math.round(this.mediaHeight * this.entity.aspectRatio);
-
-    // If width is lower than threshold, add extra padding
-    const minStageWidth = this.stageWidthPaddingThreshold + 40; // 660
-    // TODO rename minStageWidth.  Here it's 660. but technically also it goes down to 621
-
-    let maxStageWidth: number = windowWidth - 400;
-    // Don't let maxStageWidth go below minStageWidth
-    if ( maxStageWidth <= minStageWidth ) {
-      maxStageWidth = minStageWidth;
-    }
-
-    // Reset mediaWidth and stageWidth if needed
-    // If image is too wide, set width to max and rescale imageHeight and stageHeight
-      if ( this.mediaWidth >= maxStageWidth ) {
-        this.mediaWidth = maxStageWidth;
-        this.stageWidth = maxStageWidth;
-
-        // Rescale media based on new mediaWidth
-        this.mediaHeight = Math.round(this.mediaWidth / this.entity.aspectRatio);
-        if ( this.mediaHeight >= this.minStageHeight ) {
-          this.stageHeight = this.mediaHeight;
-        } else {
-          this.stageHeight = this.minStageHeight;
-        }
-      } else if ( this.mediaWidth > this.stageWidthPaddingThreshold  ) {
+      // Set heights as tall as possible
+      this.setStageHeightWithinRange(window.innerHeight);
+      this.setHeights();
+
+      // After heights are set, check that scaled width isn't too wide or narrow
+      this.maxStageWidth = Math.max(windowWidth - this.contentWidth - 40, this.minStageWidth);
+      if ( this.mediaWidth >= this.maxStageWidth ) {
+        // Too wide :(
+        this.rescaleHeightsForMaxWidth();
+      } else if ( this.mediaWidth > this.stageWidthPaddingThreshold ) {
+        // Not too wide and not too narrow :)
         this.stageWidth = this.mediaWidth;
       } else {
-        // When stageWidth goes below threshold, increase horizontal padding up to 20px minimum
-        this.stageWidth = minStageWidth;
+        // Too narrow :(
+        // If black stage background is visible on left/right, each strip should be at least 20px wide
+        this.stageWidth = this.minStageWidth;
+
+        // Continue to resize height after reaching min width
+        this.handleNarrowWindow(window.innerWidth);
       }
 
-    } else { // Fullscreen
+      // If black stage background is visible on top/bottom, each strip should be at least 20px high
+      const heightDiff = this.stageHeight - this.mediaHeight;
+      if ( 0 < heightDiff && heightDiff <= 40){
+        this.stageHeight += 40;
+      }
+
+    } else { // isFullscreen
       this.stageWidth = windowWidth;
       this.stageHeight = windowHeight;
 
       // Set mediaHeight as tall as possible but not taller than instrinsic height
       this.mediaHeight = this.entity.height < windowHeight ? this.entity.height : windowHeight;
-      this.mediaWidth = Math.round(this.mediaHeight * this.entity.aspectRatio);
+      this.mediaWidth = this.scaleWidth();
 
-      // Width was too wide, need to rescale
       if ( this.mediaWidth > windowWidth ) {
+        // Width was too wide, need to rescale heights so width fits
         this.mediaWidth = windowWidth;
-        this.mediaHeight = Math.round(this.mediaWidth / this.entity.aspectRatio);
+        this.mediaHeight = this.scaleHeight();
       }
     }
-
     this.modalWidth = this.stageWidth + this.contentWidth;
   }
 
-  getOwnerIconTime() {
-    const session = this.session.getLoggedInUser();
-    if (session && session.guid === this.entity.ownerObj.guid) {
-      return session.icontime;
+
+  setStageHeightWithinRange(windowHeight) {
+  // Initialize stageHeight as % of windowHeight
+  this.stageHeight = Math.round(windowHeight * 0.94);
+
+  // Ensure stageHeight is not taller than max (a % of screenHeight)
+  this.stageHeight = Math.min(this.stageHeight, this.maxHeight);
+
+  // Ensure stageHeight is not shorter than min (a % of screenHeight)
+  this.stageHeight = Math.max(this.stageHeight, this.minStageHeight);
+
+  // Scale width according to aspect ratio
+  this.mediaWidth = this.scaleWidth();
+  }
+
+
+  setHeights() {
+    // Set mediaHeight as tall as stage but no larger than intrinsic height
+    if (this.entity.height >= this.stageHeight) {
+      // Fit media inside stage
+      this.mediaHeight = this.stageHeight;
     } else {
-      return this.entity.ownerObj.icontime;
+      // Media is shorter than stage
+      this.mediaHeight = this.entity.height;
+      this.stageHeight = this.minStageHeight;
+    }
+
+    // Scale width according to aspect ratio
+    this.mediaWidth = this.scaleWidth();
+  }
+
+  rescaleHeightsForMaxWidth() {
+    // Media is too wide, set width to max and rescale heights
+    this.mediaWidth = this.maxStageWidth;
+    this.stageWidth = this.maxStageWidth;
+
+    this.mediaHeight = this.scaleHeight();
+    this.stageHeight = Math.max(this.mediaHeight, this.minStageHeight);
+  }
+
+  handleNarrowWindow(windowWidth) {
+    // When at minStageWidth and windowWidth falls below threshold,
+    // shrink vertically until it hits minStageHeight
+
+    // When window is narrower than this, start to shrink height
+    const verticalShrinkWidthThreshold = this.mediaWidth + this.contentWidth + 82;
+
+    const widthDiff = verticalShrinkWidthThreshold - windowWidth;
+    // Is window narrow enough to start shrinking vertically?
+    if ( widthDiff >= 1 ) {
+      // What mediaHeight would be if it shrunk proportionally to difference in width?
+      const mediaHeightPreview = Math.round((this.mediaWidth - widthDiff) / this.entity.aspectRatio);
+
+      // Shrink media if mediaHeight is still above min
+      if (mediaHeightPreview > this.minStageHeight) {
+        this.mediaWidth -= widthDiff;
+        this.mediaHeight = this.scaleHeight();
+        this.stageHeight = this.mediaHeight;
+      } else {
+        this.stageHeight = this.minStageHeight;
+        this.mediaHeight = Math.min(this.minStageHeight, this.entity.height);
+        this.mediaWidth = this.scaleWidth();
+      }
     }
   }
 
+  scaleHeight() {
+    return Math.round(this.mediaWidth / this.entity.aspectRatio);
+  }
+  scaleWidth() {
+    return Math.round(this.mediaHeight * this.entity.aspectRatio);
+  }
+
   // Listen for fullscreen change event in case user enters/exits full screen without clicking button
   @HostListener('document:fullscreenchange', ['$event'])
   @HostListener('document:webkitfullscreenchange', ['$event'])
@@ -228,7 +280,10 @@ export class MediaModalComponent implements OnInit, OnDestroy {
   @HostListener('document:MSFullscreenChange', ['$event'])
   onFullscreenChange(event) {
     this.calculateDimensions();
-    if (!document.fullscreenElement && !document['webkitFullScreenElement'] && !document['mozFullScreenElement'] && !document['msFullscreenElement']) {
+    if ( !document.fullscreenElement &&
+      !document['webkitFullScreenElement'] &&
+      !document['mozFullScreenElement'] &&
+      !document['msFullscreenElement'] ) {
       this.isFullscreen = false;
     } else {
       this.isFullscreen = true;
@@ -241,7 +296,10 @@ export class MediaModalComponent implements OnInit, OnDestroy {
     this.calculateDimensions();
 
     // If fullscreen is not already enabled
-    if (!document['fullscreenElement'] && !document['webkitFullScreenElement'] && !document['mozFullScreenElement'] && !document['msFullscreenElement']) {
+    if ( !document['fullscreenElement'] &&
+      !document['webkitFullScreenElement'] &&
+      !document['mozFullScreenElement'] &&
+      !document['msFullscreenElement'] ) {
       // Request full screen
       if (elem.requestFullscreen) {
         elem.requestFullscreen();
@@ -257,7 +315,7 @@ export class MediaModalComponent implements OnInit, OnDestroy {
     }
 
     // If fullscreen is already enabled, exit it
-    if (document.exitFullscreen) {
+    if ( document.exitFullscreen ) {
       document.exitFullscreen();
     } else if (document['webkitExitFullscreen']) {
       document['webkitExitFullscreen']();
@@ -269,21 +327,41 @@ export class MediaModalComponent implements OnInit, OnDestroy {
     this.isFullscreen = false;
   }
 
+  // Make sure progress bar updates when video controls are visible
+  onMouseEnterStage() {
+    this.videoComponent.modalHover = true;
+    this.videoComponent.onMouseEnter();
+  }
+
+  // Stop updating progress bar when controls aren't visible
+  onMouseLeaveStage() {
+    this.videoComponent.modalHover = false;
+    this.videoComponent.onMouseLeave();
+  }
+
+  getOwnerIconTime() {
+    const session = this.session.getLoggedInUser();
+    if (session && session.guid === this.entity.ownerObj.guid) {
+      return session.icontime;
+    } else {
+      return this.entity.ownerObj.icontime;
+    }
+  }
+
   // Dismiss modal when backdrop is clicked and modal is open
   @HostListener('document:click', ['$event']) clickedBackdrop($event){
     if (this.isOpen) {
-      this.dismiss();
+      this.dismissModal();
     }
   }
 
-  // Don't dismiss modal when modal is clicked
+  // Don't dismiss modal when clicking somewhere other than backdrop
   clickedModal($event) {
     $event.preventDefault();
     $event.stopPropagation();
-    console.log('***modal clicked...dont dismiss');
   }
 
-  dismiss() {
+  dismissModal() {
     this.overlayModal.dismiss();
   }
 
@@ -299,7 +377,4 @@ export class MediaModalComponent implements OnInit, OnDestroy {
       this.location.replaceState(this.entity.modal_source_url);
     }
   }
-
-
 }
-
-- 
GitLab