Better typings

This commit is contained in:
Chocobozzz 2018-10-18 14:35:31 +02:00
parent cdf4cb9eaf
commit c199c427d4
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
65 changed files with 1606 additions and 150 deletions

View File

@ -23,7 +23,7 @@ export class VideoWatchPage {
getVideosListName () { getVideosListName () {
return element.all(by.css('.videos .video-miniature .video-miniature-name')) return element.all(by.css('.videos .video-miniature .video-miniature-name'))
.getText() .getText()
.then((texts: any) => texts.map(t => t.trim())) .then((texts: any) => texts.map((t: any) => t.trim()))
} }
waitWatchVideoName (videoName: string, isMobileDevice: boolean, isSafari: boolean) { waitWatchVideoName (videoName: string, isMobileDevice: boolean, isSafari: boolean) {

View File

@ -94,7 +94,7 @@
"@types/markdown-it": "^0.0.5", "@types/markdown-it": "^0.0.5",
"@types/node": "^10.9.2", "@types/node": "^10.9.2",
"@types/sanitize-html": "1.18.0", "@types/sanitize-html": "1.18.0",
"@types/video.js": "6.2.7", "@types/video.js": "^7.2.5",
"@types/webtorrent": "^0.98.4", "@types/webtorrent": "^0.98.4",
"angular2-hotkeys": "^2.1.2", "angular2-hotkeys": "^2.1.2",
"angular2-notifications": "^1.0.2", "angular2-notifications": "^1.0.2",

View File

@ -62,7 +62,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
} }
ngOnInit () { ngOnInit () {
const formGroupData: any = { const formGroupData: { [key: string]: any } = {
instanceName: this.customConfigValidatorsService.INSTANCE_NAME, instanceName: this.customConfigValidatorsService.INSTANCE_NAME,
instanceShortDescription: this.customConfigValidatorsService.INSTANCE_SHORT_DESCRIPTION, instanceShortDescription: this.customConfigValidatorsService.INSTANCE_SHORT_DESCRIPTION,
instanceDescription: null, instanceDescription: null,
@ -202,7 +202,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
} }
private updateForm () { private updateForm () {
const data: any = { const data: { [key: string]: any } = {
instanceName: this.customConfig.instance.name, instanceName: this.customConfig.instance.name,
instanceShortDescription: this.customConfig.instance.shortDescription, instanceShortDescription: this.customConfig.instance.shortDescription,
instanceDescription: this.customConfig.instance.description, instanceDescription: this.customConfig.instance.description,

View File

@ -7,7 +7,7 @@ export abstract class UserEdit extends FormReactive {
videoQuotaOptions: { value: string, label: string }[] = [] videoQuotaOptions: { value: string, label: string }[] = []
videoQuotaDailyOptions: { value: string, label: string }[] = [] videoQuotaDailyOptions: { value: string, label: string }[] = []
roles = Object.keys(USER_ROLE_LABELS).map((key: any) => ({ value: key.toString(), label: USER_ROLE_LABELS[key] })) roles = Object.keys(USER_ROLE_LABELS).map(key => ({ value: key.toString(), label: USER_ROLE_LABELS[key] }))
protected abstract serverService: ServerService protected abstract serverService: ServerService
protected abstract configService: ConfigService protected abstract configService: ConfigService

View File

@ -23,7 +23,7 @@ export class UserListComponent extends RestTable implements OnInit {
pagination: RestPagination = { count: this.rowsPerPage, start: 0 } pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
selectedUsers: User[] = [] selectedUsers: User[] = []
bulkUserActions: DropdownAction<User>[] = [] bulkUserActions: DropdownAction<User[]>[] = []
constructor ( constructor (
private notificationsService: NotificationsService, private notificationsService: NotificationsService,
@ -45,12 +45,12 @@ export class UserListComponent extends RestTable implements OnInit {
{ {
label: this.i18n('Ban'), label: this.i18n('Ban'),
handler: users => this.openBanUserModal(users), handler: users => this.openBanUserModal(users),
isDisplayed: users => users.every((u: any) => u.blocked === false) isDisplayed: users => users.every(u => u.blocked === false)
}, },
{ {
label: this.i18n('Unban'), label: this.i18n('Unban'),
handler: users => this.unbanUsers(users), handler: users => this.unbanUsers(users),
isDisplayed: users => users.every((u: any) => u.blocked === true) isDisplayed: users => users.every(u => u.blocked === true)
} }
] ]
} }

View File

@ -1,4 +1,4 @@
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core' import { Component, OnDestroy, OnInit } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router' import { ActivatedRoute, Router } from '@angular/router'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit' import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit'
@ -17,11 +17,9 @@ import { VideoChannelValidatorsService } from '@app/shared/forms/form-validators
styleUrls: [ './my-account-video-channel-edit.component.scss' ] styleUrls: [ './my-account-video-channel-edit.component.scss' ]
}) })
export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelEdit implements OnInit, OnDestroy { export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelEdit implements OnInit, OnDestroy {
@ViewChild('avatarfileInput') avatarfileInput: any
error: string error: string
videoChannelToUpdate: VideoChannel videoChannelToUpdate: VideoChannel
private paramsSub: Subscription private paramsSub: Subscription
constructor ( constructor (

View File

@ -66,7 +66,7 @@ export class MyAccountVideosComponent extends AbstractVideoList implements OnIni
} }
isInSelectionMode () { isInSelectionMode () {
return Object.keys(this.checkedVideos).some((k: any) => this.checkedVideos[ k ] === true) return Object.keys(this.checkedVideos).some(k => this.checkedVideos[ k ] === true)
} }
getVideosObservable (page: number) { getVideosObservable (page: number) {
@ -81,7 +81,7 @@ export class MyAccountVideosComponent extends AbstractVideoList implements OnIni
async deleteSelectedVideos () { async deleteSelectedVideos () {
const toDeleteVideosIds = Object.keys(this.checkedVideos) const toDeleteVideosIds = Object.keys(this.checkedVideos)
.filter((k: any) => this.checkedVideos[ k ] === true) .filter(k => this.checkedVideos[ k ] === true)
.map(k => parseInt(k, 10)) .map(k => parseInt(k, 10))
const res = await this.confirmService.confirm( const res = await this.confirmService.confirm(
@ -168,10 +168,9 @@ export class MyAccountVideosComponent extends AbstractVideoList implements OnIni
} }
private spliceVideosById (id: number) { private spliceVideosById (id: number) {
let key: any for (const key of Object.keys(this.loadedPages)) {
for (key of Object.keys(this.loadedPages)) { const videos: Video[] = this.loadedPages[ key ]
const videos = this.loadedPages[ key ] const index = videos.findIndex(v => v.id === id)
const index = videos.findIndex((v: any) => v.id === id)
if (index !== -1) { if (index !== -1) {
videos.splice(index, 1) videos.splice(index, 1)

View File

@ -49,8 +49,7 @@ export class VideoChangeOwnershipComponent extends FormReactive implements OnIni
.catch((_) => _) // Called when closing (cancel) the modal without validating, do nothing .catch((_) => _) // Called when closing (cancel) the modal without validating, do nothing
} }
// TODO: typing search (event: { query: string }) {
search (event: any) {
const query = event.query const query = event.query
this.userService.autocomplete(query) this.userService.autocomplete(query)
.subscribe( .subscribe(

View File

@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core' import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core'
import { ServerService } from '../../core/server' import { ServerService } from '../../core/server'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { VideoChannel } from '@app/shared/video-channel/video-channel.model' import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
@ -10,7 +10,7 @@ import { Account } from '@app/shared/account/account.model'
styleUrls: [ './actor-avatar-info.component.scss' ] styleUrls: [ './actor-avatar-info.component.scss' ]
}) })
export class ActorAvatarInfoComponent { export class ActorAvatarInfoComponent {
@ViewChild('avatarfileInput') avatarfileInput: any @ViewChild('avatarfileInput') avatarfileInput: ElementRef<HTMLInputElement>
@Input() actor: VideoChannel | Account @Input() actor: VideoChannel | Account

View File

@ -221,7 +221,7 @@ export class AuthService {
} }
refreshUserInformation () { refreshUserInformation () {
const obj: any = { const obj: UserLoginWithUsername = {
access_token: this.user.getAccessToken(), access_token: this.user.getAccessToken(),
refresh_token: null, refresh_token: null,
token_type: this.user.getTokenType(), token_type: this.user.getTokenType(),

View File

@ -154,8 +154,8 @@ export class ServerService {
this.localeObservable this.localeObservable
.pipe( .pipe(
switchMap(translations => { switchMap(translations => {
return this.http.get(ServerService.BASE_VIDEO_URL + attributeName) return this.http.get<{ [id: string]: string }>(ServerService.BASE_VIDEO_URL + attributeName)
.pipe(map((data: any) => ({ data, translations }))) .pipe(map(data => ({ data, translations })))
}) })
) )
.subscribe(({ data, translations }) => { .subscribe(({ data, translations }) => {

View File

@ -18,7 +18,7 @@ export class MenuComponent implements OnInit {
userHasAdminAccess = false userHasAdminAccess = false
helpVisible = false helpVisible = false
private routesPerRight: any = { private routesPerRight: { [ role in UserRight ]?: string } = {
[UserRight.MANAGE_USERS]: '/admin/users', [UserRight.MANAGE_USERS]: '/admin/users',
[UserRight.MANAGE_SERVER_FOLLOW]: '/admin/friends', [UserRight.MANAGE_SERVER_FOLLOW]: '/admin/friends',
[UserRight.MANAGE_VIDEO_ABUSES]: '/admin/moderation/video-abuses', [UserRight.MANAGE_VIDEO_ABUSES]: '/admin/moderation/video-abuses',

View File

@ -53,7 +53,7 @@ export class AdvancedSearch {
} }
containsValues () { containsValues () {
const obj: any = this.toUrlObject() const obj = this.toUrlObject()
for (const k of Object.keys(obj)) { for (const k of Object.keys(obj)) {
if (k === 'sort') continue // Exception if (k === 'sort') continue // Exception
@ -113,7 +113,7 @@ export class AdvancedSearch {
size () { size () {
let acc = 0 let acc = 0
const obj: any = this.toUrlObject() const obj = this.toUrlObject()
for (const k of Object.keys(obj)) { for (const k of Object.keys(obj)) {
if (k === 'sort') continue // Exception if (k === 'sort') continue // Exception

View File

@ -2,9 +2,9 @@ import { Component, Input } from '@angular/core'
export type DropdownAction<T> = { export type DropdownAction<T> = {
label?: string label?: string
handler?: (T: any) => any handler?: (a: T) => any
linkBuilder?: (T: any) => (string | number)[] linkBuilder?: (a: T) => (string | number)[]
isDisplayed?: (T: any) => boolean isDisplayed?: (a: T) => boolean
} }
@Component({ @Component({

View File

@ -8,9 +8,9 @@ import { Component, Input } from '@angular/core'
export class ButtonComponent { export class ButtonComponent {
@Input() label = '' @Input() label = ''
@Input() className: any = undefined @Input() className: string = undefined
@Input() icon: any = undefined @Input() icon: string = undefined
@Input() title: any = undefined @Input() title: string = undefined
getTitle () { getTitle () {
return this.title || this.label return this.title || this.label

View File

@ -8,5 +8,5 @@ import { Component, Input } from '@angular/core'
export class EditButtonComponent { export class EditButtonComponent {
@Input() label: string @Input() label: string
@Input() routerLink: any = [] @Input() routerLink: string[] = []
} }

View File

@ -4,8 +4,10 @@ import { Observable } from 'rxjs'
import { ConfirmService } from '../../core/index' import { ConfirmService } from '../../core/index'
import { I18n } from '@ngx-translate/i18n-polyfill' import { I18n } from '@ngx-translate/i18n-polyfill'
export type CanComponentDeactivateResult = { text?: string, canDeactivate: Observable<boolean> | boolean }
export interface CanComponentDeactivate { export interface CanComponentDeactivate {
canDeactivate: () => { text?: string, canDeactivate: Observable<boolean> | boolean } canDeactivate: () => CanComponentDeactivateResult
} }
@Injectable() @Injectable()

View File

@ -60,7 +60,7 @@ export class HelpComponent implements OnInit, OnChanges {
} }
private createMarkdownList (rules: string[]) { private createMarkdownList (rules: string[]) {
const rulesToText: any = { const rulesToText = {
'emphasis': this.i18n('Emphasis'), 'emphasis': this.i18n('Emphasis'),
'link': this.i18n('Links'), 'link': this.i18n('Links'),
'newline': this.i18n('New lines'), 'newline': this.i18n('New lines'),

View File

@ -33,7 +33,7 @@ export class RestExtractor {
return this.applyToResultListData(result, this.convertDateToHuman, [ fieldsToConvert ]) return this.applyToResultListData(result, this.convertDateToHuman, [ fieldsToConvert ])
} }
convertDateToHuman (target: any, fieldsToConvert: string[]) { convertDateToHuman (target: { [ id: string ]: string }, fieldsToConvert: string[]) {
fieldsToConvert.forEach(field => target[field] = dateToHuman(target[field])) fieldsToConvert.forEach(field => target[field] = dateToHuman(target[field]))
return target return target
@ -83,7 +83,7 @@ export class RestExtractor {
errorMessage = err errorMessage = err
} }
const errorObj: any = { const errorObj: { message: string, status: string, body: string } = {
message: errorMessage, message: errorMessage,
status: undefined, status: undefined,
body: undefined body: undefined

View File

@ -32,7 +32,7 @@ export class RestService {
return newParams return newParams
} }
addObjectParams (params: HttpParams, object: any) { addObjectParams (params: HttpParams, object: { [ name: string ]: any }) {
for (const name of Object.keys(object)) { for (const name of Object.keys(object)) {
const value = object[name] const value = object[name]
if (!value) continue if (!value) continue

View File

@ -25,7 +25,7 @@ import { VideoAbuseService } from './video-abuse'
import { VideoBlacklistService } from './video-blacklist' import { VideoBlacklistService } from './video-blacklist'
import { VideoOwnershipService } from './video-ownership' import { VideoOwnershipService } from './video-ownership'
import { VideoMiniatureComponent } from './video/video-miniature.component' import { VideoMiniatureComponent } from './video/video-miniature.component'
import { VideoFeedComponent } from './video/video-feed.component' import { FeedComponent } from './video/feed.component'
import { VideoThumbnailComponent } from './video/video-thumbnail.component' import { VideoThumbnailComponent } from './video/video-thumbnail.component'
import { VideoService } from './video/video.service' import { VideoService } from './video/video.service'
import { AccountService } from '@app/shared/account/account.service' import { AccountService } from '@app/shared/account/account.service'
@ -82,7 +82,7 @@ import { BlocklistService } from '@app/shared/blocklist'
LoaderComponent, LoaderComponent,
VideoThumbnailComponent, VideoThumbnailComponent,
VideoMiniatureComponent, VideoMiniatureComponent,
VideoFeedComponent, FeedComponent,
ButtonComponent, ButtonComponent,
DeleteButtonComponent, DeleteButtonComponent,
EditButtonComponent, EditButtonComponent,
@ -122,7 +122,7 @@ import { BlocklistService } from '@app/shared/blocklist'
LoaderComponent, LoaderComponent,
VideoThumbnailComponent, VideoThumbnailComponent,
VideoMiniatureComponent, VideoMiniatureComponent,
VideoFeedComponent, FeedComponent,
ButtonComponent, ButtonComponent,
DeleteButtonComponent, DeleteButtonComponent,
EditButtonComponent, EditButtonComponent,

View File

@ -43,7 +43,6 @@ export class User implements UserServerModel {
blocked: boolean blocked: boolean
blockedReason?: string blockedReason?: string
[key: string]: any
constructor (hash: UserConstructorHash) { constructor (hash: UserConstructorHash) {
this.id = hash.id this.id = hash.id

View File

@ -3,7 +3,7 @@
<div *ngIf="titlePage" class="title-page title-page-single"> <div *ngIf="titlePage" class="title-page title-page-single">
{{ titlePage }} {{ titlePage }}
</div> </div>
<my-video-feed [syndicationItems]="syndicationItems"></my-video-feed> <my-feed [syndicationItems]="syndicationItems"></my-feed>
<div class="moderation-block" *ngIf="displayModerationBlock"> <div class="moderation-block" *ngIf="displayModerationBlock">
<my-peertube-checkbox <my-peertube-checkbox

View File

@ -17,7 +17,7 @@
margin: 0 5px 0 0; margin: 0 5px 0 0;
} }
my-video-feed { my-feed {
display: inline-block; display: inline-block;
position: relative; position: relative;
top: 1px; top: 1px;

View File

@ -12,6 +12,7 @@ import { Video } from './video.model'
import { I18n } from '@ngx-translate/i18n-polyfill' import { I18n } from '@ngx-translate/i18n-polyfill'
import { ScreenService } from '@app/shared/misc/screen.service' import { ScreenService } from '@app/shared/misc/screen.service'
import { OwnerDisplayType } from '@app/shared/video/video-miniature.component' import { OwnerDisplayType } from '@app/shared/video/video-miniature.component'
import { Syndication } from '@app/shared/video/syndication.model'
export abstract class AbstractVideoList implements OnInit, OnDestroy { export abstract class AbstractVideoList implements OnInit, OnDestroy {
private static LINES_PER_PAGE = 4 private static LINES_PER_PAGE = 4
@ -27,7 +28,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy {
sort: VideoSortField = '-publishedAt' sort: VideoSortField = '-publishedAt'
categoryOneOf?: number categoryOneOf?: number
defaultSort: VideoSortField = '-publishedAt' defaultSort: VideoSortField = '-publishedAt'
syndicationItems: any = [] syndicationItems: Syndication[] = []
loadOnInit = true loadOnInit = true
marginContent = true marginContent = true
@ -59,7 +60,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy {
private resizeSubscription: Subscription private resizeSubscription: Subscription
abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number}> abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number}>
abstract generateSyndicationList (): any abstract generateSyndicationList (): void
get user () { get user () {
return this.authService.getUser() return this.authService.getUser()
@ -209,9 +210,11 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy {
} }
protected setNewRouteParams () { protected setNewRouteParams () {
const paramsObject: any = this.buildRouteParams() const paramsObject = this.buildRouteParams()
const queryParams = Object.keys(paramsObject).map(p => p + '=' + paramsObject[p]).join('&') const queryParams = Object.keys(paramsObject)
.map(p => p + '=' + paramsObject[p])
.join('&')
this.location.replaceState(this.currentRoute, queryParams) this.location.replaceState(this.currentRoute, queryParams)
} }

View File

@ -0,0 +1,11 @@
import { Component, Input } from '@angular/core'
import { Syndication } from '@app/shared/video/syndication.model'
@Component({
selector: 'my-feed',
styleUrls: [ './feed.component.scss' ],
templateUrl: './feed.component.html'
})
export class FeedComponent {
@Input() syndicationItems: Syndication[]
}

View File

@ -0,0 +1,7 @@
import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum'
export interface Syndication {
format: FeedFormat,
label: string,
url: string
}

View File

@ -25,7 +25,6 @@ export class VideoEdit implements VideoUpdate {
uuid?: string uuid?: string
id?: number id?: number
scheduleUpdate?: VideoScheduleUpdate scheduleUpdate?: VideoScheduleUpdate
[key: string]: any
constructor (video?: Video & { tags: string[], commentsEnabled: boolean, support: string, thumbnailUrl: string, previewUrl: string }) { constructor (video?: Video & { tags: string[], commentsEnabled: boolean, support: string, thumbnailUrl: string, previewUrl: string }) {
if (video) { if (video) {
@ -50,14 +49,14 @@ export class VideoEdit implements VideoUpdate {
} }
} }
patch (values: any) { patch (values: { [ id: string ]: string }) {
Object.keys(values).forEach((key) => { Object.keys(values).forEach((key) => {
this[ key ] = values[ key ] this[ key ] = values[ key ]
}) })
// If schedule publication, the video is private and will be changed to public privacy // If schedule publication, the video is private and will be changed to public privacy
if (parseInt(values['privacy'], 10) === VideoEdit.SPECIAL_SCHEDULED_PRIVACY) { if (parseInt(values['privacy'], 10) === VideoEdit.SPECIAL_SCHEDULED_PRIVACY) {
const updateAt = (values['schedulePublicationAt'] as Date) const updateAt = new Date(values['schedulePublicationAt'])
updateAt.setSeconds(0) updateAt.setSeconds(0)
this.privacy = VideoPrivacy.PRIVATE this.privacy = VideoPrivacy.PRIVATE

View File

@ -1,10 +0,0 @@
import { Component, Input } from '@angular/core'
@Component({
selector: 'my-video-feed',
styleUrls: [ './video-feed.component.scss' ],
templateUrl: './video-feed.component.html'
})
export class VideoFeedComponent {
@Input() syndicationItems: any
}

View File

@ -274,9 +274,9 @@ export class VideoService implements VideosProvider {
loadCompleteDescription (descriptionPath: string) { loadCompleteDescription (descriptionPath: string) {
return this.authHttp return this.authHttp
.get(environment.apiUrl + descriptionPath) .get<{ description: string }>(environment.apiUrl + descriptionPath)
.pipe( .pipe(
map((res: any) => res[ 'description' ]), map(res => res.description),
catchError(err => this.restExtractor.handleError(err)) catchError(err => this.restExtractor.handleError(err))
) )
} }

View File

@ -5,6 +5,7 @@ import { VideoCaptionsValidatorsService } from '@app/shared/forms/form-validator
import { ServerService } from '@app/core' import { ServerService } from '@app/core'
import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model' import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model'
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
import { VideoConstant } from '../../../../../../shared'
@Component({ @Component({
selector: 'my-video-caption-add-modal', selector: 'my-video-caption-add-modal',
@ -19,7 +20,7 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
@ViewChild('modal') modal: ElementRef @ViewChild('modal') modal: ElementRef
videoCaptionLanguages: any = [] videoCaptionLanguages: VideoConstant<string>[] = []
private openedModal: NgbModalRef private openedModal: NgbModalRef
private closingModal = false private closingModal = false
@ -73,7 +74,7 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
this.hide() this.hide()
const languageId = this.form.value[ 'language' ] const languageId = this.form.value[ 'language' ]
const languageObject = this.videoCaptionLanguages.find((l: any) => l.id === languageId) const languageObject = this.videoCaptionLanguages.find(l => l.id === languageId)
this.captionAdded.emit({ this.captionAdded.emit({
language: languageObject, language: languageObject,

View File

@ -1,4 +1,4 @@
import { Component, EventEmitter, OnInit, Output, ViewChild } from '@angular/core' import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { VideoPrivacy, VideoUpdate } from '../../../../../../shared/models/videos' import { VideoPrivacy, VideoUpdate } from '../../../../../../shared/models/videos'
@ -23,7 +23,7 @@ import { VideoImportService } from '@app/shared/video-import'
}) })
export class VideoImportTorrentComponent extends VideoSend implements OnInit, CanComponentDeactivate { export class VideoImportTorrentComponent extends VideoSend implements OnInit, CanComponentDeactivate {
@Output() firstStepDone = new EventEmitter<string>() @Output() firstStepDone = new EventEmitter<string>()
@ViewChild('torrentfileInput') torrentfileInput: any @ViewChild('torrentfileInput') torrentfileInput: ElementRef<HTMLInputElement>
videoFileName: string videoFileName: string
magnetUri = '' magnetUri = ''
@ -64,7 +64,7 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Ca
} }
fileChange () { fileChange () {
const torrentfile = this.torrentfileInput.nativeElement.files[0] as File const torrentfile = this.torrentfileInput.nativeElement.files[0]
if (!torrentfile) return if (!torrentfile) return
this.importVideo(torrentfile) this.importVideo(torrentfile)

View File

@ -3,7 +3,6 @@ import { LoadingBarService } from '@ngx-loading-bar/core'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { catchError, switchMap, tap } from 'rxjs/operators' import { catchError, switchMap, tap } from 'rxjs/operators'
import { FormReactive } from '@app/shared' import { FormReactive } from '@app/shared'
import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard.service'
import { VideoConstant, VideoPrivacy } from '../../../../../../shared' import { VideoConstant, VideoPrivacy } from '../../../../../../shared'
import { AuthService, ServerService } from '@app/core' import { AuthService, ServerService } from '@app/core'
import { VideoService } from '@app/shared/video/video.service' import { VideoService } from '@app/shared/video/video.service'
@ -11,8 +10,9 @@ import { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.m
import { VideoCaptionService } from '@app/shared/video-caption' import { VideoCaptionService } from '@app/shared/video-caption'
import { VideoEdit } from '@app/shared/video/video-edit.model' import { VideoEdit } from '@app/shared/video/video-edit.model'
import { populateAsyncUserVideoChannels } from '@app/shared/misc/utils' import { populateAsyncUserVideoChannels } from '@app/shared/misc/utils'
import { CanComponentDeactivateResult } from '@app/shared/guards/can-deactivate-guard.service'
export abstract class VideoSend extends FormReactive implements OnInit, CanComponentDeactivate { export abstract class VideoSend extends FormReactive implements OnInit {
userVideoChannels: { id: number, label: string, support: string }[] = [] userVideoChannels: { id: number, label: string, support: string }[] = []
videoPrivacies: VideoConstant<VideoPrivacy>[] = [] videoPrivacies: VideoConstant<VideoPrivacy>[] = []
videoCaptions: VideoCaptionEdit[] = [] videoCaptions: VideoCaptionEdit[] = []
@ -30,7 +30,7 @@ export abstract class VideoSend extends FormReactive implements OnInit, CanCompo
protected videoService: VideoService protected videoService: VideoService
protected videoCaptionService: VideoCaptionService protected videoCaptionService: VideoCaptionService
abstract canDeactivate (): any abstract canDeactivate (): CanComponentDeactivateResult
ngOnInit () { ngOnInit () {
this.buildForm({}) this.buildForm({})

View File

@ -1,5 +1,5 @@
import { HttpEventType, HttpResponse } from '@angular/common/http' import { HttpEventType, HttpResponse } from '@angular/common/http'
import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' import { Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'
import { Router } from '@angular/router' import { Router } from '@angular/router'
import { LoadingBarService } from '@ngx-loading-bar/core' import { LoadingBarService } from '@ngx-loading-bar/core'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
@ -25,7 +25,7 @@ import { VideoCaptionService } from '@app/shared/video-caption'
}) })
export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy, CanComponentDeactivate { export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy, CanComponentDeactivate {
@Output() firstStepDone = new EventEmitter<string>() @Output() firstStepDone = new EventEmitter<string>()
@ViewChild('videofileInput') videofileInput: any @ViewChild('videofileInput') videofileInput: ElementRef<HTMLInputElement>
// So that it can be accessed in the template // So that it can be accessed in the template
readonly SPECIAL_SCHEDULED_PRIVACY = VideoEdit.SPECIAL_SCHEDULED_PRIVACY readonly SPECIAL_SCHEDULED_PRIVACY = VideoEdit.SPECIAL_SCHEDULED_PRIVACY
@ -110,7 +110,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
} }
uploadFirstStep () { uploadFirstStep () {
const videofile = this.videofileInput.nativeElement.files[0] as File const videofile = this.videofileInput.nativeElement.files[0]
if (!videofile) return if (!videofile) return
// Cannot upload videos > 8GB for now // Cannot upload videos > 8GB for now

View File

@ -1,5 +1,6 @@
import { Injectable } from '@angular/core' import { Injectable } from '@angular/core'
import { getAbsoluteAPIUrl } from '@app/shared/misc/utils' import { getAbsoluteAPIUrl } from '@app/shared/misc/utils'
// FIXME: use @types/linkify when https://github.com/DefinitelyTyped/DefinitelyTyped/pull/29682/files is merged?
const linkify = require('linkifyjs') const linkify = require('linkifyjs')
const linkifyHtml = require('linkifyjs/html') const linkifyHtml = require('linkifyjs/html')

View File

@ -26,7 +26,7 @@ export class VideoCommentComponent implements OnInit, OnChanges {
@Output() resetReply = new EventEmitter() @Output() resetReply = new EventEmitter()
sanitizedCommentHTML = '' sanitizedCommentHTML = ''
newParentComments: any = [] newParentComments: VideoComment[] = []
constructor ( constructor (
private linkifierService: LinkifierService, private linkifierService: LinkifierService,

View File

@ -30,9 +30,9 @@ export class VideoCommentService {
const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comment-threads' const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comment-threads'
const normalizedComment = lineFeedToHtml(comment, 'text') const normalizedComment = lineFeedToHtml(comment, 'text')
return this.authHttp.post(url, normalizedComment) return this.authHttp.post<{ comment: VideoCommentServerModel }>(url, normalizedComment)
.pipe( .pipe(
map((data: any) => this.extractVideoComment(data['comment'])), map(data => this.extractVideoComment(data.comment)),
catchError(err => this.restExtractor.handleError(err)) catchError(err => this.restExtractor.handleError(err))
) )
} }
@ -41,9 +41,9 @@ export class VideoCommentService {
const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comments/' + inReplyToCommentId const url = VideoCommentService.BASE_VIDEO_URL + videoId + '/comments/' + inReplyToCommentId
const normalizedComment = lineFeedToHtml(comment, 'text') const normalizedComment = lineFeedToHtml(comment, 'text')
return this.authHttp.post(url, normalizedComment) return this.authHttp.post<{ comment: VideoCommentServerModel }>(url, normalizedComment)
.pipe( .pipe(
map((data: any) => this.extractVideoComment(data[ 'comment' ])), map(data => this.extractVideoComment(data.comment)),
catchError(err => this.restExtractor.handleError(err)) catchError(err => this.restExtractor.handleError(err))
) )
} }

View File

@ -4,7 +4,7 @@
Comments Comments
</div> </div>
<my-video-feed [syndicationItems]="syndicationItems"></my-video-feed> <my-feed [syndicationItems]="syndicationItems"></my-feed>
</div> </div>
<ng-template [ngIf]="video.commentsEnabled === true"> <ng-template [ngIf]="video.commentsEnabled === true">

View File

@ -23,7 +23,7 @@
margin-right: 0; margin-right: 0;
} }
my-video-feed { my-feed {
display: inline-block; display: inline-block;
margin-left: 5px; margin-left: 5px;
} }

View File

@ -12,6 +12,7 @@ import { VideoDetails } from '../../../shared/video/video-details.model'
import { VideoComment } from './video-comment.model' import { VideoComment } from './video-comment.model'
import { VideoCommentService } from './video-comment.service' import { VideoCommentService } from './video-comment.service'
import { I18n } from '@ngx-translate/i18n-polyfill' import { I18n } from '@ngx-translate/i18n-polyfill'
import { Syndication } from '@app/shared/video/syndication.model'
@Component({ @Component({
selector: 'my-video-comments', selector: 'my-video-comments',
@ -35,7 +36,7 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
threadComments: { [ id: number ]: VideoCommentThreadTree } = {} threadComments: { [ id: number ]: VideoCommentThreadTree } = {}
threadLoading: { [ id: number ]: boolean } = {} threadLoading: { [ id: number ]: boolean } = {}
syndicationItems: any = [] syndicationItems: Syndication[] = []
private sub: Subscription private sub: Subscription

View File

@ -162,7 +162,7 @@ $other-videos-width: 260px;
} }
} }
my-video-feed { my-feed {
margin-left: 5px; margin-left: 5px;
margin-top: 1px; margin-top: 1px;
} }

View File

@ -7,7 +7,9 @@ import { VideoSupportComponent } from '@app/videos/+video-watch/modal/video-supp
import { MetaService } from '@ngx-meta/core' import { MetaService } from '@ngx-meta/core'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { forkJoin, Subscription } from 'rxjs' import { forkJoin, Subscription } from 'rxjs'
const videojs = require('video.js') // FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import videojs from 'video.js'
import 'videojs-hotkeys' import 'videojs-hotkeys'
import { Hotkey, HotkeysService } from 'angular2-hotkeys' import { Hotkey, HotkeysService } from 'angular2-hotkeys'
import * as WebTorrent from 'webtorrent' import * as WebTorrent from 'webtorrent'
@ -45,7 +47,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
@ViewChild('videoBlacklistModal') videoBlacklistModal: VideoBlacklistComponent @ViewChild('videoBlacklistModal') videoBlacklistModal: VideoBlacklistComponent
@ViewChild('subscribeButton') subscribeButton: SubscribeButtonComponent @ViewChild('subscribeButton') subscribeButton: SubscribeButtonComponent
player: any player: videojs.Player
playerElement: HTMLVideoElement playerElement: HTMLVideoElement
userRating: UserVideoRateType = null userRating: UserVideoRateType = null
video: VideoDetails = null video: VideoDetails = null
@ -435,7 +437,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
this.zone.runOutsideAngular(async () => { this.zone.runOutsideAngular(async () => {
videojs(this.playerElement, videojsOptions, function () { videojs(this.playerElement, videojsOptions, function () {
self.player = this self.player = this
this.on('customError', (data: any) => self.handleError(data.err)) this.on('customError', ({ err }: { err: any }) => self.handleError(err))
addContextMenu(self.player, self.video.embedUrl) addContextMenu(self.player, self.video.embedUrl)
}) })
@ -448,7 +450,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
this.checkUserRating() this.checkUserRating()
} }
private setRating (nextRating: string) { private setRating (nextRating: VideoRateType) {
let method let method
switch (nextRating) { switch (nextRating) {
case 'like': case 'like':
@ -466,11 +468,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
.subscribe( .subscribe(
() => { () => {
// Update the video like attribute // Update the video like attribute
this.updateVideoRating(this.userRating, nextRating as VideoRateType) this.updateVideoRating(this.userRating, nextRating)
this.userRating = nextRating as UserVideoRateType this.userRating = nextRating
}, },
(err: any) => this.notificationsService.error(this.i18n('Error'), err.message) (err: { message: string }) => this.notificationsService.error(this.i18n('Error'), err.message)
) )
} }

View File

@ -76,7 +76,7 @@ export class PeertubeChunkStore extends EventEmitter {
this.runCleaner() this.runCleaner()
} }
put (index: number, buf: Buffer, cb: Function) { put (index: number, buf: Buffer, cb: (err?: Error) => void) {
const isLastChunk = (index === this.lastChunkIndex) const isLastChunk = (index === this.lastChunkIndex)
if (isLastChunk && buf.length !== this.lastChunkLength) { if (isLastChunk && buf.length !== this.lastChunkLength) {
return this.nextTick(cb, new Error('Last chunk length must be ' + this.lastChunkLength)) return this.nextTick(cb, new Error('Last chunk length must be ' + this.lastChunkLength))
@ -113,7 +113,7 @@ export class PeertubeChunkStore extends EventEmitter {
}, PeertubeChunkStore.BUFFERING_PUT_MS) }, PeertubeChunkStore.BUFFERING_PUT_MS)
} }
get (index: number, opts: any, cb: any): any { get (index: number, opts: any, cb: (err?: Error, buf?: Buffer) => void): void {
if (typeof opts === 'function') return this.get(index, null, opts) if (typeof opts === 'function') return this.get(index, null, opts)
// IndexDB could be slow, use our memory index first // IndexDB could be slow, use our memory index first
@ -146,11 +146,11 @@ export class PeertubeChunkStore extends EventEmitter {
}) })
} }
close (db: any) { close (cb: (err?: Error) => void) {
return this.destroy(db) return this.destroy(cb)
} }
async destroy (cb: any) { async destroy (cb: (err?: Error) => void) {
try { try {
if (this.pendingPut) { if (this.pendingPut) {
clearTimeout(this.putBulkTimeout) clearTimeout(this.putBulkTimeout)
@ -225,7 +225,7 @@ export class PeertubeChunkStore extends EventEmitter {
} }
} }
private nextTick (cb: any, err: Error, val?: any) { private nextTick <T> (cb: (err?: Error, val?: T) => void, err: Error, val?: T) {
process.nextTick(() => cb(err, val), undefined) process.nextTick(() => cb(err, val), undefined)
} }
} }

View File

@ -1,10 +1,13 @@
import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
import { buildVideoLink } from './utils' import { buildVideoLink } from './utils'
// FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import { Player } from 'video.js'
const Button: VideoJSComponentInterface = videojsUntyped.getComponent('Button') const Button: VideoJSComponentInterface = videojsUntyped.getComponent('Button')
class PeerTubeLinkButton extends Button { class PeerTubeLinkButton extends Button {
constructor (player: any, options: any) { constructor (player: Player, options: any) {
super(player, options) super(player, options)
} }

View File

@ -1,10 +1,13 @@
import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
// FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import { Player } from 'video.js'
const Component: VideoJSComponentInterface = videojsUntyped.getComponent('Component') const Component: VideoJSComponentInterface = videojsUntyped.getComponent('Component')
class PeerTubeLoadProgressBar extends Component { class PeerTubeLoadProgressBar extends Component {
constructor (player: any, options: any) { constructor (player: Player, options: any) {
super(player, options) super(player, options)
this.partEls_ = [] this.partEls_ = []
this.on(player, 'progress', this.update) this.on(player, 'progress', this.update)

View File

@ -14,6 +14,10 @@ import { UserWatching, VideoJSCaption, videojsUntyped } from './peertube-videojs
import { buildVideoEmbed, buildVideoLink, copyToClipboard } from './utils' import { buildVideoEmbed, buildVideoLink, copyToClipboard } from './utils'
import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n' import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n'
// FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import { Player } from 'video.js'
// Change 'Playback Rate' to 'Speed' (smaller for our settings menu) // Change 'Playback Rate' to 'Speed' (smaller for our settings menu)
videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed' videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed'
// Change Captions to Subtitles/CC // Change Captions to Subtitles/CC
@ -75,12 +79,12 @@ function getVideojsOptions (options: {
enableVolumeScroll: false, enableVolumeScroll: false,
enableModifiersForNumbers: false, enableModifiersForNumbers: false,
fullscreenKey: function (event: any) { fullscreenKey: function (event: KeyboardEvent) {
// fullscreen with the f key or Ctrl+Enter // fullscreen with the f key or Ctrl+Enter
return event.key === 'f' || (event.ctrlKey && event.key === 'Enter') return event.key === 'f' || (event.ctrlKey && event.key === 'Enter')
}, },
seekStep: function (event: any) { seekStep: function (event: KeyboardEvent) {
// mimic VLC seek behavior, and default to 5 (original value is 5). // mimic VLC seek behavior, and default to 5 (original value is 5).
if (event.ctrlKey && event.altKey) { if (event.ctrlKey && event.altKey) {
return 5 * 60 return 5 * 60
@ -95,26 +99,26 @@ function getVideojsOptions (options: {
customKeys: { customKeys: {
increasePlaybackRateKey: { increasePlaybackRateKey: {
key: function (event: any) { key: function (event: KeyboardEvent) {
return event.key === '>' return event.key === '>'
}, },
handler: function (player: any) { handler: function (player: Player) {
player.playbackRate((player.playbackRate() + 0.1).toFixed(2)) player.playbackRate((player.playbackRate() + 0.1).toFixed(2))
} }
}, },
decreasePlaybackRateKey: { decreasePlaybackRateKey: {
key: function (event: any) { key: function (event: KeyboardEvent) {
return event.key === '<' return event.key === '<'
}, },
handler: function (player: any) { handler: function (player: Player) {
player.playbackRate((player.playbackRate() - 0.1).toFixed(2)) player.playbackRate((player.playbackRate() - 0.1).toFixed(2))
} }
}, },
frameByFrame: { frameByFrame: {
key: function (event: any) { key: function (event: KeyboardEvent) {
return event.key === '.' return event.key === '.'
}, },
handler: function (player: any) { handler: function (player: Player) {
player.pause() player.pause()
// Calculate movement distance (assuming 30 fps) // Calculate movement distance (assuming 30 fps)
const dist = 1 / 30 const dist = 1 / 30

View File

@ -1,11 +1,13 @@
const videojs = require('video.js') // FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import * as videojs from 'video.js'
import * as WebTorrent from 'webtorrent' import * as WebTorrent from 'webtorrent'
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'
import './settings-menu-button' import './settings-menu-button'
import { PeertubePluginOptions, UserWatching, VideoJSCaption, VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' import { PeertubePluginOptions, UserWatching, VideoJSCaption, VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
import { isMobile, timeToInt, videoFileMaxByResolution, videoFileMinByResolution } from './utils' import { isMobile, timeToInt, videoFileMaxByResolution, videoFileMinByResolution } from './utils'
const CacheChunkStore = require('cache-chunk-store')
import { PeertubeChunkStore } from './peertube-chunk-store' import { PeertubeChunkStore } from './peertube-chunk-store'
import { import {
getAverageBandwidthInStore, getAverageBandwidthInStore,
@ -17,6 +19,8 @@ import {
saveVolumeInStore saveVolumeInStore
} from './peertube-player-local-storage' } from './peertube-player-local-storage'
const CacheChunkStore = require('cache-chunk-store')
type PlayOptions = { type PlayOptions = {
forcePlay?: boolean, forcePlay?: boolean,
seek?: number, seek?: number,
@ -61,7 +65,7 @@ class PeerTubePlugin extends Plugin {
private player: any private player: any
private currentVideoFile: VideoFile private currentVideoFile: VideoFile
private torrent: any private torrent: WebTorrent.Torrent
private videoCaptions: VideoJSCaption[] private videoCaptions: VideoJSCaption[]
private renderer: any private renderer: any
@ -83,7 +87,7 @@ class PeerTubePlugin extends Plugin {
private downloadSpeeds: number[] = [] private downloadSpeeds: number[] = []
constructor (player: any, options: PeertubePluginOptions) { constructor (player: videojs.Player, options: PeertubePluginOptions) {
super(player, options) super(player, options)
// Disable auto play on iOS // Disable auto play on iOS
@ -273,7 +277,7 @@ class PeerTubePlugin extends Plugin {
const oldTorrent = this.torrent const oldTorrent = this.torrent
const torrentOptions = { const torrentOptions = {
store: (chunkLength: any, storeOpts: any) => new CacheChunkStore(new PeertubeChunkStore(chunkLength, storeOpts), { store: (chunkLength: number, storeOpts: any) => new CacheChunkStore(new PeertubeChunkStore(chunkLength, storeOpts), {
max: 100 max: 100
}) })
} }
@ -304,7 +308,7 @@ class PeerTubePlugin extends Plugin {
if (err) return this.fallbackToHttp(options, done) if (err) return this.fallbackToHttp(options, done)
return this.tryToPlay((err: Error) => { return this.tryToPlay(err => {
if (err) return done(err) if (err) return done(err)
if (options.seek) this.seek(options.seek) if (options.seek) this.seek(options.seek)
@ -344,7 +348,7 @@ class PeerTubePlugin extends Plugin {
}) })
} }
private tryToPlay (done?: Function) { private tryToPlay (done?: (err?: Error) => void) {
if (!done) done = function () { /* empty */ } if (!done) done = function () { /* empty */ }
const playPromise = this.player.play() const playPromise = this.player.play()
@ -641,7 +645,7 @@ class PeerTubePlugin extends Plugin {
return this.videoFiles[Math.floor(this.videoFiles.length / 2)] return this.videoFiles[Math.floor(this.videoFiles.length / 2)]
} }
private stopTorrent (torrent: any) { private stopTorrent (torrent: WebTorrent.Torrent) {
torrent.pause() torrent.pause()
// Pause does not remove actual peers (in particular the webseed peer) // Pause does not remove actual peers (in particular the webseed peer)
torrent.removePeer(torrent[ 'ws' ]) torrent.removePeer(torrent[ 'ws' ])

View File

@ -1,4 +1,7 @@
const videojs = require('video.js') // FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import * as videojs from 'video.js'
import { VideoFile } from '../../../../shared/models/videos/video.model' import { VideoFile } from '../../../../shared/models/videos/video.model'
import { PeerTubePlugin } from './peertube-videojs-plugin' import { PeerTubePlugin } from './peertube-videojs-plugin'

View File

@ -1,3 +1,7 @@
// FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import { Player } from 'video.js'
import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
import { ResolutionMenuItem } from './resolution-menu-item' import { ResolutionMenuItem } from './resolution-menu-item'
@ -6,7 +10,7 @@ const MenuButton: VideoJSComponentInterface = videojsUntyped.getComponent('MenuB
class ResolutionMenuButton extends MenuButton { class ResolutionMenuButton extends MenuButton {
label: HTMLElement label: HTMLElement
constructor (player: any, options: any) { constructor (player: Player, options: any) {
super(player, options) super(player, options)
this.player = player this.player = player

View File

@ -1,9 +1,13 @@
// FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import { Player } from 'video.js'
import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
const MenuItem: VideoJSComponentInterface = videojsUntyped.getComponent('MenuItem') const MenuItem: VideoJSComponentInterface = videojsUntyped.getComponent('MenuItem')
class ResolutionMenuItem extends MenuItem { class ResolutionMenuItem extends MenuItem {
constructor (player: any, options: any) { constructor (player: Player, options: any) {
const currentResolutionId = player.peertube().getCurrentResolutionId() const currentResolutionId = player.peertube().getCurrentResolutionId()
options.selectable = true options.selectable = true
options.selected = options.id === currentResolutionId options.selected = options.id === currentResolutionId

View File

@ -1,7 +1,10 @@
// Author: Yanko Shterev // Author: Yanko Shterev
// Thanks https://github.com/yshterev/videojs-settings-menu // Thanks https://github.com/yshterev/videojs-settings-menu
const videojs = require('video.js') // FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import * as videojs from 'video.js'
import { SettingsMenuItem } from './settings-menu-item' import { SettingsMenuItem } from './settings-menu-item'
import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
import { toTitleCase } from './utils' import { toTitleCase } from './utils'
@ -11,7 +14,7 @@ const Menu: VideoJSComponentInterface = videojsUntyped.getComponent('Menu')
const Component: VideoJSComponentInterface = videojsUntyped.getComponent('Component') const Component: VideoJSComponentInterface = videojsUntyped.getComponent('Component')
class SettingsButton extends Button { class SettingsButton extends Button {
constructor (player: any, options: any) { constructor (player: videojs.Player, options: any) {
super(player, options) super(player, options)
this.playerComponent = player this.playerComponent = player
@ -48,7 +51,7 @@ class SettingsButton extends Button {
} }
} }
onDisposeSettingsItem (name: string) { onDisposeSettingsItem (event: any, name: string) {
if (name === undefined) { if (name === undefined) {
let children = this.menu.children() let children = this.menu.children()
@ -74,7 +77,7 @@ class SettingsButton extends Button {
} }
} }
onAddSettingsItem (data: any) { onAddSettingsItem (event: any, data: any) {
const [ entry, options ] = data const [ entry, options ] = data
this.addMenuItem(entry, options) this.addMenuItem(entry, options)
@ -218,7 +221,7 @@ class SettingsButton extends Button {
} }
class SettingsPanel extends Component { class SettingsPanel extends Component {
constructor (player: any, options: any) { constructor (player: videojs.Player, options: any) {
super(player, options) super(player, options)
} }
@ -232,7 +235,7 @@ class SettingsPanel extends Component {
} }
class SettingsPanelChild extends Component { class SettingsPanelChild extends Component {
constructor (player: any, options: any) { constructor (player: videojs.Player, options: any) {
super(player, options) super(player, options)
} }
@ -246,7 +249,7 @@ class SettingsPanelChild extends Component {
} }
class SettingsDialog extends Component { class SettingsDialog extends Component {
constructor (player: any, options: any) { constructor (player: videojs.Player, options: any) {
super(player, options) super(player, options)
this.hide() this.hide()
} }

View File

@ -1,6 +1,10 @@
// Author: Yanko Shterev // Author: Yanko Shterev
// Thanks https://github.com/yshterev/videojs-settings-menu // Thanks https://github.com/yshterev/videojs-settings-menu
// FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import * as videojs from 'video.js'
import { toTitleCase } from './utils' import { toTitleCase } from './utils'
import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
@ -9,7 +13,7 @@ const component: VideoJSComponentInterface = videojsUntyped.getComponent('Compon
class SettingsMenuItem extends MenuItem { class SettingsMenuItem extends MenuItem {
constructor (player: any, options: any, entry: string, menuButton: VideoJSComponentInterface) { constructor (player: videojs.Player, options: any, entry: string, menuButton: VideoJSComponentInterface) {
super(player, options) super(player, options)
this.settingsButton = menuButton this.settingsButton = menuButton
@ -229,7 +233,7 @@ class SettingsMenuItem extends MenuItem {
} }
update (event?: any) { update (event?: any) {
let target = null let target: HTMLElement = null
let subMenu = this.subMenu.name() let subMenu = this.subMenu.name()
if (event && event.type === 'tap') { if (event && event.type === 'tap') {

View File

@ -1,3 +1,7 @@
// FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import * as videojs from 'video.js'
import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings' import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
import { saveTheaterInStore, getStoredTheater } from './peertube-player-local-storage' import { saveTheaterInStore, getStoredTheater } from './peertube-player-local-storage'
@ -6,7 +10,7 @@ class TheaterButton extends Button {
private static readonly THEATER_MODE_CLASS = 'vjs-theater-enabled' private static readonly THEATER_MODE_CLASS = 'vjs-theater-enabled'
constructor (player: any, options: any) { constructor (player: videojs.Player, options: any) {
super(player, options) super(player, options)
const enabled = getStoredTheater() const enabled = getStoredTheater()

View File

@ -12,7 +12,7 @@ const dictionaryBytes: Array<{max: number, type: string}> = [
{ max: 1073741824, type: 'MB' }, { max: 1073741824, type: 'MB' },
{ max: 1.0995116e12, type: 'GB' } { max: 1.0995116e12, type: 'GB' }
] ]
function bytes (value: any) { function bytes (value: number) {
const format = dictionaryBytes.find(d => value < d.max) || dictionaryBytes[dictionaryBytes.length - 1] const format = dictionaryBytes.find(d => value < d.max) || dictionaryBytes[dictionaryBytes.length - 1]
const calc = Math.floor(value / (format.max / 1024)).toString() const calc = Math.floor(value / (format.max / 1024)).toString()

View File

@ -65,7 +65,7 @@ class WebtorrentInfoButton extends Button {
subDivHttp.appendChild(subDivHttpText) subDivHttp.appendChild(subDivHttpText)
div.appendChild(subDivHttp) div.appendChild(subDivHttp)
this.player_.peertube().on('torrentInfo', (data: any) => { this.player_.peertube().on('torrentInfo', (event: any, data: any) => {
// We are in HTTP fallback // We are in HTTP fallback
if (!data) { if (!data) {
subDivHttp.className = 'vjs-peertube-displayed' subDivHttp.className = 'vjs-peertube-displayed'

View File

@ -17,7 +17,10 @@ import 'core-js/es6/set'
// For google bot that uses Chrome 41 and does not understand fetch // For google bot that uses Chrome 41 and does not understand fetch
import 'whatwg-fetch' import 'whatwg-fetch'
const vjs = require('video.js') // FIXME: something weird with our path definition in tsconfig and typings
// @ts-ignore
import vjs from 'video.js'
import * as Channel from 'jschannel' import * as Channel from 'jschannel'
import { peertubeTranslate, ResultList, VideoDetails } from '../../../../shared' import { peertubeTranslate, ResultList, VideoDetails } from '../../../../shared'
@ -304,7 +307,7 @@ class PeerTubeEmbed {
this.playerOptions = videojsOptions this.playerOptions = videojsOptions
this.player = vjs(this.videoContainerId, videojsOptions, () => { this.player = vjs(this.videoContainerId, videojsOptions, () => {
this.player.on('customError', (data: any) => this.handleError(data.err)) this.player.on('customError', (event: any, data: any) => this.handleError(data.err))
window[ 'videojsPlayer' ] = this.player window[ 'videojsPlayer' ] = this.player

View File

@ -1,6 +1,6 @@
import './test-embed.scss' import './test-embed.scss'
import { PeerTubePlayer } from '../player/player' import { PeerTubePlayer } from '../player/player'
import { PlayerEventType } from '../player/definitions' import { PeerTubeResolution, PlayerEventType } from '../player/definitions'
window.addEventListener('load', async () => { window.addEventListener('load', async () => {
const urlParts = window.location.href.split('/') const urlParts = window.location.href.split('/')
@ -66,11 +66,11 @@ window.addEventListener('load', async () => {
updateRates() updateRates()
}) })
let updateResolutions = ((resolutions: any) => { let updateResolutions = ((resolutions: PeerTubeResolution[]) => {
let resolutionListEl = document.querySelector('#resolution-list') let resolutionListEl = document.querySelector('#resolution-list')
resolutionListEl.innerHTML = '' resolutionListEl.innerHTML = ''
resolutions.forEach((resolution: any) => { resolutions.forEach(resolution => {
if (resolution.active) { if (resolution.active) {
let itemEl = document.createElement('strong') let itemEl = document.createElement('strong')
itemEl.innerText = `${resolution.label} (active)` itemEl.innerText = `${resolution.label} (active)`

View File

@ -1,6 +1,6 @@
/* SystemJS module definition */ /* SystemJS module definition */
declare var module: NodeModule; declare var module: NodeModule
interface NodeModule { interface NodeModule {
id: string; id: string
[key: string]: any
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
export const LOCALE_FILES = [ 'player', 'server' ] export const LOCALE_FILES = [ 'player', 'server' ]
export const I18N_LOCALES: any = { export const I18N_LOCALES = {
'en-US': 'English', 'en-US': 'English',
'fr-FR': 'Français', 'fr-FR': 'Français',
'eu-ES': 'Euskara', 'eu-ES': 'Euskara',
@ -17,7 +17,7 @@ export const I18N_LOCALES: any = {
'zh-Hans-CN': '简体中文(中国)' 'zh-Hans-CN': '简体中文(中国)'
} }
const I18N_LOCALE_ALIAS: any = { const I18N_LOCALE_ALIAS = {
'en': 'en-US', 'en': 'en-US',
'fr': 'fr-FR', 'fr': 'fr-FR',
'eu': 'eu-ES', 'eu': 'eu-ES',

View File

@ -15,5 +15,4 @@ export interface VideosOverview {
tag: string tag: string
videos: Video[] videos: Video[]
}[] }[]
[key: string]: any
} }

View File

@ -55,7 +55,6 @@ export interface CustomConfig {
'480p': boolean '480p': boolean
'720p': boolean '720p': boolean
'1080p': boolean '1080p': boolean
[key: string]: boolean
} }
} }

View File

@ -20,5 +20,4 @@ export interface User {
blockedReason?: string blockedReason?: string
videoQuotaUsed?: number videoQuotaUsed?: number
[key: string]: any
} }