1
0
Fork 0

BEARKING CHANGE: Update videos API response

before beta
This commit is contained in:
Chocobozzz 2018-03-19 11:04:40 +01:00
parent ae5a3dd664
commit 09700934b9
No known key found for this signature in database
GPG key ID: 583A612D890159BE
12 changed files with 86 additions and 86 deletions

View file

@ -1,5 +1,32 @@
# Changelog # Changelog
## v1.0.0-alpha.9
### BREAKING CHANGES
* Update videos list/search/get API response:
* Removed `resolution` field
* Removed `resolutionLabel` field
* Removed `category` field
* Removed `categoryLabel` field
* Removed `licence` field
* Removed `licenceLabel` field
* Removed `language` field
* Removed `languageLabel` field
* Removed `privacy` field
* Removed `privacyLabel` field
* Added `resolution.id` field
* Added `resolution.label` field
* Added `category.id` field
* Added `category.label` field
* Added `licence.id` field
* Added `licence.label` field
* Added `language.id` field
* Added `language.label` field
* Added `privacy.id` field
* Added `privacy.label` field
## v1.0.0-alpha.8 ## v1.0.0-alpha.8
### Features ### Features

View file

@ -1,57 +1,33 @@
import { import {
UserRight, VideoChannel, VideoDetails as VideoDetailsServerModel, VideoFile, VideoPrivacy, UserRight,
VideoChannel,
VideoDetails as VideoDetailsServerModel,
VideoFile,
VideoPrivacy,
VideoResolution VideoResolution
} from '../../../../../shared' } from '../../../../../shared'
import { Account } from '../../../../../shared/models/actors' import { Account } from '../../../../../shared/models/actors'
import { VideoConstant } from '../../../../../shared/models/videos/video.model'
import { AuthUser } from '../../core' import { AuthUser } from '../../core'
import { Video } from '../../shared/video/video.model' import { Video } from '../../shared/video/video.model'
export class VideoDetails extends Video implements VideoDetailsServerModel { export class VideoDetails extends Video implements VideoDetailsServerModel {
accountName: string privacy: VideoConstant<VideoPrivacy>
by: string
createdAt: Date
updatedAt: Date
categoryLabel: string
category: number
licenceLabel: string
licence: number
languageLabel: string
language: number
description: string
support: string
duration: number
durationLabel: string
id: number
uuid: string
isLocal: boolean
name: string
serverHost: string
tags: string[]
thumbnailPath: string
thumbnailUrl: string
previewPath: string
previewUrl: string
embedPath: string
embedUrl: string
views: number
likes: number
dislikes: number
nsfw: boolean
descriptionPath: string descriptionPath: string
files: VideoFile[] support: string
channel: VideoChannel channel: VideoChannel
privacy: VideoPrivacy tags: string[]
privacyLabel: string files: VideoFile[]
account: Account account: Account
commentsEnabled: boolean
likesPercent: number likesPercent: number
dislikesPercent: number dislikesPercent: number
commentsEnabled: boolean
constructor (hash: VideoDetailsServerModel) { constructor (hash: VideoDetailsServerModel) {
super(hash) super(hash)
this.privacy = hash.privacy this.privacy = hash.privacy
this.privacyLabel = hash.privacyLabel
this.descriptionPath = hash.descriptionPath this.descriptionPath = hash.descriptionPath
this.files = hash.files this.files = hash.files
this.channel = hash.channel this.channel = hash.channel
@ -72,14 +48,14 @@ export class VideoDetails extends Video implements VideoDetailsServerModel {
// If the download speed is too bad, return the lowest resolution we have // If the download speed is too bad, return the lowest resolution we have
if (betterResolutionFile === undefined) { if (betterResolutionFile === undefined) {
betterResolutionFile = this.files.find(f => f.resolution === VideoResolution.H_240P) betterResolutionFile = this.files.find(f => f.resolution.id === VideoResolution.H_240P)
} }
return betterResolutionFile.magnetUri return betterResolutionFile.magnetUri
} }
isRemovableBy (user: AuthUser) { isRemovableBy (user: AuthUser) {
return user && this.isLocal === true && (this.accountName === user.username || user.hasRight(UserRight.REMOVE_ANY_VIDEO)) return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.REMOVE_ANY_VIDEO))
} }
isBlackistableBy (user: AuthUser) { isBlackistableBy (user: AuthUser) {
@ -87,7 +63,7 @@ export class VideoDetails extends Video implements VideoDetailsServerModel {
} }
isUpdatableBy (user: AuthUser) { isUpdatableBy (user: AuthUser) {
return user && this.isLocal === true && (this.accountName === user.username || user.hasRight(UserRight.UPDATE_ANY_VIDEO)) return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.UPDATE_ANY_VIDEO))
} }
buildLikeAndDislikePercents () { buildLikeAndDislikePercents () {

View file

@ -24,16 +24,16 @@ export class VideoEdit {
if (videoDetails) { if (videoDetails) {
this.id = videoDetails.id this.id = videoDetails.id
this.uuid = videoDetails.uuid this.uuid = videoDetails.uuid
this.category = videoDetails.category this.category = videoDetails.category.id
this.licence = videoDetails.licence this.licence = videoDetails.licence.id
this.language = videoDetails.language this.language = videoDetails.language.id
this.description = videoDetails.description this.description = videoDetails.description
this.name = videoDetails.name this.name = videoDetails.name
this.tags = videoDetails.tags this.tags = videoDetails.tags
this.nsfw = videoDetails.nsfw this.nsfw = videoDetails.nsfw
this.commentsEnabled = videoDetails.commentsEnabled this.commentsEnabled = videoDetails.commentsEnabled
this.channel = videoDetails.channel.id this.channel = videoDetails.channel.id
this.privacy = videoDetails.privacy this.privacy = videoDetails.privacy.id
this.support = videoDetails.support this.support = videoDetails.support
this.thumbnailUrl = videoDetails.thumbnailUrl this.thumbnailUrl = videoDetails.thumbnailUrl
this.previewUrl = videoDetails.previewUrl this.previewUrl = videoDetails.previewUrl

View file

@ -2,18 +2,16 @@ import { Account } from '@app/shared/account/account.model'
import { User } from '../' import { User } from '../'
import { Video as VideoServerModel } from '../../../../../shared' import { Video as VideoServerModel } from '../../../../../shared'
import { Avatar } from '../../../../../shared/models/avatars/avatar.model' import { Avatar } from '../../../../../shared/models/avatars/avatar.model'
import { VideoConstant } from '../../../../../shared/models/videos/video.model'
import { getAbsoluteAPIUrl } from '../misc/utils' import { getAbsoluteAPIUrl } from '../misc/utils'
export class Video implements VideoServerModel { export class Video implements VideoServerModel {
by: string by: string
createdAt: Date createdAt: Date
updatedAt: Date updatedAt: Date
categoryLabel: string category: VideoConstant<number>
category: number licence: VideoConstant<number>
licenceLabel: string language: VideoConstant<number>
licence: number
languageLabel: string
language: number
description: string description: string
duration: number duration: number
durationLabel: string durationLabel: string
@ -58,11 +56,8 @@ export class Video implements VideoServerModel {
const absoluteAPIUrl = getAbsoluteAPIUrl() const absoluteAPIUrl = getAbsoluteAPIUrl()
this.createdAt = new Date(hash.createdAt.toString()) this.createdAt = new Date(hash.createdAt.toString())
this.categoryLabel = hash.categoryLabel
this.category = hash.category this.category = hash.category
this.licenceLabel = hash.licenceLabel
this.licence = hash.licence this.licence = hash.licence
this.languageLabel = hash.languageLabel
this.language = hash.language this.language = hash.language
this.description = hash.description this.description = hash.description
this.duration = hash.duration this.duration = hash.duration

View file

@ -72,7 +72,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
] ]
// We cannot set private a video that was not private // We cannot set private a video that was not private
if (video.privacy !== VideoPrivacy.PRIVATE) { if (video.privacy.id !== VideoPrivacy.PRIVATE) {
const newVideoPrivacies = [] const newVideoPrivacies = []
for (const p of this.videoPrivacies) { for (const p of this.videoPrivacies) {
if (p.id !== VideoPrivacy.PRIVATE) newVideoPrivacies.push(p) if (p.id !== VideoPrivacy.PRIVATE) newVideoPrivacies.push(p)

View file

@ -9,8 +9,8 @@
<div class="modal-body"> <div class="modal-body">
<div class="peertube-select-container"> <div class="peertube-select-container">
<select [(ngModel)]="resolution"> <select [(ngModel)]="resolutionId">
<option *ngFor="let file of video.files" [value]="file.resolution">{{ file.resolutionLabel }}</option> <option *ngFor="let file of video.files" [value]="file.resolution.id">{{ file.resolution.label }}</option>
</select> </select>
</div> </div>

View file

@ -13,14 +13,14 @@ export class VideoDownloadComponent implements OnInit {
@ViewChild('modal') modal: ModalDirective @ViewChild('modal') modal: ModalDirective
downloadType: 'direct' | 'torrent' = 'torrent' downloadType: 'direct' | 'torrent' = 'torrent'
resolution: number | string = -1 resolutionId: number | string = -1
constructor () { constructor () {
// empty // empty
} }
ngOnInit () { ngOnInit () {
this.resolution = this.video.files[0].resolution this.resolutionId = this.video.files[0].resolution.id
} }
show () { show () {
@ -33,11 +33,11 @@ export class VideoDownloadComponent implements OnInit {
download () { download () {
// HTML select send us a string, so convert it to a number // HTML select send us a string, so convert it to a number
this.resolution = parseInt(this.resolution.toString(), 10) this.resolutionId = parseInt(this.resolutionId.toString(), 10)
const file = this.video.files.find(f => f.resolution === this.resolution) const file = this.video.files.find(f => f.resolution.id === this.resolutionId)
if (!file) { if (!file) {
console.error('Could not find file with resolution %d.', this.resolution) console.error('Could not find file with resolution %d.', this.resolutionId)
return return
} }

View file

@ -122,7 +122,7 @@
Privacy Privacy
</span> </span>
<span class="video-attribute-value"> <span class="video-attribute-value">
{{ video.privacyLabel }} {{ video.privacy.label }}
</span> </span>
</div> </div>
@ -131,7 +131,7 @@
Category Category
</span> </span>
<span class="video-attribute-value"> <span class="video-attribute-value">
{{ video.categoryLabel }} {{ video.category.label }}
</span> </span>
</div> </div>
@ -140,7 +140,7 @@
Licence Licence
</span> </span>
<span class="video-attribute-value"> <span class="video-attribute-value">
{{ video.licenceLabel }} {{ video.licence.label }}
</span> </span>
</div> </div>
@ -149,7 +149,7 @@
Language Language
</span> </span>
<span class="video-attribute-value"> <span class="video-attribute-value">
{{ video.languageLabel }} {{ video.language.label }}
</span> </span>
</div> </div>

View file

@ -2,6 +2,7 @@
import * as videojs from 'video.js' import * as videojs from 'video.js'
import * as WebTorrent from 'webtorrent' import * as WebTorrent from 'webtorrent'
import { VideoConstant, VideoResolution } from '../../../../shared/models/videos'
import { VideoFile } from '../../../../shared/models/videos/video.model' import { VideoFile } from '../../../../shared/models/videos/video.model'
import { renderVideo } from './video-renderer' import { renderVideo } from './video-renderer'
@ -52,8 +53,8 @@ class ResolutionMenuItem extends MenuItem {
options.selectable = true options.selectable = true
super(player, options) super(player, options)
const currentResolution = this.player_.peertube().getCurrentResolution() const currentResolutionId = this.player_.peertube().getCurrentResolutionId()
this.selected(this.options_.id === currentResolution) this.selected(this.options_.id === currentResolutionId)
} }
handleClick (event) { handleClick (event) {
@ -89,10 +90,10 @@ class ResolutionMenuButton extends MenuButton {
menuItems.push(new ResolutionMenuItem( menuItems.push(new ResolutionMenuItem(
this.player_, this.player_,
{ {
id: videoFile.resolution, id: videoFile.resolution.id,
label: videoFile.resolutionLabel, label: videoFile.resolution.label,
src: videoFile.magnetUri, src: videoFile.magnetUri,
selected: videoFile.resolution === this.currentSelection selected: videoFile.resolution.id === this.currentSelectionId
}) })
) )
} }
@ -269,12 +270,12 @@ class PeerTubePlugin extends Plugin {
this.flushVideoFile(this.currentVideoFile, false) this.flushVideoFile(this.currentVideoFile, false)
} }
getCurrentResolution () { getCurrentResolutionId () {
return this.currentVideoFile ? this.currentVideoFile.resolution : -1 return this.currentVideoFile ? this.currentVideoFile.resolution.id : -1
} }
getCurrentResolutionLabel () { getCurrentResolutionLabel () {
return this.currentVideoFile ? this.currentVideoFile.resolutionLabel : '' return this.currentVideoFile ? this.currentVideoFile.resolution.label : ''
} }
updateVideoFile (videoFile?: VideoFile, done?: () => void) { updateVideoFile (videoFile?: VideoFile, done?: () => void) {
@ -339,7 +340,7 @@ class PeerTubePlugin extends Plugin {
this.trigger('videoFileUpdate') this.trigger('videoFileUpdate')
} }
updateResolution (resolution) { updateResolution (resolutionId: number) {
// Remember player state // Remember player state
const currentTime = this.player.currentTime() const currentTime = this.player.currentTime()
const isPaused = this.player.paused() const isPaused = this.player.paused()
@ -352,7 +353,7 @@ class PeerTubePlugin extends Plugin {
this.player.bigPlayButton.hide() this.player.bigPlayButton.hide()
} }
const newVideoFile = this.videoFiles.find(f => f.resolution === resolution) const newVideoFile = this.videoFiles.find(f => f.resolution.id === resolutionId)
this.updateVideoFile(newVideoFile, () => { this.updateVideoFile(newVideoFile, () => {
this.player.currentTime(currentTime) this.player.currentTime(currentTime)
this.player.handleTechSeeked_() this.player.handleTechSeeked_()

View file

@ -327,7 +327,7 @@ function areDifferences (videos1: Video[], videos2: Video[]) {
return `Video ${video1.uuid} has missing video file ${videoFile1.magnetUri}.` return `Video ${video1.uuid} has missing video file ${videoFile1.magnetUri}.`
} }
if (videoFile1.size !== videoFile2.size || videoFile1.resolutionLabel !== videoFile2.resolutionLabel) { if (videoFile1.size !== videoFile2.size || videoFile1.resolution.label !== videoFile2.resolution.label) {
return `Video ${video1.uuid} has different video file ${videoFile1.magnetUri}.` return `Video ${video1.uuid} has different video file ${videoFile1.magnetUri}.`
} }
}) })

View file

@ -407,12 +407,12 @@ async function completeVideoCheck (
if (!attributes.dislikes) attributes.dislikes = 0 if (!attributes.dislikes) attributes.dislikes = 0
expect(video.name).to.equal(attributes.name) expect(video.name).to.equal(attributes.name)
expect(video.category).to.equal(attributes.category) expect(video.category.id).to.equal(attributes.category)
expect(video.categoryLabel).to.equal(VIDEO_CATEGORIES[attributes.category] || 'Misc') expect(video.category.label).to.equal(VIDEO_CATEGORIES[attributes.category] || 'Misc')
expect(video.licence).to.equal(attributes.licence) expect(video.licence.id).to.equal(attributes.licence)
expect(video.licenceLabel).to.equal(VIDEO_LICENCES[attributes.licence] || 'Unknown') expect(video.licence.label).to.equal(VIDEO_LICENCES[attributes.licence] || 'Unknown')
expect(video.language).to.equal(attributes.language) expect(video.language.id).to.equal(attributes.language)
expect(video.languageLabel).to.equal(VIDEO_LANGUAGES[attributes.language] || 'Unknown') expect(video.language.label).to.equal(VIDEO_LANGUAGES[attributes.language] || 'Unknown')
expect(video.nsfw).to.equal(attributes.nsfw) expect(video.nsfw).to.equal(attributes.nsfw)
expect(video.description).to.equal(attributes.description) expect(video.description).to.equal(attributes.description)
expect(video.account.host).to.equal(attributes.account.host) expect(video.account.host).to.equal(attributes.account.host)
@ -429,8 +429,8 @@ async function completeVideoCheck (
expect(videoDetails.files).to.have.lengthOf(attributes.files.length) expect(videoDetails.files).to.have.lengthOf(attributes.files.length)
expect(videoDetails.tags).to.deep.equal(attributes.tags) expect(videoDetails.tags).to.deep.equal(attributes.tags)
expect(videoDetails.privacy).to.deep.equal(attributes.privacy) expect(videoDetails.privacy.id).to.deep.equal(attributes.privacy)
expect(videoDetails.privacyLabel).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy]) expect(videoDetails.privacy.label).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy])
expect(videoDetails.account.name).to.equal(attributes.account.name) expect(videoDetails.account.name).to.equal(attributes.account.name)
expect(videoDetails.account.host).to.equal(attributes.account.host) expect(videoDetails.account.host).to.equal(attributes.account.host)
expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled) expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled)
@ -453,8 +453,8 @@ async function completeVideoCheck (
expect(file.magnetUri).to.have.lengthOf.above(2) expect(file.magnetUri).to.have.lengthOf.above(2)
expect(file.torrentUrl).to.equal(`http://${attributes.account.host}/static/torrents/${videoDetails.uuid}-${file.resolution}.torrent`) expect(file.torrentUrl).to.equal(`http://${attributes.account.host}/static/torrents/${videoDetails.uuid}-${file.resolution}.torrent`)
expect(file.fileUrl).to.equal(`http://${attributes.account.host}/static/webseed/${videoDetails.uuid}-${file.resolution}${extension}`) expect(file.fileUrl).to.equal(`http://${attributes.account.host}/static/webseed/${videoDetails.uuid}-${file.resolution}${extension}`)
expect(file.resolution).to.equal(attributeFile.resolution) expect(file.resolution.id).to.equal(attributeFile.resolution)
expect(file.resolutionLabel).to.equal(attributeFile.resolution + 'p') expect(file.resolution.label).to.equal(attributeFile.resolution + 'p')
const minSize = attributeFile.size - ((10 * attributeFile.size) / 100) const minSize = attributeFile.size - ((10 * attributeFile.size) / 100)
const maxSize = attributeFile.size + ((10 * attributeFile.size) / 100) const maxSize = attributeFile.size + ((10 * attributeFile.size) / 100)

View file

@ -1,3 +1,4 @@
import { VideoResolution } from '../../index'
import { Account } from '../actors' import { Account } from '../actors'
import { Avatar } from '../avatars/avatar.model' import { Avatar } from '../avatars/avatar.model'
import { VideoChannel } from './video-channel.model' import { VideoChannel } from './video-channel.model'
@ -10,7 +11,7 @@ export interface VideoConstant <T> {
export interface VideoFile { export interface VideoFile {
magnetUri: string magnetUri: string
resolution: VideoConstant<number> resolution: VideoConstant<VideoResolution>
size: number // Bytes size: number // Bytes
torrentUrl: string torrentUrl: string
fileUrl: string fileUrl: string