]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Handle theater mode for playlists
authorChocobozzz <me@florianbigard.com>
Mon, 18 Mar 2019 09:26:53 +0000 (10:26 +0100)
committerChocobozzz <chocobozzz@cpy.re>
Mon, 18 Mar 2019 10:17:59 +0000 (11:17 +0100)
client/src/app/videos/+video-watch/video-watch.component.html
client/src/app/videos/+video-watch/video-watch.component.scss
client/src/app/videos/+video-watch/video-watch.component.ts
client/src/assets/player/videojs-components/theater-button.ts
server/tests/api/users/user-notifications.ts

index 3df5b7b1913b7d6d10a93cd0449854a226d62b36..91f77cbf3929819bdb63369c5eedf8875b73d633 100644 (file)
@@ -1,4 +1,4 @@
-<div class="root-row row">
+<div class="root" [ngClass]="{ 'theater-enabled': theaterEnabled }">
   <!-- We need the video container for videojs so we just hide it -->
   <div id="video-wrapper">
     <div *ngIf="remoteServerDown" class="remote-server-down">
 
   <!-- Video information -->
   <div *ngIf="video" class="margin-content video-bottom">
-    <div class="row fullWidth">
-      <div class="col-12 col-lg-auto video-info">
-        <div class="video-info-first-row">
-          <div>
-            <div class="d-block d-sm-none"> <!-- only shown on small devices, has its conterpart for larger viewports below -->
+    <div class="video-info">
+      <div class="video-info-first-row">
+        <div>
+          <div class="d-block d-md-none"> <!-- only shown on medium devices, has its conterpart for larger viewports below -->
+            <h1 class="video-info-name">{{ video.name }}</h1>
+            <div i18n class="video-info-date-views">
+              Published {{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views
+            </div>
+          </div>
+
+          <div class="d-flex justify-content-between align-items-md-end">
+            <div class="d-none d-md-block">
               <h1 class="video-info-name">{{ video.name }}</h1>
+
               <div i18n class="video-info-date-views">
                 Published {{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views
               </div>
             </div>
 
-            <div class="d-flex justify-content-between align-items-sm-end">
-              <div class="d-none d-sm-block">
-                <h1 class="video-info-name">{{ video.name }}</h1>
+            <div class="video-actions-rates">
+              <div class="video-actions fullWidth justify-content-end">
+                <div
+                  *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'like' }" (click)="setLike()"
+                  class="action-button action-button-like" role="button" [attr.aria-pressed]="userRating === 'like'"
+                  i18n-title title="Like this video"
+                >
+                  <my-global-icon iconName="like"></my-global-icon>
+                </div>
 
-                <div i18n class="video-info-date-views">
-                  Published {{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views
+                <div
+                  *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'dislike' }" (click)="setDislike()"
+                  class="action-button action-button-dislike" role="button" [attr.aria-pressed]="userRating === 'dislike'"
+                  i18n-title title="Dislike this video"
+                >
+                  <my-global-icon iconName="dislike"></my-global-icon>
                 </div>
-              </div>
 
-              <div class="video-actions-rates">
-                <div class="video-actions fullWidth justify-content-end">
-                  <div
-                    *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'like' }" (click)="setLike()"
-                    class="action-button action-button-like" role="button" [attr.aria-pressed]="userRating === 'like'"
-                    i18n-title title="Like this video"
-                  >
-                    <my-global-icon iconName="like"></my-global-icon>
-                  </div>
+                <div *ngIf="video.support" (click)="showSupportModal()" class="action-button">
+                  <my-global-icon iconName="heart"></my-global-icon>
+                  <span class="icon-text" i18n>Support</span>
+                </div>
 
-                  <div
-                    *ngIf="isUserLoggedIn()" [ngClass]="{ 'activated': userRating === 'dislike' }" (click)="setDislike()"
-                    class="action-button action-button-dislike" role="button" [attr.aria-pressed]="userRating === 'dislike'"
-                    i18n-title title="Dislike this video"
-                  >
-                    <my-global-icon iconName="dislike"></my-global-icon>
-                  </div>
+                <div (click)="showShareModal()" class="action-button" role="button">
+                  <my-global-icon iconName="share"></my-global-icon>
+                  <span class="icon-text" i18n>Share</span>
+                </div>
 
-                  <div *ngIf="video.support" (click)="showSupportModal()" class="action-button">
-                    <my-global-icon iconName="heart"></my-global-icon>
-                    <span class="icon-text" i18n>Support</span>
+                <div
+                  class="action-dropdown" ngbDropdown placement="top" role="button" autoClose="outside"
+                   *ngIf="isUserLoggedIn()" (openChange)="addContent.openChange($event)"
+                >
+                  <div class="action-button action-button-save" ngbDropdownToggle role="button">
+                    <my-global-icon iconName="playlist-add"></my-global-icon>
+                    <span class="icon-text" i18n>Save</span>
                   </div>
 
-                  <div (click)="showShareModal()" class="action-button" role="button">
-                    <my-global-icon iconName="share"></my-global-icon>
-                    <span class="icon-text" i18n>Share</span>
+                  <div ngbDropdownMenu>
+                    <my-video-add-to-playlist #addContent [video]="video"></my-video-add-to-playlist>
                   </div>
+                </div>
 
-                  <div
-                    class="action-dropdown" ngbDropdown placement="top" role="button" autoClose="outside"
-                     *ngIf="isUserLoggedIn()" (openChange)="addContent.openChange($event)"
-                  >
-                    <div class="action-button action-button-save" ngbDropdownToggle role="button">
-                      <my-global-icon iconName="playlist-add"></my-global-icon>
-                      <span class="icon-text" i18n>Save</span>
-                    </div>
-
-                    <div ngbDropdownMenu>
-                      <my-video-add-to-playlist #addContent [video]="video"></my-video-add-to-playlist>
-                    </div>
+                <div class="action-dropdown" ngbDropdown placement="top" role="button">
+                  <div class="action-button" ngbDropdownToggle role="button">
+                    <my-global-icon class="more-icon" iconName="more-horizontal"></my-global-icon>
                   </div>
 
-                  <div class="action-dropdown" ngbDropdown placement="top" role="button">
-                    <div class="action-button" ngbDropdownToggle role="button">
-                      <my-global-icon class="more-icon" iconName="more-horizontal"></my-global-icon>
-                    </div>
+                  <div ngbDropdownMenu>
+                    <a *ngIf="isVideoDownloadable()" class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)">
+                      <my-global-icon iconName="download"></my-global-icon> <ng-container i18n>Download</ng-container>
+                    </a>
 
-                    <div ngbDropdownMenu>
-                      <a *ngIf="isVideoDownloadable()" class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)">
-                        <my-global-icon iconName="download"></my-global-icon> <ng-container i18n>Download</ng-container>
-                      </a>
+                    <a *ngIf="isUserLoggedIn()" class="dropdown-item" i18n-title title="Report this video" href="#" (click)="showReportModal($event)">
+                      <my-global-icon iconName="alert"></my-global-icon> <ng-container i18n>Report</ng-container>
+                    </a>
 
-                      <a *ngIf="isUserLoggedIn()" class="dropdown-item" i18n-title title="Report this video" href="#" (click)="showReportModal($event)">
-                        <my-global-icon iconName="alert"></my-global-icon> <ng-container i18n>Report</ng-container>
-                      </a>
+                    <a *ngIf="isVideoUpdatable()" class="dropdown-item" i18n-title title="Update this video" href="#" [routerLink]="[ '/videos/update', video.uuid ]">
+                      <my-global-icon iconName="edit"></my-global-icon> <ng-container i18n>Update</ng-container>
+                    </a>
 
-                      <a *ngIf="isVideoUpdatable()" class="dropdown-item" i18n-title title="Update this video" href="#" [routerLink]="[ '/videos/update', video.uuid ]">
-                        <my-global-icon iconName="edit"></my-global-icon> <ng-container i18n>Update</ng-container>
-                      </a>
+                    <a *ngIf="isVideoBlacklistable()" class="dropdown-item" i18n-title title="Blacklist this video" href="#" (click)="showBlacklistModal($event)">
+                      <my-global-icon iconName="no"></my-global-icon> <ng-container i18n>Blacklist</ng-container>
+                    </a>
 
-                      <a *ngIf="isVideoBlacklistable()" class="dropdown-item" i18n-title title="Blacklist this video" href="#" (click)="showBlacklistModal($event)">
-                        <my-global-icon iconName="no"></my-global-icon> <ng-container i18n>Blacklist</ng-container>
-                      </a>
+                    <a *ngIf="isVideoUnblacklistable()" class="dropdown-item" i18n-title title="Unblacklist this video" href="#" (click)="unblacklistVideo($event)">
+                      <my-global-icon iconName="undo"></my-global-icon> <ng-container i18n>Unblacklist</ng-container>
+                    </a>
 
-                      <a *ngIf="isVideoUnblacklistable()" class="dropdown-item" i18n-title title="Unblacklist this video" href="#" (click)="unblacklistVideo($event)">
-                        <my-global-icon iconName="undo"></my-global-icon> <ng-container i18n>Unblacklist</ng-container>
-                      </a>
-
-                      <a *ngIf="isVideoRemovable()" class="dropdown-item" i18n-title title="Delete this video" href="#" (click)="removeVideo($event)">
-                        <my-global-icon iconName="delete"></my-global-icon> <ng-container i18n>Delete</ng-container>
-                      </a>
-                    </div>
+                    <a *ngIf="isVideoRemovable()" class="dropdown-item" i18n-title title="Delete this video" href="#" (click)="removeVideo($event)">
+                      <my-global-icon iconName="delete"></my-global-icon> <ng-container i18n>Delete</ng-container>
+                    </a>
                   </div>
                 </div>
+              </div>
 
-                <div
-                  class="video-info-likes-dislikes-bar"
-                  *ngIf="video.likes !== 0 || video.dislikes !== 0"
-                  [ngbTooltip]="likesBarTooltipText"
-                  placement="bottom"
-                >
-                  <div class="likes-bar" [ngStyle]="{ 'width.%': video.likesPercent }"></div>
-                </div>
+              <div
+                class="video-info-likes-dislikes-bar"
+                *ngIf="video.likes !== 0 || video.dislikes !== 0"
+                [ngbTooltip]="likesBarTooltipText"
+                placement="bottom"
+              >
+                <div class="likes-bar" [ngStyle]="{ 'width.%': video.likesPercent }"></div>
               </div>
             </div>
+          </div>
 
 
-            <div class="pt-3 border-top video-info-channel">
-              <a [routerLink]="[ '/video-channels', video.byVideoChannel ]" i18n-title title="Go the channel page">
-                {{ video.channel.displayName }}
-
-                <img [src]="video.videoChannelAvatarUrl" alt="Video channel avatar" />
-              </a>
+          <div class="pt-3 border-top video-info-channel">
+            <a [routerLink]="[ '/video-channels', video.byVideoChannel ]" i18n-title title="Go the channel page">
+              {{ video.channel.displayName }}
 
-              <my-subscribe-button #subscribeButton [videoChannel]="video.channel" size="small"></my-subscribe-button>
-            </div>
+              <img [src]="video.videoChannelAvatarUrl" alt="Video channel avatar" />
+            </a>
 
-            <div class="video-info-by">
-              <a [routerLink]="[ '/accounts', video.byAccount ]" i18n-title title="Go to the account page">
-                <span i18n>By {{ video.byAccount }}</span>
-                <img [src]="video.accountAvatarUrl" alt="Account avatar" />
-              </a>
-            </div>
+            <my-subscribe-button #subscribeButton [videoChannel]="video.channel" size="small"></my-subscribe-button>
           </div>
 
+          <div class="video-info-by">
+            <a [routerLink]="[ '/accounts', video.byAccount ]" i18n-title title="Go to the account page">
+              <span i18n>By {{ video.byAccount }}</span>
+              <img [src]="video.accountAvatarUrl" alt="Account avatar" />
+            </a>
+          </div>
         </div>
 
-        <div class="video-info-description">
-          <div class="video-info-description-html" [innerHTML]="videoHTMLDescription"></div>
+      </div>
 
-          <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()">
-            <ng-container i18n>Show more</ng-container>
-            <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span>
-            <my-small-loader class="description-loading" [loading]="descriptionLoading"></my-small-loader>
-          </div>
+      <div class="video-info-description">
+        <div class="video-info-description-html" [innerHTML]="videoHTMLDescription"></div>
 
-          <div *ngIf="completeDescriptionShown === true" (click)="showLessDescription()" class="video-info-description-more">
-            <ng-container i18n>Show less</ng-container>
-            <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-up"></span>
-          </div>
+        <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()">
+          <ng-container i18n>Show more</ng-container>
+          <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-down"></span>
+          <my-small-loader class="description-loading" [loading]="descriptionLoading"></my-small-loader>
         </div>
 
-        <div class="video-attributes">
-          <div class="video-attribute">
-            <span i18n class="video-attribute-label">Privacy</span>
-            <span class="video-attribute-value">{{ video.privacy.label }}</span>
-          </div>
+        <div *ngIf="completeDescriptionShown === true" (click)="showLessDescription()" class="video-info-description-more">
+          <ng-container i18n>Show less</ng-container>
+          <span *ngIf="descriptionLoading === false" class="glyphicon glyphicon-menu-up"></span>
+        </div>
+      </div>
 
-          <div *ngIf="!!video.originallyPublishedAt" class="video-attribute">
-            <span i18n class="video-attribute-label">Originally published</span>
-            <span class="video-attribute-value">{{ video.originallyPublishedAt | date: 'dd MMMM yyyy' }}</span>
-          </div>
+      <div class="video-attributes">
+        <div class="video-attribute">
+          <span i18n class="video-attribute-label">Privacy</span>
+          <span class="video-attribute-value">{{ video.privacy.label }}</span>
+        </div>
 
-          <div class="video-attribute">
-            <span i18n class="video-attribute-label">Category</span>
-            <span *ngIf="!video.category.id" class="video-attribute-value">{{ video.category.label }}</span>
-            <a
-              *ngIf="video.category.id" class="video-attribute-value"
-              [routerLink]="[ '/search' ]" [queryParams]="{ categoryOneOf: [ video.category.id ] }"
-            >{{ video.category.label }}</a>
-          </div>
+        <div *ngIf="!!video.originallyPublishedAt" class="video-attribute">
+          <span i18n class="video-attribute-label">Originally published</span>
+          <span class="video-attribute-value">{{ video.originallyPublishedAt | date: 'dd MMMM yyyy' }}</span>
+        </div>
 
-          <div class="video-attribute">
-            <span i18n class="video-attribute-label">Licence</span>
-            <span *ngIf="!video.licence.id" class="video-attribute-value">{{ video.licence.label }}</span>
-            <a
-              *ngIf="video.licence.id" class="video-attribute-value"
-              [routerLink]="[ '/search' ]" [queryParams]="{ licenceOneOf: [ video.licence.id ] }"
-            >{{ video.licence.label }}</a>
-          </div>
+        <div class="video-attribute">
+          <span i18n class="video-attribute-label">Category</span>
+          <span *ngIf="!video.category.id" class="video-attribute-value">{{ video.category.label }}</span>
+          <a
+            *ngIf="video.category.id" class="video-attribute-value"
+            [routerLink]="[ '/search' ]" [queryParams]="{ categoryOneOf: [ video.category.id ] }"
+          >{{ video.category.label }}</a>
+        </div>
 
-          <div class="video-attribute">
-            <span i18n class="video-attribute-label">Language</span>
-            <span *ngIf="!video.language.id" class="video-attribute-value">{{ video.language.label }}</span>
-            <a
-              *ngIf="video.language.id" class="video-attribute-value"
-              [routerLink]="[ '/search' ]" [queryParams]="{ languageOneOf: [ video.language.id ] }"
-            >{{ video.language.label }}</a>
-          </div>
+        <div class="video-attribute">
+          <span i18n class="video-attribute-label">Licence</span>
+          <span *ngIf="!video.licence.id" class="video-attribute-value">{{ video.licence.label }}</span>
+          <a
+            *ngIf="video.licence.id" class="video-attribute-value"
+            [routerLink]="[ '/search' ]" [queryParams]="{ licenceOneOf: [ video.licence.id ] }"
+          >{{ video.licence.label }}</a>
+        </div>
 
-          <div class="video-attribute video-attribute-tags">
-            <span i18n class="video-attribute-label">Tags</span>
-            <a
-              *ngFor="let tag of getVideoTags()"
-              class="video-attribute-value" [routerLink]="[ '/search' ]" [queryParams]="{ tagsOneOf: [ tag ] }"
-            >{{ tag }}</a>
-          </div>
+        <div class="video-attribute">
+          <span i18n class="video-attribute-label">Language</span>
+          <span *ngIf="!video.language.id" class="video-attribute-value">{{ video.language.label }}</span>
+          <a
+            *ngIf="video.language.id" class="video-attribute-value"
+            [routerLink]="[ '/search' ]" [queryParams]="{ languageOneOf: [ video.language.id ] }"
+          >{{ video.language.label }}</a>
         </div>
 
-        <my-video-comments [video]="video" [user]="user"></my-video-comments>
+        <div class="video-attribute video-attribute-tags">
+          <span i18n class="video-attribute-label">Tags</span>
+          <a
+            *ngFor="let tag of getVideoTags()"
+            class="video-attribute-value" [routerLink]="[ '/search' ]" [queryParams]="{ tagsOneOf: [ tag ] }"
+          >{{ tag }}</a>
+        </div>
       </div>
 
-      <my-recommended-videos [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }" [user]="user"></my-recommended-videos>
+      <my-video-comments [video]="video" [user]="user"></my-video-comments>
     </div>
+
+    <my-recommended-videos [inputRecommendation]="{ uuid: video.uuid, tags: video.tags }" [user]="user"></my-recommended-videos>
   </div>
 
   <div class="privacy-concerns" *ngIf="hasAlreadyAcceptedPrivacyConcern === false">
index 281b9240b8a03e086bd796352b19e5f232534498..11406e88702c61ee765ce139d451442677dacccd 100644 (file)
@@ -4,9 +4,43 @@
 @import '_miniature';
 
 $other-videos-width: 260px;
+$player-factor: 1.7; // 16/9
 
-.root-row {
-  flex-direction: column;
+@function getPlayerHeight($width){
+  @return calc(#{$width} / #{$player-factor})
+}
+
+@function getPlayerWidth($height){
+  @return calc(#{$height} * #{$player-factor})
+}
+
+@mixin playlist-below-player {
+  width: 100%;
+  border-bottom: 1px solid $separator-border-color;
+}
+
+.root {
+  margin: 0 -15px;
+
+  &.theater-enabled #video-wrapper {
+    flex-direction: column;
+    justify-content: center;
+
+    #videojs-wrapper {
+      width: 100%;
+    }
+
+    /deep/ .video-js {
+      $height: calc(100vh - #{$header-height} - #{$theater-bottom-space});
+
+      height: $height;
+      width: 100%;
+    }
+
+    .playlist {
+      @include playlist-below-player;
+    }
+  }
 }
 
 .blacklisted-label {
@@ -17,7 +51,6 @@ $other-videos-width: 260px;
   background-color: #000;
   display: flex;
   justify-content: center;
-  flex-grow: 1;
 
   .remote-server-down {
     color: #fff;
@@ -93,14 +126,9 @@ $other-videos-width: 260px;
   }
 
   /deep/ .video-js {
-    width: calc(66vh * 1.77);
+    width: getPlayerWidth(66vh);
     height: 66vh;
 
-    &.vjs-theater-enabled {
-      height: calc(100vh - #{$header-height} - #{$theater-bottom-space});
-      width: 100%;
-    }
-
     // VideoJS create an inner video player
     video {
       outline: 0;
@@ -112,7 +140,7 @@ $other-videos-width: 260px;
     .remote-server-down,
     /deep/ .video-js {
       width: 100vw;
-      height: calc(100vw / 1.7); // 16/9
+      height: getPlayerHeight(100vw)
     }
   }
 }
@@ -131,6 +159,7 @@ $other-videos-width: 260px;
 }
 
 .video-bottom {
+  display: flex;
   margin-top: 40px;
 
   .video-info {
@@ -366,7 +395,7 @@ $other-videos-width: 260px;
 
   /deep/ .other-videos {
     padding-left: 15px;
-    width: $other-videos-width;
+    flex-basis: $other-videos-width;
 
     .title-page {
       margin-top: 0 !important;
@@ -374,14 +403,11 @@ $other-videos-width: 260px;
 
     .video-miniature {
       display: flex;
+      width: $other-videos-width;
       height: 100%;
       margin-bottom: 20px;
       flex-wrap: wrap;
 
-      .video-miniature-information {
-        flex-grow: 1;
-      }
-
       .video-thumbnail {
         margin-right: 10px
       }
@@ -455,12 +481,6 @@ my-video-comments {
   }
 }
 
-@media screen and (min-width: map-get($grid-breakpoints, xl)) {
-  .video-bottom .video-info {
-    max-width: calc(100% - #{$other-videos-width});
-  }
-}
-
 @media screen and (max-width: 1600px) {
   .video-bottom .video-info .video-attributes .video-attribute {
     margin-bottom: 5px;
@@ -478,6 +498,37 @@ my-video-comments {
   }
 }
 
+@media screen and (max-width: 1100px) {
+  .video-bottom {
+    flex-direction: column;
+
+    /deep/ .other-videos {
+      padding-left: 0 !important;
+
+      /deep/ .video-miniature  {
+        flex-direction: row;
+        width: auto;
+      }
+    }
+  }
+}
+
+@media screen and (max-width: 900px) {
+  #video-wrapper {
+    flex-direction: column;
+    justify-content: center;
+
+    #videojs-wrapper {
+      display: flex;
+      justify-content: center;
+    }
+
+    .playlist {
+      @include playlist-below-player;
+    }
+  }
+}
+
 @media screen and (max-width: 600px) {
   .video-bottom {
     margin: 20px 0 0 0;
@@ -495,12 +546,8 @@ my-video-comments {
     }
   }
 
-  /deep/ .other-videos {
-    padding-left: 0 !important;
-
-    /deep/ .video-miniature  {
-      flex-direction: column;
-    }
+  /deep/ .other-videos .video-miniature  {
+    flex-direction: column;
   }
 
   .privacy-concerns {
index adb728abae9db7f57519ecae890573afef3ece1d..cedbbf985536ae1abcc6d256bb2d937eb38e90bd 100644 (file)
@@ -50,6 +50,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
   player: any
   playerElement: HTMLVideoElement
+  theaterEnabled = false
   userRating: UserVideoRateType = null
   video: VideoDetails = null
   descriptionLoading = false
@@ -572,6 +573,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
     this.zone.runOutsideAngular(async () => {
       this.player = await PeertubePlayerManager.initialize(mode, options)
+      this.theaterEnabled = this.player.theaterEnabled
+
       this.player.on('customError', ({ err }: { err: any }) => this.handleError(err))
 
       this.player.on('timeupdate', () => {
@@ -589,6 +592,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
           this.zone.run(() => this.navigateToNextPlaylistVideo())
         }
       })
+
+      this.player.on('theaterChange', (_: any, enabled: boolean) => {
+        this.zone.run(() => this.theaterEnabled = enabled)
+      })
     })
 
     this.setVideoDescriptionHTML()
index 1e11a95466be63c640e6ee59b144e8fef7119463..bf383cf34827392a98f1a2a41f844e82869e7907 100644 (file)
@@ -16,8 +16,11 @@ class TheaterButton extends Button {
     const enabled = getStoredTheater()
     if (enabled === true) {
       this.player_.addClass(TheaterButton.THEATER_MODE_CLASS)
+
       this.handleTheaterChange()
     }
+
+    this.player_.theaterEnabled = enabled
   }
 
   buildCSSClass () {
@@ -25,13 +28,17 @@ class TheaterButton extends Button {
   }
 
   handleTheaterChange () {
-    if (this.isTheaterEnabled()) {
+    const theaterEnabled = this.isTheaterEnabled()
+
+    if (theaterEnabled) {
       this.controlText('Normal mode')
     } else {
       this.controlText('Theater mode')
     }
 
-    saveTheaterInStore(this.isTheaterEnabled())
+    saveTheaterInStore(theaterEnabled)
+
+    this.player_.trigger('theaterChange', theaterEnabled)
   }
 
   handleClick () {
index 6c6d208f55187acd9ea9c9b34020c096243e17c7..d573bf0245836a178e226d37284709170f753eb7 100644 (file)
@@ -216,7 +216,7 @@ describe('Test users notifications', function () {
     })
 
     it('Should send a new video notification on a remote scheduled publication', async function () {
-      this.timeout(20000)
+      this.timeout(50000)
 
       // In 2 seconds
       let updateAt = new Date(new Date().getTime() + 2000)
@@ -238,7 +238,7 @@ describe('Test users notifications', function () {
     it('Should not send a notification before the video is published', async function () {
       this.timeout(20000)
 
-      let updateAt = new Date(new Date().getTime() + 100000)
+      let updateAt = new Date(new Date().getTime() + 1000000)
 
       const data = {
         privacy: VideoPrivacy.PRIVATE,