Chocobozzz пре 2 година
родитељ
комит
9df52d660f
100 измењених фајлова са 479 додато и 259 уклоњено
  1. 169 0
      client/.eslintrc.json
  2. 7 18
      client/angular.json
  3. 1 1
      client/e2e/local-protractor.conf.js
  4. 1 1
      client/e2e/protractor.conf.js
  5. 0 0
      client/e2e/tsconfig.json
  6. 13 6
      client/package.json
  7. 1 1
      client/src/app/+about/about-follows/about-follows.component.ts
  8. 1 1
      client/src/app/+about/about-instance/about-instance.component.ts
  9. 4 4
      client/src/app/+about/about-instance/contact-admin-modal.component.ts
  10. 0 1
      client/src/app/+about/about-routing.module.ts
  11. 7 5
      client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
  12. 1 1
      client/src/app/+accounts/account-videos/account-videos.component.ts
  13. 3 3
      client/src/app/+accounts/accounts.component.html
  14. 10 4
      client/src/app/+accounts/accounts.component.ts
  15. 1 1
      client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.ts
  16. 3 1
      client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
  17. 1 1
      client/src/app/+admin/config/edit-custom-config/edit-homepage.component.ts
  18. 1 2
      client/src/app/+admin/follows/following-list/following-list.component.ts
  19. 1 1
      client/src/app/+admin/follows/shared/redundancy-checkbox.component.ts
  20. 2 2
      client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.ts
  21. 2 2
      client/src/app/+admin/moderation/video-block-list/video-block-list.component.html
  22. 2 2
      client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts
  23. 3 3
      client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts
  24. 1 1
      client/src/app/+admin/plugins/plugin-search/plugin-search.component.html
  25. 3 3
      client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts
  26. 1 3
      client/src/app/+admin/plugins/shared/plugin-api.service.ts
  27. 4 4
      client/src/app/+admin/system/jobs/job.service.ts
  28. 3 3
      client/src/app/+admin/system/logs/logs.service.ts
  29. 4 2
      client/src/app/+admin/users/user-edit/user-create.component.ts
  30. 1 1
      client/src/app/+admin/users/user-edit/user-edit.ts
  31. 4 2
      client/src/app/+admin/users/user-edit/user-password.component.ts
  32. 10 4
      client/src/app/+admin/users/user-edit/user-update.component.ts
  33. 1 1
      client/src/app/+admin/users/user-list/user-list.component.ts
  34. 1 1
      client/src/app/+login/login.component.html
  35. 1 1
      client/src/app/+login/login.component.ts
  36. 1 0
      client/src/app/+my-account/my-account-applications/my-account-applications.component.ts
  37. 3 3
      client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts
  38. 9 5
      client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts
  39. 2 1
      client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts
  40. 1 1
      client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
  41. 1 1
      client/src/app/+my-account/my-account.component.ts
  42. 2 2
      client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts
  43. 6 2
      client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts
  44. 4 4
      client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts
  45. 3 4
      client/src/app/+my-library/my-history/my-history.component.ts
  46. 1 1
      client/src/app/+my-library/my-library.component.ts
  47. 1 1
      client/src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.ts
  48. 4 2
      client/src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts
  49. 1 3
      client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts
  50. 7 3
      client/src/app/+my-library/my-video-playlists/my-video-playlist-update.component.ts
  51. 4 2
      client/src/app/+my-library/my-videos/modals/video-change-ownership.component.ts
  52. 2 2
      client/src/app/+my-library/my-videos/my-videos.component.ts
  53. 1 1
      client/src/app/+remote-interaction/remote-interaction.component.ts
  54. 1 1
      client/src/app/+reset-password/reset-password.component.ts
  55. 3 3
      client/src/app/+signup/+register/custom-stepper.component.ts
  56. 7 4
      client/src/app/+signup/+register/register.component.ts
  57. 1 1
      client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts
  58. 1 1
      client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
  59. 1 1
      client/src/app/+video-channels/video-channels.component.html
  60. 4 4
      client/src/app/+video-channels/video-channels.component.ts
  61. 1 1
      client/src/app/+videos/+video-edit/shared/i18n-primeng-calendar.service.ts
  62. 4 4
      client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.ts
  63. 1 1
      client/src/app/+videos/+video-edit/shared/video-edit-utils.ts
  64. 5 5
      client/src/app/+videos/+video-edit/shared/video-edit.component.ts
  65. 4 4
      client/src/app/+videos/+video-edit/video-add-components/drag-drop.directive.ts
  66. 1 1
      client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts
  67. 1 1
      client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.html
  68. 2 2
      client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts
  69. 1 1
      client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts
  70. 1 1
      client/src/app/+videos/+video-edit/video-add-components/video-send.ts
  71. 1 1
      client/src/app/+videos/+video-edit/video-add-components/video-upload.component.html
  72. 4 1
      client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
  73. 2 3
      client/src/app/+videos/+video-edit/video-update.component.ts
  74. 3 3
      client/src/app/+videos/+video-edit/video-update.resolver.ts
  75. 1 1
      client/src/app/+videos/+video-watch/player-styles.component.ts
  76. 3 3
      client/src/app/+videos/+video-watch/shared/comment/video-comment-add.component.ts
  77. 1 1
      client/src/app/+videos/+video-watch/shared/comment/video-comment.component.html
  78. 1 1
      client/src/app/+videos/+video-watch/shared/comment/video-comment.component.ts
  79. 6 2
      client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts
  80. 1 1
      client/src/app/+videos/+video-watch/shared/information/video-alert.component.ts
  81. 1 1
      client/src/app/+videos/+video-watch/shared/metadata/video-description.component.html
  82. 5 5
      client/src/app/+videos/+video-watch/shared/playlist/video-watch-playlist.component.ts
  83. 1 1
      client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.html
  84. 1 1
      client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.ts
  85. 4 4
      client/src/app/+videos/+video-watch/shared/timestamp-route-transformer.directive.ts
  86. 20 19
      client/src/app/+videos/+video-watch/video-watch.component.ts
  87. 1 1
      client/src/app/+videos/video-list/overview/overview.service.ts
  88. 1 1
      client/src/app/+videos/video-list/trending/video-trending-header.component.ts
  89. 3 3
      client/src/app/+videos/video-list/trending/video-trending.component.ts
  90. 1 1
      client/src/app/+videos/video-list/video-local.component.ts
  91. 2 2
      client/src/app/app.component.ts
  92. 4 2
      client/src/app/core/auth/auth.service.ts
  93. 3 3
      client/src/app/core/hotkeys/hotkeys.component.ts
  94. 2 2
      client/src/app/core/menu/menu.service.ts
  95. 4 6
      client/src/app/core/plugins/hooks.service.ts
  96. 5 5
      client/src/app/core/plugins/plugin.service.ts
  97. 7 7
      client/src/app/core/renderer/markdown.service.ts
  98. 15 11
      client/src/app/core/rest/rest-extractor.service.ts
  99. 2 2
      client/src/app/core/routing/custom-reuse-strategy.ts
  100. 14 4
      client/src/app/core/routing/menu-guard.service.ts

+ 169 - 0
client/.eslintrc.json

@@ -0,0 +1,169 @@
+{
+  "root": true,
+  "ignorePatterns": [
+    "projects/**/*",
+    "node_modules/"
+  ],
+  "overrides": [
+    {
+      "files": [
+        "*.ts"
+      ],
+      "parserOptions": {
+        "project": [
+          "tsconfig.json",
+          "e2e/tsconfig.json"
+        ],
+        "createDefaultProgram": true
+      },
+      "extends": [
+        "../.eslintrc.json",
+        "plugin:@angular-eslint/ng-cli-compat",
+        "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
+        "plugin:@angular-eslint/template/process-inline-templates"
+      ],
+      "rules": {
+        "lines-between-class-members": "off",
+        "@typescript-eslint/lines-between-class-members": [ "off" ],
+        "arrow-body-style": "off",
+        "import/no-webpack-loader-syntax": "off",
+        "no-underscore-dangle": "off",
+        "node/no-callback-literal": "off",
+        "@angular-eslint/component-selector": [
+          "error",
+          {
+            "type": [ "element", "attribute" ],
+            "prefix": "my",
+            "style": "kebab-case"
+          }
+        ],
+        "@angular-eslint/directive-selector": [
+          "error",
+          {
+            "type": [ "element", "attribute" ],
+            "prefix": "my",
+            "style": "camelCase"
+          }
+        ],
+        "@typescript-eslint/no-this-alias": [
+          "error",
+          {
+            "allowDestructuring": true,
+            "allowedNames": ["self", "player"]
+          }
+        ],
+        "@typescript-eslint/prefer-readonly": "off",
+        "@angular-eslint/use-component-view-encapsulation": "error",
+        "prefer-arrow/prefer-arrow-functions": "off",
+        "@typescript-eslint/await-thenable": "error",
+        "@typescript-eslint/consistent-type-definitions": "off",
+        "@typescript-eslint/dot-notation": "off",
+        "@typescript-eslint/explicit-member-accessibility": [
+          "off",
+          {
+            "accessibility": "explicit"
+          }
+        ],
+        "@typescript-eslint/member-ordering": [
+          "off"
+        ],
+        "@typescript-eslint/member-delimiter-style": [
+          "error",
+          {
+            "multiline": {
+              "delimiter": "none",
+              "requireLast": true
+            },
+            "singleline": {
+              "delimiter": "comma",
+              "requireLast": false
+            }
+          }
+        ],
+        "@typescript-eslint/prefer-for-of": "off",
+        "@typescript-eslint/no-empty-function": "error",
+        "@typescript-eslint/no-floating-promises": "off",
+        "@typescript-eslint/no-inferrable-types": "error",
+        "@typescript-eslint/no-shadow": [
+          "off",
+          {
+            "hoist": "all"
+          }
+        ],
+        "@typescript-eslint/no-unnecessary-qualifier": "error",
+        "@typescript-eslint/no-unnecessary-type-assertion": "error",
+        "@typescript-eslint/no-unused-expressions": [
+          "error",
+          {
+            "allowTaggedTemplates": true,
+            "allowShortCircuit": true
+          }
+        ],
+        "@typescript-eslint/quotes": [
+          "error",
+          "single",
+          {
+            "avoidEscape": true,
+            "allowTemplateLiterals": true
+          }
+        ],
+        "@typescript-eslint/semi": [
+          "error",
+          "never"
+        ],
+        "brace-style": [
+          "error",
+          "1tbs"
+        ],
+        "comma-dangle": "error",
+        "curly": [
+          "error",
+          "multi-line"
+        ],
+        "dot-notation": "off",
+        "no-useless-return": "off",
+        "indent": "off",
+        "no-bitwise": "off",
+        "no-console": "off",
+        "no-return-assign": "off",
+        "no-constant-condition": "error",
+        "no-control-regex": "error",
+        "no-duplicate-imports": "error",
+        "no-empty": "error",
+        "no-empty-function": [
+          "error",
+          { "allow": [ "constructors" ] }
+        ],
+        "no-invalid-regexp": "error",
+        "no-multiple-empty-lines": "error",
+        "no-redeclare": "error",
+        "no-regex-spaces": "error",
+        "no-return-await": "error",
+        "no-shadow": "off",
+        "no-unused-expressions": "error",
+        "semi": "error",
+        "space-before-function-paren": [
+          "error",
+          "always"
+        ],
+        "space-in-parens": [
+          "error",
+          "never"
+        ],
+        "object-shorthand": [
+          "error",
+          "properties"
+        ]
+      }
+    },
+    {
+      "files": [
+        "*.html"
+      ],
+      "extends": [
+        "plugin:@angular-eslint/template/recommended"
+      ],
+      "rules": {}
+    }
+  ]
+}

+ 7 - 18
client/angular.json

@@ -203,7 +203,9 @@
               ]
             },
             "ar-locale": {
-              "localize": ["ar"],
+              "localize": [
+                "ar"
+              ],
               "budgets": [
                 {
                   "type": "anyComponentStyle",
@@ -295,13 +297,11 @@
           }
         },
         "lint": {
-          "builder": "@angular-devkit/build-angular:tslint",
+          "builder": "@angular-eslint/builder:lint",
           "options": {
-            "tsConfig": [
-              "tsconfig.json"
-            ],
-            "exclude": [
-              "**/node_modules/**"
+            "lintFilePatterns": [
+              "src/**/*.ts",
+              "src/**/*.html"
             ]
           }
         },
@@ -378,17 +378,6 @@
               "protractorConfig": "e2e/local-protractor.conf.js"
             }
           }
-        },
-        "lint": {
-          "builder": "@angular-devkit/build-angular:tslint",
-          "options": {
-            "tsConfig": [
-              "e2e/tsconfig.e2e.json"
-            ],
-            "exclude": [
-              "**/node_modules/**"
-            ]
-          }
         }
       }
     }

+ 1 - 1
client/e2e/local-protractor.conf.js

@@ -49,7 +49,7 @@ exports.config = {
 
   onPrepare() {
     require('ts-node').register({
-      project: require('path').join(__dirname, './tsconfig.e2e.json')
+      project: require('path').join(__dirname, './tsconfig.json')
     })
     jasmine.getEnv().addReporter(new SpecReporter({   spec:  {  displayStacktrace: true    }  }))
   }

+ 1 - 1
client/e2e/protractor.conf.js

@@ -83,7 +83,7 @@ exports.config = {
 
   onPrepare() {
     require('ts-node').register({
-      project: require('path').join(__dirname, './tsconfig.e2e.json')
+      project: require('path').join(__dirname, './tsconfig.json')
     })
     jasmine.getEnv().addReporter(new SpecReporter({
       spec: { displayStacktrace: 'raw' }

+ 0 - 0
client/e2e/tsconfig.e2e.json → client/e2e/tsconfig.json


+ 13 - 6
client/package.json

@@ -14,10 +14,10 @@
   },
   "scripts": {
     "lint": "npm run lint-ts && npm run lint-scss",
-    "lint-ts": "tslint --project ./tsconfig.json -c ./tslint.json 'src/app/**/*.ts' 'src/standalone/**/*.ts'",
+    "lint-ts": "eslint --ext .ts src/standalone/**/*.ts && npm run ng lint",
     "lint-scss": "stylelint 'src/**/*.scss'",
     "webpack": "webpack",
-    "tslint": "tslint",
+    "eslint": "eslint",
     "ng": "ng",
     "webpack-bundle-analyzer": "webpack-bundle-analyzer",
     "webdriver-manager": "webdriver-manager",
@@ -27,6 +27,11 @@
   "typings": "*.d.ts",
   "devDependencies": {
     "@angular-devkit/build-angular": "^12.0.0",
+    "@angular-eslint/builder": "12.3.1",
+    "@angular-eslint/eslint-plugin": "12.3.1",
+    "@angular-eslint/eslint-plugin-template": "12.3.1",
+    "@angular-eslint/schematics": "12.3.1",
+    "@angular-eslint/template-parser": "12.3.1",
     "@angular/animations": "^12.0.0",
     "@angular/cdk": "^12.0.0",
     "@angular/cli": "^12.0.0",
@@ -64,17 +69,22 @@
     "@types/sha.js": "^2.4.0",
     "@types/video.js": "^7.3.8",
     "@types/webtorrent": "^0.109.0",
+    "@typescript-eslint/eslint-plugin": "4.28.2",
+    "@typescript-eslint/parser": "4.28.2",
     "angular2-hotkeys": "^2.1.2",
     "angularx-qrcode": "11.0.0",
     "bootstrap": "^4.1.3",
     "buffer": "^6.0.3",
     "cache-chunk-store": "^3.0.0",
     "chart.js": "^2.9.3",
-    "codelyzer": "^6.0.0",
     "core-js": "^3.1.4",
     "css-loader": "^6.2.0",
     "debug": "^4.3.1",
     "dexie": "^3.0.0",
+    "eslint": "^7.26.0",
+    "eslint-plugin-import": "latest",
+    "eslint-plugin-jsdoc": "latest",
+    "eslint-plugin-prefer-arrow": "latest",
     "focus-visible": "^5.0.2",
     "hls.js": "^1.0.7",
     "html-loader": "^2.1.2",
@@ -112,9 +122,6 @@
     "terser-webpack-plugin": "^5.1.2",
     "ts-loader": "^9.2.2",
     "tslib": "^2.0.0",
-    "tslint": "~6.1.0",
-    "tslint-angular": "^3.0.2",
-    "tslint-config-standard": "^9.0.0",
     "typescript": "~4.3.4",
     "video.js": "^7",
     "videojs-contextmenu-pt": "^5.4.1",

+ 1 - 1
client/src/app/+about/about-follows/about-follows.component.ts

@@ -90,7 +90,7 @@ export class AboutFollowsComponent implements OnInit {
   private loadMoreFollowers (reset = false) {
     const pagination = this.restService.componentPaginationToRestPagination(this.followersPagination)
 
-    this.followService.getFollowers({ pagination: pagination, sort: this.sort, state: 'accepted' })
+    this.followService.getFollowers({ pagination, sort: this.sort, state: 'accepted' })
         .subscribe({
           next: resultList => {
             if (reset) this.followers = []

+ 1 - 1
client/src/app/+about/about-instance/about-instance.component.ts

@@ -95,6 +95,6 @@ export class AboutInstanceComponent implements OnInit, AfterViewChecked {
   onClickCopyLink (anchor: HTMLAnchorElement) {
     const link = anchor.href
     copyToClipboard(link)
-    this.notifier.success(link, $localize `Link copied`)
+    this.notifier.success(link, $localize`Link copied`)
   }
 }

+ 4 - 4
client/src/app/+about/about-instance/contact-admin-modal.component.ts

@@ -77,10 +77,10 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit {
   }
 
   sendForm () {
-    const fromName = this.form.value[ 'fromName' ]
-    const fromEmail = this.form.value[ 'fromEmail' ]
-    const subject = this.form.value[ 'subject' ]
-    const body = this.form.value[ 'body' ]
+    const fromName = this.form.value['fromName']
+    const fromEmail = this.form.value['fromEmail']
+    const subject = this.form.value['subject']
+    const body = this.form.value['body']
 
     this.instanceService.contactAdministrator(fromEmail, fromName, subject, body)
         .subscribe({

+ 0 - 1
client/src/app/+about/about-routing.module.ts

@@ -3,7 +3,6 @@ import { RouterModule, Routes } from '@angular/router'
 import { AboutFollowsComponent } from '@app/+about/about-follows/about-follows.component'
 import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component'
 import { AboutInstanceResolver } from '@app/+about/about-instance/about-instance.resolver'
-import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component'
 import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component'
 import { AboutComponent } from './about.component'
 

+ 7 - 5
client/src/app/+accounts/account-video-channels/account-video-channels.component.ts

@@ -1,10 +1,10 @@
 import { from, Subject, Subscription } from 'rxjs'
 import { concatMap, map, switchMap, tap } from 'rxjs/operators'
 import { Component, OnDestroy, OnInit } from '@angular/core'
-import { ComponentPagination, hasMoreItems, MarkdownService, ScreenService, User, UserService } from '@app/core'
+import { ComponentPagination, hasMoreItems, MarkdownService, User, UserService } from '@app/core'
 import { Account, AccountService, Video, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
-import { NSFWPolicyType, VideoSortField } from '@shared/models'
 import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature'
+import { NSFWPolicyType, VideoSortField } from '@shared/models'
 
 @Component({
   selector: 'my-account-video-channels',
@@ -87,7 +87,9 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
 
     this.videoChannelService.listAccountVideoChannels(options)
       .pipe(
-        tap(res => this.channelPagination.totalItems = res.total),
+        tap(res => {
+          this.channelPagination.totalItems = res.total
+        }),
         switchMap(res => from(res.data)),
         concatMap(videoChannel => {
           const options = {
@@ -113,14 +115,14 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
   }
 
   getVideosOf (videoChannel: VideoChannel) {
-    const obj = this.videos[ videoChannel.id ]
+    const obj = this.videos[videoChannel.id]
     if (!obj) return []
 
     return obj.videos
   }
 
   getTotalVideosOf (videoChannel: VideoChannel) {
-    const obj = this.videos[ videoChannel.id ]
+    const obj = this.videos[videoChannel.id]
     if (!obj) return undefined
 
     return obj.total

+ 1 - 1
client/src/app/+accounts/account-videos/account-videos.component.ts

@@ -1,5 +1,5 @@
 import { forkJoin, Subscription } from 'rxjs'
-import { first, tap } from 'rxjs/operators'
+import { first } from 'rxjs/operators'
 import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
 import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'

+ 3 - 3
client/src/app/+accounts/accounts.component.html

@@ -71,14 +71,14 @@
       <a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
     </ng-template>
 
-    <list-overflow [hidden]="hideMenu" [items]="links" [itemTemplate]="linkTemplate"></list-overflow>
+    <my-list-overflow [hidden]="hideMenu" [items]="links" [itemTemplate]="linkTemplate"></my-list-overflow>
 
-    <simple-search-input
+    <my-simple-search-input
       [alwaysShow]="!isInSmallView()" (searchChanged)="searchChanged($event)"
       (inputDisplayChanged)="onSearchInputDisplayChanged($event)" name="search-videos"
       i18n-iconTitle icon-title="Search account videos"
       i18n-placeholder placeholder="Search account videos"
-    ></simple-search-input>
+    ></my-simple-search-input>
   </div>
 
   <router-outlet (activate)="onOutletLoaded($event)"></router-outlet>

+ 10 - 4
client/src/app/+accounts/accounts.component.ts

@@ -61,7 +61,7 @@ export class AccountsComponent implements OnInit, OnDestroy {
   ngOnInit () {
     this.routeSub = this.route.params
                         .pipe(
-                          map(params => params[ 'accountId' ]),
+                          map(params => params['accountId']),
                           distinctUntilChanged(),
                           switchMap(accountId => this.accountService.getAccount(accountId)),
                           tap(account => this.onAccount(account)),
@@ -72,7 +72,9 @@ export class AccountsComponent implements OnInit, OnDestroy {
                           ]))
                         )
                         .subscribe({
-                          next: videoChannels => this.videoChannels = videoChannels.data,
+                          next: videoChannels => {
+                            this.videoChannels = videoChannels.data
+                          },
 
                           error: err => this.notifier.error(err.message)
                         })
@@ -176,7 +178,9 @@ export class AccountsComponent implements OnInit, OnDestroy {
     if (user.hasRight(UserRight.MANAGE_USERS)) {
       this.userService.getUser(account.userId)
         .subscribe({
-          next: accountUser => this.accountUser = accountUser,
+          next: accountUser => {
+            this.accountUser = accountUser
+          },
 
           error: err => this.notifier.error(err.message)
         })
@@ -209,6 +213,8 @@ export class AccountsComponent implements OnInit, OnDestroy {
         itemsPerPage: 0
       },
       sort: '-publishedAt'
-    }).subscribe(res => this.accountVideosCount = res.total)
+    }).subscribe(res => {
+      this.accountVideosCount = res.total
+    })
   }
 }

+ 1 - 1
client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.ts

@@ -97,7 +97,7 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
       .pipe(pairwise())
       .subscribe(([ oldValue, newValue ]) => {
         if (oldValue !== true && newValue === true) {
-          // tslint:disable:max-line-length
+          /* eslint-disable max-len */
           this.signupAlertMessage = $localize`You enabled signup: we automatically enabled the "Block new videos automatically" checkbox of the "Videos" section just below.`
 
           this.form.patchValue({

+ 3 - 1
client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts

@@ -277,7 +277,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
 
           // Reload general configuration
           this.serverService.resetConfig()
-            .subscribe(config => this.serverConfig = config)
+            .subscribe(config => {
+              this.serverConfig = config
+            })
 
           this.updateForm()
 

+ 1 - 1
client/src/app/+admin/config/edit-custom-config/edit-homepage.component.ts

@@ -1,4 +1,4 @@
-import { Component, Input, OnInit } from '@angular/core'
+import { Component, Input } from '@angular/core'
 import { FormGroup } from '@angular/forms'
 import { CustomMarkupService } from '@app/shared/shared-custom-markup'
 

+ 1 - 2
client/src/app/+admin/follows/following-list/following-list.component.ts

@@ -2,7 +2,6 @@ import { SortMeta } from 'primeng/api'
 import { Component, OnInit, ViewChild } from '@angular/core'
 import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
 import { InstanceFollowService } from '@app/shared/shared-instance'
-import { BatchDomainsModalComponent } from '@app/shared/shared-moderation'
 import { ActorFollow } from '@shared/models'
 import { FollowModalComponent } from './follow-modal.component'
 
@@ -22,7 +21,7 @@ export class FollowingListComponent extends RestTable implements OnInit {
     private notifier: Notifier,
     private confirmService: ConfirmService,
     private followService: InstanceFollowService
-    ) {
+  ) {
     super()
   }
 

+ 1 - 1
client/src/app/+admin/follows/shared/redundancy-checkbox.component.ts

@@ -14,7 +14,7 @@ export class RedundancyCheckboxComponent {
   constructor (
     private notifier: Notifier,
     private redundancyService: RedundancyService
-    ) { }
+  ) { }
 
   updateRedundancyState () {
     this.redundancyService.updateRedundancy(this.host, this.redundancyAllowed)

+ 2 - 2
client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.ts

@@ -21,7 +21,7 @@ export class VideoRedundanciesListComponent extends RestTable implements OnInit
   pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
   displayType: VideoRedundanciesTarget = 'my-videos'
 
-  redundanciesGraphsData: { stats: VideosRedundancyStats, graphData: object, options: object }[] = []
+  redundanciesGraphsData: { stats: VideosRedundancyStats, graphData: any, options: any }[] = []
 
   noRedundancies = false
 
@@ -32,7 +32,7 @@ export class VideoRedundanciesListComponent extends RestTable implements OnInit
     private confirmService: ConfirmService,
     private redundancyService: RedundancyService,
     private serverService: ServerService
-    ) {
+  ) {
     super()
 
     this.bytesPipe = new BytesPipe()

+ 2 - 2
client/src/app/+admin/moderation/video-block-list/video-block-list.component.html

@@ -21,7 +21,7 @@
 
   <ng-template pTemplate="header">
     <tr>
-      <th style="width: 40px"></th>
+      <th style="width: 40px;"></th>
       <th style="width: 150px;"></th>
       <th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th>
       <th style="width: 100px;" i18n>Sensitive</th>
@@ -54,7 +54,7 @@
             </div>
             <div class="table-video-text">
               <div>
-                <my-global-icon i18n-title title="The video was blocked due to automatic blocking of new videos" *ngIf="videoBlock.type == 2" iconName="robot"></my-global-icon>
+                <my-global-icon i18n-title title="The video was blocked due to automatic blocking of new videos" *ngIf="videoBlock.type === 2" iconName="robot"></my-global-icon>
                 {{ videoBlock.video.name }}
               </div>
               <div class="text-muted">by {{ videoBlock.video.channel?.displayName }} on {{ videoBlock.video.channel?.host }} </div>

+ 2 - 2
client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts

@@ -28,11 +28,11 @@ export class VideoBlockListComponent extends RestTable implements OnInit {
 
   inputFilters: AdvancedInputFilter[] = [
     {
-      queryParams: { 'search': 'type:auto' },
+      queryParams: { search: 'type:auto' },
       label: $localize`Automatic blocks`
     },
     {
-      queryParams: { 'search': 'type:manual' },
+      queryParams: { search: 'type:manual' },
       label: $localize`Manual blocks`
     }
   ]

+ 3 - 3
client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts

@@ -44,11 +44,11 @@ export class VideoCommentListComponent extends RestTable implements OnInit {
 
   inputFilters: AdvancedInputFilter[] = [
     {
-      queryParams: { 'search': 'local:true' },
+      queryParams: { search: 'local:true' },
       label: $localize`Local comments`
     },
     {
-      queryParams: { 'search': 'local:false' },
+      queryParams: { search: 'local:false' },
       label: $localize`Remote comments`
     }
   ]
@@ -66,7 +66,7 @@ export class VideoCommentListComponent extends RestTable implements OnInit {
     private videoCommentService: VideoCommentService,
     private markdownRenderer: MarkdownService,
     private bulkService: BulkService
-    ) {
+  ) {
     super()
 
     this.videoCommentActions = [

+ 1 - 1
client/src/app/+admin/plugins/plugin-search/plugin-search.component.html

@@ -3,7 +3,7 @@
 </div>
 
 <div class="search-bar">
-  <input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..." autofocus />
+  <input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..." myAutofocus />
 </div>
 
 <div class="alert alert-info" i18n *ngIf="pluginInstalled">

+ 3 - 3
client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts

@@ -103,8 +103,8 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
     const settingsValues: any = {}
 
     for (const setting of this.registeredSettings) {
-      buildOptions[ setting.name ] = null
-      settingsValues[ setting.name ] = this.getSetting(setting.name)
+      buildOptions[setting.name] = null
+      settingsValues[setting.name] = this.getSetting(setting.name)
     }
 
     this.buildForm(buildOptions)
@@ -117,7 +117,7 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
   private getSetting (name: string) {
     const settings = this.plugin.settings
 
-    if (settings && settings[name] !== undefined) return settings[name]
+    if (settings?.[name] !== undefined) return settings[name]
 
     const registered = this.registeredSettings.find(r => r.name === name)
 

+ 1 - 3
client/src/app/+admin/plugins/shared/plugin-api.service.ts

@@ -1,10 +1,8 @@
-import { Observable } from 'rxjs'
-import { catchError, map, switchMap } from 'rxjs/operators'
+import { catchError } from 'rxjs/operators'
 import { HttpClient, HttpParams } from '@angular/common/http'
 import { Injectable } from '@angular/core'
 import { ComponentPagination, RestExtractor, RestService } from '@app/core'
 import { PluginService } from '@app/core/plugins/plugin.service'
-import { peertubeTranslate } from '@shared/core-utils/i18n'
 import {
   InstallOrUpdatePlugin,
   ManagePlugin,

+ 4 - 4
client/src/app/+admin/system/jobs/job.service.ts

@@ -20,9 +20,9 @@ export class JobService {
   ) {}
 
   getJobs (options: {
-    jobState?: JobStateClient,
-    jobType: JobTypeClient,
-    pagination: RestPagination,
+    jobState?: JobStateClient
+    jobType: JobTypeClient
+    pagination: RestPagination
     sort: SortMeta
   }): Observable<ResultList<Job>> {
     const { jobState, jobType, pagination, sort } = options
@@ -32,7 +32,7 @@ export class JobService {
 
     if (jobType !== 'all') params = params.append('jobType', jobType)
 
-    return this.authHttp.get<ResultList<Job>>(JobService.BASE_JOB_URL + `/${jobState ? jobState : ''}`, { params })
+    return this.authHttp.get<ResultList<Job>>(JobService.BASE_JOB_URL + `/${jobState || ''}`, { params })
                .pipe(
                  map(res => {
                    return this.restExtractor.convertResultListDateToHuman(res, [ 'createdAt', 'processedOn', 'finishedOn' ])

+ 3 - 3
client/src/app/+admin/system/logs/logs.service.ts

@@ -18,9 +18,9 @@ export class LogsService {
   ) {}
 
   getLogs (options: {
-    isAuditLog: boolean,
-    startDate: string,
-    level?: LogLevel,
+    isAuditLog: boolean
+    startDate: string
+    level?: LogLevel
     endDate?: string
   }): Observable<any[]> {
     const { isAuditLog, startDate } = options

+ 4 - 2
client/src/app/+admin/users/user-edit/user-create.component.ts

@@ -33,7 +33,7 @@ export class UserCreateComponent extends UserEdit implements OnInit {
     private router: Router,
     private notifier: Notifier,
     private userService: UserService
-    ) {
+  ) {
     super()
 
     this.buildQuotaOptions()
@@ -78,7 +78,9 @@ export class UserCreateComponent extends UserEdit implements OnInit {
           this.router.navigate([ '/admin/users/list' ])
         },
 
-        error: err => this.error = err.message
+        error: err => {
+          this.error = err.message
+        }
       })
   }
 

+ 1 - 1
client/src/app/+admin/users/user-edit/user-edit.ts

@@ -7,7 +7,7 @@ import { HTMLServerConfig, UserAdminFlag, UserRole, VideoResolution } from '@sha
 import { SelectOptionsItem } from '../../../../types/select-options-item.model'
 
 @Directive()
-// tslint:disable-next-line: directive-class-suffix
+// eslint-disable-next-line @angular-eslint/directive-class-suffix
 export abstract class UserEdit extends FormReactive implements OnInit {
   videoQuotaOptions: SelectOptionsItem[] = []
   videoQuotaDailyOptions: SelectOptionsItem[] = []

+ 4 - 2
client/src/app/+admin/users/user-edit/user-password.component.ts

@@ -20,7 +20,7 @@ export class UserPasswordComponent extends FormReactive implements OnInit {
     protected formValidatorService: FormValidatorService,
     private notifier: Notifier,
     private userService: UserService
-    ) {
+  ) {
     super()
   }
 
@@ -39,7 +39,9 @@ export class UserPasswordComponent extends FormReactive implements OnInit {
       .subscribe({
         next: () => this.notifier.success($localize`Password changed for user ${this.username}.`),
 
-        error: err => this.error = err.message
+        error: err => {
+          this.error = err.message
+        }
       })
   }
 

+ 10 - 4
client/src/app/+admin/users/user-edit/user-update.component.ts

@@ -33,7 +33,7 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
     private router: Router,
     private notifier: Notifier,
     private userService: UserService
-    ) {
+  ) {
     super()
 
     this.buildQuotaOptions()
@@ -63,7 +63,9 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
         .subscribe({
           next: user => this.onUserFetched(user),
 
-          error: err => this.error = err.message
+          error: err => {
+            this.error = err.message
+          }
         })
     })
   }
@@ -91,7 +93,9 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
           this.router.navigate([ '/admin/users/list' ])
         },
 
-        error: err => this.error = err.message
+        error: err => {
+          this.error = err.message
+        }
       })
   }
 
@@ -114,7 +118,9 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
           this.notifier.success($localize`An email asking for password reset has been sent to ${this.user.username}.`)
         },
 
-        error: err => this.error = err.message
+        error: err => {
+          this.error = err.message
+        }
       })
   }
 

+ 1 - 1
client/src/app/+admin/users/user-list/user-list.component.ts

@@ -36,7 +36,7 @@ export class UserListComponent extends RestTable implements OnInit {
 
   inputFilters: AdvancedInputFilter[] = [
     {
-      queryParams: { 'search': 'banned:true' },
+      queryParams: { search: 'banned:true' },
       label: $localize`Banned users`
     }
   ]

+ 1 - 1
client/src/app/+login/login.component.html

@@ -21,7 +21,7 @@
               <label i18n for="username">User</label>
               <input
                 type="text" id="username" i18n-placeholder placeholder="Username or email address" required tabindex="1"
-                formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" autofocus
+                formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" myAutofocus
               >
             </div>
 

+ 1 - 1
client/src/app/+login/login.component.ts

@@ -46,7 +46,7 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni
     private redirectService: RedirectService,
     private notifier: Notifier,
     private hooks: HooksService
-    ) {
+  ) {
     super()
   }
 

+ 1 - 0
client/src/app/+my-account/my-account-applications/my-account-applications.component.ts

@@ -36,6 +36,7 @@ export class MyAccountApplicationsComponent implements OnInit {
 
   async renewToken () {
     const res = await this.confirmService.confirm(
+      // eslint-disable-next-line max-len
       $localize`Renewing the token will disallow previously configured clients from retrieving the feed until they use the new token. Proceed?`,
       $localize`Renew token`
     )

+ 3 - 3
client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts

@@ -28,7 +28,7 @@ export class MyAccountChangeEmailComponent extends FormReactive implements OnIni
   ngOnInit () {
     this.buildForm({
       'new-email': USER_EMAIL_VALIDATOR,
-      'password': USER_PASSWORD_VALIDATOR
+      password: USER_PASSWORD_VALIDATOR
     })
 
     this.user = this.authService.getUser()
@@ -38,8 +38,8 @@ export class MyAccountChangeEmailComponent extends FormReactive implements OnIni
     this.error = null
     this.success = null
 
-    const password = this.form.value[ 'password' ]
-    const email = this.form.value[ 'new-email' ]
+    const password = this.form.value['password']
+    const email = this.form.value['new-email']
 
     forkJoin([
       this.serverService.getConfig(),

+ 9 - 5
client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts

@@ -1,7 +1,11 @@
 import { filter } from 'rxjs/operators'
 import { Component, OnInit } from '@angular/core'
 import { AuthService, Notifier, UserService } from '@app/core'
-import { USER_CONFIRM_PASSWORD_VALIDATOR, USER_PASSWORD_VALIDATOR, USER_EXISTING_PASSWORD_VALIDATOR } from '@app/shared/form-validators/user-validators'
+import {
+  USER_CONFIRM_PASSWORD_VALIDATOR,
+  USER_EXISTING_PASSWORD_VALIDATOR,
+  USER_PASSWORD_VALIDATOR
+} from '@app/shared/form-validators/user-validators'
 import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
 import { User } from '@shared/models'
 
@@ -19,7 +23,7 @@ export class MyAccountChangePasswordComponent extends FormReactive implements On
     private notifier: Notifier,
     private authService: AuthService,
     private userService: UserService
-    ) {
+  ) {
     super()
   }
 
@@ -35,13 +39,13 @@ export class MyAccountChangePasswordComponent extends FormReactive implements On
     const confirmPasswordControl = this.form.get('new-confirmed-password')
 
     confirmPasswordControl.valueChanges
-                          .pipe(filter(v => v !== this.form.value[ 'new-password' ]))
+                          .pipe(filter(v => v !== this.form.value['new-password']))
                           .subscribe(() => confirmPasswordControl.setErrors({ matchPassword: true }))
   }
 
   changePassword () {
-    const currentPassword = this.form.value[ 'current-password' ]
-    const newPassword = this.form.value[ 'new-password' ]
+    const currentPassword = this.form.value['current-password']
+    const newPassword = this.form.value['new-password']
 
     this.userService.changePassword(currentPassword, newPassword)
       .subscribe({

+ 2 - 1
client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts

@@ -15,10 +15,11 @@ export class MyAccountDangerZoneComponent {
     private userService: UserService,
     private confirmService: ConfirmService,
     private redirectService: RedirectService
-    ) { }
+  ) { }
 
   async deleteMe () {
     const res = await this.confirmService.confirmWithInput(
+      // eslint-disable-next-line max-len
       $localize`Are you sure you want to delete your account? This will delete all your data, including channels, videos and comments. Content cached by other servers and other third-parties might make longer to be deleted.`,
       $localize`Type your username to confirm`,
       this.user.username,

+ 1 - 1
client/src/app/+my-account/my-account-settings/my-account-settings.component.ts

@@ -19,7 +19,7 @@ export class MyAccountSettingsComponent implements OnInit, AfterViewChecked {
     private userService: UserService,
     private authService: AuthService,
     private notifier: Notifier
-    ) {}
+  ) {}
 
   get userInformationLoaded () {
     return this.authService.userInformationLoaded

+ 1 - 1
client/src/app/+my-account/my-account.component.ts

@@ -13,7 +13,7 @@ export class MyAccountComponent implements OnInit {
 
   constructor (
     private screenService: ScreenService
-    ) { }
+  ) { }
 
   get isBroadcastMessageDisplayed () {
     return this.screenService.isBroadcastMessageDisplayed

+ 2 - 2
client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts

@@ -31,7 +31,7 @@ export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements
     private notifier: Notifier,
     private router: Router,
     private videoChannelService: VideoChannelService
-    ) {
+  ) {
     super()
   }
 
@@ -64,7 +64,7 @@ export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements
           this.authService.refreshUserInformation()
 
           this.notifier.success($localize`Video channel ${videoChannelCreate.displayName} created.`)
-          this.router.navigate(['/my-library', 'video-channels'])
+          this.router.navigate([ '/my-library', 'video-channels' ])
         },
 
         error: err => {

+ 6 - 2
client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts

@@ -66,7 +66,9 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
             })
           },
 
-          error: err => this.error = err.message
+          error: err => {
+            this.error = err.message
+          }
         })
     })
   }
@@ -96,7 +98,9 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
           this.router.navigate([ '/my-library', 'video-channels' ])
         },
 
-        error: err => this.error = err.message
+        error: err => {
+          this.error = err.message
+        }
       })
   }
 

+ 4 - 4
client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts

@@ -121,16 +121,16 @@ channel with the same name (${videoChannel.name})!`,
         display: false
       },
       scales: {
-        xAxes: [{
+        xAxes: [ {
           display: false
-        }],
-        yAxes: [{
+        } ],
+        yAxes: [ {
           display: false,
           ticks: {
             min: Math.max(0, this.videoChannelsMinimumDailyViews - (3 * this.videoChannelsMaximumDailyViews / 100)),
             max: Math.max(1, this.videoChannelsMaximumDailyViews)
           }
-        }]
+        } ]
       },
       layout: {
         padding: {

+ 3 - 4
client/src/app/+my-library/my-history/my-history.component.ts

@@ -1,4 +1,3 @@
-import { Subject } from 'rxjs'
 import { tap } from 'rxjs/operators'
 import { Component, ComponentFactoryResolver, OnInit, ViewChild } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
@@ -109,9 +108,9 @@ export class MyHistoryComponent implements OnInit, DisableForReuseHook {
     this.userService.updateMyProfile({ videosHistoryEnabled: this.videosHistoryEnabled })
       .subscribe({
         next: () => {
-          const message = this.videosHistoryEnabled === true ?
-            $localize`Videos history is enabled` :
-            $localize`Videos history is disabled`
+          const message = this.videosHistoryEnabled === true
+            ? $localize`Videos history is enabled`
+            : $localize`Videos history is disabled`
 
           this.notifier.success(message)
 

+ 1 - 1
client/src/app/+my-library/my-library.component.ts

@@ -17,7 +17,7 @@ export class MyLibraryComponent implements OnInit {
     private serverService: ServerService,
     private authService: AuthService,
     private screenService: ScreenService
-    ) { }
+  ) { }
 
   get isBroadcastMessageDisplayed () {
     return this.screenService.isBroadcastMessageDisplayed

+ 1 - 1
client/src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.ts

@@ -29,7 +29,7 @@ export class MyAcceptOwnershipComponent extends FormReactive implements OnInit {
     private notifier: Notifier,
     private authService: AuthService,
     private modalService: NgbModal
-    ) {
+  ) {
     super()
   }
 

+ 4 - 2
client/src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts

@@ -29,7 +29,7 @@ export class MyVideoPlaylistCreateComponent extends MyVideoPlaylistEdit implemen
     private router: Router,
     private videoPlaylistService: VideoPlaylistService,
     private serverService: ServerService
-    ) {
+  ) {
     super()
   }
 
@@ -78,7 +78,9 @@ export class MyVideoPlaylistCreateComponent extends MyVideoPlaylistEdit implemen
           this.router.navigate([ '/my-library', 'video-playlists' ])
         },
 
-        error: err => this.error = err.message
+        error: err => {
+          this.error = err.message
+        }
       })
   }
 

+ 1 - 3
client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts

@@ -57,7 +57,7 @@ export class MyVideoPlaylistElementsComponent implements OnInit, OnDestroy {
     ]
 
     this.paramsSub = this.route.params.subscribe(routeParams => {
-      this.videoPlaylistId = routeParams[ 'videoPlaylistId' ]
+      this.videoPlaylistId = routeParams['videoPlaylistId']
       this.loadElements()
 
       this.loadPlaylistInfo()
@@ -145,8 +145,6 @@ export class MyVideoPlaylistElementsComponent implements OnInit, OnDestroy {
    * we add a delay to prevent unwanted drag&drop.
    *
    * @see {@link https://github.com/Chocobozzz/PeerTube/issues/2078}
-   *
-   * @returns {null|number} Null for no delay, or a number in milliseconds.
    */
   getDragStartDelay (): null | number {
     if (this.screenService.isInTouchScreen()) {

+ 7 - 3
client/src/app/+my-library/my-video-playlists/my-video-playlist-update.component.ts

@@ -65,14 +65,16 @@ export class MyVideoPlaylistUpdateComponent extends MyVideoPlaylistEdit implemen
                            })
                          )
                          .subscribe({
-                           next: ([ videoPlaylistToUpdate, videoPlaylistPrivacies]) => {
+                           next: ([ videoPlaylistToUpdate, videoPlaylistPrivacies ]) => {
                              this.videoPlaylistToUpdate = videoPlaylistToUpdate
                              this.videoPlaylistPrivacies = videoPlaylistPrivacies
 
                              this.hydrateFormFromPlaylist()
                            },
 
-                           error: err => this.error = err.message
+                           error: err => {
+                             this.error = err.message
+                           }
                          })
   }
 
@@ -99,7 +101,9 @@ export class MyVideoPlaylistUpdateComponent extends MyVideoPlaylistEdit implemen
           this.router.navigate([ '/my-library', 'video-playlists' ])
         },
 
-        error: err => this.error = err.message
+        error: err => {
+          this.error = err.message
+        }
       })
   }
 

+ 4 - 2
client/src/app/+my-library/my-videos/modals/video-change-ownership.component.ts

@@ -25,7 +25,7 @@ export class VideoChangeOwnershipComponent extends FormReactive implements OnIni
     private notifier: Notifier,
     private userService: UserService,
     private modalService: NgbModal
-    ) {
+  ) {
     super()
   }
 
@@ -49,7 +49,9 @@ export class VideoChangeOwnershipComponent extends FormReactive implements OnIni
     const query = event.query
     this.userService.autocomplete(query)
       .subscribe({
-        next: usernames => this.usernamePropositions = usernames,
+        next: usernames => {
+          this.usernamePropositions = usernames
+        },
 
         error: err => this.notifier.error(err.message)
       })

+ 2 - 2
client/src/app/+my-library/my-videos/my-videos.component.ts

@@ -49,7 +49,7 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
 
   inputFilters: AdvancedInputFilter[] = [
     {
-      queryParams: { 'search': 'isLive:true' },
+      queryParams: { search: 'isLive:true' },
       label: $localize`Only live videos`
     }
   ]
@@ -107,7 +107,7 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
 
   async deleteSelectedVideos () {
     const toDeleteVideosIds = Object.keys(this.selection)
-                                    .filter(k => this.selection[ k ] === true)
+                                    .filter(k => this.selection[k] === true)
                                     .map(k => parseInt(k, 10))
 
     const res = await this.confirmService.confirm(

+ 1 - 1
client/src/app/+remote-interaction/remote-interaction.component.ts

@@ -7,7 +7,7 @@ import { SearchService } from '@app/shared/shared-search'
 @Component({
   selector: 'my-remote-interaction',
   templateUrl: './remote-interaction.component.html',
-  styleUrls: ['./remote-interaction.component.scss']
+  styleUrls: [ './remote-interaction.component.scss' ]
 })
 export class RemoteInteractionComponent implements OnInit {
   error = ''

+ 1 - 1
client/src/app/+reset-password/reset-password.component.ts

@@ -21,7 +21,7 @@ export class ResetPasswordComponent extends FormReactive implements OnInit {
     private notifier: Notifier,
     private router: Router,
     private route: ActivatedRoute
-    ) {
+  ) {
     super()
   }
 

+ 3 - 3
client/src/app/+signup/+register/custom-stepper.component.ts

@@ -1,5 +1,5 @@
-import { Component } from '@angular/core'
 import { CdkStep, CdkStepper } from '@angular/cdk/stepper'
+import { Component } from '@angular/core'
 
 @Component({
   selector: 'my-custom-stepper',
@@ -14,13 +14,13 @@ export class CustomStepperComponent extends CdkStepper {
   }
 
   isCompleted (step: CdkStep) {
-    return step.stepControl && step.stepControl.dirty && step.stepControl.valid
+    return step.stepControl?.dirty && step.stepControl.valid
   }
 
   isAccessible (index: number) {
     const stepsCompletedMap = this.steps.map(step => this.isCompleted(step))
     return index === 0
       ? true
-      : stepsCompletedMap[ index - 1 ]
+      : stepsCompletedMap[index - 1]
   }
 }

+ 7 - 4
client/src/app/+signup/+register/register.component.ts

@@ -49,8 +49,7 @@ export class RegisterComponent implements OnInit {
     private authService: AuthService,
     private userService: UserService,
     private hooks: HooksService
-    ) {
-  }
+  ) { }
 
   get requiresEmailVerification () {
     return this.serverConfig.signup.requiresEmailVerification
@@ -138,11 +137,15 @@ export class RegisterComponent implements OnInit {
               this.success = $localize`You are now logged in as ${body.username}!`
             },
 
-            error: err => this.error = err.message
+            error: err => {
+              this.error = err.message
+            }
           })
       },
 
-      error: err => this.error = err.message
+      error: err => {
+        this.error = err.message
+      }
     })
   }
 }

+ 1 - 1
client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts

@@ -20,7 +20,7 @@ export class VerifyAccountEmailComponent implements OnInit {
     private authService: AuthService,
     private notifier: Notifier,
     private route: ActivatedRoute
-    ) {
+  ) {
   }
 
   ngOnInit () {

+ 1 - 1
client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts

@@ -1,5 +1,5 @@
 import { forkJoin, Subscription } from 'rxjs'
-import { first, tap } from 'rxjs/operators'
+import { first } from 'rxjs/operators'
 import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
 import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'

+ 1 - 1
client/src/app/+video-channels/video-channels.component.html

@@ -114,7 +114,7 @@
       <a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
     </ng-template>
 
-    <list-overflow [items]="links" [itemTemplate]="linkTemplate"></list-overflow>
+    <my-list-overflow [items]="links" [itemTemplate]="linkTemplate"></my-list-overflow>
   </div>
 
   <router-outlet></router-outlet>

+ 4 - 4
client/src/app/+video-channels/video-channels.component.ts

@@ -44,7 +44,7 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
   ngOnInit () {
     this.routeSub = this.route.params
                         .pipe(
-                          map(params => params[ 'videoChannelName' ]),
+                          map(params => params['videoChannelName']),
                           distinctUntilChanged(),
                           switchMap(videoChannelName => this.videoChannelService.getVideoChannel(videoChannelName)),
                           catchError(err => this.restExtractor.redirectTo404IfNotFound(err, 'other', [
@@ -64,9 +64,9 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
 
     this.hotkeys = [
       new Hotkey('S', (event: KeyboardEvent): boolean => {
-        this.subscribeButton.subscribed ?
-          this.subscribeButton.unsubscribe() :
-          this.subscribeButton.subscribe()
+        if (this.subscribeButton.subscribed) this.subscribeButton.unsubscribe()
+        else this.subscribeButton.subscribe()
+
         return false
       }, undefined, $localize`Subscribe to the account`)
     ]

+ 1 - 1
client/src/app/+videos/+video-edit/shared/i18n-primeng-calendar.service.ts

@@ -73,7 +73,7 @@ export class I18nPrimengCalendarService {
   }
 
   getTimezone () {
-    const gmt = new Date().toString().match(/([A-Z]+[\+-][0-9]+)/)[1]
+    const gmt = new Date().toString().match(/([A-Z]+[+-][0-9]+)/)[1]
     const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
 
     return `${timezone} - ${gmt}`

+ 4 - 4
client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.ts

@@ -66,18 +66,18 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
   isReplacingExistingCaption () {
     if (this.closingModal === true) return false
 
-    const languageId = this.form.value[ 'language' ]
+    const languageId = this.form.value['language']
 
-    return languageId && this.existingCaptions.indexOf(languageId) !== -1
+    return languageId && this.existingCaptions.includes(languageId)
   }
 
   async addCaption () {
-    const languageId = this.form.value[ 'language' ]
+    const languageId = this.form.value['language']
     const languageObject = this.videoCaptionLanguages.find(l => l.id === languageId)
 
     this.captionAdded.emit({
       language: languageObject,
-      captionfile: this.form.value[ 'captionfile' ]
+      captionfile: this.form.value['captionfile']
     })
 
     this.hide()

+ 1 - 1
client/src/app/+videos/+video-edit/shared/video-edit-utils.ts

@@ -24,7 +24,7 @@ function hydrateFormFromVideo (formGroup: FormGroup, video: VideoEdit, thumbnail
       .then(response => response.blob())
       .then(data => {
         formGroup.patchValue({
-          [ obj.name ]: data
+          [obj.name]: data
         })
       })
   }

+ 5 - 5
client/src/app/+videos/+video-edit/shared/video-edit.component.ts

@@ -233,7 +233,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
 
   async deleteCaption (caption: VideoCaptionEdit) {
     // Caption recovers his former state
-    if (caption.action && this.initialVideoCaptions.indexOf(caption.language.id) !== -1) {
+    if (caption.action && this.initialVideoCaptions.includes(caption.language.id)) {
       caption.action = undefined
       return
     }
@@ -297,7 +297,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
 
   private trackPrivacyChange () {
     // We will update the schedule input and the wait transcoding checkbox validators
-    this.form.controls[ 'privacy' ]
+    this.form.controls['privacy']
       .valueChanges
       .pipe(map(res => parseInt(res.toString(), 10)))
       .subscribe(
@@ -336,12 +336,12 @@ export class VideoEditComponent implements OnInit, OnDestroy {
 
   private trackChannelChange () {
     // We will update the "support" field depending on the channel
-    this.form.controls[ 'channelId' ]
+    this.form.controls['channelId']
       .valueChanges
       .pipe(map(res => parseInt(res.toString(), 10)))
       .subscribe(
         newChannelId => {
-          const oldChannelId = parseInt(this.form.value[ 'channelId' ], 10)
+          const oldChannelId = parseInt(this.form.value['channelId'], 10)
 
           // Not initialized yet
           if (isNaN(newChannelId)) return
@@ -350,7 +350,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
 
           // Wait support field update
           setTimeout(() => {
-            const currentSupport = this.form.value[ 'support' ]
+            const currentSupport = this.form.value['support']
 
             // First time we set the channel?
             if (isNaN(oldChannelId)) {

+ 4 - 4
client/src/app/+videos/+video-edit/video-add-components/drag-drop.directive.ts

@@ -1,26 +1,26 @@
 import { Directive, Output, EventEmitter, HostBinding, HostListener } from '@angular/core'
 
 @Directive({
-  selector: '[dragDrop]'
+  selector: '[myDragDrop]'
 })
 export class DragDropDirective {
   @Output() fileDropped = new EventEmitter<FileList>()
 
   @HostBinding('class.dragover') dragover = false
 
-  @HostListener('dragover', ['$event']) onDragOver (e: Event) {
+  @HostListener('dragover', [ '$event' ]) onDragOver (e: Event) {
     e.preventDefault()
     e.stopPropagation()
     this.dragover = true
   }
 
-  @HostListener('dragleave', ['$event']) public onDragLeave (e: Event) {
+  @HostListener('dragleave', [ '$event' ]) public onDragLeave (e: Event) {
     e.preventDefault()
     e.stopPropagation()
     this.dragover = false
   }
 
-  @HostListener('drop', ['$event']) public ondrop (e: DragEvent) {
+  @HostListener('drop', [ '$event' ]) public ondrop (e: DragEvent) {
     e.preventDefault()
     e.stopPropagation()
     this.dragover = false

+ 1 - 1
client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts

@@ -41,7 +41,7 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, AfterView
     private liveVideoService: LiveVideoService,
     private router: Router,
     private hooks: HooksService
-    ) {
+  ) {
     super()
   }
 

+ 1 - 1
client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.html

@@ -1,4 +1,4 @@
-<div *ngIf="!hasImportedVideo" class="upload-video-container" dragDrop (fileDropped)="setTorrentFile($event)">
+<div *ngIf="!hasImportedVideo" class="upload-video-container" myDragDrop (fileDropped)="setTorrentFile($event)">
   <div class="first-step-block">
     <my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
 

+ 2 - 2
client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts

@@ -5,7 +5,7 @@ import { scrollToTop } from '@app/helpers'
 import { FormValidatorService } from '@app/shared/shared-forms'
 import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main'
 import { LoadingBarService } from '@ngx-loading-bar/core'
-import { PeerTubeProblemDocument, ServerErrorCode, VideoPrivacy, VideoUpdate } from '@shared/models'
+import { PeerTubeProblemDocument, ServerErrorCode, VideoUpdate } from '@shared/models'
 import { hydrateFormFromVideo } from '../shared/video-edit-utils'
 import { VideoSend } from './video-send'
 
@@ -43,7 +43,7 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Af
     private router: Router,
     private videoImportService: VideoImportService,
     private hooks: HooksService
-    ) {
+  ) {
     super()
   }
 

+ 1 - 1
client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts

@@ -59,7 +59,7 @@ export class VideoImportUrlComponent extends VideoSend implements OnInit, AfterV
   }
 
   isTargetUrlValid () {
-    return this.targetUrl && this.targetUrl.match(/https?:\/\//)
+    return this.targetUrl?.match(/https?:\/\//)
   }
 
   importVideo () {

+ 1 - 1
client/src/app/+videos/+video-edit/video-add-components/video-send.ts

@@ -9,7 +9,7 @@ import { LoadingBarService } from '@ngx-loading-bar/core'
 import { HTMLServerConfig, VideoConstant, VideoPrivacy } from '@shared/models'
 
 @Directive()
-// tslint:disable-next-line: directive-class-suffix
+// eslint-disable-next-line @angular-eslint/directive-class-suffix
 export abstract class VideoSend extends FormReactive implements OnInit {
   userVideoChannels: SelectChannelItem[] = []
   videoPrivacies: VideoConstant<VideoPrivacy>[] = []

+ 1 - 1
client/src/app/+videos/+video-edit/video-add-components/video-upload.component.html

@@ -1,4 +1,4 @@
-<div *ngIf="!isUploadingVideo" class="upload-video-container" dragDrop (fileDropped)="onFileDropped($event)">
+<div *ngIf="!isUploadingVideo" class="upload-video-container" myDragDrop (fileDropped)="onFileDropped($event)">
   <div class="first-step-block">
     <my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
 

+ 4 - 1
client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts

@@ -128,7 +128,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
 
   onUploadVideoOngoing (state: UploadState) {
     switch (state.status) {
-      case 'error':
+      case 'error': {
         const error = state.response?.error || 'Unknow error'
 
         this.handleUploadError({
@@ -143,6 +143,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
           url: state.url
         })
         break
+      }
 
       case 'cancelled':
         this.isUploadingVideo = false
@@ -323,6 +324,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
       const videoQuotaUsedBytes = bytePipes.transform(this.userVideoQuotaUsed, 0)
       const videoQuotaBytes = bytePipes.transform(videoQuota, 0)
 
+      // eslint-disable-next-line max-len
       const msg = $localize`Your video quota is exceeded with this video (video size: ${videoSizeBytes}, used: ${videoQuotaUsedBytes}, quota: ${videoQuotaBytes})`
       this.notifier.error(msg)
 
@@ -341,6 +343,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
       const videoSizeBytes = bytePipes.transform(videofile.size, 0)
       const quotaUsedDailyBytes = bytePipes.transform(this.userVideoQuotaUsedDaily, 0)
       const quotaDailyBytes = bytePipes.transform(videoQuotaDaily, 0)
+      // eslint-disable-next-line max-len
       const msg = $localize`Your daily video quota is exceeded with this video (video size: ${videoSizeBytes}, used: ${quotaUsedDailyBytes}, quota: ${quotaDailyBytes})`
       this.notifier.error(msg)
 

+ 2 - 3
client/src/app/+videos/+video-edit/video-update.component.ts

@@ -38,7 +38,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
     private loadingBar: LoadingBarService,
     private videoCaptionService: VideoCaptionService,
     private liveVideoService: LiveVideoService
-    ) {
+  ) {
     super()
   }
 
@@ -119,8 +119,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
   }
 
   update () {
-    if (this.checkForm() === false
-      || this.isUpdatingVideo === true) {
+    if (this.checkForm() === false || this.isUpdatingVideo === true) {
       return
     }
 

+ 3 - 3
client/src/app/+videos/+video-edit/video-update.resolver.ts

@@ -18,7 +18,7 @@ export class VideoUpdateResolver implements Resolve<any> {
   }
 
   resolve (route: ActivatedRouteSnapshot) {
-    const uuid: string = route.params[ 'uuid' ]
+    const uuid: string = route.params['uuid']
 
     return this.videoService.getVideo({ videoId: uuid })
                .pipe(
@@ -42,8 +42,8 @@ export class VideoUpdateResolver implements Resolve<any> {
         ),
 
       video.isLive
-          ? this.liveVideoService.getVideoLive(video.id)
-          : of(undefined)
+        ? this.liveVideoService.getVideoLive(video.id)
+        : of(undefined)
     ]
   }
 }

+ 1 - 1
client/src/app/+videos/+video-watch/player-styles.component.ts

@@ -8,7 +8,7 @@ import { Component, ViewEncapsulation } from '@angular/core'
   selector: 'my-player-styles',
   template: '',
   styleUrls: [ './player-styles.component.scss' ],
-  // tslint:disable:use-component-view-encapsulation
+  /* eslint-disable @angular-eslint/use-component-view-encapsulation */
   encapsulation: ViewEncapsulation.None
 })
 export class PlayerStylesComponent {

+ 3 - 3
client/src/app/+videos/+video-watch/shared/comment/video-comment-add.component.ts

@@ -25,7 +25,7 @@ import { VideoCommentCreate } from '@shared/models'
 @Component({
   selector: 'my-video-comment-add',
   templateUrl: './video-comment-add.component.html',
-  styleUrls: ['./video-comment-add.component.scss']
+  styleUrls: [ './video-comment-add.component.scss' ]
 })
 export class VideoCommentAddComponent extends FormReactive implements OnChanges, OnInit {
   @Input() user: User
@@ -64,7 +64,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnChanges,
     for (const emojiMarkupName in emojiMarkupObjectList) {
       if (emojiMarkupName) {
         const emoji = emojiMarkupObjectList[emojiMarkupName]
-        emojiMarkupArrayList.push([emoji, emojiMarkupName])
+        emojiMarkupArrayList.push([ emoji, emojiMarkupName ])
       }
     }
 
@@ -91,7 +91,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnChanges,
     // Not initialized yet
     if (!this.form) return
 
-    if (changes.textValue && changes.textValue.currentValue && changes.textValue.currentValue !== changes.textValue.previousValue) {
+    if (changes.textValue?.currentValue && changes.textValue.currentValue !== changes.textValue.previousValue) {
       this.patchTextValue(changes.textValue.currentValue, true)
     }
   }

+ 1 - 1
client/src/app/+videos/+video-watch/shared/comment/video-comment.component.html

@@ -29,7 +29,7 @@
           class="comment-html"
           [innerHTML]="sanitizedCommentHTML"
           (timestampClicked)="handleTimestampClicked($event)"
-          timestampRouteTransformer
+          myTimestampRouteTransformer
         ></div>
 
         <div class="comment-actions">

+ 1 - 1
client/src/app/+videos/+video-watch/shared/comment/video-comment.component.ts

@@ -10,7 +10,7 @@ import { User, UserRight } from '@shared/models'
 @Component({
   selector: 'my-video-comment',
   templateUrl: './video-comment.component.html',
-  styleUrls: ['./video-comment.component.scss']
+  styleUrls: [ './video-comment.component.scss' ]
 })
 export class VideoCommentComponent implements OnInit, OnChanges {
   @ViewChild('commentReportModal') commentReportModal: CommentReportComponent

+ 6 - 2
client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts

@@ -9,7 +9,7 @@ import { VideoComment, VideoCommentService, VideoCommentThreadTree } from '@app/
 @Component({
   selector: 'my-video-comments',
   templateUrl: './video-comments.component.html',
-  styleUrls: ['./video-comments.component.scss']
+  styleUrls: [ './video-comments.component.scss' ]
 })
 export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
   @ViewChild('commentHighlightBlock') commentHighlightBlock: ElementRef
@@ -200,7 +200,11 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
   }
 
   async onWantedToRedraft (commentToRedraft: VideoComment) {
-    const confirm = await this.onWantedToDelete(commentToRedraft, $localize`Delete and re-draft`, $localize`Do you really want to delete and re-draft this comment?`)
+    const confirm = await this.onWantedToDelete(
+      commentToRedraft,
+      $localize`Delete and re-draft`,
+      $localize`Do you really want to delete and re-draft this comment?`
+    )
 
     if (confirm) {
       this.inReplyToCommentId = commentToRedraft.inReplyToCommentId

+ 1 - 1
client/src/app/+videos/+video-watch/shared/information/video-alert.component.ts

@@ -23,7 +23,7 @@ export class VideoAlertComponent {
   }
 
   hasVideoScheduledPublication () {
-    return this.video && this.video.scheduledUpdate !== undefined
+    return this.video?.scheduledUpdate !== undefined
   }
 
   isWaitingForLive () {

+ 1 - 1
client/src/app/+videos/+video-watch/shared/metadata/video-description.component.html

@@ -3,7 +3,7 @@
     class="video-info-description-html"
     [innerHTML]="videoHTMLDescription"
     (timestampClicked)="onTimestampClicked($event)"
-    timestampRouteTransformer
+    myTimestampRouteTransformer
   ></div>
 
   <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()">

+ 5 - 5
client/src/app/+videos/+video-watch/shared/playlist/video-watch-playlist.component.ts

@@ -39,7 +39,7 @@ export class VideoWatchPlaylistComponent {
     private notifier: Notifier,
     private videoPlaylist: VideoPlaylistService,
     private localStorageService: LocalStorageService,
-    private sessionStorageService: SessionStorageService,
+    private sessionStorage: SessionStorageService,
     private router: Router
   ) {
     // defaults to true
@@ -50,7 +50,7 @@ export class VideoWatchPlaylistComponent {
     this.setAutoPlayNextVideoPlaylistSwitchText()
 
     // defaults to false
-    this.loopPlaylist = this.sessionStorageService.getItem(VideoWatchPlaylistComponent.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) === 'true'
+    this.loopPlaylist = this.sessionStorage.getItem(VideoWatchPlaylistComponent.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) === 'true'
     this.setLoopPlaylistSwitchText()
   }
 
@@ -145,7 +145,7 @@ export class VideoWatchPlaylistComponent {
 
     const start = previous.startTimestamp
     const stop = previous.stopTimestamp
-    this.router.navigate([],{ queryParams: { playlistPosition: previous.position, start, stop } })
+    this.router.navigate([], { queryParams: { playlistPosition: previous.position, start, stop } })
   }
 
   findPlaylistVideo (position: number, type: 'previous' | 'next'): VideoPlaylistElement {
@@ -163,7 +163,7 @@ export class VideoWatchPlaylistComponent {
     }
 
     const found = this.playlistElements.find(e => e.position === position)
-    if (found && found.video) return found
+    if (found?.video) return found
 
     const newPosition = type === 'previous'
       ? position - 1
@@ -178,7 +178,7 @@ export class VideoWatchPlaylistComponent {
 
     const start = next.startTimestamp
     const stop = next.stopTimestamp
-    this.router.navigate([],{ queryParams: { playlistPosition: next.position, start, stop } })
+    this.router.navigate([], { queryParams: { playlistPosition: next.position, start, stop } })
   }
 
   switchAutoPlayNextVideoPlaylist () {

+ 1 - 1
client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.html

@@ -20,7 +20,7 @@
       >
       </my-video-miniature>
 
-      <hr *ngIf="!playlist && i == 0 && length > 1" />
+      <hr *ngIf="!playlist && i === 0 && length > 1" />
     </ng-container>
   </ng-container>
 </div>

+ 1 - 1
client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.ts

@@ -51,7 +51,7 @@ export class RecommendedVideosComponent implements OnInit, OnChanges {
     } else {
       this.autoPlayNextVideo = this.sessionStorageService.getItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true'
 
-      this.sessionStorageService.watch([UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO]).subscribe(
+      this.sessionStorageService.watch([ UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO ]).subscribe(
         () => {
           this.autoPlayNextVideo = this.sessionStorageService.getItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true'
         }

+ 4 - 4
client/src/app/+videos/+video-watch/shared/timestamp-route-transformer.directive.ts

@@ -1,12 +1,12 @@
 import { Directive, EventEmitter, HostListener, Output } from '@angular/core'
 
 @Directive({
-  selector: '[timestampRouteTransformer]'
+  selector: '[myTimestampRouteTransformer]'
 })
 export class TimestampRouteTransformerDirective {
   @Output() timestampClicked = new EventEmitter<number>()
 
-  @HostListener('click', ['$event'])
+  @HostListener('click', [ '$event' ])
   public onClick ($event: Event) {
     const target = $event.target as HTMLLinkElement
 
@@ -21,10 +21,10 @@ export class TimestampRouteTransformerDirective {
     const ngxLinkParams = new URLSearchParams(ngxLink.search)
     if (ngxLinkParams.has('start') !== true) return
 
-    const separators = ['h', 'm', 's']
+    const separators = [ 'h', 'm', 's' ]
     const start = ngxLinkParams
       .get('start')
-      .match(new RegExp('(\\d{1,9}[' + separators.join('') + '])','g')) // match digits before any given separator
+      .match(new RegExp('(\\d{1,9}[' + separators.join('') + '])', 'g')) // match digits before any given separator
       .map(t => {
         if (t.includes('h')) return parseInt(t, 10) * 3600
         if (t.includes('m')) return parseInt(t, 10) * 60

+ 20 - 19
client/src/app/+videos/+video-watch/video-watch.component.ts

@@ -195,10 +195,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
   private loadRouteParams () {
     this.paramsSub = this.route.params.subscribe(routeParams => {
-      const videoId = routeParams[ 'videoId' ]
+      const videoId = routeParams['videoId']
       if (videoId) return this.loadVideo(videoId)
 
-      const playlistId = routeParams[ 'playlistId' ]
+      const playlistId = routeParams['playlistId']
       if (playlistId) return this.loadPlaylist(playlistId)
     })
   }
@@ -206,7 +206,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
   private loadRouteQuery () {
     this.queryParamsSub = this.route.queryParams.subscribe(queryParams => {
       // Handle the ?playlistPosition
-      const positionParam = queryParams[ 'playlistPosition' ] ?? 1
+      const positionParam = queryParams['playlistPosition'] ?? 1
 
       this.playlistPosition = positionParam === 'last'
         ? -1 // Handle the "last" index
@@ -219,7 +219,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
       this.videoWatchPlaylist.updatePlaylistIndex(this.playlistPosition)
 
-      const start = queryParams[ 'start' ]
+      const start = queryParams['start']
       if (this.player && start) this.player.currentTime(parseInt(start, 10))
     })
   }
@@ -237,7 +237,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
       'filter:api.video-watch.video.get.result'
     )
 
-    forkJoin([ videoObs, this.videoCaptionService.listCaptions(videoId)])
+    forkJoin([ videoObs, this.videoCaptionService.listCaptions(videoId) ])
       .subscribe({
         next: ([ video, captionsResult ]) => {
           const queryParams = this.route.snapshot.queryParams
@@ -292,6 +292,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
       const originUrl = errorBody.originUrl + (window.location.search ?? '')
 
       const res = await this.confirmService.confirm(
+        // eslint-disable-next-line max-len
         $localize`This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="${originUrl}">${originUrl}</a>?`,
         $localize`Redirection`
       )
@@ -312,7 +313,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
     if (!errorMessage) return
 
     // Display a message in the video player instead of a notification
-    if (errorMessage.indexOf('from xs param') !== -1) {
+    if (errorMessage.includes('from xs param')) {
       this.flushPlayer()
       this.remoteServerDown = true
 
@@ -466,7 +467,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
     if (this.nextVideoUUID) {
       this.router.navigate([ '/w', this.nextVideoUUID ])
-      return
     }
   }
 
@@ -483,14 +483,14 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
   private isAutoPlayNext () {
     return (
-      (this.user && this.user.autoPlayNextVideo) ||
+      (this.user?.autoPlayNextVideo) ||
       this.anonymousUser.autoPlayNextVideo
     )
   }
 
   private isPlaylistAutoPlayNext () {
     return (
-      (this.user && this.user.autoPlayNextVideoPlaylist) ||
+      (this.user?.autoPlayNextVideoPlaylist) ||
       this.anonymousUser.autoPlayNextVideoPlaylist
     )
   }
@@ -508,9 +508,9 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
   }
 
   private buildPlayerManagerOptions (params: {
-    video: VideoDetails,
-    videoCaptions: VideoCaption[],
-    urlOptions: CustomizationOptions & { playerMode: PlayerMode },
+    video: VideoDetails
+    videoCaptions: VideoCaption[]
+    urlOptions: CustomizationOptions & { playerMode: PlayerMode }
     user?: AuthUser
   }) {
     const { video, videoCaptions, urlOptions, user } = params
@@ -573,10 +573,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
         language: this.localeId,
 
-        userWatching: user && user.videosHistoryEnabled === true ? {
-          url: this.videoService.getUserWatchingVideoUrl(video.uuid),
-          authorizationHeader: this.authService.getRequestHeaderValue()
-        } : undefined,
+        userWatching: user && user.videosHistoryEnabled === true
+          ? {
+            url: this.videoService.getUserWatchingVideoUrl(video.uuid),
+            authorizationHeader: this.authService.getRequestHeaderValue()
+          }
+          : undefined,
 
         serverUrl: environment.apiUrl,
 
@@ -704,9 +706,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
     if (this.isUserLoggedIn()) {
       this.hotkeys = this.hotkeys.concat([
         new Hotkey('shift+s', () => {
-          this.subscribeButton.isSubscribedToAll()
-            ? this.subscribeButton.unsubscribe()
-            : this.subscribeButton.subscribe()
+          if (this.subscribeButton.isSubscribedToAll()) this.subscribeButton.unsubscribe()
+          else this.subscribeButton.subscribe()
 
           return false
         }, undefined, $localize`Subscribe to the account`)

+ 1 - 1
client/src/app/+videos/video-list/overview/overview.service.ts

@@ -43,7 +43,7 @@ export class OverviewService {
 
     // Build videos objects
     for (const key of Object.keys(serverVideosOverview)) {
-      for (const object of serverVideosOverview[ key ]) {
+      for (const object of serverVideosOverview[key]) {
         observables.push(
           of(object.videos)
             .pipe(

+ 1 - 1
client/src/app/+videos/video-list/trending/video-trending-header.component.ts

@@ -15,7 +15,7 @@ interface VideoTrendingHeaderItem {
 }
 
 @Component({
-  selector: 'video-trending-title-page',
+  selector: 'my-video-trending-title-page',
   styleUrls: [ './video-trending-header.component.scss' ],
   templateUrl: './video-trending-header.component.html'
 })

+ 3 - 3
client/src/app/+videos/video-list/trending/video-trending.component.ts

@@ -63,7 +63,7 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
 
         if (oldSort !== this.sort) this.reloadVideos()
       }
-    )
+      )
   }
 
   ngOnDestroy () {
@@ -97,12 +97,12 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
 
   getInjector () {
     return Injector.create({
-      providers: [{
+      providers: [ {
         provide: 'data',
         useValue: {
           model: this.defaultSort
         }
-      }]
+      } ]
     })
   }
 

+ 1 - 1
client/src/app/+videos/video-list/video-local.component.ts

@@ -5,7 +5,7 @@ import { HooksService } from '@app/core/plugins/hooks.service'
 import { immutableAssign } from '@app/helpers'
 import { VideoService } from '@app/shared/shared-main'
 import { AbstractVideoList } from '@app/shared/shared-video-miniature'
-import { UserRight, VideoFilter, VideoSortField } from '@shared/models'
+import { VideoFilter, VideoSortField } from '@shared/models'
 
 @Component({
   selector: 'my-videos-local',

+ 2 - 2
client/src/app/app.component.ts

@@ -243,7 +243,7 @@ export class AppComponent implements OnInit, AfterViewInit {
     // Inject JS
     if (this.serverConfig.instance.customizations.javascript) {
       try {
-        // tslint:disable:no-eval
+        /* eslint-disable no-eval */
         eval(this.serverConfig.instance.customizations.javascript)
       } catch (err) {
         console.error('Cannot eval custom JavaScript.', err)
@@ -294,7 +294,7 @@ export class AppComponent implements OnInit, AfterViewInit {
 
   private initHotkeys () {
     this.hotkeysService.add([
-      new Hotkey(['/', 's'], (event: KeyboardEvent): boolean => {
+      new Hotkey([ '/', 's' ], (event: KeyboardEvent): boolean => {
         document.getElementById('search-video').focus()
         return false
       }, undefined, $localize`Focus the search bar`),

+ 4 - 2
client/src/app/core/auth/auth.service.ts

@@ -48,7 +48,7 @@ export class AuthService {
     private hotkeysService: HotkeysService,
     private restExtractor: RestExtractor,
     private router: Router
-    ) {
+  ) {
     this.loginChanged = new Subject<AuthStatus>()
     this.loginChangedSource = this.loginChanged.asObservable()
 
@@ -206,7 +206,9 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular
     this.refreshingTokenObservable = this.http.post<UserRefreshToken>(AuthService.BASE_TOKEN_URL, body, { headers })
                                          .pipe(
                                            map(res => this.handleRefreshToken(res)),
-                                           tap(() => { this.refreshingTokenObservable = null }),
+                                           tap(() => {
+                                             this.refreshingTokenObservable = null
+                                           }),
                                            catchError(err => {
                                              this.refreshingTokenObservable = null
 

+ 3 - 3
client/src/app/core/hotkeys/hotkeys.component.ts

@@ -3,8 +3,8 @@ import { Subscription } from 'rxjs'
 import { Component, Input, OnDestroy, OnInit } from '@angular/core'
 
 @Component({
-  selector : 'my-hotkeys-cheatsheet',
-  templateUrl : './hotkeys.component.html',
+  selector: 'my-hotkeys-cheatsheet',
+  templateUrl: './hotkeys.component.html',
   styleUrls: [ './hotkeys.component.scss' ]
 })
 export class CheatSheetComponent implements OnInit, OnDestroy {
@@ -16,7 +16,7 @@ export class CheatSheetComponent implements OnInit, OnDestroy {
 
   constructor (
     private hotkeysService: HotkeysService
-    ) {}
+  ) {}
 
   public ngOnInit (): void {
     this.subscription = this.hotkeysService.cheatSheetToggle.subscribe((isOpen) => {

+ 2 - 2
client/src/app/core/menu/menu.service.ts

@@ -25,7 +25,7 @@ export type MenuSection = {
 export class MenuService {
   isMenuDisplayed = true
   isMenuChangedByUser = false
-  menuWidth = 240  // should be kept equal to $menu-width
+  menuWidth = 240 // should be kept equal to $menu-width
 
   constructor (
     private screenService: ScreenService
@@ -55,7 +55,7 @@ export class MenuService {
     // On touch screens, lock body scroll and display content overlay when memu is opened
     if (this.isMenuDisplayed) {
       document.body.classList.add('menu-open')
-      this.screenService.onFingerSwipe('left', () => { this.setMenuDisplay(false) })
+      this.screenService.onFingerSwipe('left', () => this.setMenuDisplay(false))
       return
     }
 

+ 4 - 6
client/src/app/core/plugins/hooks.service.ts

@@ -27,9 +27,8 @@ export class HooksService {
     })
   }
 
-  wrapObsFun
-    <P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName>
-    (fun: ObservableFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
+  wrapObsFun <P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName>
+  (fun: ObservableFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
     return from(this.pluginService.ensurePluginsAreLoaded(scope))
       .pipe(
         mergeMap(() => this.wrapObjectWithoutScopeLoad(params, hookParamName)),
@@ -38,9 +37,8 @@ export class HooksService {
       )
   }
 
-  async wrapFun
-    <P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName>
-    (fun: RawFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
+  async wrapFun <P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName>
+  (fun: RawFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
     await this.pluginService.ensurePluginsAreLoaded(scope)
 
     const newParams = await this.wrapObjectWithoutScopeLoad(params, hookParamName)

+ 5 - 5
client/src/app/core/plugins/plugin.service.ts

@@ -188,7 +188,7 @@ export class PluginService implements ClientHook {
         if (!this.authService.isLoggedIn()) return undefined
 
         const value = this.authService.getRequestHeaderValue()
-        return { 'Authorization': value }
+        return { Authorization: value }
       },
 
       notifier: {
@@ -198,10 +198,10 @@ export class PluginService implements ClientHook {
       },
 
       showModal: (input: {
-        title: string,
-        content: string,
-        close?: boolean,
-        cancel?: { value: string, action?: () => void },
+        title: string
+        content: string
+        close?: boolean
+        cancel?: { value: string, action?: () => void }
         confirm?: { value: string, action?: () => void }
       }) => {
         this.zone.run(() => this.customModal.show(input))

+ 7 - 7
client/src/app/core/renderer/markdown.service.ts

@@ -103,20 +103,20 @@ export class MarkdownService {
     const { name, markdown, withEmoji, additionalAllowedTags } = options
     if (!markdown) return ''
 
-    const config = this.parsersConfig[ name ]
-    if (!this.markdownParsers[ name ]) {
-      this.markdownParsers[ name ] = await this.createMarkdownIt(config)
+    const config = this.parsersConfig[name]
+    if (!this.markdownParsers[name]) {
+      this.markdownParsers[name] = await this.createMarkdownIt(config)
 
       if (withEmoji) {
         if (!this.emojiModule) {
           this.emojiModule = (await import('markdown-it-emoji/light')).default
         }
 
-        this.markdownParsers[ name ].use(this.emojiModule)
+        this.markdownParsers[name].use(this.emojiModule)
       }
     }
 
-    let html = this.markdownParsers[ name ].render(markdown)
+    let html = this.markdownParsers[name].render(markdown)
     html = this.avoidTruncatedTags(html)
 
     if (config.escape) return this.htmlRenderer.toSafeHtml(html, additionalAllowedTags)
@@ -156,7 +156,7 @@ export class MarkdownService {
       if (relIndex < 0) token.attrPush([ 'rel', 'noopener noreferrer' ])
       else token.attrs[relIndex][1] = 'noopener noreferrer'
 
-      // pass token to default renderer.
+      // pass token to default renderer.*
       return defaultRender(tokens, index, options, env, self)
     }
   }
@@ -164,7 +164,7 @@ export class MarkdownService {
   private avoidTruncatedTags (html: string) {
     return html.replace(/\*\*?([^*]+)$/, '$1')
       .replace(/<a[^>]+>([^<]+)<\/a>\s*...((<\/p>)|(<\/li>)|(<\/strong>))?$/mi, '$1...')
-      .replace(/\[[^\]]+\]\(([^\)]+)$/m, '$1')
+      .replace(/\[[^\]]+\]\(([^)]+)$/m, '$1')
       .replace(/\s?\[[^\]]+\]?[.]{3}<\/p>$/m, '...</p>')
   }
 }

+ 15 - 11
client/src/app/core/rest/rest-extractor.service.ts

@@ -13,15 +13,16 @@ export class RestExtractor {
     return true
   }
 
-  applyToResultListData <T> (result: ResultList<T>, fun: Function, additionalArgs?: any[]): ResultList<T> {
+  applyToResultListData <T, A, U> (
+    result: ResultList<T>,
+    fun: (data: T, ...args: A[]) => U,
+    additionalArgs: A[] = []
+  ): ResultList<U> {
     const data: T[] = result.data
-    const newData: T[] = []
-
-    data.forEach(d => newData.push(fun.apply(this, [ d ].concat(additionalArgs))))
 
     return {
       total: result.total,
-      data: newData
+      data: data.map(d => fun.apply(this, [ d, ...additionalArgs ]))
     }
   }
 
@@ -29,8 +30,10 @@ export class RestExtractor {
     return this.applyToResultListData(result, this.convertDateToHuman, [ fieldsToConvert ])
   }
 
-  convertDateToHuman (target: { [ id: string ]: string }, fieldsToConvert: string[]) {
-    fieldsToConvert.forEach(field => target[field] = dateToHuman(target[field]))
+  convertDateToHuman (target: any, fieldsToConvert: string[]) {
+    fieldsToConvert.forEach(field => {
+      target[field] = dateToHuman(target[field])
+    })
 
     return target
   }
@@ -46,7 +49,7 @@ export class RestExtractor {
       errorMessage = err.error
     } else if (err.status !== undefined) {
       // A server-side error occurred.
-      if (err.error && err.error.errors) {
+      if (err.error?.errors) {
         const errors = err.error.errors
         const errorsArray: string[] = []
 
@@ -55,9 +58,10 @@ export class RestExtractor {
         })
 
         errorMessage = errorsArray.join('. ')
-      } else if (err.error && err.error.error) {
+      } else if (err.error?.error) {
         errorMessage = err.error.error
       } else if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413) {
+        // eslint-disable-next-line max-len
         errorMessage = $localize`Media is too large for the server. Please contact you administrator if you want to increase the limit size.`
       } else if (err.status === HttpStatusCode.TOO_MANY_REQUESTS_429) {
         const secondsLeft = err.headers.get('retry-after')
@@ -71,7 +75,7 @@ export class RestExtractor {
         errorMessage = $localize`Server error. Please retry later.`
       }
 
-      errorMessage = errorMessage ? errorMessage : 'Unknown error.'
+      errorMessage = errorMessage || 'Unknown error.'
       console.error(`Backend returned code ${err.status}, errorMessage is: ${errorMessage}`)
     } else {
       console.error(err)
@@ -93,7 +97,7 @@ export class RestExtractor {
   }
 
   redirectTo404IfNotFound (obj: { status: number }, type: 'video' | 'other', status = [ HttpStatusCode.NOT_FOUND_404 ]) {
-    if (obj && obj.status && status.indexOf(obj.status) !== -1) {
+    if (obj?.status && status.includes(obj.status)) {
       // Do not use redirectService to avoid circular dependencies
       this.router.navigate([ '/404' ], { state: { type, obj }, skipLocationChange: true })
     }

+ 2 - 2
client/src/app/core/routing/custom-reuse-strategy.ts

@@ -1,5 +1,5 @@
-import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router'
 import { Injectable } from '@angular/core'
+import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router'
 
 @Injectable()
 export class CustomReuseStrategy implements RouteReuseStrategy {
@@ -78,6 +78,6 @@ export class CustomReuseStrategy implements RouteReuseStrategy {
   }
 
   private isReuseEnabled (route: ActivatedRouteSnapshot) {
-    return route.data.reuse && route.data.reuse.enabled && route.queryParams[ 'a-state' ]
+    return route.data.reuse?.enabled && route.queryParams['a-state']
   }
 }

+ 14 - 4
client/src/app/core/routing/menu-guard.service.ts

@@ -17,33 +17,43 @@ abstract class MenuGuard implements CanActivate, CanDeactivate<any> {
     if (!this.screen.isInMobileView() && this.screen.isInMediumView()) {
       this.menu.setMenuDisplay(this.display)
     }
+
     return true
   }
 }
 
 @Injectable()
 export class OpenMenuGuard extends MenuGuard {
-  constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, true) }
+  constructor (menu: MenuService, screen: ScreenService) {
+    super(menu, screen, true)
+  }
 }
 
 @Injectable()
 export class OpenMenuAlwaysGuard extends MenuGuard {
-  constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, true) }
+  constructor (menu: MenuService, screen: ScreenService) {
+    super(menu, screen, true)
+  }
 
   canActivate (): boolean {
     this.menu.setMenuDisplay(this.display)
+
     return true
   }
 }
 
 @Injectable()
 export class CloseMenuGuard extends MenuGuard {
-  constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, false) }
+  constructor (menu: MenuService, screen: ScreenService) {
+    super(menu, screen, false)
+  }
 }
 
 @Injectable()
 export class CloseMenuAlwaysGuard extends MenuGuard {
-  constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, false) }
+  constructor (menu: MenuService, screen: ScreenService) {
+    super(menu, screen, false)
+  }
 
   canActivate (): boolean {
     this.menu.setMenuDisplay(this.display)

Неке датотеке нису приказане због велике количине промена