Adapt client with video channels

This commit is contained in:
Chocobozzz 2017-10-25 16:43:19 +02:00
parent f5028693a8
commit 404b54e14f
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
13 changed files with 159 additions and 113 deletions

View File

@ -1,5 +1,23 @@
import { User as UserServerModel, UserRole } from '../../../../../shared'
import {
User as UserServerModel,
UserRole,
VideoChannel
} from '../../../../../shared'
export type UserConstructorHash = {
id: number,
username: string,
email: string,
role: UserRole,
videoQuota?: number,
displayNSFW?: boolean,
createdAt?: Date,
author?: {
id: number
uuid: string
},
videoChannels?: VideoChannel[]
}
export class User implements UserServerModel {
id: number
username: string
@ -7,21 +25,23 @@ export class User implements UserServerModel {
role: UserRole
displayNSFW: boolean
videoQuota: number
author: {
id: number
uuid: string
}
videoChannels: VideoChannel[]
createdAt: Date
constructor (hash: {
id: number,
username: string,
email: string,
role: UserRole,
videoQuota?: number,
displayNSFW?: boolean,
createdAt?: Date
}) {
constructor (hash: UserConstructorHash) {
this.id = hash.id
this.username = hash.username
this.email = hash.email
this.role = hash.role
this.author = hash.author
if (hash.videoChannels !== undefined) {
this.videoChannels = hash.videoChannels
}
if (hash.videoQuota !== undefined) {
this.videoQuota = hash.videoQuota

View File

@ -14,7 +14,7 @@ import {
VIDEO_DESCRIPTION,
VIDEO_TAGS
} from '../../shared'
import { Video, VideoService } from '../shared'
import { VideoEdit, VideoService } from '../shared'
@Component({
selector: 'my-videos-update',
@ -27,7 +27,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
videoCategories = []
videoLicences = []
videoLanguages = []
video: Video
video: VideoEdit
tagValidators = VIDEO_TAGS.VALIDATORS
tagValidatorsMessages = VIDEO_TAGS.MESSAGES

View File

@ -2,7 +2,7 @@ import { Component, Input, ViewChild } from '@angular/core'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { Video } from '../shared'
import { VideoDetails } from '../shared'
@Component({
selector: 'my-video-download',
@ -10,7 +10,7 @@ import { Video } from '../shared'
styles: [ '.resolution-block { margin-top: 20px; }' ]
})
export class VideoDownloadComponent {
@Input() video: Video = null
@Input() video: VideoDetails = null
@ViewChild('modal') modal: ModalDirective

View File

@ -5,14 +5,14 @@ import { ModalDirective } from 'ngx-bootstrap/modal'
import { NotificationsService } from 'angular2-notifications'
import { FormReactive, VideoAbuseService, VIDEO_ABUSE_REASON } from '../../shared'
import { Video, VideoService } from '../shared'
import { VideoDetails, VideoService } from '../shared'
@Component({
selector: 'my-video-report',
templateUrl: './video-report.component.html'
})
export class VideoReportComponent extends FormReactive implements OnInit {
@Input() video: Video = null
@Input() video: VideoDetails = null
@ViewChild('modal') modal: ModalDirective

View File

@ -2,14 +2,14 @@ import { Component, Input, ViewChild } from '@angular/core'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { Video } from '../shared'
import { VideoDetails } from '../shared'
@Component({
selector: 'my-video-share',
templateUrl: './video-share.component.html'
})
export class VideoShareComponent {
@Input() video: Video = null
@Input() video: VideoDetails = null
@ViewChild('modal') modal: ModalDirective

View File

@ -13,7 +13,7 @@ import { AuthService, ConfirmService } from '../../core'
import { VideoDownloadComponent } from './video-download.component'
import { VideoShareComponent } from './video-share.component'
import { VideoReportComponent } from './video-report.component'
import { Video, VideoService } from '../shared'
import { VideoDetails, VideoService } from '../shared'
import { VideoBlacklistService } from '../../shared'
import { UserVideoRateType, VideoRateType } from '../../../../../shared'
@ -35,7 +35,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
playerElement: HTMLMediaElement
uploadSpeed: number
userRating: UserVideoRateType = null
video: Video = null
video: VideoDetails = null
videoPlayerLoaded = false
videoNotFound = false
@ -211,7 +211,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
)
}
private onVideoFetched (video: Video) {
private onVideoFetched (video: VideoDetails) {
this.video = video
let observable

View File

@ -1,4 +1,6 @@
export * from './sort-field.type'
export * from './video.model'
export * from './video-details.model'
export * from './video-edit.model'
export * from './video.service'
export * from './video-pagination.model'

View File

@ -0,0 +1,75 @@
import { Video } from './video.model'
import {
VideoDetails as VideoDetailsServerModel,
VideoFile,
VideoChannel,
VideoResolution
} from '../../../../../shared'
export class VideoDetails extends Video implements VideoDetailsServerModel {
author: string
by: string
createdAt: Date
updatedAt: Date
categoryLabel: string
category: number
licenceLabel: string
licence: number
languageLabel: string
language: number
description: string
duration: number
durationLabel: string
id: number
uuid: string
isLocal: boolean
name: string
podHost: string
tags: string[]
thumbnailPath: string
thumbnailUrl: string
previewPath: string
previewUrl: string
embedPath: string
embedUrl: string
views: number
likes: number
dislikes: number
nsfw: boolean
files: VideoFile[]
channel: VideoChannel
constructor (hash: VideoDetailsServerModel) {
super(hash)
this.files = hash.files
this.channel = hash.channel
}
getAppropriateMagnetUri (actualDownloadSpeed = 0) {
if (this.files === undefined || this.files.length === 0) return ''
if (this.files.length === 1) return this.files[0].magnetUri
// Find first video that is good for our download speed (remember they are sorted)
let betterResolutionFile = this.files.find(f => actualDownloadSpeed > (f.size / this.duration))
// If the download speed is too bad, return the lowest resolution we have
if (betterResolutionFile === undefined) {
betterResolutionFile = this.files.find(f => f.resolution === VideoResolution.H_240P)
}
return betterResolutionFile.magnetUri
}
isRemovableBy (user) {
return user && this.isLocal === true && (this.author === user.username || user.isAdmin() === true)
}
isBlackistableBy (user) {
return user && user.isAdmin() === true && this.isLocal === false
}
isUpdatableBy (user) {
return user && this.isLocal === true && user.username === this.author
}
}

View File

@ -0,0 +1,31 @@
export class VideoEdit {
category: number
licence: number
language: number
description: string
name: string
tags: string[]
nsfw: boolean
channel: number
uuid?: string
id?: number
patch (values: Object) {
Object.keys(values).forEach((key) => {
this[key] = values[key]
})
}
toJSON () {
return {
category: this.category,
licence: this.licence,
language: this.language,
description: this.description,
name: this.name,
tags: this.tags,
nsfw: this.nsfw,
channel: this.channel
}
}
}

View File

@ -1,6 +1,5 @@
import { Video as VideoServerModel, VideoFile } from '../../../../../shared'
import { Video as VideoServerModel } from '../../../../../shared'
import { User } from '../../shared'
import { VideoResolution } from '../../../../../shared/models/videos/video-resolution.enum'
export class Video implements VideoServerModel {
author: string
@ -32,7 +31,6 @@ export class Video implements VideoServerModel {
likes: number
dislikes: number
nsfw: boolean
files: VideoFile[]
private static createByString (author: string, podHost: string) {
return author + '@' + podHost
@ -47,32 +45,7 @@ export class Video implements VideoServerModel {
return minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString()
}
constructor (hash: {
author: string,
createdAt: Date | string,
categoryLabel: string,
category: number,
licenceLabel: string,
licence: number,
languageLabel: string
language: number
description: string,
duration: number
id: number,
uuid: string,
isLocal: boolean,
name: string,
podHost: string,
tags: string[],
thumbnailPath: string,
previewPath: string,
embedPath: string,
views: number,
likes: number,
dislikes: number,
nsfw: boolean,
files: VideoFile[]
}) {
constructor (hash: VideoServerModel) {
let absoluteAPIUrl = API_URL
if (!absoluteAPIUrl) {
// The API is on the same domain
@ -106,69 +79,12 @@ export class Video implements VideoServerModel {
this.likes = hash.likes
this.dislikes = hash.dislikes
this.nsfw = hash.nsfw
this.files = hash.files
this.by = Video.createByString(hash.author, hash.podHost)
}
isRemovableBy (user) {
return user && this.isLocal === true && (this.author === user.username || user.isAdmin() === true)
}
isBlackistableBy (user) {
return user && user.isAdmin() === true && this.isLocal === false
}
isUpdatableBy (user) {
return user && this.isLocal === true && user.username === this.author
}
isVideoNSFWForUser (user: User) {
// If the video is NSFW and the user is not logged in, or the user does not want to display NSFW videos...
return (this.nsfw && (!user || user.displayNSFW === false))
}
getAppropriateMagnetUri (actualDownloadSpeed = 0) {
if (this.files === undefined || this.files.length === 0) return ''
if (this.files.length === 1) return this.files[0].magnetUri
// Find first video that is good for our download speed (remember they are sorted)
let betterResolutionFile = this.files.find(f => actualDownloadSpeed > (f.size / this.duration))
// If the download speed is too bad, return the lowest resolution we have
if (betterResolutionFile === undefined) {
betterResolutionFile = this.files.find(f => f.resolution === VideoResolution.H_240P)
}
return betterResolutionFile.magnetUri
}
patch (values: Object) {
Object.keys(values).forEach((key) => {
this[key] = values[key]
})
}
toJSON () {
return {
author: this.author,
createdAt: this.createdAt,
category: this.category,
licence: this.licence,
language: this.language,
description: this.description,
duration: this.duration,
id: this.id,
isLocal: this.isLocal,
name: this.name,
podHost: this.podHost,
tags: this.tags,
thumbnailPath: this.thumbnailPath,
views: this.views,
likes: this.likes,
dislikes: this.dislikes,
nsfw: this.nsfw,
files: this.files
}
}
}

View File

@ -12,6 +12,8 @@ import {
UserService
} from '../../shared'
import { Video } from './video.model'
import { VideoDetails } from './video-details.model'
import { VideoEdit } from './video-edit.model'
import { VideoPagination } from './video-pagination.model'
import {
UserVideoRate,
@ -20,6 +22,7 @@ import {
VideoAbuseCreate,
UserVideoRateUpdate,
Video as VideoServerModel,
VideoDetails as VideoDetailsServerModel,
ResultList
} from '../../../../../shared'
@ -34,12 +37,12 @@ export class VideoService {
) {}
getVideo (uuid: string) {
return this.authHttp.get<VideoServerModel>(VideoService.BASE_VIDEO_URL + uuid)
.map(videoHash => new Video(videoHash))
return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + uuid)
.map(videoHash => new VideoDetails(videoHash))
.catch((res) => this.restExtractor.handleError(res))
}
updateVideo (video: Video) {
updateVideo (video: VideoEdit) {
const language = video.language ? video.language : null
const body: VideoUpdate = {

View File

@ -3,9 +3,9 @@ import './embed.scss'
import videojs from 'video.js'
import '../../assets/player/peertube-videojs-plugin'
import 'videojs-dock/dist/videojs-dock.es.js'
import { Video } from '../../../../shared'
import { VideoDetails } from '../../../../shared'
function loadVideoInfo (videoId: string, callback: (err: Error, res?: Video) => void) {
function loadVideoInfo (videoId: string, callback: (err: Error, res?: VideoDetails) => void) {
const xhttp = new XMLHttpRequest()
xhttp.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {

View File

@ -1,6 +1,5 @@
import * as express from 'express'
import * as Sequelize from 'sequelize'
import * as Promise from 'bluebird'
import { pseudoRandomBytesPromise } from './core-utils'
import { CONFIG, database as db } from '../initializers'