diff options
author | Chocobozzz <me@florianbigard.com> | 2019-12-05 10:05:00 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2019-12-05 10:05:00 +0100 |
commit | 3a1fed11c52705002cbf2a17294509fb5a89237c (patch) | |
tree | 9140310efbd9ba7f1b7254e3fd580e84322792a7 | |
parent | 689a4f6946e47ddf4871fd43bbd1284a4dc79e68 (diff) | |
download | PeerTube-3a1fed11c52705002cbf2a17294509fb5a89237c.tar.gz PeerTube-3a1fed11c52705002cbf2a17294509fb5a89237c.tar.zst PeerTube-3a1fed11c52705002cbf2a17294509fb5a89237c.zip |
Support playlists in share modal
9 files changed, 204 insertions, 141 deletions
diff --git a/client/src/app/shared/forms/input-readonly-copy.component.html b/client/src/app/shared/forms/input-readonly-copy.component.html new file mode 100644 index 000000000..27571b63f --- /dev/null +++ b/client/src/app/shared/forms/input-readonly-copy.component.html | |||
@@ -0,0 +1,9 @@ | |||
1 | <div class="input-group"> | ||
2 | <input #urlInput (click)="urlInput.select()" type="text" class="form-control readonly" readonly [value]="value" /> | ||
3 | |||
4 | <div class="input-group-append"> | ||
5 | <button [ngxClipboard]="urlInput" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary"> | ||
6 | <span class="glyphicon glyphicon-copy"></span> | ||
7 | </button> | ||
8 | </div> | ||
9 | </div> | ||
diff --git a/client/src/app/shared/forms/input-readonly-copy.component.scss b/client/src/app/shared/forms/input-readonly-copy.component.scss new file mode 100644 index 000000000..8dc4f113c --- /dev/null +++ b/client/src/app/shared/forms/input-readonly-copy.component.scss | |||
@@ -0,0 +1,3 @@ | |||
1 | input.readonly { | ||
2 | font-size: 15px; | ||
3 | } | ||
diff --git a/client/src/app/shared/forms/input-readonly-copy.component.ts b/client/src/app/shared/forms/input-readonly-copy.component.ts new file mode 100644 index 000000000..7528fb7a1 --- /dev/null +++ b/client/src/app/shared/forms/input-readonly-copy.component.ts | |||
@@ -0,0 +1,21 @@ | |||
1 | import { Component, Input } from '@angular/core' | ||
2 | import { Notifier } from '@app/core' | ||
3 | import { I18n } from '@ngx-translate/i18n-polyfill' | ||
4 | |||
5 | @Component({ | ||
6 | selector: 'my-input-readonly-copy', | ||
7 | templateUrl: './input-readonly-copy.component.html', | ||
8 | styleUrls: [ './input-readonly-copy.component.scss' ] | ||
9 | }) | ||
10 | export class InputReadonlyCopyComponent { | ||
11 | @Input() value = '' | ||
12 | |||
13 | constructor ( | ||
14 | private notifier: Notifier, | ||
15 | private i18n: I18n | ||
16 | ) { } | ||
17 | |||
18 | activateCopiedMessage () { | ||
19 | this.notifier.success(this.i18n('Copied')) | ||
20 | } | ||
21 | } | ||
diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 8cbb15bfa..29ddf7b81 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts | |||
@@ -95,6 +95,7 @@ import { ClipboardModule } from 'ngx-clipboard' | |||
95 | import { FollowService } from '@app/shared/instance/follow.service' | 95 | import { FollowService } from '@app/shared/instance/follow.service' |
96 | import { MultiSelectModule } from 'primeng/multiselect' | 96 | import { MultiSelectModule } from 'primeng/multiselect' |
97 | import { FeatureBooleanComponent } from '@app/shared/instance/feature-boolean.component' | 97 | import { FeatureBooleanComponent } from '@app/shared/instance/feature-boolean.component' |
98 | import { InputReadonlyCopyComponent } from '@app/shared/forms/input-readonly-copy.component' | ||
98 | 99 | ||
99 | @NgModule({ | 100 | @NgModule({ |
100 | imports: [ | 101 | imports: [ |
@@ -155,6 +156,7 @@ import { FeatureBooleanComponent } from '@app/shared/instance/feature-boolean.co | |||
155 | ReactiveFileComponent, | 156 | ReactiveFileComponent, |
156 | PeertubeCheckboxComponent, | 157 | PeertubeCheckboxComponent, |
157 | TimestampInputComponent, | 158 | TimestampInputComponent, |
159 | InputReadonlyCopyComponent, | ||
158 | 160 | ||
159 | SubscribeButtonComponent, | 161 | SubscribeButtonComponent, |
160 | RemoteSubscribeComponent, | 162 | RemoteSubscribeComponent, |
@@ -220,6 +222,7 @@ import { FeatureBooleanComponent } from '@app/shared/instance/feature-boolean.co | |||
220 | InfiniteScrollerDirective, | 222 | InfiniteScrollerDirective, |
221 | TextareaAutoResizeDirective, | 223 | TextareaAutoResizeDirective, |
222 | HelpComponent, | 224 | HelpComponent, |
225 | InputReadonlyCopyComponent, | ||
223 | 226 | ||
224 | ReactiveFileComponent, | 227 | ReactiveFileComponent, |
225 | PeertubeCheckboxComponent, | 228 | PeertubeCheckboxComponent, |
diff --git a/client/src/app/videos/+video-watch/modal/video-share.component.html b/client/src/app/videos/+video-watch/modal/video-share.component.html index e0be9f265..549a9f30e 100644 --- a/client/src/app/videos/+video-watch/modal/video-share.component.html +++ b/client/src/app/videos/+video-watch/modal/video-share.component.html | |||
@@ -4,167 +4,176 @@ | |||
4 | <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> | 4 | <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> |
5 | </div> | 5 | </div> |
6 | 6 | ||
7 | |||
7 | <div class="modal-body"> | 8 | <div class="modal-body"> |
8 | <ngb-tabset class="root-tabset bootstrap" (tabChange)="onTabChange($event)"> | 9 | <div class="playlist" *ngIf="hasPlaylist()"> |
9 | 10 | <div class="title-page title-page-single" i18n>Share the playlist</div> | |
10 | <ngb-tab i18n-title title="URL" id="url"> | ||
11 | <ng-template ngbTabContent> | ||
12 | |||
13 | <div class="tab-content"> | ||
14 | <div class="input-group"> | ||
15 | <input #urlInput (click)="urlInput.select()" type="text" class="form-control readonly" readonly [value]="getVideoUrl()" /> | ||
16 | <div class="input-group-append"> | ||
17 | <button [ngxClipboard]="urlInput" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary"> | ||
18 | <span class="glyphicon glyphicon-copy"></span> | ||
19 | </button> | ||
20 | </div> | ||
21 | </div> | ||
22 | </div> | ||
23 | 11 | ||
24 | </ng-template> | 12 | <my-input-readonly-copy [value]="getPlaylistUrl()"></my-input-readonly-copy> |
25 | </ngb-tab> | ||
26 | 13 | ||
27 | <ngb-tab i18n-title title="QR-Code" id="qrcode"> | 14 | <div class="filters"> |
28 | <ng-template ngbTabContent> | ||
29 | <div class="tab-content"> | ||
30 | <qrcode [qrdata]="getVideoUrl()" size="256" level="Q"></qrcode> | ||
31 | </div> | ||
32 | </ng-template> | ||
33 | </ngb-tab> | ||
34 | |||
35 | <ngb-tab i18n-title title="Embed" id="embed"> | ||
36 | <ng-template ngbTabContent> | ||
37 | <div class="tab-content"> | ||
38 | <div class="input-group"> | ||
39 | <input #shareInput (click)="shareInput.select()" type="text" class="form-control readonly" readonly [value]="getVideoIframeCode()" /> | ||
40 | <div class="input-group-append"> | ||
41 | <button [ngxClipboard]="shareInput" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary"> | ||
42 | <span class="glyphicon glyphicon-copy"></span> | ||
43 | </button> | ||
44 | </div> | ||
45 | </div> | ||
46 | 15 | ||
47 | <div i18n *ngIf="notSecure()" class="alert alert-warning"> | 16 | <div class="form-group"> |
48 | 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). | ||
49 | </div> | ||
50 | </div> | ||
51 | </ng-template> | ||
52 | </ngb-tab> | ||
53 | |||
54 | </ngb-tabset> | ||
55 | |||
56 | <div class="filters"> | ||
57 | <div> | ||
58 | <div class="form-group start-at"> | ||
59 | <my-peertube-checkbox | 17 | <my-peertube-checkbox |
60 | inputName="startAt" [(ngModel)]="customizations.startAtCheckbox" | 18 | inputName="includeVideoInPlaylist" [(ngModel)]="includeVideoInPlaylist" |
61 | i18n-labelText labelText="Start at" | 19 | i18n-labelText labelText="Share the playlist at this video position" |
62 | ></my-peertube-checkbox> | 20 | ></my-peertube-checkbox> |
63 | |||
64 | <my-timestamp-input | ||
65 | [timestamp]="customizations.startAt" | ||
66 | [maxTimestamp]="video.duration" | ||
67 | [disabled]="!customizations.startAtCheckbox" | ||
68 | [(ngModel)]="customizations.startAt" | ||
69 | > | ||
70 | </my-timestamp-input> | ||
71 | </div> | 21 | </div> |
72 | 22 | ||
73 | <div *ngIf="videoCaptions.length !== 0" class="form-group video-caption-block"> | ||
74 | <my-peertube-checkbox | ||
75 | inputName="subtitleCheckbox" [(ngModel)]="customizations.subtitleCheckbox" | ||
76 | i18n-labelText labelText="Auto select subtitle" | ||
77 | ></my-peertube-checkbox> | ||
78 | |||
79 | <div class="peertube-select-container" [ngClass]="{ disabled: !customizations.subtitleCheckbox }"> | ||
80 | <select [(ngModel)]="customizations.subtitle" [disabled]="!customizations.subtitleCheckbox"> | ||
81 | <option *ngFor="let caption of videoCaptions" [value]="caption.language.id">{{ caption.language.label }}</option> | ||
82 | </select> | ||
83 | </div> | ||
84 | </div> | ||
85 | </div> | 23 | </div> |
24 | </div> | ||
86 | 25 | ||
87 | <div (click)="isAdvancedCustomizationCollapsed = !isAdvancedCustomizationCollapsed" role="button" class="advanced-filters-button" | ||
88 | [attr.aria-expanded]="!isAdvancedCustomizationCollapsed" aria-controls="collapseBasic"> | ||
89 | 26 | ||
90 | <ng-container *ngIf="isAdvancedCustomizationCollapsed"> | 27 | <div class="video"> |
91 | <span class="glyphicon glyphicon-menu-down"></span> | 28 | <div class="title-page title-page-single" *ngIf="hasPlaylist()" i18n>Share the video</div> |
92 | 29 | ||
93 | <ng-container i18n> | 30 | <ngb-tabset class="root-tabset bootstrap" (tabChange)="onTabChange($event)"> |
94 | More customization | ||
95 | </ng-container> | ||
96 | </ng-container> | ||
97 | 31 | ||
98 | <ng-container *ngIf="!isAdvancedCustomizationCollapsed"> | 32 | <ngb-tab i18n-title title="URL" id="url"> |
99 | <span class="glyphicon glyphicon-menu-up"></span> | 33 | <ng-template ngbTabContent> |
100 | 34 | ||
101 | <ng-container i18n> | 35 | <div class="tab-content"> |
102 | Less customization | 36 | <my-input-readonly-copy [value]="getVideoUrl()"></my-input-readonly-copy> |
103 | </ng-container> | 37 | </div> |
104 | </ng-container> | 38 | |
105 | </div> | 39 | </ng-template> |
40 | </ngb-tab> | ||
41 | |||
42 | <ngb-tab i18n-title title="QR-Code" id="qrcode"> | ||
43 | <ng-template ngbTabContent> | ||
44 | <div class="tab-content"> | ||
45 | <qrcode [qrdata]="getVideoUrl()" size="256" level="Q"></qrcode> | ||
46 | </div> | ||
47 | </ng-template> | ||
48 | </ngb-tab> | ||
106 | 49 | ||
107 | <div class="advanced-filters collapse-transition" [ngbCollapse]="isAdvancedCustomizationCollapsed"> | 50 | <ngb-tab i18n-title title="Embed" id="embed"> |
51 | <ng-template ngbTabContent> | ||
52 | <div class="tab-content"> | ||
53 | <my-input-readonly-copy [value]="getVideoIframeCode()"></my-input-readonly-copy> | ||
54 | |||
55 | <div i18n *ngIf="notSecure()" class="alert alert-warning"> | ||
56 | 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). | ||
57 | </div> | ||
58 | </div> | ||
59 | </ng-template> | ||
60 | </ngb-tab> | ||
61 | |||
62 | </ngb-tabset> | ||
63 | |||
64 | <div class="filters"> | ||
108 | <div> | 65 | <div> |
109 | <div class="form-group stop-at"> | 66 | <div class="form-group start-at"> |
110 | <my-peertube-checkbox | 67 | <my-peertube-checkbox |
111 | inputName="stopAt" [(ngModel)]="customizations.stopAtCheckbox" | 68 | inputName="startAt" [(ngModel)]="customizations.startAtCheckbox" |
112 | i18n-labelText labelText="Stop at" | 69 | i18n-labelText labelText="Start at" |
113 | ></my-peertube-checkbox> | 70 | ></my-peertube-checkbox> |
114 | 71 | ||
115 | <my-timestamp-input | 72 | <my-timestamp-input |
116 | [timestamp]="customizations.stopAt" | 73 | [timestamp]="customizations.startAt" |
117 | [maxTimestamp]="video.duration" | 74 | [maxTimestamp]="video.duration" |
118 | [disabled]="!customizations.stopAtCheckbox" | 75 | [disabled]="!customizations.startAtCheckbox" |
119 | [(ngModel)]="customizations.stopAt" | 76 | [(ngModel)]="customizations.startAt" |
120 | > | 77 | > |
121 | </my-timestamp-input> | 78 | </my-timestamp-input> |
122 | </div> | 79 | </div> |
123 | 80 | ||
124 | <div class="form-group"> | 81 | <div *ngIf="videoCaptions.length !== 0" class="form-group video-caption-block"> |
125 | <my-peertube-checkbox | 82 | <my-peertube-checkbox |
126 | inputName="autoplay" [(ngModel)]="customizations.autoplay" | 83 | inputName="subtitleCheckbox" [(ngModel)]="customizations.subtitleCheckbox" |
127 | i18n-labelText labelText="Autoplay" | 84 | i18n-labelText labelText="Auto select subtitle" |
128 | ></my-peertube-checkbox> | 85 | ></my-peertube-checkbox> |
129 | </div> | ||
130 | 86 | ||
131 | <div class="form-group"> | 87 | <div class="peertube-select-container" [ngClass]="{ disabled: !customizations.subtitleCheckbox }"> |
132 | <my-peertube-checkbox | 88 | <select [(ngModel)]="customizations.subtitle" [disabled]="!customizations.subtitleCheckbox"> |
133 | inputName="muted" [(ngModel)]="customizations.muted" | 89 | <option *ngFor="let caption of videoCaptions" [value]="caption.language.id">{{ caption.language.label }}</option> |
134 | i18n-labelText labelText="Muted" | 90 | </select> |
135 | ></my-peertube-checkbox> | 91 | </div> |
136 | </div> | 92 | </div> |
93 | </div> | ||
137 | 94 | ||
138 | <div class="form-group"> | 95 | <div (click)="isAdvancedCustomizationCollapsed = !isAdvancedCustomizationCollapsed" role="button" class="advanced-filters-button" |
139 | <my-peertube-checkbox | 96 | [attr.aria-expanded]="!isAdvancedCustomizationCollapsed" aria-controls="collapseBasic"> |
140 | inputName="loop" [(ngModel)]="customizations.loop" | 97 | |
141 | i18n-labelText labelText="Loop" | 98 | <ng-container *ngIf="isAdvancedCustomizationCollapsed"> |
142 | ></my-peertube-checkbox> | 99 | <span class="glyphicon glyphicon-menu-down"></span> |
143 | </div> | 100 | |
101 | <ng-container i18n> | ||
102 | More customization | ||
103 | </ng-container> | ||
104 | </ng-container> | ||
105 | |||
106 | <ng-container *ngIf="!isAdvancedCustomizationCollapsed"> | ||
107 | <span class="glyphicon glyphicon-menu-up"></span> | ||
108 | |||
109 | <ng-container i18n> | ||
110 | Less customization | ||
111 | </ng-container> | ||
112 | </ng-container> | ||
144 | </div> | 113 | </div> |
145 | 114 | ||
146 | <ng-container *ngIf="isInEmbedTab()"> | 115 | <div class="advanced-filters collapse-transition" [ngbCollapse]="isAdvancedCustomizationCollapsed"> |
147 | <div class="form-group"> | 116 | <div> |
148 | <my-peertube-checkbox | 117 | <div class="form-group stop-at"> |
149 | inputName="title" [(ngModel)]="customizations.title" | 118 | <my-peertube-checkbox |
150 | i18n-labelText labelText="Display video title" | 119 | inputName="stopAt" [(ngModel)]="customizations.stopAtCheckbox" |
151 | ></my-peertube-checkbox> | 120 | i18n-labelText labelText="Stop at" |
152 | </div> | 121 | ></my-peertube-checkbox> |
122 | |||
123 | <my-timestamp-input | ||
124 | [timestamp]="customizations.stopAt" | ||
125 | [maxTimestamp]="video.duration" | ||
126 | [disabled]="!customizations.stopAtCheckbox" | ||
127 | [(ngModel)]="customizations.stopAt" | ||
128 | > | ||
129 | </my-timestamp-input> | ||
130 | </div> | ||
153 | 131 | ||
154 | <div class="form-group"> | 132 | <div class="form-group"> |
155 | <my-peertube-checkbox | 133 | <my-peertube-checkbox |
156 | inputName="warningTitle" [(ngModel)]="customizations.warningTitle" | 134 | inputName="autoplay" [(ngModel)]="customizations.autoplay" |
157 | i18n-labelText labelText="Display privacy warning" | 135 | i18n-labelText labelText="Autoplay" |
158 | ></my-peertube-checkbox> | 136 | ></my-peertube-checkbox> |
159 | </div> | 137 | </div> |
160 | 138 | ||
161 | <div class="form-group"> | 139 | <div class="form-group"> |
162 | <my-peertube-checkbox | 140 | <my-peertube-checkbox |
163 | inputName="controls" [(ngModel)]="customizations.controls" | 141 | inputName="muted" [(ngModel)]="customizations.muted" |
164 | i18n-labelText labelText="Display player controls" | 142 | i18n-labelText labelText="Muted" |
165 | ></my-peertube-checkbox> | 143 | ></my-peertube-checkbox> |
144 | </div> | ||
145 | |||
146 | <div class="form-group"> | ||
147 | <my-peertube-checkbox | ||
148 | inputName="loop" [(ngModel)]="customizations.loop" | ||
149 | i18n-labelText labelText="Loop" | ||
150 | ></my-peertube-checkbox> | ||
151 | </div> | ||
166 | </div> | 152 | </div> |
167 | </ng-container> | 153 | |
154 | <ng-container *ngIf="isInEmbedTab()"> | ||
155 | <div class="form-group"> | ||
156 | <my-peertube-checkbox | ||
157 | inputName="title" [(ngModel)]="customizations.title" | ||
158 | i18n-labelText labelText="Display video title" | ||
159 | ></my-peertube-checkbox> | ||
160 | </div> | ||
161 | |||
162 | <div class="form-group"> | ||
163 | <my-peertube-checkbox | ||
164 | inputName="warningTitle" [(ngModel)]="customizations.warningTitle" | ||
165 | i18n-labelText labelText="Display privacy warning" | ||
166 | ></my-peertube-checkbox> | ||
167 | </div> | ||
168 | |||
169 | <div class="form-group"> | ||
170 | <my-peertube-checkbox | ||
171 | inputName="controls" [(ngModel)]="customizations.controls" | ||
172 | i18n-labelText labelText="Display player controls" | ||
173 | ></my-peertube-checkbox> | ||
174 | </div> | ||
175 | </ng-container> | ||
176 | </div> | ||
168 | </div> | 177 | </div> |
169 | </div> | 178 | </div> |
170 | </div> | 179 | </div> |
diff --git a/client/src/app/videos/+video-watch/modal/video-share.component.scss b/client/src/app/videos/+video-watch/modal/video-share.component.scss index c48abf9e0..8b5952da6 100644 --- a/client/src/app/videos/+video-watch/modal/video-share.component.scss +++ b/client/src/app/videos/+video-watch/modal/video-share.component.scss | |||
@@ -1,6 +1,18 @@ | |||
1 | @import '_mixins'; | 1 | @import '_mixins'; |
2 | @import '_variables'; | 2 | @import '_variables'; |
3 | 3 | ||
4 | my-input-readonly-copy { | ||
5 | width: 100%; | ||
6 | } | ||
7 | |||
8 | .title-page.title-page-single { | ||
9 | margin-top: 0; | ||
10 | } | ||
11 | |||
12 | .playlist { | ||
13 | margin-bottom: 50px; | ||
14 | } | ||
15 | |||
4 | .peertube-select-container { | 16 | .peertube-select-container { |
5 | @include peertube-select-container(200px); | 17 | @include peertube-select-container(200px); |
6 | } | 18 | } |
@@ -25,10 +37,6 @@ | |||
25 | margin-top: 20px; | 37 | margin-top: 20px; |
26 | } | 38 | } |
27 | 39 | ||
28 | input.readonly { | ||
29 | font-size: 15px; | ||
30 | } | ||
31 | |||
32 | .filters { | 40 | .filters { |
33 | margin-top: 30px; | 41 | margin-top: 30px; |
34 | padding-top: 30px; | 42 | padding-top: 30px; |
diff --git a/client/src/app/videos/+video-watch/modal/video-share.component.ts b/client/src/app/videos/+video-watch/modal/video-share.component.ts index f45afccfb..a9a7a0eab 100644 --- a/client/src/app/videos/+video-watch/modal/video-share.component.ts +++ b/client/src/app/videos/+video-watch/modal/video-share.component.ts | |||
@@ -5,6 +5,7 @@ import { buildVideoEmbed, buildVideoLink } from '../../../../assets/player/utils | |||
5 | import { I18n } from '@ngx-translate/i18n-polyfill' | 5 | import { I18n } from '@ngx-translate/i18n-polyfill' |
6 | import { NgbModal, NgbTabChangeEvent } from '@ng-bootstrap/ng-bootstrap' | 6 | import { NgbModal, NgbTabChangeEvent } from '@ng-bootstrap/ng-bootstrap' |
7 | import { VideoCaption } from '@shared/models' | 7 | import { VideoCaption } from '@shared/models' |
8 | import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' | ||
8 | 9 | ||
9 | type Customizations = { | 10 | type Customizations = { |
10 | startAtCheckbox: boolean | 11 | startAtCheckbox: boolean |
@@ -34,18 +35,16 @@ export class VideoShareComponent { | |||
34 | 35 | ||
35 | @Input() video: VideoDetails = null | 36 | @Input() video: VideoDetails = null |
36 | @Input() videoCaptions: VideoCaption[] = [] | 37 | @Input() videoCaptions: VideoCaption[] = [] |
38 | @Input() playlist: VideoPlaylist = null | ||
37 | 39 | ||
38 | activeId: 'url' | 'qrcode' | 'embed' | 40 | activeId: 'url' | 'qrcode' | 'embed' |
39 | customizations: Customizations | 41 | customizations: Customizations |
40 | isAdvancedCustomizationCollapsed = true | 42 | isAdvancedCustomizationCollapsed = true |
43 | includeVideoInPlaylist = false | ||
41 | 44 | ||
42 | private currentVideoTimestamp: number | 45 | private currentVideoTimestamp: number |
43 | 46 | ||
44 | constructor ( | 47 | constructor (private modalService: NgbModal) { } |
45 | private modalService: NgbModal, | ||
46 | private notifier: Notifier, | ||
47 | private i18n: I18n | ||
48 | ) { } | ||
49 | 48 | ||
50 | show (currentVideoTimestamp?: number) { | 49 | show (currentVideoTimestamp?: number) { |
51 | this.currentVideoTimestamp = currentVideoTimestamp | 50 | this.currentVideoTimestamp = currentVideoTimestamp |
@@ -86,17 +85,22 @@ export class VideoShareComponent { | |||
86 | } | 85 | } |
87 | 86 | ||
88 | getVideoUrl () { | 87 | getVideoUrl () { |
89 | const options = this.getOptions() | 88 | const baseUrl = window.location.origin + '/videos/watch/' + this.video.uuid |
89 | const options = this.getOptions(baseUrl) | ||
90 | 90 | ||
91 | return buildVideoLink(options) | 91 | return buildVideoLink(options) |
92 | } | 92 | } |
93 | 93 | ||
94 | notSecure () { | 94 | getPlaylistUrl () { |
95 | return window.location.protocol === 'http:' | 95 | const base = window.location.origin + '/videos/watch/playlist/' + this.playlist.uuid |
96 | |||
97 | if (!this.includeVideoInPlaylist) return base | ||
98 | |||
99 | return base + '?videoId=' + this.video.uuid | ||
96 | } | 100 | } |
97 | 101 | ||
98 | activateCopiedMessage () { | 102 | notSecure () { |
99 | this.notifier.success(this.i18n('Copied')) | 103 | return window.location.protocol === 'http:' |
100 | } | 104 | } |
101 | 105 | ||
102 | onTabChange (event: NgbTabChangeEvent) { | 106 | onTabChange (event: NgbTabChangeEvent) { |
@@ -107,6 +111,10 @@ export class VideoShareComponent { | |||
107 | return this.activeId === 'embed' | 111 | return this.activeId === 'embed' |
108 | } | 112 | } |
109 | 113 | ||
114 | hasPlaylist () { | ||
115 | return !!this.playlist | ||
116 | } | ||
117 | |||
110 | private getOptions (baseUrl?: string) { | 118 | private getOptions (baseUrl?: string) { |
111 | return { | 119 | return { |
112 | baseUrl, | 120 | baseUrl, |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index 38ad4e948..5b2e91bc5 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html | |||
@@ -224,5 +224,5 @@ | |||
224 | 224 | ||
225 | <ng-container *ngIf="video !== null"> | 225 | <ng-container *ngIf="video !== null"> |
226 | <my-video-support #videoSupportModal [video]="video"></my-video-support> | 226 | <my-video-support #videoSupportModal [video]="video"></my-video-support> |
227 | <my-video-share #videoShareModal [video]="video" [videoCaptions]="videoCaptions"></my-video-share> | 227 | <my-video-share #videoShareModal [video]="video" [videoCaptions]="videoCaptions" [playlist]="playlist"></my-video-share> |
228 | </ng-container> | 228 | </ng-container> |
diff --git a/client/src/assets/player/utils.ts b/client/src/assets/player/utils.ts index 777abb568..629634985 100644 --- a/client/src/assets/player/utils.ts +++ b/client/src/assets/player/utils.ts | |||
@@ -51,6 +51,8 @@ function buildVideoLink (options: { | |||
51 | : window.location.origin + window.location.pathname.replace('/embed/', '/watch/') | 51 | : window.location.origin + window.location.pathname.replace('/embed/', '/watch/') |
52 | 52 | ||
53 | const params = new URLSearchParams(window.location.search) | 53 | const params = new URLSearchParams(window.location.search) |
54 | // Remove this unused parameter when we are on a playlist page | ||
55 | params.delete('videoId') | ||
54 | 56 | ||
55 | if (options.startTime) { | 57 | if (options.startTime) { |
56 | const startTimeInt = Math.floor(options.startTime) | 58 | const startTimeInt = Math.floor(options.startTime) |