2019-03-18 09:26:53 +00:00
< div class = "root" [ ngClass ] = " { ' theater-enabled ' : theaterEnabled } " >
2017-04-21 16:26:09 +00:00
<!-- We need the video container for videojs so we just hide it -->
2019-03-13 13:18:58 +00:00
< div id = "video-wrapper" >
2018-07-16 17:15:20 +00:00
< div * ngIf = "remoteServerDown" class = "remote-server-down" >
Sorry, but this video is not available because the remote instance is not responding.
< br / >
Please try again later.
< / div >
2019-03-13 13:18:58 +00:00
2021-02-22 09:53:25 +00:00
< div id = "videojs-wrapper" >
< img * ngIf = "playerPlaceholderImgSrc" [ src ] = " playerPlaceholderImgSrc " alt = "Placeholder image" i18n-alt >
< / div >
2019-03-13 13:18:58 +00:00
2019-05-13 09:18:24 +00:00
< my-video-watch-playlist
#videoWatchPlaylist
2020-08-19 07:21:46 +00:00
[playlist]="playlist" class="playlist"
(videoFound)="onPlaylistVideoFound($event)"
2019-05-13 09:18:24 +00:00
>< / my-video-watch-playlist >
2016-11-04 15:04:50 +00:00
< / div >
2017-04-21 16:26:09 +00:00
2019-04-11 08:21:45 +00:00
< div class = "row" >
< div i18n class = "col-md-12 alert alert-warning" * ngIf = "isVideoToImport()" >
The video is being imported, it will be available when the import is finished.
< / div >
2018-08-03 07:43:00 +00:00
2019-04-11 08:21:45 +00:00
< div i18n class = "col-md-12 alert alert-warning" * ngIf = "isVideoToTranscode()" >
The video is being transcoded, it may not work properly.
< / div >
2018-06-12 18:04:58 +00:00
2019-04-11 08:21:45 +00:00
< div i18n class = "col-md-12 alert alert-info" * ngIf = "hasVideoScheduledPublication()" >
This video will be published on {{ video.scheduledUpdate.updateAt | date: 'full' }}.
< / div >
2018-08-14 07:08:47 +00:00
2020-09-25 08:04:21 +00:00
< div i18n class = "col-md-12 alert alert-info" * ngIf = "isWaitingForLive()" >
This live has not started yet.
< / div >
< div i18n class = "col-md-12 alert alert-info" * ngIf = "isLiveEnded()" >
2020-11-13 13:36:30 +00:00
This live has ended.
2020-09-25 08:04:21 +00:00
< / div >
2019-04-11 08:21:45 +00:00
< div class = "col-md-12 alert alert-danger" * ngIf = "video?.blacklisted" >
2020-06-02 18:50:42 +00:00
< div class = "blocked-label" i18n > This video is blocked.< / div >
{{ video.blockedReason }}
2019-04-11 08:21:45 +00:00
< / div >
2018-06-15 14:52:15 +00:00
< / div >
2017-12-11 09:02:17 +00:00
<!-- Video information -->
2018-09-03 13:01:52 +00:00
< div * ngIf = "video" class = "margin-content video-bottom" >
2019-03-18 09:26:53 +00:00
< div class = "video-info" >
< div class = "video-info-first-row" >
< div >
2019-12-04 08:29:20 +00:00
< div class = "d-block d-md-none" > <!-- only shown on medium devices, has its counterpart for larger viewports below -->
2019-03-18 09:26:53 +00:00
< h1 class = "video-info-name" > {{ video.name }}< / h1 >
2019-12-04 08:29:20 +00:00
2020-11-13 13:36:30 +00:00
< div class = "video-info-date-views" >
< ng-container i18n > Published < my-date-toggle [ date ] = " video . publishedAt " > < / my-date-toggle > < / ng-container >
2020-12-09 14:00:02 +00:00
•
< my-video-views-counter [ video ] = " video " > < / my-video-views-counter >
2019-03-18 09:26:53 +00:00
< / div >
< / div >
2019-12-04 08:29:20 +00:00
< div class = "d-flex justify-content-between flex-direction-column" >
2019-03-18 09:26:53 +00:00
< div class = "d-none d-md-block" >
2018-09-19 23:08:46 +00:00
< h1 class = "video-info-name" > {{ video.name }}< / h1 >
2019-12-04 08:29:20 +00:00
< / div >
2019-03-18 09:26:53 +00:00
2019-12-04 08:29:20 +00:00
< div class = "video-info-first-row-bottom" >
2020-11-13 13:36:30 +00:00
< div class = "d-none d-md-block video-info-date-views" >
< ng-container i18n > Published < my-date-toggle [ date ] = " video . publishedAt " > < / my-date-toggle > < / ng-container >
2020-12-10 09:20:04 +00:00
•
< my-video-views-counter [ video ] = " video " > < / my-video-views-counter >
2018-08-30 09:15:22 +00:00
< / div >
2019-12-04 08:29:20 +00:00
< div class = "video-actions-rates" >
2020-10-30 10:30:21 +00:00
< ng-template # ratePopoverText >
< span [ innerHTML ] = " getRatePopoverText ( ) " > < / span >
< / ng-template >
2019-12-04 08:29:20 +00:00
< div class = "video-actions fullWidth justify-content-end" >
2020-06-11 17:19:23 +00:00
< button
2020-10-30 10:30:21 +00:00
[ngbPopover]="getRatePopoverText() & & ratePopoverText" [ngClass]="{ 'activated': userRating === 'like' }" (click)="setLike()" (keyup.enter)="setLike()"
2020-06-11 17:19:23 +00:00
class="action-button action-button-like" [attr.aria-pressed]="userRating === 'like'" [attr.aria-label]="tooltipLike"
2019-12-12 18:42:37 +00:00
[ngbTooltip]="tooltipLike"
placement="bottom auto"
2019-12-04 08:29:20 +00:00
>
< my-global-icon iconName = "like" > < / my-global-icon >
< span * ngIf = "video.likes" class = "count" > {{ video.likes }}< / span >
2020-06-11 17:19:23 +00:00
< / button >
2018-08-30 12:58:00 +00:00
2020-06-11 17:19:23 +00:00
< button
2020-10-30 10:30:21 +00:00
[ngbPopover]="getRatePopoverText() & & ratePopoverText" [ngClass]="{ 'activated': userRating === 'dislike' }" (click)="setDislike()" (keyup.enter)="setDislike()"
2020-06-11 17:19:23 +00:00
class="action-button action-button-dislike" [attr.aria-pressed]="userRating === 'dislike'" [attr.aria-label]="tooltipDislike"
2019-12-12 18:42:37 +00:00
[ngbTooltip]="tooltipDislike"
placement="bottom auto"
2019-12-04 08:29:20 +00:00
>
< my-global-icon iconName = "dislike" > < / my-global-icon >
< span * ngIf = "video.dislikes" class = "count" > {{ video.dislikes }}< / span >
2020-06-11 17:19:23 +00:00
< / button >
2019-12-13 09:35:55 +00:00
2020-06-11 17:19:23 +00:00
< button * ngIf = "video.support" ( click ) = " showSupportModal ( ) " ( keyup . enter ) = " showSupportModal ( ) " class = "action-button action-button-support" [ attr . aria-label ] = " tooltipSupport "
2019-12-12 18:42:37 +00:00
[ngbTooltip]="tooltipSupport"
placement="bottom auto"
>
2020-06-11 17:19:23 +00:00
< my-global-icon iconName = "support" aria-hidden = "true" > < / my-global-icon >
2020-02-21 15:50:12 +00:00
< span class = "icon-text" i18n > SUPPORT< / span >
2020-06-11 17:19:23 +00:00
< / button >
2019-12-13 09:35:55 +00:00
2020-06-11 17:19:23 +00:00
< button ( click ) = " showShareModal ( ) " ( keyup . enter ) = " showShareModal ( ) " class = "action-button" >
2020-06-08 17:42:51 +00:00
< my-global-icon iconName = "share" aria-hidden = "true" > < / my-global-icon >
2020-02-21 15:50:12 +00:00
< span class = "icon-text" i18n > SHARE< / span >
2020-06-11 17:19:23 +00:00
< / button >
2019-12-13 09:35:55 +00:00
2019-12-04 08:29:20 +00:00
< div
class="action-dropdown" ngbDropdown placement="top" role="button" autoClose="outside"
*ngIf="isUserLoggedIn()" (openChange)="addContent.openChange($event)"
2019-12-12 18:42:37 +00:00
[ngbTooltip]="tooltipSaveToPlaylist"
placement="bottom auto"
2019-12-04 08:29:20 +00:00
>
2020-06-11 17:19:23 +00:00
< button class = "action-button action-button-save" ngbDropdownToggle >
2020-06-08 17:42:51 +00:00
< my-global-icon iconName = "playlist-add" aria-hidden = "true" > < / my-global-icon >
2020-02-21 15:50:12 +00:00
< span class = "icon-text" i18n > SAVE< / span >
2020-06-11 17:19:23 +00:00
< / button >
2019-12-13 09:35:55 +00:00
2019-12-04 08:29:20 +00:00
< div ngbDropdownMenu >
< my-video-add-to-playlist # addContent [ video ] = " video " > < / my-video-add-to-playlist >
< / div >
< / div >
2019-12-13 09:35:55 +00:00
2020-09-25 08:04:21 +00:00
< ng-container * ngIf = "!isUserLoggedIn() && !isLive()" >
2020-08-03 19:06:45 +00:00
< button
*ngIf="isVideoDownloadable()" class="action-button action-button-save"
(click)="showDownloadModal()" (keydown.enter)="showDownloadModal()"
>
< my-global-icon iconName = "download" aria-hidden = "true" > < / my-global-icon >
< span class = "icon-text d-none d-sm-inline" i18n > DOWNLOAD< / span >
< / button >
2020-08-07 14:29:30 +00:00
2020-08-03 19:06:45 +00:00
< my-video-download # videoDownloadModal > < / my-video-download >
< / ng-container >
2020-08-07 14:29:30 +00:00
2020-08-03 19:06:45 +00:00
< ng-container * ngIf = "isUserLoggedIn()" >
< my-video-actions-dropdown
placement="bottom auto" buttonDirection="horizontal" [buttonStyled]="true" [video]="video" [videoCaptions]="videoCaptions"
2021-04-08 11:37:57 +00:00
[displayOptions]="videoActionsOptions" (videoRemoved)="onVideoRemoved()"
2020-08-03 19:06:45 +00:00
>< / my-video-actions-dropdown >
< / ng-container >
2019-03-18 09:26:53 +00:00
< / div >
2019-12-13 09:35:55 +00:00
2019-12-20 16:49:57 +00:00
< div class = "video-info-likes-dislikes-bar-outer-container" >
2019-12-15 23:13:31 +00:00
< div
2019-12-20 16:49:57 +00:00
class="video-info-likes-dislikes-bar-inner-container"
2019-12-15 23:13:31 +00:00
*ngIf="video.likes !== 0 || video.dislikes !== 0"
[ngbTooltip]="likesBarTooltipText"
placement="bottom"
>
< div
class="video-info-likes-dislikes-bar"
>
2019-12-24 13:04:37 +00:00
< div class = "likes-bar" [ ngClass ] = " { ' liked ' : userRating ! = = ' none ' } " [ ngStyle ] = " { ' width . % ' : video . likesPercent } " > < / div >
2019-12-15 23:13:31 +00:00
< / div >
< / div >
2019-03-18 09:26:53 +00:00
< / div >
< / div >
2018-08-30 12:58:00 +00:00
2019-03-18 09:26:53 +00:00
< 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 >
2018-08-30 09:15:22 +00:00
< / div >
2018-01-31 10:38:05 +00:00
< / div >
2019-03-18 09:26:53 +00:00
< / div >
2017-12-06 17:04:40 +00:00
2018-02-20 15:13:05 +00:00
2019-12-15 20:27:37 +00:00
< div class = "pt-3 border-top video-info-channel d-flex" >
< div class = "video-info-channel-left d-flex" >
2020-11-25 10:44:31 +00:00
< my-video-avatar-channel [ video ] = " video " [ genericChannel ] = " isChannelDisplayNameGeneric ( ) " > < / my-video-avatar-channel >
2020-01-10 09:30:08 +00:00
2019-12-15 20:27:37 +00:00
< div class = "video-info-channel-left-links ml-1" >
2020-07-24 06:49:59 +00:00
< ng-container * ngIf = "!isChannelDisplayNameGeneric()" >
< a [ routerLink ] = " [ ' / video-channels ' , video . byVideoChannel ] " i18n-title title = "Channel page" >
{{ video.channel.displayName }}
< / a >
< a [ routerLink ] = " [ ' / accounts ' , video . byAccount ] " i18n-title title = "Account page" >
< span i18n > By {{ video.byAccount }}< / span >
< / a >
< / ng-container >
< ng-container * ngIf = "isChannelDisplayNameGeneric()" >
< a [ routerLink ] = " [ ' / accounts ' , video . byAccount ] " class = "single-link" i18n-title title = "Account page" >
< span i18n > {{ video.byAccount }}< / span >
< / a >
< / ng-container >
2019-12-15 20:27:37 +00:00
< / div >
< / div >
2018-08-09 12:55:06 +00:00
2020-01-07 22:51:14 +00:00
< my-subscribe-button # subscribeButton [ videoChannels ] = " [ video . channel ] " size = "small" > < / my-subscribe-button >
2018-08-30 09:15:22 +00:00
< / div >
< / div >
2018-08-13 14:57:13 +00:00
2019-03-18 09:26:53 +00:00
< / div >
2018-08-14 07:08:47 +00:00
2019-12-15 20:27:37 +00:00
< div class = "video-info-description" >
2019-12-16 15:21:42 +00:00
< div
class="video-info-description-html"
2019-12-17 08:59:26 +00:00
[innerHTML]="videoHTMLDescription"
2019-12-16 15:21:42 +00:00
(timestampClicked)="handleTimestampClicked($event)"
timestampRouteTransformer
>< / div >
2017-03-27 19:11:37 +00:00
2019-03-18 09:26:53 +00:00
< 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 >
2018-01-31 10:38:05 +00:00
< / div >
2017-04-21 14:40:45 +00:00
2019-03-18 09:26:53 +00:00
< 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 >
2019-01-12 13:45:39 +00:00
2019-12-15 20:27:37 +00:00
< div class = "video-attributes mb-3" >
2019-03-18 09:26:53 +00:00
< div class = "video-attribute" >
< span i18n class = "video-attribute-label" > Privacy< / span >
< span class = "video-attribute-value" > {{ video.privacy.label }}< / span >
< / div >
2017-10-30 19:26:06 +00:00
2020-01-29 12:59:40 +00:00
< div * ngIf = "video.isLocal === false" class = "video-attribute" >
< span i18n class = "video-attribute-label" > Origin instance< / span >
< a class = "video-attribute-value" target = "_blank" rel = "noopener noreferrer" [ href ] = " video . originInstanceUrl " > {{ video.originInstanceHost }}< / a >
< / div >
2019-03-18 09:26:53 +00:00
< 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 >
2017-10-30 19:26:06 +00:00
2019-03-18 09:26:53 +00:00
< 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 >
2017-04-07 12:57:05 +00:00
2019-03-18 09:26:53 +00:00
< 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 >
2017-10-31 10:52:52 +00:00
2019-03-18 09:26:53 +00:00
< 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 >
2017-12-11 09:02:17 +00:00
< / div >
2017-04-21 14:40:45 +00:00
2019-03-18 09:26:53 +00:00
< 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 >
2020-01-07 13:38:01 +00:00
2020-10-27 07:45:30 +00:00
< div class = "video-attribute" * ngIf = "!video.isLive" >
2020-01-07 13:38:01 +00:00
< span i18n class = "video-attribute-label" > Duration< / span >
2020-10-26 15:44:23 +00:00
< span class = "video-attribute-value" > {{ video.duration | myDurationFormatter }}< / span >
2020-01-10 09:30:08 +00:00
< / div >
2018-09-04 16:35:39 +00:00
< / div >
2019-12-16 15:21:42 +00:00
< my-video-comments
class="border-top"
[video]="video"
[user]="user"
(timestampClicked)="handleTimestampClicked($event)"
>< / my-video-comments >
2016-11-04 15:04:50 +00:00
< / div >
2019-03-18 09:26:53 +00:00
2019-09-24 06:48:01 +00:00
< my-recommended-videos
2021-04-01 09:10:27 +00:00
[displayAsRow]="displayOtherVideosAsRow()"
2020-06-16 09:00:35 +00:00
[inputRecommendation]="{ uuid: video.uuid, tags: video.tags }"
[playlist]="playlist"
(gotRecommendations)="onRecommendations($event)"
2019-09-24 06:48:01 +00:00
>< / my-recommended-videos >
2016-11-04 15:04:50 +00:00
< / div >
2018-09-05 09:20:44 +00:00
2019-04-11 08:21:45 +00:00
< div class = "row privacy-concerns" * ngIf = "hasAlreadyAcceptedPrivacyConcern === false" >
2018-03-07 16:35:30 +00:00
< div class = "privacy-concerns-text" >
2020-03-05 09:01:57 +00:00
< span class = "mr-2" >
< strong i18n > Friendly Reminder: < / strong >
< ng-container i18n >
the sharing system used for this video implies that some technical information about your system (such as a public IP address) can be sent to other peers.
< / ng-container >
2020-02-28 12:52:21 +00:00
< / span >
2020-03-23 22:43:51 +00:00
< a i18n i18n-title title = "Get more information" target = "_blank" rel = "noopener noreferrer" href = "/about/peertube#privacy" > More information< / a >
2018-03-07 16:35:30 +00:00
< / div >
2020-02-28 12:52:21 +00:00
< div i18n class = "privacy-concerns-button privacy-concerns-okay" ( click ) = " acceptedPrivacyConcern ( ) " >
2020-03-05 09:01:57 +00:00
OK
2018-03-07 16:35:30 +00:00
< / div >
< / div >
2019-05-13 12:26:00 +00:00
< / div >
2016-11-04 15:04:50 +00:00
2019-11-21 16:01:24 +00:00
< ng-container * ngIf = "video !== null" >
2021-03-29 13:56:01 +00:00
< my-support-modal # supportModal [ video ] = " video " > < / my-support-modal >
2019-12-05 09:05:00 +00:00
< my-video-share # videoShareModal [ video ] = " video " [ videoCaptions ] = " videoCaptions " [ playlist ] = " playlist " > < / my-video-share >
2019-11-21 16:01:24 +00:00
< / ng-container >