Force live type specification in first step
This commit is contained in:
parent
3eb7ee658d
commit
1e2fe802d1
|
@ -16,7 +16,24 @@
|
|||
></my-select-options>
|
||||
</div>
|
||||
|
||||
<div class="form-group live-type">
|
||||
<div class="peertube-radio-container">
|
||||
<input type="radio" id="permanentLiveFalse" [(ngModel)]="firstStepPermanentLive" [value]="false">
|
||||
<label i18n for="permanentLiveFalse" class="radio">Normal live</label>
|
||||
|
||||
<span class="form-group-description">{{ getNormalLiveDescription() }}</span>
|
||||
</div>
|
||||
|
||||
<div class="peertube-radio-container">
|
||||
<input type="radio" id="permanentLiveTrue" [(ngModel)]="firstStepPermanentLive" [value]="true">
|
||||
<label i18n for="permanentLiveTrue" class="radio">Permanent/recurring live</label>
|
||||
|
||||
<span class="form-group-description" i18n>{{ getPermanentLiveDescription() }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
[disabled]="firstStepPermanentLive !== true && firstStepPermanentLive !== false"
|
||||
type="button" i18n-value value="Go Live" (click)="goLive()"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
.live-type {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.peertube-radio-container {
|
||||
width: 250px;
|
||||
|
||||
.form-group-description {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import { forkJoin } from 'rxjs'
|
||||
import { AfterViewInit, Component, EventEmitter, OnInit, Output } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
|
@ -16,6 +15,7 @@ import { VideoSend } from './video-send'
|
|||
templateUrl: './video-go-live.component.html',
|
||||
styleUrls: [
|
||||
'../shared/video-edit.component.scss',
|
||||
'./video-go-live.component.scss',
|
||||
'./video-send.scss'
|
||||
]
|
||||
})
|
||||
|
@ -23,6 +23,8 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, AfterView
|
|||
@Output() firstStepDone = new EventEmitter<string>()
|
||||
@Output() firstStepError = new EventEmitter<void>()
|
||||
|
||||
firstStepPermanentLive: boolean
|
||||
|
||||
isInUpdateForm = false
|
||||
|
||||
liveVideo: LiveVideo
|
||||
|
@ -70,8 +72,8 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, AfterView
|
|||
waitTranscoding: true,
|
||||
commentsEnabled: true,
|
||||
downloadEnabled: true,
|
||||
permanentLive: false,
|
||||
saveReplay: false,
|
||||
permanentLive: this.firstStepPermanentLive,
|
||||
saveReplay: this.firstStepPermanentLive === false && this.isReplayAllowed(),
|
||||
channelId: this.firstStepChannelId
|
||||
}
|
||||
|
||||
|
@ -154,6 +156,26 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, AfterView
|
|||
return this.form.value['saveReplay'] === true
|
||||
}
|
||||
|
||||
getNormalLiveDescription () {
|
||||
if (this.isReplayAllowed()) {
|
||||
return $localize`Stream only once and save a replay of your live`
|
||||
}
|
||||
|
||||
return $localize`Stream only once`
|
||||
}
|
||||
|
||||
getPermanentLiveDescription () {
|
||||
if (this.isReplayAllowed()) {
|
||||
return $localize`Stream multiple times, replays can't be saved`
|
||||
}
|
||||
|
||||
return $localize`Stream multiple times using the same URL`
|
||||
}
|
||||
|
||||
private isReplayAllowed () {
|
||||
return this.serverConfig.live.allowReplay
|
||||
}
|
||||
|
||||
private fetchVideoLive () {
|
||||
this.liveVideoService.getVideoLive(this.videoId)
|
||||
.subscribe({
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@use '_variables' as *;
|
||||
@use '_mixins' as *;
|
||||
|
||||
$width-size: 190px;
|
||||
$width-size: 250px;
|
||||
|
||||
.alert.alert-danger {
|
||||
text-align: center;
|
||||
|
@ -29,6 +29,7 @@ $width-size: 190px;
|
|||
my-select-options ::ng-deep ng-select,
|
||||
my-select-channel ::ng-deep ng-select {
|
||||
width: $width-size;
|
||||
|
||||
@media screen and (max-width: $width-size) {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ export const VIDEO_SUPPORT_VALIDATOR: BuildFormValidator = {
|
|||
}
|
||||
|
||||
export const VIDEO_SCHEDULE_PUBLICATION_AT_VALIDATOR: BuildFormValidator = {
|
||||
VALIDATORS: [ ],
|
||||
VALIDATORS: [ ], // Required is set dynamically
|
||||
MESSAGES: {
|
||||
required: $localize`A date is required to schedule video update.`
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
$form-base-input-width: auto;
|
||||
|
||||
.text-muted {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
ng-select {
|
||||
width: $form-base-input-width;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<div class="modal-body" *ngIf="live">
|
||||
<div>
|
||||
<div class="badge badge-info" *ngIf="live.permanentLive" i18n>Permanent live</div>
|
||||
<div class="badge badge-info" *ngIf="live.permanentLive" i18n>Permanent/Recurring live</div>
|
||||
<div class="badge badge-info" *ngIf="live.saveReplay" i18n>Replay will be saved</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -478,7 +478,7 @@
|
|||
|
||||
.form-group-description {
|
||||
display: block;
|
||||
margin-top: -10px;
|
||||
margin-top: -7px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 29px;
|
||||
}
|
||||
|
|
|
@ -119,7 +119,7 @@ export abstract class APVideoAbstractBuilder {
|
|||
}
|
||||
|
||||
protected async setStreamingPlaylists (video: MVideoFullLight, t: Transaction) {
|
||||
const streamingPlaylistAttributes = getStreamingPlaylistAttributesFromObject(video, this.videoObject, video.VideoFiles || [])
|
||||
const streamingPlaylistAttributes = getStreamingPlaylistAttributesFromObject(video, this.videoObject)
|
||||
const newStreamingPlaylists = streamingPlaylistAttributes.map(a => new VideoStreamingPlaylistModel(a))
|
||||
|
||||
// Remove video playlists that do not exist anymore
|
||||
|
|
|
@ -11,7 +11,7 @@ import { VideoCaptionModel } from '@server/models/video/video-caption'
|
|||
import { VideoFileModel } from '@server/models/video/video-file'
|
||||
import { VideoStreamingPlaylistModel } from '@server/models/video/video-streaming-playlist'
|
||||
import { FilteredModelAttributes } from '@server/types'
|
||||
import { isStreamingPlaylist, MChannelId, MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoId } from '@server/types/models'
|
||||
import { isStreamingPlaylist, MChannelId, MStreamingPlaylistVideo, MVideo, MVideoId } from '@server/types/models'
|
||||
import {
|
||||
ActivityHashTagObject,
|
||||
ActivityMagnetUrlObject,
|
||||
|
@ -110,7 +110,7 @@ function getFileAttributesFromUrl (
|
|||
return attributes
|
||||
}
|
||||
|
||||
function getStreamingPlaylistAttributesFromObject (video: MVideoId, videoObject: VideoObject, videoFiles: MVideoFile[]) {
|
||||
function getStreamingPlaylistAttributesFromObject (video: MVideoId, videoObject: VideoObject) {
|
||||
const playlistUrls = videoObject.url.filter(u => isAPStreamingPlaylistUrlObject(u)) as ActivityPlaylistUrlObject[]
|
||||
if (playlistUrls.length === 0) return []
|
||||
|
||||
|
@ -118,7 +118,7 @@ function getStreamingPlaylistAttributesFromObject (video: MVideoId, videoObject:
|
|||
for (const playlistUrlObject of playlistUrls) {
|
||||
const segmentsSha256UrlObject = playlistUrlObject.tag.find(isAPPlaylistSegmentHashesUrlObject)
|
||||
|
||||
let files: unknown[] = playlistUrlObject.tag.filter(u => isAPVideoUrlObject(u)) as ActivityVideoUrlObject[]
|
||||
const files: unknown[] = playlistUrlObject.tag.filter(u => isAPVideoUrlObject(u)) as ActivityVideoUrlObject[]
|
||||
|
||||
if (!segmentsSha256UrlObject) {
|
||||
logger.warn('No segment sha256 URL found in AP playlist object.', { playlistUrl: playlistUrlObject })
|
||||
|
|
Loading…
Reference in New Issue