Support playlists in share modal

This commit is contained in:
Chocobozzz 2019-12-05 10:05:00 +01:00
parent 689a4f6946
commit 3a1fed11c5
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
9 changed files with 205 additions and 142 deletions

View File

@ -0,0 +1,9 @@
<div class="input-group">
<input #urlInput (click)="urlInput.select()" type="text" class="form-control readonly" readonly [value]="value" />
<div class="input-group-append">
<button [ngxClipboard]="urlInput" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary">
<span class="glyphicon glyphicon-copy"></span>
</button>
</div>
</div>

View File

@ -0,0 +1,3 @@
input.readonly {
font-size: 15px;
}

View File

@ -0,0 +1,21 @@
import { Component, Input } from '@angular/core'
import { Notifier } from '@app/core'
import { I18n } from '@ngx-translate/i18n-polyfill'
@Component({
selector: 'my-input-readonly-copy',
templateUrl: './input-readonly-copy.component.html',
styleUrls: [ './input-readonly-copy.component.scss' ]
})
export class InputReadonlyCopyComponent {
@Input() value = ''
constructor (
private notifier: Notifier,
private i18n: I18n
) { }
activateCopiedMessage () {
this.notifier.success(this.i18n('Copied'))
}
}

View File

@ -95,6 +95,7 @@ import { ClipboardModule } from 'ngx-clipboard'
import { FollowService } from '@app/shared/instance/follow.service' import { FollowService } from '@app/shared/instance/follow.service'
import { MultiSelectModule } from 'primeng/multiselect' import { MultiSelectModule } from 'primeng/multiselect'
import { FeatureBooleanComponent } from '@app/shared/instance/feature-boolean.component' import { FeatureBooleanComponent } from '@app/shared/instance/feature-boolean.component'
import { InputReadonlyCopyComponent } from '@app/shared/forms/input-readonly-copy.component'
@NgModule({ @NgModule({
imports: [ imports: [
@ -155,6 +156,7 @@ import { FeatureBooleanComponent } from '@app/shared/instance/feature-boolean.co
ReactiveFileComponent, ReactiveFileComponent,
PeertubeCheckboxComponent, PeertubeCheckboxComponent,
TimestampInputComponent, TimestampInputComponent,
InputReadonlyCopyComponent,
SubscribeButtonComponent, SubscribeButtonComponent,
RemoteSubscribeComponent, RemoteSubscribeComponent,
@ -220,6 +222,7 @@ import { FeatureBooleanComponent } from '@app/shared/instance/feature-boolean.co
InfiniteScrollerDirective, InfiniteScrollerDirective,
TextareaAutoResizeDirective, TextareaAutoResizeDirective,
HelpComponent, HelpComponent,
InputReadonlyCopyComponent,
ReactiveFileComponent, ReactiveFileComponent,
PeertubeCheckboxComponent, PeertubeCheckboxComponent,

View File

@ -4,21 +4,36 @@
<my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="playlist" *ngIf="hasPlaylist()">
<div class="title-page title-page-single" i18n>Share the playlist</div>
<my-input-readonly-copy [value]="getPlaylistUrl()"></my-input-readonly-copy>
<div class="filters">
<div class="form-group">
<my-peertube-checkbox
inputName="includeVideoInPlaylist" [(ngModel)]="includeVideoInPlaylist"
i18n-labelText labelText="Share the playlist at this video position"
></my-peertube-checkbox>
</div>
</div>
</div>
<div class="video">
<div class="title-page title-page-single" *ngIf="hasPlaylist()" i18n>Share the video</div>
<ngb-tabset class="root-tabset bootstrap" (tabChange)="onTabChange($event)"> <ngb-tabset class="root-tabset bootstrap" (tabChange)="onTabChange($event)">
<ngb-tab i18n-title title="URL" id="url"> <ngb-tab i18n-title title="URL" id="url">
<ng-template ngbTabContent> <ng-template ngbTabContent>
<div class="tab-content"> <div class="tab-content">
<div class="input-group"> <my-input-readonly-copy [value]="getVideoUrl()"></my-input-readonly-copy>
<input #urlInput (click)="urlInput.select()" type="text" class="form-control readonly" readonly [value]="getVideoUrl()" />
<div class="input-group-append">
<button [ngxClipboard]="urlInput" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary">
<span class="glyphicon glyphicon-copy"></span>
</button>
</div>
</div>
</div> </div>
</ng-template> </ng-template>
@ -35,14 +50,7 @@
<ngb-tab i18n-title title="Embed" id="embed"> <ngb-tab i18n-title title="Embed" id="embed">
<ng-template ngbTabContent> <ng-template ngbTabContent>
<div class="tab-content"> <div class="tab-content">
<div class="input-group"> <my-input-readonly-copy [value]="getVideoIframeCode()"></my-input-readonly-copy>
<input #shareInput (click)="shareInput.select()" type="text" class="form-control readonly" readonly [value]="getVideoIframeCode()" />
<div class="input-group-append">
<button [ngxClipboard]="shareInput" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary">
<span class="glyphicon glyphicon-copy"></span>
</button>
</div>
</div>
<div i18n *ngIf="notSecure()" class="alert alert-warning"> <div i18n *ngIf="notSecure()" class="alert alert-warning">
The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites). The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites).
@ -168,6 +176,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="modal-footer inputs"> <div class="modal-footer inputs">
<span i18n class="action-button action-button-cancel" (click)="hide()">Close</span> <span i18n class="action-button action-button-cancel" (click)="hide()">Close</span>

View File

@ -1,6 +1,18 @@
@import '_mixins'; @import '_mixins';
@import '_variables'; @import '_variables';
my-input-readonly-copy {
width: 100%;
}
.title-page.title-page-single {
margin-top: 0;
}
.playlist {
margin-bottom: 50px;
}
.peertube-select-container { .peertube-select-container {
@include peertube-select-container(200px); @include peertube-select-container(200px);
} }
@ -25,10 +37,6 @@
margin-top: 20px; margin-top: 20px;
} }
input.readonly {
font-size: 15px;
}
.filters { .filters {
margin-top: 30px; margin-top: 30px;
padding-top: 30px; padding-top: 30px;

View File

@ -5,6 +5,7 @@ import { buildVideoEmbed, buildVideoLink } from '../../../../assets/player/utils
import { I18n } from '@ngx-translate/i18n-polyfill' import { I18n } from '@ngx-translate/i18n-polyfill'
import { NgbModal, NgbTabChangeEvent } from '@ng-bootstrap/ng-bootstrap' import { NgbModal, NgbTabChangeEvent } from '@ng-bootstrap/ng-bootstrap'
import { VideoCaption } from '@shared/models' import { VideoCaption } from '@shared/models'
import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
type Customizations = { type Customizations = {
startAtCheckbox: boolean startAtCheckbox: boolean
@ -34,18 +35,16 @@ export class VideoShareComponent {
@Input() video: VideoDetails = null @Input() video: VideoDetails = null
@Input() videoCaptions: VideoCaption[] = [] @Input() videoCaptions: VideoCaption[] = []
@Input() playlist: VideoPlaylist = null
activeId: 'url' | 'qrcode' | 'embed' activeId: 'url' | 'qrcode' | 'embed'
customizations: Customizations customizations: Customizations
isAdvancedCustomizationCollapsed = true isAdvancedCustomizationCollapsed = true
includeVideoInPlaylist = false
private currentVideoTimestamp: number private currentVideoTimestamp: number
constructor ( constructor (private modalService: NgbModal) { }
private modalService: NgbModal,
private notifier: Notifier,
private i18n: I18n
) { }
show (currentVideoTimestamp?: number) { show (currentVideoTimestamp?: number) {
this.currentVideoTimestamp = currentVideoTimestamp this.currentVideoTimestamp = currentVideoTimestamp
@ -86,17 +85,22 @@ export class VideoShareComponent {
} }
getVideoUrl () { getVideoUrl () {
const options = this.getOptions() const baseUrl = window.location.origin + '/videos/watch/' + this.video.uuid
const options = this.getOptions(baseUrl)
return buildVideoLink(options) return buildVideoLink(options)
} }
notSecure () { getPlaylistUrl () {
return window.location.protocol === 'http:' const base = window.location.origin + '/videos/watch/playlist/' + this.playlist.uuid
if (!this.includeVideoInPlaylist) return base
return base + '?videoId=' + this.video.uuid
} }
activateCopiedMessage () { notSecure () {
this.notifier.success(this.i18n('Copied')) return window.location.protocol === 'http:'
} }
onTabChange (event: NgbTabChangeEvent) { onTabChange (event: NgbTabChangeEvent) {
@ -107,6 +111,10 @@ export class VideoShareComponent {
return this.activeId === 'embed' return this.activeId === 'embed'
} }
hasPlaylist () {
return !!this.playlist
}
private getOptions (baseUrl?: string) { private getOptions (baseUrl?: string) {
return { return {
baseUrl, baseUrl,

View File

@ -224,5 +224,5 @@
<ng-container *ngIf="video !== null"> <ng-container *ngIf="video !== null">
<my-video-support #videoSupportModal [video]="video"></my-video-support> <my-video-support #videoSupportModal [video]="video"></my-video-support>
<my-video-share #videoShareModal [video]="video" [videoCaptions]="videoCaptions"></my-video-share> <my-video-share #videoShareModal [video]="video" [videoCaptions]="videoCaptions" [playlist]="playlist"></my-video-share>
</ng-container> </ng-container>

View File

@ -51,6 +51,8 @@ function buildVideoLink (options: {
: window.location.origin + window.location.pathname.replace('/embed/', '/watch/') : window.location.origin + window.location.pathname.replace('/embed/', '/watch/')
const params = new URLSearchParams(window.location.search) const params = new URLSearchParams(window.location.search)
// Remove this unused parameter when we are on a playlist page
params.delete('videoId')
if (options.startTime) { if (options.startTime) {
const startTimeInt = Math.floor(options.startTime) const startTimeInt = Math.floor(options.startTime)