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 () {
return element.all(by.css('.videos .video-miniature .video-miniature-name'))
.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) {

View File

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

View File

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

View File

@ -7,7 +7,7 @@ export abstract class UserEdit extends FormReactive {
videoQuotaOptions: { 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 configService: ConfigService

View File

@ -23,7 +23,7 @@ export class UserListComponent extends RestTable implements OnInit {
pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
selectedUsers: User[] = []
bulkUserActions: DropdownAction<User>[] = []
bulkUserActions: DropdownAction<User[]>[] = []
constructor (
private notificationsService: NotificationsService,
@ -45,12 +45,12 @@ export class UserListComponent extends RestTable implements OnInit {
{
label: this.i18n('Ban'),
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'),
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 { NotificationsService } from 'angular2-notifications'
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' ]
})
export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelEdit implements OnInit, OnDestroy {
@ViewChild('avatarfileInput') avatarfileInput: any
error: string
videoChannelToUpdate: VideoChannel
private paramsSub: Subscription
constructor (

View File

@ -66,7 +66,7 @@ export class MyAccountVideosComponent extends AbstractVideoList implements OnIni
}
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) {
@ -81,7 +81,7 @@ export class MyAccountVideosComponent extends AbstractVideoList implements OnIni
async deleteSelectedVideos () {
const toDeleteVideosIds = Object.keys(this.checkedVideos)
.filter((k: any) => this.checkedVideos[ k ] === true)
.filter(k => this.checkedVideos[ k ] === true)
.map(k => parseInt(k, 10))
const res = await this.confirmService.confirm(
@ -168,10 +168,9 @@ export class MyAccountVideosComponent extends AbstractVideoList implements OnIni
}
private spliceVideosById (id: number) {
let key: any
for (key of Object.keys(this.loadedPages)) {
const videos = this.loadedPages[ key ]
const index = videos.findIndex((v: any) => v.id === id)
for (const key of Object.keys(this.loadedPages)) {
const videos: Video[] = this.loadedPages[ key ]
const index = videos.findIndex(v => v.id === id)
if (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
}
// TODO: typing
search (event: any) {
search (event: { query: string }) {
const query = event.query
this.userService.autocomplete(query)
.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 { NotificationsService } from 'angular2-notifications'
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' ]
})
export class ActorAvatarInfoComponent {
@ViewChild('avatarfileInput') avatarfileInput: any
@ViewChild('avatarfileInput') avatarfileInput: ElementRef<HTMLInputElement>
@Input() actor: VideoChannel | Account

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,5 +8,5 @@ import { Component, Input } from '@angular/core'
export class EditButtonComponent {
@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 { I18n } from '@ngx-translate/i18n-polyfill'
export type CanComponentDeactivateResult = { text?: string, canDeactivate: Observable<boolean> | boolean }
export interface CanComponentDeactivate {
canDeactivate: () => { text?: string, canDeactivate: Observable<boolean> | boolean }
canDeactivate: () => CanComponentDeactivateResult
}
@Injectable()

View File

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

View File

@ -33,7 +33,7 @@ export class RestExtractor {
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]))
return target
@ -83,7 +83,7 @@ export class RestExtractor {
errorMessage = err
}
const errorObj: any = {
const errorObj: { message: string, status: string, body: string } = {
message: errorMessage,
status: undefined,
body: undefined

View File

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

View File

@ -25,7 +25,7 @@ import { VideoAbuseService } from './video-abuse'
import { VideoBlacklistService } from './video-blacklist'
import { VideoOwnershipService } from './video-ownership'
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 { VideoService } from './video/video.service'
import { AccountService } from '@app/shared/account/account.service'
@ -82,7 +82,7 @@ import { BlocklistService } from '@app/shared/blocklist'
LoaderComponent,
VideoThumbnailComponent,
VideoMiniatureComponent,
VideoFeedComponent,
FeedComponent,
ButtonComponent,
DeleteButtonComponent,
EditButtonComponent,
@ -122,7 +122,7 @@ import { BlocklistService } from '@app/shared/blocklist'
LoaderComponent,
VideoThumbnailComponent,
VideoMiniatureComponent,
VideoFeedComponent,
FeedComponent,
ButtonComponent,
DeleteButtonComponent,
EditButtonComponent,

View File

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

View File

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

View File

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

View File

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

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
id?: number
scheduleUpdate?: VideoScheduleUpdate
[key: string]: any
constructor (video?: Video & { tags: string[], commentsEnabled: boolean, support: string, thumbnailUrl: string, previewUrl: string }) {
if (video) {
@ -50,14 +49,14 @@ export class VideoEdit implements VideoUpdate {
}
}
patch (values: any) {
patch (values: { [ id: string ]: string }) {
Object.keys(values).forEach((key) => {
this[ key ] = values[ key ]
})
// If schedule publication, the video is private and will be changed to public 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)
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) {
return this.authHttp
.get(environment.apiUrl + descriptionPath)
.get<{ description: string }>(environment.apiUrl + descriptionPath)
.pipe(
map((res: any) => res[ 'description' ]),
map(res => res.description),
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 { VideoCaptionEdit } from '@app/shared/video-caption/video-caption-edit.model'
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
import { VideoConstant } from '../../../../../../shared'
@Component({
selector: 'my-video-caption-add-modal',
@ -19,7 +20,7 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
@ViewChild('modal') modal: ElementRef
videoCaptionLanguages: any = []
videoCaptionLanguages: VideoConstant<string>[] = []
private openedModal: NgbModalRef
private closingModal = false
@ -73,7 +74,7 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
this.hide()
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({
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 { NotificationsService } from 'angular2-notifications'
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 {
@Output() firstStepDone = new EventEmitter<string>()
@ViewChild('torrentfileInput') torrentfileInput: any
@ViewChild('torrentfileInput') torrentfileInput: ElementRef<HTMLInputElement>
videoFileName: string
magnetUri = ''
@ -64,7 +64,7 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Ca
}
fileChange () {
const torrentfile = this.torrentfileInput.nativeElement.files[0] as File
const torrentfile = this.torrentfileInput.nativeElement.files[0]
if (!torrentfile) return
this.importVideo(torrentfile)

View File

@ -3,7 +3,6 @@ import { LoadingBarService } from '@ngx-loading-bar/core'
import { NotificationsService } from 'angular2-notifications'
import { catchError, switchMap, tap } from 'rxjs/operators'
import { FormReactive } from '@app/shared'
import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard.service'
import { VideoConstant, VideoPrivacy } from '../../../../../../shared'
import { AuthService, ServerService } from '@app/core'
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 { VideoEdit } from '@app/shared/video/video-edit.model'
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 }[] = []
videoPrivacies: VideoConstant<VideoPrivacy>[] = []
videoCaptions: VideoCaptionEdit[] = []
@ -30,7 +30,7 @@ export abstract class VideoSend extends FormReactive implements OnInit, CanCompo
protected videoService: VideoService
protected videoCaptionService: VideoCaptionService
abstract canDeactivate (): any
abstract canDeactivate (): CanComponentDeactivateResult
ngOnInit () {
this.buildForm({})

View File

@ -1,5 +1,5 @@
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 { LoadingBarService } from '@ngx-loading-bar/core'
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 {
@Output() firstStepDone = new EventEmitter<string>()
@ViewChild('videofileInput') videofileInput: any
@ViewChild('videofileInput') videofileInput: ElementRef<HTMLInputElement>
// So that it can be accessed in the template
readonly SPECIAL_SCHEDULED_PRIVACY = VideoEdit.SPECIAL_SCHEDULED_PRIVACY
@ -110,7 +110,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
}
uploadFirstStep () {
const videofile = this.videofileInput.nativeElement.files[0] as File
const videofile = this.videofileInput.nativeElement.files[0]
if (!videofile) return
// Cannot upload videos > 8GB for now

View File

@ -1,5 +1,6 @@
import { Injectable } from '@angular/core'
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 linkifyHtml = require('linkifyjs/html')

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -162,7 +162,7 @@ $other-videos-width: 260px;
}
}
my-video-feed {
my-feed {
margin-left: 5px;
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 { NotificationsService } from 'angular2-notifications'
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 { Hotkey, HotkeysService } from 'angular2-hotkeys'
import * as WebTorrent from 'webtorrent'
@ -45,7 +47,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
@ViewChild('videoBlacklistModal') videoBlacklistModal: VideoBlacklistComponent
@ViewChild('subscribeButton') subscribeButton: SubscribeButtonComponent
player: any
player: videojs.Player
playerElement: HTMLVideoElement
userRating: UserVideoRateType = null
video: VideoDetails = null
@ -435,7 +437,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
this.zone.runOutsideAngular(async () => {
videojs(this.playerElement, videojsOptions, function () {
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)
})
@ -448,7 +450,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
this.checkUserRating()
}
private setRating (nextRating: string) {
private setRating (nextRating: VideoRateType) {
let method
switch (nextRating) {
case 'like':
@ -466,11 +468,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
.subscribe(
() => {
// Update the video like attribute
this.updateVideoRating(this.userRating, nextRating as VideoRateType)
this.userRating = nextRating as UserVideoRateType
this.updateVideoRating(this.userRating, nextRating)
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()
}
put (index: number, buf: Buffer, cb: Function) {
put (index: number, buf: Buffer, cb: (err?: Error) => void) {
const isLastChunk = (index === this.lastChunkIndex)
if (isLastChunk && buf.length !== 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)
}
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)
// IndexDB could be slow, use our memory index first
@ -146,11 +146,11 @@ export class PeertubeChunkStore extends EventEmitter {
})
}
close (db: any) {
return this.destroy(db)
close (cb: (err?: Error) => void) {
return this.destroy(cb)
}
async destroy (cb: any) {
async destroy (cb: (err?: Error) => void) {
try {
if (this.pendingPut) {
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)
}
}

View File

@ -1,10 +1,13 @@
import { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
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')
class PeerTubeLinkButton extends Button {
constructor (player: any, options: any) {
constructor (player: Player, options: any) {
super(player, options)
}

View File

@ -1,10 +1,13 @@
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')
class PeerTubeLoadProgressBar extends Component {
constructor (player: any, options: any) {
constructor (player: Player, options: any) {
super(player, options)
this.partEls_ = []
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 { 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)
videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed'
// Change Captions to Subtitles/CC
@ -75,12 +79,12 @@ function getVideojsOptions (options: {
enableVolumeScroll: false,
enableModifiersForNumbers: false,
fullscreenKey: function (event: any) {
fullscreenKey: function (event: KeyboardEvent) {
// fullscreen with the f key or Ctrl+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).
if (event.ctrlKey && event.altKey) {
return 5 * 60
@ -95,26 +99,26 @@ function getVideojsOptions (options: {
customKeys: {
increasePlaybackRateKey: {
key: function (event: any) {
key: function (event: KeyboardEvent) {
return event.key === '>'
},
handler: function (player: any) {
handler: function (player: Player) {
player.playbackRate((player.playbackRate() + 0.1).toFixed(2))
}
},
decreasePlaybackRateKey: {
key: function (event: any) {
key: function (event: KeyboardEvent) {
return event.key === '<'
},
handler: function (player: any) {
handler: function (player: Player) {
player.playbackRate((player.playbackRate() - 0.1).toFixed(2))
}
},
frameByFrame: {
key: function (event: any) {
key: function (event: KeyboardEvent) {
return event.key === '.'
},
handler: function (player: any) {
handler: function (player: Player) {
player.pause()
// Calculate movement distance (assuming 30 fps)
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 { VideoFile } from '../../../../shared/models/videos/video.model'
import { renderVideo } from './video-renderer'
import './settings-menu-button'
import { PeertubePluginOptions, UserWatching, VideoJSCaption, VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
import { isMobile, timeToInt, videoFileMaxByResolution, videoFileMinByResolution } from './utils'
const CacheChunkStore = require('cache-chunk-store')
import { PeertubeChunkStore } from './peertube-chunk-store'
import {
getAverageBandwidthInStore,
@ -17,6 +19,8 @@ import {
saveVolumeInStore
} from './peertube-player-local-storage'
const CacheChunkStore = require('cache-chunk-store')
type PlayOptions = {
forcePlay?: boolean,
seek?: number,
@ -61,7 +65,7 @@ class PeerTubePlugin extends Plugin {
private player: any
private currentVideoFile: VideoFile
private torrent: any
private torrent: WebTorrent.Torrent
private videoCaptions: VideoJSCaption[]
private renderer: any
@ -83,7 +87,7 @@ class PeerTubePlugin extends Plugin {
private downloadSpeeds: number[] = []
constructor (player: any, options: PeertubePluginOptions) {
constructor (player: videojs.Player, options: PeertubePluginOptions) {
super(player, options)
// Disable auto play on iOS
@ -273,7 +277,7 @@ class PeerTubePlugin extends Plugin {
const oldTorrent = this.torrent
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
})
}
@ -304,7 +308,7 @@ class PeerTubePlugin extends Plugin {
if (err) return this.fallbackToHttp(options, done)
return this.tryToPlay((err: Error) => {
return this.tryToPlay(err => {
if (err) return done(err)
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 */ }
const playPromise = this.player.play()
@ -641,7 +645,7 @@ class PeerTubePlugin extends Plugin {
return this.videoFiles[Math.floor(this.videoFiles.length / 2)]
}
private stopTorrent (torrent: any) {
private stopTorrent (torrent: WebTorrent.Torrent) {
torrent.pause()
// Pause does not remove actual peers (in particular the webseed peer)
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 { 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 { ResolutionMenuItem } from './resolution-menu-item'
@ -6,7 +10,7 @@ const MenuButton: VideoJSComponentInterface = videojsUntyped.getComponent('MenuB
class ResolutionMenuButton extends MenuButton {
label: HTMLElement
constructor (player: any, options: any) {
constructor (player: Player, options: any) {
super(player, options)
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'
const MenuItem: VideoJSComponentInterface = videojsUntyped.getComponent('MenuItem')
class ResolutionMenuItem extends MenuItem {
constructor (player: any, options: any) {
constructor (player: Player, options: any) {
const currentResolutionId = player.peertube().getCurrentResolutionId()
options.selectable = true
options.selected = options.id === currentResolutionId

View File

@ -1,7 +1,10 @@
// Author: Yanko Shterev
// 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 { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
import { toTitleCase } from './utils'
@ -11,7 +14,7 @@ const Menu: VideoJSComponentInterface = videojsUntyped.getComponent('Menu')
const Component: VideoJSComponentInterface = videojsUntyped.getComponent('Component')
class SettingsButton extends Button {
constructor (player: any, options: any) {
constructor (player: videojs.Player, options: any) {
super(player, options)
this.playerComponent = player
@ -48,7 +51,7 @@ class SettingsButton extends Button {
}
}
onDisposeSettingsItem (name: string) {
onDisposeSettingsItem (event: any, name: string) {
if (name === undefined) {
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
this.addMenuItem(entry, options)
@ -218,7 +221,7 @@ class SettingsButton extends Button {
}
class SettingsPanel extends Component {
constructor (player: any, options: any) {
constructor (player: videojs.Player, options: any) {
super(player, options)
}
@ -232,7 +235,7 @@ class SettingsPanel extends Component {
}
class SettingsPanelChild extends Component {
constructor (player: any, options: any) {
constructor (player: videojs.Player, options: any) {
super(player, options)
}
@ -246,7 +249,7 @@ class SettingsPanelChild extends Component {
}
class SettingsDialog extends Component {
constructor (player: any, options: any) {
constructor (player: videojs.Player, options: any) {
super(player, options)
this.hide()
}

View File

@ -1,6 +1,10 @@
// Author: Yanko Shterev
// 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 { VideoJSComponentInterface, videojsUntyped } from './peertube-videojs-typings'
@ -9,7 +13,7 @@ const component: VideoJSComponentInterface = videojsUntyped.getComponent('Compon
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)
this.settingsButton = menuButton
@ -229,7 +233,7 @@ class SettingsMenuItem extends MenuItem {
}
update (event?: any) {
let target = null
let target: HTMLElement = null
let subMenu = this.subMenu.name()
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 { saveTheaterInStore, getStoredTheater } from './peertube-player-local-storage'
@ -6,7 +10,7 @@ class TheaterButton extends Button {
private static readonly THEATER_MODE_CLASS = 'vjs-theater-enabled'
constructor (player: any, options: any) {
constructor (player: videojs.Player, options: any) {
super(player, options)
const enabled = getStoredTheater()

View File

@ -12,7 +12,7 @@ const dictionaryBytes: Array<{max: number, type: string}> = [
{ max: 1073741824, type: 'MB' },
{ 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 calc = Math.floor(value / (format.max / 1024)).toString()

View File

@ -65,7 +65,7 @@ class WebtorrentInfoButton extends Button {
subDivHttp.appendChild(subDivHttpText)
div.appendChild(subDivHttp)
this.player_.peertube().on('torrentInfo', (data: any) => {
this.player_.peertube().on('torrentInfo', (event: any, data: any) => {
// We are in HTTP fallback
if (!data) {
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
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 { peertubeTranslate, ResultList, VideoDetails } from '../../../../shared'
@ -304,7 +307,7 @@ class PeerTubeEmbed {
this.playerOptions = 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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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