From c47106315ae3c403239cda29c49b4bba51ddccb2 Mon Sep 17 00:00:00 2001
From: Chocobozzz <me@florianbigard.com>
Date: Tue, 2 Apr 2019 18:30:26 +0200
Subject: [PATCH] tslint update

---
 client/package.json                           |  2 +-
 .../src/app/+accounts/accounts.component.ts   |  1 -
 .../video-channel-playlists.component.html    |  2 +-
 client/src/app/shared/forms/form-reactive.ts  |  2 +-
 client/src/app/shared/misc/utils.ts           |  4 +-
 .../app/shared/renderer/markdown.service.ts   |  2 +-
 ...-playlist-element-miniature.component.html |  4 +-
 .../video-playlist-miniature.component.html   |  2 +-
 .../+video-watch/video-watch.component.html   |  2 +-
 .../p2p-media-loader/segment-url-builder.ts   |  4 +-
 client/src/assets/player/utils.ts             |  4 +-
 .../resolution-menu-button.ts                 |  2 +-
 .../settings-menu-button.ts                   | 18 +++---
 .../videojs-components/settings-menu-item.ts  | 10 ++--
 .../player/webtorrent/peertube-chunk-store.ts |  6 +-
 .../player/webtorrent/video-renderer.ts       |  2 +-
 .../player/webtorrent/webtorrent-plugin.ts    |  2 +-
 client/src/polyfills.ts                       |  1 +
 client/src/standalone/player/definitions.ts   |  4 +-
 client/src/standalone/player/events.ts        |  4 +-
 client/src/standalone/videos/embed.ts         | 12 ++--
 client/src/standalone/videos/test-embed.ts    | 24 ++++----
 client/tsconfig.json                          |  1 +
 client/tslint.json                            | 30 ++--------
 client/yarn.lock                              | 56 ++++++-------------
 shared/models/videos/video-resolution.enum.ts | 42 +++++++-------
 26 files changed, 102 insertions(+), 141 deletions(-)

diff --git a/client/package.json b/client/package.json
index edcddcfee1..c1532ee625 100644
--- a/client/package.json
+++ b/client/package.json
@@ -73,7 +73,6 @@
     "bootstrap": "^4.1.3",
     "buffer": "^5.1.0",
     "cache-chunk-store": "^3.0.0",
-    "codelyzer": "^5.0.0",
     "core-js": "^3.0.0",
     "css-loader": "^2.1.1",
     "dexie": "^2.0.4",
@@ -118,6 +117,7 @@
     "stream-http": "^3.0.0",
     "terser-webpack-plugin": "^1.1.0",
     "tslint": "^5.7.0",
+    "tslint-angular": "^1.1.2",
     "tslint-config-standard": "^8.0.1",
     "typescript": "3.2",
     "video.js": "^7",
diff --git a/client/src/app/+accounts/accounts.component.ts b/client/src/app/+accounts/accounts.component.ts
index e8339b78bd..d9786fb5cb 100644
--- a/client/src/app/+accounts/accounts.component.ts
+++ b/client/src/app/+accounts/accounts.component.ts
@@ -7,7 +7,6 @@ import { catchError, distinctUntilChanged, map, switchMap, tap } from 'rxjs/oper
 import { Subscription } from 'rxjs'
 import { AuthService, Notifier, RedirectService } from '@app/core'
 import { User, UserRight } from '../../../../shared'
-import { I18n } from '@ngx-translate/i18n-polyfill'
 
 @Component({
   templateUrl: './accounts.component.html',
diff --git a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html
index 0d9fba3756..befc7143cd 100644
--- a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html
+++ b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html
@@ -1,5 +1,5 @@
 <div i18n class="title-page title-page-single">
-  Created {{pagination.totalItems}} playlists
+  Created {{ pagination.totalItems }} playlists
 </div>
 
 <div i18n class="no-results" *ngIf="pagination.totalItems === 0">This channel does not have playlists.</div>
diff --git a/client/src/app/shared/forms/form-reactive.ts b/client/src/app/shared/forms/form-reactive.ts
index b9873af2c4..0d40b6f4ae 100644
--- a/client/src/app/shared/forms/form-reactive.ts
+++ b/client/src/app/shared/forms/form-reactive.ts
@@ -59,7 +59,7 @@ export abstract class FormReactive {
       const isDirty = control.dirty || forceCheck === true
       if (control && isDirty && !control.valid) {
         const messages = validationMessages[ field ]
-        for (const key in control.errors) {
+        for (const key of Object.keys(control.errors)) {
           formErrors[ field ] += messages[ key ] + ' '
         }
       }
diff --git a/client/src/app/shared/misc/utils.ts b/client/src/app/shared/misc/utils.ts
index 8a1d342c9e..85fc1c3a09 100644
--- a/client/src/app/shared/misc/utils.ts
+++ b/client/src/app/shared/misc/utils.ts
@@ -78,10 +78,10 @@ function objectToUrlEncoded (obj: any) {
 
 // Thanks: https://gist.github.com/ghinda/8442a57f22099bdb2e34
 function objectToFormData (obj: any, form?: FormData, namespace?: string) {
-  let fd = form || new FormData()
+  const fd = form || new FormData()
   let formKey
 
-  for (let key of Object.keys(obj)) {
+  for (const key of Object.keys(obj)) {
     if (namespace) formKey = `${namespace}[${key}]`
     else formKey = key
 
diff --git a/client/src/app/shared/renderer/markdown.service.ts b/client/src/app/shared/renderer/markdown.service.ts
index 69dc60aaf7..9a90663511 100644
--- a/client/src/app/shared/renderer/markdown.service.ts
+++ b/client/src/app/shared/renderer/markdown.service.ts
@@ -45,7 +45,7 @@ export class MarkdownService {
 
     const markdownIt = new MarkdownItClass('zero', { linkify: true, breaks: true })
 
-    for (let rule of rules) {
+    for (const rule of rules) {
       markdownIt.enable(rule)
     }
 
diff --git a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html
index 4764fc0e15..ab5a789286 100644
--- a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html
+++ b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html
@@ -19,7 +19,7 @@
       <a *ngIf="accountLink" tabindex="-1" class="video-info-account" [routerLink]="[ '/accounts', video.byAccount ]">{{ video.byAccount }}</a>
       <span *ngIf="!accountLink" tabindex="-1" class="video-info-account">{{ video.byAccount }}</span>
 
-      <span tabindex="-1" class="video-info-timestamp">{{ formatTimestamp(video)}}</span>
+      <span tabindex="-1" class="video-info-timestamp">{{ formatTimestamp(video) }}</span>
     </div>
   </a>
 
@@ -66,7 +66,7 @@
       </div>
 
       <span class="dropdown-item" (click)="removeFromPlaylist(video)">
-            <my-global-icon iconName="delete"></my-global-icon> <ng-container i18n>Delete from {{playlist?.displayName}}</ng-container>
+            <my-global-icon iconName="delete"></my-global-icon> <ng-container i18n>Delete from {{ playlist?.displayName }}</ng-container>
           </span>
     </div>
   </div>
diff --git a/client/src/app/shared/video-playlist/video-playlist-miniature.component.html b/client/src/app/shared/video-playlist/video-playlist-miniature.component.html
index c01c730122..faf906c593 100644
--- a/client/src/app/shared/video-playlist/video-playlist-miniature.component.html
+++ b/client/src/app/shared/video-playlist/video-playlist-miniature.component.html
@@ -6,7 +6,7 @@
     <img alt="" [attr.aria-labelledby]="playlist.displayName" [attr.src]="playlist.thumbnailUrl" />
 
     <div class="miniature-playlist-info-overlay">
-      <ng-container i18n>{playlist.videosLength, plural, =0 {No videos} =1 {1 video} other {{{playlist.videosLength}} videos}}</ng-container>
+      <ng-container i18n>{playlist.videosLength, plural, =0 {No videos} =1 {1 video} other {{{ playlist.videosLength }} videos}}</ng-container>
     </div>
 
     <div class="play-overlay">
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html
index 91f77cbf39..ad1d04b702 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.html
+++ b/client/src/app/videos/+video-watch/video-watch.component.html
@@ -22,7 +22,7 @@
         <div class="playlist-by-index">
           <div class="playlist-by">{{ playlist.ownerBy }}</div>
           <div class="playlist-index">
-            <span>{{currentPlaylistPosition}}</span><span>{{playlistPagination.totalItems}}</span>
+            <span>{{ currentPlaylistPosition }}</span><span>{{ playlistPagination.totalItems }}</span>
           </div>
         </div>
       </div>
diff --git a/client/src/assets/player/p2p-media-loader/segment-url-builder.ts b/client/src/assets/player/p2p-media-loader/segment-url-builder.ts
index 32e7ce4f2b..fb990a19dd 100644
--- a/client/src/assets/player/p2p-media-loader/segment-url-builder.ts
+++ b/client/src/assets/player/p2p-media-loader/segment-url-builder.ts
@@ -8,8 +8,8 @@ function segmentUrlBuilderFactory (baseUrls: string[]) {
 
     if (i === max - 1) return segment.url
 
-    let newBaseUrl = baseUrls[i]
-    let middlePart = newBaseUrl.endsWith('/') ? '' : '/'
+    const newBaseUrl = baseUrls[i]
+    const middlePart = newBaseUrl.endsWith('/') ? '' : '/'
 
     return newBaseUrl + middlePart + basename(segment.url)
   }
diff --git a/client/src/assets/player/utils.ts b/client/src/assets/player/utils.ts
index 54f1313105..0966027ace 100644
--- a/client/src/assets/player/utils.ts
+++ b/client/src/assets/player/utils.ts
@@ -61,12 +61,12 @@ function secondsToTime (seconds: number, full = false, symbol?: string) {
   const minuteSymbol = (symbol || 'm')
   const secondsSymbol = full ? '' : 's'
 
-  let hours = Math.floor(seconds / 3600)
+  const hours = Math.floor(seconds / 3600)
   if (hours >= 1) time = hours + hourSymbol
   else if (full) time = '0' + hourSymbol
 
   seconds %= 3600
-  let minutes = Math.floor(seconds / 60)
+  const minutes = Math.floor(seconds / 60)
   if (minutes >= 1 && minutes < 10 && full) time += '0' + minutes + minuteSymbol
   else if (minutes >= 1) time += minutes + minuteSymbol
   else if (full) time += '00' + minuteSymbol
diff --git a/client/src/assets/player/videojs-components/resolution-menu-button.ts b/client/src/assets/player/videojs-components/resolution-menu-button.ts
index abcc16411d..cff44de72e 100644
--- a/client/src/assets/player/videojs-components/resolution-menu-button.ts
+++ b/client/src/assets/player/videojs-components/resolution-menu-button.ts
@@ -49,7 +49,7 @@ class ResolutionMenuButton extends MenuButton {
 
   private addClickListener (component: any) {
     component.on('click', () => {
-      let children = this.menu.children()
+      const children = this.menu.children()
 
       for (const child of children) {
         if (component !== child) {
diff --git a/client/src/assets/player/videojs-components/settings-menu-button.ts b/client/src/assets/player/videojs-components/settings-menu-button.ts
index 14cb8ba433..5e09032b41 100644
--- a/client/src/assets/player/videojs-components/settings-menu-button.ts
+++ b/client/src/assets/player/videojs-components/settings-menu-button.ts
@@ -53,7 +53,7 @@ class SettingsButton extends Button {
 
   onDisposeSettingsItem (event: any, name: string) {
     if (name === undefined) {
-      let children = this.menu.children()
+      const children = this.menu.children()
 
       while (children.length > 0) {
         children[0].dispose()
@@ -62,7 +62,7 @@ class SettingsButton extends Button {
 
       this.addClass('vjs-hidden')
     } else {
-      let item = this.menu.getChild(name)
+      const item = this.menu.getChild(name)
 
       if (item) {
         item.dispose()
@@ -148,8 +148,8 @@ class SettingsButton extends Button {
       return
     }
 
-    let offset = this.options_.setup.maxHeightOffset
-    let maxHeight = this.playerComponent.el_.offsetHeight - offset
+    const offset = this.options_.setup.maxHeightOffset
+    const maxHeight = this.playerComponent.el_.offsetHeight - offset
 
     if (height > maxHeight) {
       height = maxHeight
@@ -166,7 +166,7 @@ class SettingsButton extends Button {
   buildMenu () {
     this.menu = new Menu(this.player())
     this.menu.addClass('vjs-main-menu')
-    let entries = this.options_.entries
+    const entries = this.options_.entries
 
     if (entries.length === 0) {
       this.addClass('vjs-hidden')
@@ -174,7 +174,7 @@ class SettingsButton extends Button {
       return
     }
 
-    for (let entry of entries) {
+    for (const entry of entries) {
       this.addMenuItem(entry, this.options_)
     }
 
@@ -191,7 +191,7 @@ class SettingsButton extends Button {
     }
 
     options.name = toTitleCase(entry)
-    let settingsMenuItem = new SettingsMenuItem(this.player(), options, entry, this as any)
+    const settingsMenuItem = new SettingsMenuItem(this.player(), options, entry, this as any)
 
     this.menu.addChild(settingsMenuItem)
 
@@ -204,7 +204,7 @@ class SettingsButton extends Button {
   }
 
   resetChildren () {
-    for (let menuChild of this.menu.children()) {
+    for (const menuChild of this.menu.children()) {
       menuChild.reset()
     }
   }
@@ -213,7 +213,7 @@ class SettingsButton extends Button {
    * Hide all the sub menus
    */
   hideChildren () {
-    for (let menuChild of this.menu.children()) {
+    for (const menuChild of this.menu.children()) {
       menuChild.hideSubMenu()
     }
   }
diff --git a/client/src/assets/player/videojs-components/settings-menu-item.ts b/client/src/assets/player/videojs-components/settings-menu-item.ts
index f14959f9cf..78879a2ec3 100644
--- a/client/src/assets/player/videojs-components/settings-menu-item.ts
+++ b/client/src/assets/player/videojs-components/settings-menu-item.ts
@@ -167,7 +167,7 @@ class SettingsMenuItem extends MenuItem {
    * @method PrefixedEvent
    */
   PrefixedEvent (element: any, type: any, callback: any, action = 'addEvent') {
-    let prefix = ['webkit', 'moz', 'MS', 'o', '']
+    const prefix = ['webkit', 'moz', 'MS', 'o', '']
 
     for (let p = 0; p < prefix.length; p++) {
       if (!prefix[p]) {
@@ -249,7 +249,7 @@ class SettingsMenuItem extends MenuItem {
 
   update (event?: any) {
     let target: HTMLElement = null
-    let subMenu = this.subMenu.name()
+    const subMenu = this.subMenu.name()
 
     if (event && event.type === 'tap') {
       target = event.target
@@ -264,7 +264,7 @@ class SettingsMenuItem extends MenuItem {
       setTimeout(() => this.settingsSubMenuValueEl_.innerHTML = this.subMenu.labelEl_.innerHTML, 250)
     } else {
       // Loop trough the submenu items to find the selected child
-      for (let subMenuItem of this.subMenu.menu.children_) {
+      for (const subMenuItem of this.subMenu.menu.children_) {
         if (!(subMenuItem instanceof component)) {
           continue
         }
@@ -287,7 +287,7 @@ class SettingsMenuItem extends MenuItem {
   }
 
   bindClickEvents () {
-    for (let item of this.subMenu.menu.children()) {
+    for (const item of this.subMenu.menu.children()) {
       if (!(item instanceof component)) {
         continue
       }
@@ -307,7 +307,7 @@ class SettingsMenuItem extends MenuItem {
   }
 
   setMargin () {
-    let [width] = this.size
+    const [ width ] = this.size
 
     this.settingsSubMenuEl_.style.marginRight = `-${width}px`
   }
diff --git a/client/src/assets/player/webtorrent/peertube-chunk-store.ts b/client/src/assets/player/webtorrent/peertube-chunk-store.ts
index 54cc0ea64d..66762bef8a 100644
--- a/client/src/assets/player/webtorrent/peertube-chunk-store.ts
+++ b/client/src/assets/player/webtorrent/peertube-chunk-store.ts
@@ -131,7 +131,7 @@ export class PeertubeChunkStore extends EventEmitter {
     // Chunk in store
     this.db.transaction('r', this.db.chunks, async () => {
       const result = await this.db.chunks.get({ id: index })
-      if (result === undefined) return cb(null, new Buffer(0))
+      if (result === undefined) return cb(null, Buffer.alloc(0))
 
       const buf = result.buf
       if (!opts) return this.nextTick(cb, null, buf)
@@ -162,13 +162,13 @@ export class PeertubeChunkStore extends EventEmitter {
       }
 
       if (this.db) {
-        await this.db.close()
+        this.db.close()
 
         await this.dropDatabase(this.databaseName)
       }
 
       if (this.expirationDB) {
-        await this.expirationDB.close()
+        this.expirationDB.close()
         this.expirationDB = null
       }
 
diff --git a/client/src/assets/player/webtorrent/video-renderer.ts b/client/src/assets/player/webtorrent/video-renderer.ts
index a3415937b9..4dce871124 100644
--- a/client/src/assets/player/webtorrent/video-renderer.ts
+++ b/client/src/assets/player/webtorrent/video-renderer.ts
@@ -29,7 +29,7 @@ function renderVideo (
 
 function renderMedia (file: any, elem: HTMLVideoElement, opts: RenderMediaOptions, callback: (err: Error, renderer?: any) => void) {
   const extension = extname(file.name).toLowerCase()
-  let preparedElem: any = undefined
+  let preparedElem: any
   let currentTime = 0
   let renderer: any
 
diff --git a/client/src/assets/player/webtorrent/webtorrent-plugin.ts b/client/src/assets/player/webtorrent/webtorrent-plugin.ts
index c7182acc94..eee3d4db9f 100644
--- a/client/src/assets/player/webtorrent/webtorrent-plugin.ts
+++ b/client/src/assets/player/webtorrent/webtorrent-plugin.ts
@@ -347,7 +347,7 @@ class WebTorrentPlugin extends Plugin {
     if (!averageDownloadSpeed) averageDownloadSpeed = this.getAndSaveActualDownloadSpeed()
 
     // Limit resolution according to player height
-    const playerHeight = this.playerElement.offsetHeight as number
+    const playerHeight = this.playerElement.offsetHeight
 
     // We take the first resolution just above the player height
     // Example: player height is 530px, we want the 720p file instead of 480p
diff --git a/client/src/polyfills.ts b/client/src/polyfills.ts
index 3689084324..b68c07fdb9 100644
--- a/client/src/polyfills.ts
+++ b/client/src/polyfills.ts
@@ -76,6 +76,7 @@ import 'core-js/es7/object'
 /***************************************************************************************************
  * Zone JS is required by default for Angular itself.
  */
+// tslint:disable
 import 'zone.js/dist/zone'  // Included with Angular CLI.
 
 /***************************************************************************************************
diff --git a/client/src/standalone/player/definitions.ts b/client/src/standalone/player/definitions.ts
index 7f9ef9b6f9..afd10541bb 100644
--- a/client/src/standalone/player/definitions.ts
+++ b/client/src/standalone/player/definitions.ts
@@ -1,6 +1,4 @@
-export interface EventHandler<T> {
-  (ev: T): void
-}
+export type EventHandler<T> = (ev: T) => void
 
 export type PlayerEventType =
   'pause' | 'play' |
diff --git a/client/src/standalone/player/events.ts b/client/src/standalone/player/events.ts
index f1639ef19d..28a13c727b 100644
--- a/client/src/standalone/player/events.ts
+++ b/client/src/standalone/player/events.ts
@@ -13,13 +13,13 @@ export class EventRegistrar {
   private eventRegistrations: PlayerEventRegistrationMap = {}
 
   public bindToChannel (channel: Channel.MessagingChannel) {
-    for (let name of Object.keys(this.eventRegistrations)) {
+    for (const name of Object.keys(this.eventRegistrations)) {
       channel.bind(name, (txn, params) => this.fire(name, params))
     }
   }
 
   public registerTypes (names: string[]) {
-    for (let name of names) {
+    for (const name of names) {
       this.eventRegistrations[ name ] = { registrations: [] }
     }
   }
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts
index b55b4bace0..626d55a7c2 100644
--- a/client/src/standalone/videos/embed.ts
+++ b/client/src/standalone/videos/embed.ts
@@ -40,7 +40,7 @@ class PeerTubeEmbedApi {
   }
 
   private constructChannel () {
-    let channel = Channel.build({ window: window.parent, origin: '*', scope: this.embed.scope })
+    const channel = Channel.build({ window: window.parent, origin: '*', scope: this.embed.scope })
 
     channel.bind('play', (txn, params) => this.embed.player.play())
     channel.bind('pause', (txn, params) => this.embed.player.pause())
@@ -82,8 +82,8 @@ class PeerTubeEmbedApi {
     let currentState: 'playing' | 'paused' | 'unstarted' = 'unstarted'
 
     setInterval(() => {
-      let position = this.element.currentTime
-      let volume = this.element.volume
+      const position = this.element.currentTime
+      const volume = this.element.volume
 
       this.channel.notify({
         method: 'playbackStatusUpdate',
@@ -114,8 +114,8 @@ class PeerTubeEmbedApi {
   }
 
   private loadWebTorrentResolutions () {
-    let resolutions = []
-    let currentResolutionId = this.embed.player.webtorrent().getCurrentResolutionId()
+    const resolutions = []
+    const currentResolutionId = this.embed.player.webtorrent().getCurrentResolutionId()
 
     for (const videoFile of this.embed.player.webtorrent().videoFiles) {
       let label = videoFile.resolution.label
@@ -235,7 +235,7 @@ class PeerTubeEmbed {
 
   private loadParams () {
     try {
-      let params = new URL(window.location.toString()).searchParams
+      const params = new URL(window.location.toString()).searchParams
 
       this.autoplay = this.getParamToggle(params, 'autoplay')
       this.controls = this.getParamToggle(params, 'controls')
diff --git a/client/src/standalone/videos/test-embed.ts b/client/src/standalone/videos/test-embed.ts
index 30a298573a..8e83d92a92 100644
--- a/client/src/standalone/videos/test-embed.ts
+++ b/client/src/standalone/videos/test-embed.ts
@@ -7,13 +7,13 @@ window.addEventListener('load', async () => {
   const lastPart = urlParts[ urlParts.length - 1 ]
   const videoId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ]
 
-  let iframe = document.createElement('iframe')
+  const iframe = document.createElement('iframe')
   iframe.src = `/videos/embed/${videoId}?autoplay=1&controls=0&api=1`
-  let mainElement = document.querySelector('#host')
+  const mainElement = document.querySelector('#host')
   mainElement.appendChild(iframe)
 
   console.log(`Document finished loading.`)
-  let player = new PeerTubePlayer(document.querySelector('iframe'))
+  const player = new PeerTubePlayer(document.querySelector('iframe'))
 
   window[ 'player' ] = player
 
@@ -21,7 +21,7 @@ window.addEventListener('load', async () => {
   await player.ready
   console.log(`Player is ready.`)
 
-  let monitoredEvents = [
+  const monitoredEvents = [
     'pause',
     'play',
     'playbackStatusUpdate',
@@ -36,18 +36,18 @@ window.addEventListener('load', async () => {
   let playbackRates: number[] = []
   let currentRate = await player.getPlaybackRate()
 
-  let updateRates = async () => {
-    let rateListEl = document.querySelector('#rate-list')
+  const updateRates = async () => {
+    const rateListEl = document.querySelector('#rate-list')
     rateListEl.innerHTML = ''
 
     playbackRates.forEach(rate => {
       if (currentRate === rate) {
-        let itemEl = document.createElement('strong')
+        const itemEl = document.createElement('strong')
         itemEl.innerText = `${rate} (active)`
         itemEl.style.display = 'block'
         rateListEl.appendChild(itemEl)
       } else {
-        let itemEl = document.createElement('a')
+        const itemEl = document.createElement('a')
         itemEl.href = 'javascript:;'
         itemEl.innerText = rate.toString()
         itemEl.addEventListener('click', () => {
@@ -66,18 +66,18 @@ window.addEventListener('load', async () => {
     updateRates()
   })
 
-  let updateResolutions = ((resolutions: PeerTubeResolution[]) => {
-    let resolutionListEl = document.querySelector('#resolution-list')
+  const updateResolutions = ((resolutions: PeerTubeResolution[]) => {
+    const resolutionListEl = document.querySelector('#resolution-list')
     resolutionListEl.innerHTML = ''
 
     resolutions.forEach(resolution => {
       if (resolution.active) {
-        let itemEl = document.createElement('strong')
+        const itemEl = document.createElement('strong')
         itemEl.innerText = `${resolution.label} (active)`
         itemEl.style.display = 'block'
         resolutionListEl.appendChild(itemEl)
       } else {
-        let itemEl = document.createElement('a')
+        const itemEl = document.createElement('a')
         itemEl.href = 'javascript:;'
         itemEl.innerText = resolution.label
         itemEl.addEventListener('click', () => {
diff --git a/client/tsconfig.json b/client/tsconfig.json
index a0fbc27c68..e46528d1c9 100644
--- a/client/tsconfig.json
+++ b/client/tsconfig.json
@@ -43,6 +43,7 @@
     "fullTemplateTypeCheck": true
   },
   "include": [
+    "./src",
     "../../shared"
   ],
   "exclude": [
diff --git a/client/tslint.json b/client/tslint.json
index fcc866ee38..f45b1d576d 100644
--- a/client/tslint.json
+++ b/client/tslint.json
@@ -1,12 +1,12 @@
 {
-  "extends": "tslint-config-standard",
-  "rulesDirectory": ["./node_modules/codelyzer"],
+  "extends": [ "tslint-angular", "tslint-config-standard" ],
   "rules": {
     "no-inferrable-types": true,
     "eofline": true,
     "max-line-length": [true, 140],
     "no-floating-promises": false,
     "no-unused-variable": false, // Memory issues
+    "await-promise": [true, "PromiseLike"],
     "member-ordering": [true, {
       "order": [
         "public-static-field",
@@ -21,27 +21,9 @@
         ]}
     ],
 
-    "angular-whitespace": [true, "check-interpolation", "check-semicolon"],
-    "banana-in-box": true,
-    "templates-no-negated-async": true,
-    "directive-selector": [true, "attribute", "my", "camelCase"],
-    "component-selector": [true, "element", "my", "kebab-case"],
-    "use-input-property-decorator": true,
-    "use-output-property-decorator": true,
-    "use-host-property-decorator": true,
-    "use-view-encapsulation": true,
-    "no-attribute-parameter-decorator": true,
-    "no-input-rename": true,
-    "no-output-rename": true,
-    "no-output-on-prefix": true,
-    "no-forward-ref": false,
-    "use-life-cycle-interface": true,
-    "contextual-life-cycle": true,
-    "trackBy-function": false,
-    "use-pipe-transform-interface": true,
-    "pipe-prefix": [true, "my"],
-    "component-class-suffix": true,
-    "directive-class-suffix": true,
-    "pipe-impure": true
+    "no-shadowed-variable": false,
+    "no-bitwise": false,
+    "max-classes-per-file": false,
+    "interface-over-type-literal": false
   }
 }
diff --git a/client/yarn.lock b/client/yarn.lock
index 361aa1e196..5be2cf642e 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -961,14 +961,6 @@ argparse@^1.0.7:
   dependencies:
     sprintf-js "~1.0.2"
 
-aria-query@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc"
-  integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=
-  dependencies:
-    ast-types-flow "0.0.7"
-    commander "^2.11.0"
-
 arr-diff@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
@@ -1064,11 +1056,6 @@ assign-symbols@^1.0.0:
   resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
   integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
 
-ast-types-flow@0.0.7:
-  version "0.0.7"
-  resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
-  integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0=
-
 ast-types@0.9.6:
   version "0.9.6"
   resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
@@ -1147,13 +1134,6 @@ aws4@^1.8.0:
   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
   integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
 
-axobject-query@^2.0.2:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9"
-  integrity sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==
-  dependencies:
-    ast-types-flow "0.0.7"
-
 babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
@@ -1969,20 +1949,17 @@ code-point-at@^1.0.0:
   resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
   integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
 
-codelyzer@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-5.0.0.tgz#e4032efb23a7c5d4bcfe7321fc1789490c679837"
-  integrity sha512-Bif70XYt8NFf/Q9GPTxmC86OsBRfQZq1dBjdruJ5kZhJ8/jKhJL6MvCLKnYtSOG6Rhiv/44DU0cHk6GYthjy8Q==
+codelyzer@^4.0.2:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-4.5.0.tgz#a65ddeeeca2894653253a89bfa229118ff9f59b1"
+  integrity sha512-oO6vCkjqsVrEsmh58oNlnJkRXuA30hF8cdNAQV9DytEalDwyOFRvHMnlKFzmOStNerOmPGZU9GAHnBo4tGvtiQ==
   dependencies:
     app-root-path "^2.1.0"
-    aria-query "^3.0.0"
-    axobject-query "^2.0.2"
-    css-selector-tokenizer "^0.7.1"
+    css-selector-tokenizer "^0.7.0"
     cssauron "^1.4.0"
-    damerau-levenshtein "^1.0.4"
     semver-dsl "^1.0.1"
     source-map "^0.5.7"
-    sprintf-js "^1.1.2"
+    sprintf-js "^1.1.1"
 
 collection-visit@^1.0.0:
   version "1.0.0"
@@ -2026,7 +2003,7 @@ commander@2.17.x:
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
   integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
 
-commander@^2.11.0, commander@^2.12.1, commander@^2.18.0, commander@^2.19.0, commander@^2.9.0, commander@~2.19.0:
+commander@^2.12.1, commander@^2.18.0, commander@^2.19.0, commander@^2.9.0, commander@~2.19.0:
   version "2.19.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
   integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
@@ -2345,7 +2322,7 @@ css-select@^1.1.0:
     domutils "1.5.1"
     nth-check "~1.0.1"
 
-css-selector-tokenizer@^0.7.1:
+css-selector-tokenizer@^0.7.0:
   version "0.7.1"
   resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz#a177271a8bca5019172f4f891fc6eed9cbf68d5d"
   integrity sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==
@@ -2415,11 +2392,6 @@ d@1:
   dependencies:
     es5-ext "^0.10.9"
 
-damerau-levenshtein@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514"
-  integrity sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=
-
 dashdash@^1.12.0:
   version "1.14.1"
   resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -8065,7 +8037,7 @@ split@^1.0.0:
   dependencies:
     through "2"
 
-sprintf-js@^1.1.2:
+sprintf-js@^1.1.1:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
   integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
@@ -8592,6 +8564,14 @@ tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@~1.9.0:
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
   integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
 
+tslint-angular@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/tslint-angular/-/tslint-angular-1.1.2.tgz#5ce7020968e3b9dc7a40b6d15dadd6da34787309"
+  integrity sha512-YDLdgQXBSFcVdDZH3mThx21fKzRctIgmCWpuwmppFLc7QHV3tdWDaFnD5lwUmgvLH8W0o+KsXhSzZ2uIsFJ+YA==
+  dependencies:
+    codelyzer "^4.0.2"
+    tslint "^5.8.0"
+
 tslint-config-standard@^8.0.1:
   version "8.0.1"
   resolved "https://registry.yarnpkg.com/tslint-config-standard/-/tslint-config-standard-8.0.1.tgz#e4dd3128e84b0e34b51990b68715a641f2b417e4"
@@ -8608,7 +8588,7 @@ tslint-eslint-rules@^5.3.1:
     tslib "1.9.0"
     tsutils "^3.0.0"
 
-tslint@^5.7.0:
+tslint@^5.7.0, tslint@^5.8.0:
   version "5.15.0"
   resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.15.0.tgz#6ffb180986d63afa1e531feb2a134dbf961e27d3"
   integrity sha512-6bIEujKR21/3nyeoX2uBnE8s+tMXCQXhqMmaIPJpHmXJoBJPTLcI7/VHRtUwMhnLVdwLqqY3zmd8Dxqa5CVdJA==
diff --git a/shared/models/videos/video-resolution.enum.ts b/shared/models/videos/video-resolution.enum.ts
index 7da5e71004..5ba2c1faa4 100644
--- a/shared/models/videos/video-resolution.enum.ts
+++ b/shared/models/videos/video-resolution.enum.ts
@@ -17,27 +17,27 @@ export enum VideoResolution {
  */
 function getBaseBitrate (resolution: VideoResolution) {
   switch (resolution) {
-  case VideoResolution.H_240P:
-    // quality according to Google Live Encoder: 300 - 700 Kbps
-    // Quality according to YouTube Video Info: 186 Kbps
-    return 250 * 1000
-  case VideoResolution.H_360P:
-    // quality according to Google Live Encoder: 400 - 1,000 Kbps
-    // Quality according to YouTube Video Info: 480 Kbps
-    return 500 * 1000
-  case VideoResolution.H_480P:
-    // quality according to Google Live Encoder: 500 - 2,000 Kbps
-    // Quality according to YouTube Video Info: 879 Kbps
-    return 900 * 1000
-  case VideoResolution.H_720P:
-    // quality according to Google Live Encoder: 1,500 - 4,000 Kbps
-    // Quality according to YouTube Video Info: 1752 Kbps
-    return 1750 * 1000
-  case VideoResolution.H_1080P: // fallthrough
-  default:
-    // quality according to Google Live Encoder: 3000 - 6000 Kbps
-    // Quality according to YouTube Video Info: 3277 Kbps
-    return 3300 * 1000
+    case VideoResolution.H_240P:
+      // quality according to Google Live Encoder: 300 - 700 Kbps
+      // Quality according to YouTube Video Info: 186 Kbps
+      return 250 * 1000
+    case VideoResolution.H_360P:
+      // quality according to Google Live Encoder: 400 - 1,000 Kbps
+      // Quality according to YouTube Video Info: 480 Kbps
+      return 500 * 1000
+    case VideoResolution.H_480P:
+      // quality according to Google Live Encoder: 500 - 2,000 Kbps
+      // Quality according to YouTube Video Info: 879 Kbps
+      return 900 * 1000
+    case VideoResolution.H_720P:
+      // quality according to Google Live Encoder: 1,500 - 4,000 Kbps
+      // Quality according to YouTube Video Info: 1752 Kbps
+      return 1750 * 1000
+    case VideoResolution.H_1080P: // fallthrough
+    default:
+      // quality according to Google Live Encoder: 3000 - 6000 Kbps
+      // Quality according to YouTube Video Info: 3277 Kbps
+      return 3300 * 1000
   }
 }
 
-- 
GitLab