diff options
Diffstat (limited to 'client/src/app')
11 files changed, 157 insertions, 110 deletions
diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts index bf12876c7..7beea5910 100644 --- a/client/src/app/shared/users/user.model.ts +++ b/client/src/app/shared/users/user.model.ts | |||
@@ -1,5 +1,23 @@ | |||
1 | import { User as UserServerModel, UserRole } from '../../../../../shared' | 1 | import { |
2 | User as UserServerModel, | ||
3 | UserRole, | ||
4 | VideoChannel | ||
5 | } from '../../../../../shared' | ||
2 | 6 | ||
7 | export type UserConstructorHash = { | ||
8 | id: number, | ||
9 | username: string, | ||
10 | email: string, | ||
11 | role: UserRole, | ||
12 | videoQuota?: number, | ||
13 | displayNSFW?: boolean, | ||
14 | createdAt?: Date, | ||
15 | author?: { | ||
16 | id: number | ||
17 | uuid: string | ||
18 | }, | ||
19 | videoChannels?: VideoChannel[] | ||
20 | } | ||
3 | export class User implements UserServerModel { | 21 | export class User implements UserServerModel { |
4 | id: number | 22 | id: number |
5 | username: string | 23 | username: string |
@@ -7,21 +25,23 @@ export class User implements UserServerModel { | |||
7 | role: UserRole | 25 | role: UserRole |
8 | displayNSFW: boolean | 26 | displayNSFW: boolean |
9 | videoQuota: number | 27 | videoQuota: number |
28 | author: { | ||
29 | id: number | ||
30 | uuid: string | ||
31 | } | ||
32 | videoChannels: VideoChannel[] | ||
10 | createdAt: Date | 33 | createdAt: Date |
11 | 34 | ||
12 | constructor (hash: { | 35 | constructor (hash: UserConstructorHash) { |
13 | id: number, | ||
14 | username: string, | ||
15 | email: string, | ||
16 | role: UserRole, | ||
17 | videoQuota?: number, | ||
18 | displayNSFW?: boolean, | ||
19 | createdAt?: Date | ||
20 | }) { | ||
21 | this.id = hash.id | 36 | this.id = hash.id |
22 | this.username = hash.username | 37 | this.username = hash.username |
23 | this.email = hash.email | 38 | this.email = hash.email |
24 | this.role = hash.role | 39 | this.role = hash.role |
40 | this.author = hash.author | ||
41 | |||
42 | if (hash.videoChannels !== undefined) { | ||
43 | this.videoChannels = hash.videoChannels | ||
44 | } | ||
25 | 45 | ||
26 | if (hash.videoQuota !== undefined) { | 46 | if (hash.videoQuota !== undefined) { |
27 | this.videoQuota = hash.videoQuota | 47 | this.videoQuota = hash.videoQuota |
diff --git a/client/src/app/videos/+video-edit/video-update.component.ts b/client/src/app/videos/+video-edit/video-update.component.ts index 6d45265e7..70cb334fd 100644 --- a/client/src/app/videos/+video-edit/video-update.component.ts +++ b/client/src/app/videos/+video-edit/video-update.component.ts | |||
@@ -14,7 +14,7 @@ import { | |||
14 | VIDEO_DESCRIPTION, | 14 | VIDEO_DESCRIPTION, |
15 | VIDEO_TAGS | 15 | VIDEO_TAGS |
16 | } from '../../shared' | 16 | } from '../../shared' |
17 | import { Video, VideoService } from '../shared' | 17 | import { VideoEdit, VideoService } from '../shared' |
18 | 18 | ||
19 | @Component({ | 19 | @Component({ |
20 | selector: 'my-videos-update', | 20 | selector: 'my-videos-update', |
@@ -27,7 +27,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { | |||
27 | videoCategories = [] | 27 | videoCategories = [] |
28 | videoLicences = [] | 28 | videoLicences = [] |
29 | videoLanguages = [] | 29 | videoLanguages = [] |
30 | video: Video | 30 | video: VideoEdit |
31 | 31 | ||
32 | tagValidators = VIDEO_TAGS.VALIDATORS | 32 | tagValidators = VIDEO_TAGS.VALIDATORS |
33 | tagValidatorsMessages = VIDEO_TAGS.MESSAGES | 33 | tagValidatorsMessages = VIDEO_TAGS.MESSAGES |
diff --git a/client/src/app/videos/+video-watch/video-download.component.ts b/client/src/app/videos/+video-watch/video-download.component.ts index 22149aa6b..c32f8d586 100644 --- a/client/src/app/videos/+video-watch/video-download.component.ts +++ b/client/src/app/videos/+video-watch/video-download.component.ts | |||
@@ -2,7 +2,7 @@ import { Component, Input, ViewChild } from '@angular/core' | |||
2 | 2 | ||
3 | import { ModalDirective } from 'ngx-bootstrap/modal' | 3 | import { ModalDirective } from 'ngx-bootstrap/modal' |
4 | 4 | ||
5 | import { Video } from '../shared' | 5 | import { VideoDetails } from '../shared' |
6 | 6 | ||
7 | @Component({ | 7 | @Component({ |
8 | selector: 'my-video-download', | 8 | selector: 'my-video-download', |
@@ -10,7 +10,7 @@ import { Video } from '../shared' | |||
10 | styles: [ '.resolution-block { margin-top: 20px; }' ] | 10 | styles: [ '.resolution-block { margin-top: 20px; }' ] |
11 | }) | 11 | }) |
12 | export class VideoDownloadComponent { | 12 | export class VideoDownloadComponent { |
13 | @Input() video: Video = null | 13 | @Input() video: VideoDetails = null |
14 | 14 | ||
15 | @ViewChild('modal') modal: ModalDirective | 15 | @ViewChild('modal') modal: ModalDirective |
16 | 16 | ||
diff --git a/client/src/app/videos/+video-watch/video-report.component.ts b/client/src/app/videos/+video-watch/video-report.component.ts index d9c83a640..fc9b5a9d4 100644 --- a/client/src/app/videos/+video-watch/video-report.component.ts +++ b/client/src/app/videos/+video-watch/video-report.component.ts | |||
@@ -5,14 +5,14 @@ import { ModalDirective } from 'ngx-bootstrap/modal' | |||
5 | import { NotificationsService } from 'angular2-notifications' | 5 | import { NotificationsService } from 'angular2-notifications' |
6 | 6 | ||
7 | import { FormReactive, VideoAbuseService, VIDEO_ABUSE_REASON } from '../../shared' | 7 | import { FormReactive, VideoAbuseService, VIDEO_ABUSE_REASON } from '../../shared' |
8 | import { Video, VideoService } from '../shared' | 8 | import { VideoDetails, VideoService } from '../shared' |
9 | 9 | ||
10 | @Component({ | 10 | @Component({ |
11 | selector: 'my-video-report', | 11 | selector: 'my-video-report', |
12 | templateUrl: './video-report.component.html' | 12 | templateUrl: './video-report.component.html' |
13 | }) | 13 | }) |
14 | export class VideoReportComponent extends FormReactive implements OnInit { | 14 | export class VideoReportComponent extends FormReactive implements OnInit { |
15 | @Input() video: Video = null | 15 | @Input() video: VideoDetails = null |
16 | 16 | ||
17 | @ViewChild('modal') modal: ModalDirective | 17 | @ViewChild('modal') modal: ModalDirective |
18 | 18 | ||
diff --git a/client/src/app/videos/+video-watch/video-share.component.ts b/client/src/app/videos/+video-watch/video-share.component.ts index 414ed28c6..aeef65ecf 100644 --- a/client/src/app/videos/+video-watch/video-share.component.ts +++ b/client/src/app/videos/+video-watch/video-share.component.ts | |||
@@ -2,14 +2,14 @@ import { Component, Input, ViewChild } from '@angular/core' | |||
2 | 2 | ||
3 | import { ModalDirective } from 'ngx-bootstrap/modal' | 3 | import { ModalDirective } from 'ngx-bootstrap/modal' |
4 | 4 | ||
5 | import { Video } from '../shared' | 5 | import { VideoDetails } from '../shared' |
6 | 6 | ||
7 | @Component({ | 7 | @Component({ |
8 | selector: 'my-video-share', | 8 | selector: 'my-video-share', |
9 | templateUrl: './video-share.component.html' | 9 | templateUrl: './video-share.component.html' |
10 | }) | 10 | }) |
11 | export class VideoShareComponent { | 11 | export class VideoShareComponent { |
12 | @Input() video: Video = null | 12 | @Input() video: VideoDetails = null |
13 | 13 | ||
14 | @ViewChild('modal') modal: ModalDirective | 14 | @ViewChild('modal') modal: ModalDirective |
15 | 15 | ||
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index f45ffd82f..529e2e84f 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -13,7 +13,7 @@ import { AuthService, ConfirmService } from '../../core' | |||
13 | import { VideoDownloadComponent } from './video-download.component' | 13 | import { VideoDownloadComponent } from './video-download.component' |
14 | import { VideoShareComponent } from './video-share.component' | 14 | import { VideoShareComponent } from './video-share.component' |
15 | import { VideoReportComponent } from './video-report.component' | 15 | import { VideoReportComponent } from './video-report.component' |
16 | import { Video, VideoService } from '../shared' | 16 | import { VideoDetails, VideoService } from '../shared' |
17 | import { VideoBlacklistService } from '../../shared' | 17 | import { VideoBlacklistService } from '../../shared' |
18 | import { UserVideoRateType, VideoRateType } from '../../../../../shared' | 18 | import { UserVideoRateType, VideoRateType } from '../../../../../shared' |
19 | 19 | ||
@@ -35,7 +35,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
35 | playerElement: HTMLMediaElement | 35 | playerElement: HTMLMediaElement |
36 | uploadSpeed: number | 36 | uploadSpeed: number |
37 | userRating: UserVideoRateType = null | 37 | userRating: UserVideoRateType = null |
38 | video: Video = null | 38 | video: VideoDetails = null |
39 | videoPlayerLoaded = false | 39 | videoPlayerLoaded = false |
40 | videoNotFound = false | 40 | videoNotFound = false |
41 | 41 | ||
@@ -211,7 +211,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
211 | ) | 211 | ) |
212 | } | 212 | } |
213 | 213 | ||
214 | private onVideoFetched (video: Video) { | 214 | private onVideoFetched (video: VideoDetails) { |
215 | this.video = video | 215 | this.video = video |
216 | 216 | ||
217 | let observable | 217 | let observable |
diff --git a/client/src/app/videos/shared/index.ts b/client/src/app/videos/shared/index.ts index 8168e3bfd..dcaa4e090 100644 --- a/client/src/app/videos/shared/index.ts +++ b/client/src/app/videos/shared/index.ts | |||
@@ -1,4 +1,6 @@ | |||
1 | export * from './sort-field.type' | 1 | export * from './sort-field.type' |
2 | export * from './video.model' | 2 | export * from './video.model' |
3 | export * from './video-details.model' | ||
4 | export * from './video-edit.model' | ||
3 | export * from './video.service' | 5 | export * from './video.service' |
4 | export * from './video-pagination.model' | 6 | export * from './video-pagination.model' |
diff --git a/client/src/app/videos/shared/video-details.model.ts b/client/src/app/videos/shared/video-details.model.ts new file mode 100644 index 000000000..e99a5ce2e --- /dev/null +++ b/client/src/app/videos/shared/video-details.model.ts | |||
@@ -0,0 +1,75 @@ | |||
1 | import { Video } from './video.model' | ||
2 | import { | ||
3 | VideoDetails as VideoDetailsServerModel, | ||
4 | VideoFile, | ||
5 | VideoChannel, | ||
6 | VideoResolution | ||
7 | } from '../../../../../shared' | ||
8 | |||
9 | export class VideoDetails extends Video implements VideoDetailsServerModel { | ||
10 | author: string | ||
11 | by: string | ||
12 | createdAt: Date | ||
13 | updatedAt: Date | ||
14 | categoryLabel: string | ||
15 | category: number | ||
16 | licenceLabel: string | ||
17 | licence: number | ||
18 | languageLabel: string | ||
19 | language: number | ||
20 | description: string | ||
21 | duration: number | ||
22 | durationLabel: string | ||
23 | id: number | ||
24 | uuid: string | ||
25 | isLocal: boolean | ||
26 | name: string | ||
27 | podHost: string | ||
28 | tags: string[] | ||
29 | thumbnailPath: string | ||
30 | thumbnailUrl: string | ||
31 | previewPath: string | ||
32 | previewUrl: string | ||
33 | embedPath: string | ||
34 | embedUrl: string | ||
35 | views: number | ||
36 | likes: number | ||
37 | dislikes: number | ||
38 | nsfw: boolean | ||
39 | files: VideoFile[] | ||
40 | channel: VideoChannel | ||
41 | |||
42 | constructor (hash: VideoDetailsServerModel) { | ||
43 | super(hash) | ||
44 | |||
45 | this.files = hash.files | ||
46 | this.channel = hash.channel | ||
47 | } | ||
48 | |||
49 | getAppropriateMagnetUri (actualDownloadSpeed = 0) { | ||
50 | if (this.files === undefined || this.files.length === 0) return '' | ||
51 | if (this.files.length === 1) return this.files[0].magnetUri | ||
52 | |||
53 | // Find first video that is good for our download speed (remember they are sorted) | ||
54 | let betterResolutionFile = this.files.find(f => actualDownloadSpeed > (f.size / this.duration)) | ||
55 | |||
56 | // If the download speed is too bad, return the lowest resolution we have | ||
57 | if (betterResolutionFile === undefined) { | ||
58 | betterResolutionFile = this.files.find(f => f.resolution === VideoResolution.H_240P) | ||
59 | } | ||
60 | |||
61 | return betterResolutionFile.magnetUri | ||
62 | } | ||
63 | |||
64 | isRemovableBy (user) { | ||
65 | return user && this.isLocal === true && (this.author === user.username || user.isAdmin() === true) | ||
66 | } | ||
67 | |||
68 | isBlackistableBy (user) { | ||
69 | return user && user.isAdmin() === true && this.isLocal === false | ||
70 | } | ||
71 | |||
72 | isUpdatableBy (user) { | ||
73 | return user && this.isLocal === true && user.username === this.author | ||
74 | } | ||
75 | } | ||
diff --git a/client/src/app/videos/shared/video-edit.model.ts b/client/src/app/videos/shared/video-edit.model.ts new file mode 100644 index 000000000..f30d8feba --- /dev/null +++ b/client/src/app/videos/shared/video-edit.model.ts | |||
@@ -0,0 +1,31 @@ | |||
1 | export class VideoEdit { | ||
2 | category: number | ||
3 | licence: number | ||
4 | language: number | ||
5 | description: string | ||
6 | name: string | ||
7 | tags: string[] | ||
8 | nsfw: boolean | ||
9 | channel: number | ||
10 | uuid?: string | ||
11 | id?: number | ||
12 | |||
13 | patch (values: Object) { | ||
14 | Object.keys(values).forEach((key) => { | ||
15 | this[key] = values[key] | ||
16 | }) | ||
17 | } | ||
18 | |||
19 | toJSON () { | ||
20 | return { | ||
21 | category: this.category, | ||
22 | licence: this.licence, | ||
23 | language: this.language, | ||
24 | description: this.description, | ||
25 | name: this.name, | ||
26 | tags: this.tags, | ||
27 | nsfw: this.nsfw, | ||
28 | channel: this.channel | ||
29 | } | ||
30 | } | ||
31 | } | ||
diff --git a/client/src/app/videos/shared/video.model.ts b/client/src/app/videos/shared/video.model.ts index 6e8dfaa6f..7f2871032 100644 --- a/client/src/app/videos/shared/video.model.ts +++ b/client/src/app/videos/shared/video.model.ts | |||
@@ -1,6 +1,5 @@ | |||
1 | import { Video as VideoServerModel, VideoFile } from '../../../../../shared' | 1 | import { Video as VideoServerModel } from '../../../../../shared' |
2 | import { User } from '../../shared' | 2 | import { User } from '../../shared' |
3 | import { VideoResolution } from '../../../../../shared/models/videos/video-resolution.enum' | ||
4 | 3 | ||
5 | export class Video implements VideoServerModel { | 4 | export class Video implements VideoServerModel { |
6 | author: string | 5 | author: string |
@@ -32,7 +31,6 @@ export class Video implements VideoServerModel { | |||
32 | likes: number | 31 | likes: number |
33 | dislikes: number | 32 | dislikes: number |
34 | nsfw: boolean | 33 | nsfw: boolean |
35 | files: VideoFile[] | ||
36 | 34 | ||
37 | private static createByString (author: string, podHost: string) { | 35 | private static createByString (author: string, podHost: string) { |
38 | return author + '@' + podHost | 36 | return author + '@' + podHost |
@@ -47,32 +45,7 @@ export class Video implements VideoServerModel { | |||
47 | return minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString() | 45 | return minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString() |
48 | } | 46 | } |
49 | 47 | ||
50 | constructor (hash: { | 48 | constructor (hash: VideoServerModel) { |
51 | author: string, | ||
52 | createdAt: Date | string, | ||
53 | categoryLabel: string, | ||
54 | category: number, | ||
55 | licenceLabel: string, | ||
56 | licence: number, | ||
57 | languageLabel: string | ||
58 | language: number | ||
59 | description: string, | ||
60 | duration: number | ||
61 | id: number, | ||
62 | uuid: string, | ||
63 | isLocal: boolean, | ||
64 | name: string, | ||
65 | podHost: string, | ||
66 | tags: string[], | ||
67 | thumbnailPath: string, | ||
68 | previewPath: string, | ||
69 | embedPath: string, | ||
70 | views: number, | ||
71 | likes: number, | ||
72 | dislikes: number, | ||
73 | nsfw: boolean, | ||
74 | files: VideoFile[] | ||
75 | }) { | ||
76 | let absoluteAPIUrl = API_URL | 49 | let absoluteAPIUrl = API_URL |
77 | if (!absoluteAPIUrl) { | 50 | if (!absoluteAPIUrl) { |
78 | // The API is on the same domain | 51 | // The API is on the same domain |
@@ -106,69 +79,12 @@ export class Video implements VideoServerModel { | |||
106 | this.likes = hash.likes | 79 | this.likes = hash.likes |
107 | this.dislikes = hash.dislikes | 80 | this.dislikes = hash.dislikes |
108 | this.nsfw = hash.nsfw | 81 | this.nsfw = hash.nsfw |
109 | this.files = hash.files | ||
110 | 82 | ||
111 | this.by = Video.createByString(hash.author, hash.podHost) | 83 | this.by = Video.createByString(hash.author, hash.podHost) |
112 | } | 84 | } |
113 | 85 | ||
114 | isRemovableBy (user) { | ||
115 | return user && this.isLocal === true && (this.author === user.username || user.isAdmin() === true) | ||
116 | } | ||
117 | |||
118 | isBlackistableBy (user) { | ||
119 | return user && user.isAdmin() === true && this.isLocal === false | ||
120 | } | ||
121 | |||
122 | isUpdatableBy (user) { | ||
123 | return user && this.isLocal === true && user.username === this.author | ||
124 | } | ||
125 | |||
126 | isVideoNSFWForUser (user: User) { | 86 | isVideoNSFWForUser (user: User) { |
127 | // If the video is NSFW and the user is not logged in, or the user does not want to display NSFW videos... | 87 | // If the video is NSFW and the user is not logged in, or the user does not want to display NSFW videos... |
128 | return (this.nsfw && (!user || user.displayNSFW === false)) | 88 | return (this.nsfw && (!user || user.displayNSFW === false)) |
129 | } | 89 | } |
130 | |||
131 | getAppropriateMagnetUri (actualDownloadSpeed = 0) { | ||
132 | if (this.files === undefined || this.files.length === 0) return '' | ||
133 | if (this.files.length === 1) return this.files[0].magnetUri | ||
134 | |||
135 | // Find first video that is good for our download speed (remember they are sorted) | ||
136 | let betterResolutionFile = this.files.find(f => actualDownloadSpeed > (f.size / this.duration)) | ||
137 | |||
138 | // If the download speed is too bad, return the lowest resolution we have | ||
139 | if (betterResolutionFile === undefined) { | ||
140 | betterResolutionFile = this.files.find(f => f.resolution === VideoResolution.H_240P) | ||
141 | } | ||
142 | |||
143 | return betterResolutionFile.magnetUri | ||
144 | } | ||
145 | |||
146 | patch (values: Object) { | ||
147 | Object.keys(values).forEach((key) => { | ||
148 | this[key] = values[key] | ||
149 | }) | ||
150 | } | ||
151 | |||
152 | toJSON () { | ||
153 | return { | ||
154 | author: this.author, | ||
155 | createdAt: this.createdAt, | ||
156 | category: this.category, | ||
157 | licence: this.licence, | ||
158 | language: this.language, | ||
159 | description: this.description, | ||
160 | duration: this.duration, | ||
161 | id: this.id, | ||
162 | isLocal: this.isLocal, | ||
163 | name: this.name, | ||
164 | podHost: this.podHost, | ||
165 | tags: this.tags, | ||
166 | thumbnailPath: this.thumbnailPath, | ||
167 | views: this.views, | ||
168 | likes: this.likes, | ||
169 | dislikes: this.dislikes, | ||
170 | nsfw: this.nsfw, | ||
171 | files: this.files | ||
172 | } | ||
173 | } | ||
174 | } | 90 | } |
diff --git a/client/src/app/videos/shared/video.service.ts b/client/src/app/videos/shared/video.service.ts index fc552f2b5..06fb3313e 100644 --- a/client/src/app/videos/shared/video.service.ts +++ b/client/src/app/videos/shared/video.service.ts | |||
@@ -12,6 +12,8 @@ import { | |||
12 | UserService | 12 | UserService |
13 | } from '../../shared' | 13 | } from '../../shared' |
14 | import { Video } from './video.model' | 14 | import { Video } from './video.model' |
15 | import { VideoDetails } from './video-details.model' | ||
16 | import { VideoEdit } from './video-edit.model' | ||
15 | import { VideoPagination } from './video-pagination.model' | 17 | import { VideoPagination } from './video-pagination.model' |
16 | import { | 18 | import { |
17 | UserVideoRate, | 19 | UserVideoRate, |
@@ -20,6 +22,7 @@ import { | |||
20 | VideoAbuseCreate, | 22 | VideoAbuseCreate, |
21 | UserVideoRateUpdate, | 23 | UserVideoRateUpdate, |
22 | Video as VideoServerModel, | 24 | Video as VideoServerModel, |
25 | VideoDetails as VideoDetailsServerModel, | ||
23 | ResultList | 26 | ResultList |
24 | } from '../../../../../shared' | 27 | } from '../../../../../shared' |
25 | 28 | ||
@@ -34,12 +37,12 @@ export class VideoService { | |||
34 | ) {} | 37 | ) {} |
35 | 38 | ||
36 | getVideo (uuid: string) { | 39 | getVideo (uuid: string) { |
37 | return this.authHttp.get<VideoServerModel>(VideoService.BASE_VIDEO_URL + uuid) | 40 | return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + uuid) |
38 | .map(videoHash => new Video(videoHash)) | 41 | .map(videoHash => new VideoDetails(videoHash)) |
39 | .catch((res) => this.restExtractor.handleError(res)) | 42 | .catch((res) => this.restExtractor.handleError(res)) |
40 | } | 43 | } |
41 | 44 | ||
42 | updateVideo (video: Video) { | 45 | updateVideo (video: VideoEdit) { |
43 | const language = video.language ? video.language : null | 46 | const language = video.language ? video.language : null |
44 | 47 | ||
45 | const body: VideoUpdate = { | 48 | const body: VideoUpdate = { |