aboutsummaryrefslogtreecommitdiffhomepage
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/.eslintrc.json169
-rw-r--r--client/angular.json25
-rw-r--r--client/e2e/local-protractor.conf.js2
-rw-r--r--client/e2e/protractor.conf.js2
-rw-r--r--client/e2e/tsconfig.json (renamed from client/e2e/tsconfig.e2e.json)0
-rw-r--r--client/package.json19
-rw-r--r--client/src/app/+about/about-follows/about-follows.component.ts2
-rw-r--r--client/src/app/+about/about-instance/about-instance.component.ts2
-rw-r--r--client/src/app/+about/about-instance/contact-admin-modal.component.ts8
-rw-r--r--client/src/app/+about/about-routing.module.ts1
-rw-r--r--client/src/app/+accounts/account-video-channels/account-video-channels.component.ts12
-rw-r--r--client/src/app/+accounts/account-videos/account-videos.component.ts2
-rw-r--r--client/src/app/+accounts/accounts.component.html6
-rw-r--r--client/src/app/+accounts/accounts.component.ts14
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.ts2
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts4
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-homepage.component.ts2
-rw-r--r--client/src/app/+admin/follows/following-list/following-list.component.ts3
-rw-r--r--client/src/app/+admin/follows/shared/redundancy-checkbox.component.ts2
-rw-r--r--client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.ts4
-rw-r--r--client/src/app/+admin/moderation/video-block-list/video-block-list.component.html4
-rw-r--r--client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts4
-rw-r--r--client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts6
-rw-r--r--client/src/app/+admin/plugins/plugin-search/plugin-search.component.html2
-rw-r--r--client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts6
-rw-r--r--client/src/app/+admin/plugins/shared/plugin-api.service.ts4
-rw-r--r--client/src/app/+admin/system/jobs/job.service.ts8
-rw-r--r--client/src/app/+admin/system/logs/logs.service.ts6
-rw-r--r--client/src/app/+admin/users/user-edit/user-create.component.ts6
-rw-r--r--client/src/app/+admin/users/user-edit/user-edit.ts2
-rw-r--r--client/src/app/+admin/users/user-edit/user-password.component.ts6
-rw-r--r--client/src/app/+admin/users/user-edit/user-update.component.ts14
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.ts2
-rw-r--r--client/src/app/+login/login.component.html2
-rw-r--r--client/src/app/+login/login.component.ts2
-rw-r--r--client/src/app/+my-account/my-account-applications/my-account-applications.component.ts1
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts6
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts14
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts3
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-settings.component.ts2
-rw-r--r--client/src/app/+my-account/my-account.component.ts2
-rw-r--r--client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts4
-rw-r--r--client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts8
-rw-r--r--client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts8
-rw-r--r--client/src/app/+my-library/my-history/my-history.component.ts7
-rw-r--r--client/src/app/+my-library/my-library.component.ts2
-rw-r--r--client/src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.ts2
-rw-r--r--client/src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts6
-rw-r--r--client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts4
-rw-r--r--client/src/app/+my-library/my-video-playlists/my-video-playlist-update.component.ts10
-rw-r--r--client/src/app/+my-library/my-videos/modals/video-change-ownership.component.ts6
-rw-r--r--client/src/app/+my-library/my-videos/my-videos.component.ts4
-rw-r--r--client/src/app/+remote-interaction/remote-interaction.component.ts2
-rw-r--r--client/src/app/+reset-password/reset-password.component.ts2
-rw-r--r--client/src/app/+signup/+register/custom-stepper.component.ts6
-rw-r--r--client/src/app/+signup/+register/register.component.ts11
-rw-r--r--client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts2
-rw-r--r--client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts2
-rw-r--r--client/src/app/+video-channels/video-channels.component.html2
-rw-r--r--client/src/app/+video-channels/video-channels.component.ts8
-rw-r--r--client/src/app/+videos/+video-edit/shared/i18n-primeng-calendar.service.ts2
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.ts8
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-edit-utils.ts2
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-edit.component.ts10
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/drag-drop.directive.ts8
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts2
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.html2
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts4
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts2
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-send.ts2
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-upload.component.html2
-rw-r--r--client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts5
-rw-r--r--client/src/app/+videos/+video-edit/video-update.component.ts5
-rw-r--r--client/src/app/+videos/+video-edit/video-update.resolver.ts6
-rw-r--r--client/src/app/+videos/+video-watch/player-styles.component.ts2
-rw-r--r--client/src/app/+videos/+video-watch/shared/comment/video-comment-add.component.ts6
-rw-r--r--client/src/app/+videos/+video-watch/shared/comment/video-comment.component.html2
-rw-r--r--client/src/app/+videos/+video-watch/shared/comment/video-comment.component.ts2
-rw-r--r--client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts8
-rw-r--r--client/src/app/+videos/+video-watch/shared/information/video-alert.component.ts2
-rw-r--r--client/src/app/+videos/+video-watch/shared/metadata/video-description.component.html2
-rw-r--r--client/src/app/+videos/+video-watch/shared/playlist/video-watch-playlist.component.ts10
-rw-r--r--client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.html2
-rw-r--r--client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.ts2
-rw-r--r--client/src/app/+videos/+video-watch/shared/timestamp-route-transformer.directive.ts8
-rw-r--r--client/src/app/+videos/+video-watch/video-watch.component.ts39
-rw-r--r--client/src/app/+videos/video-list/overview/overview.service.ts2
-rw-r--r--client/src/app/+videos/video-list/trending/video-trending-header.component.ts2
-rw-r--r--client/src/app/+videos/video-list/trending/video-trending.component.ts6
-rw-r--r--client/src/app/+videos/video-list/video-local.component.ts2
-rw-r--r--client/src/app/app.component.ts4
-rw-r--r--client/src/app/core/auth/auth.service.ts6
-rw-r--r--client/src/app/core/hotkeys/hotkeys.component.ts6
-rw-r--r--client/src/app/core/menu/menu.service.ts4
-rw-r--r--client/src/app/core/plugins/hooks.service.ts10
-rw-r--r--client/src/app/core/plugins/plugin.service.ts10
-rw-r--r--client/src/app/core/renderer/markdown.service.ts14
-rw-r--r--client/src/app/core/rest/rest-extractor.service.ts26
-rw-r--r--client/src/app/core/routing/custom-reuse-strategy.ts4
-rw-r--r--client/src/app/core/routing/menu-guard.service.ts18
-rw-r--r--client/src/app/core/routing/meta-guard.service.ts2
-rw-r--r--client/src/app/core/routing/preload-selected-modules-list.ts2
-rw-r--r--client/src/app/core/scoped-tokens/scoped-tokens.service.ts7
-rw-r--r--client/src/app/core/server/server.service.ts4
-rw-r--r--client/src/app/core/theme/theme.service.ts4
-rw-r--r--client/src/app/core/users/user.service.ts4
-rw-r--r--client/src/app/header/search-typeahead.component.ts2
-rw-r--r--client/src/app/helpers/locales/oc.ts114
-rw-r--r--client/src/app/helpers/utils.ts10
-rw-r--r--client/src/app/menu/language-chooser.component.ts2
-rw-r--r--client/src/app/menu/menu.component.ts2
-rw-r--r--client/src/app/modal/custom-modal.component.ts8
-rw-r--r--client/src/app/shared/form-validators/abuse-validators.ts24
-rw-r--r--client/src/app/shared/form-validators/custom-config-validators.ts88
-rw-r--r--client/src/app/shared/form-validators/form-validator.model.ts2
-rw-r--r--client/src/app/shared/form-validators/host-validators.ts20
-rw-r--r--client/src/app/shared/form-validators/instance-validators.ts24
-rw-r--r--client/src/app/shared/form-validators/login-validators.ts4
-rw-r--r--client/src/app/shared/form-validators/reset-password-validators.ts2
-rw-r--r--client/src/app/shared/form-validators/user-validators.ts64
-rw-r--r--client/src/app/shared/form-validators/video-block-validators.ts4
-rw-r--r--client/src/app/shared/form-validators/video-captions-validators.ts4
-rw-r--r--client/src/app/shared/form-validators/video-channel-validators.ts22
-rw-r--r--client/src/app/shared/form-validators/video-comment-validators.ts6
-rw-r--r--client/src/app/shared/form-validators/video-ownership-change-validators.ts8
-rw-r--r--client/src/app/shared/form-validators/video-playlist-validators.ts16
-rw-r--r--client/src/app/shared/form-validators/video-validators.ts32
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts10
-rw-r--r--client/src/app/shared/shared-abuse-list/moderation-comment-modal.component.ts2
-rw-r--r--client/src/app/shared/shared-abuse-list/processed-abuse.model.ts2
-rw-r--r--client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts2
-rw-r--r--client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts4
-rw-r--r--client/src/app/shared/shared-actor-image/actor-avatar.component.ts36
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts8
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts4
-rw-r--r--client/src/app/shared/shared-forms/form-reactive.ts6
-rw-r--r--client/src/app/shared/shared-forms/form-validator.service.ts8
-rw-r--r--client/src/app/shared/shared-forms/reactive-file.component.ts2
-rw-r--r--client/src/app/shared/shared-icons/global-icon.component.ts106
-rw-r--r--client/src/app/shared/shared-instance/instance-about-accordion.component.ts2
-rw-r--r--client/src/app/shared/shared-instance/instance-follow.service.ts16
-rw-r--r--client/src/app/shared/shared-instance/instance-statistics.component.ts4
-rw-r--r--client/src/app/shared/shared-instance/instance.service.ts2
-rw-r--r--client/src/app/shared/shared-instance/shared-instance.module.ts1
-rw-r--r--client/src/app/shared/shared-main/account/account.model.ts2
-rw-r--r--client/src/app/shared/shared-main/account/actor.model.ts2
-rw-r--r--client/src/app/shared/shared-main/angular/autofocus.directive.ts2
-rw-r--r--client/src/app/shared/shared-main/angular/link.component.ts2
-rw-r--r--client/src/app/shared/shared-main/angular/peertube-template.directive.ts1
-rw-r--r--client/src/app/shared/shared-main/feeds/syndication.model.ts4
-rw-r--r--client/src/app/shared/shared-main/misc/help.component.ts12
-rw-r--r--client/src/app/shared/shared-main/misc/list-overflow.component.ts4
-rw-r--r--client/src/app/shared/shared-main/misc/simple-search-input.component.ts2
-rw-r--r--client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts2
-rw-r--r--client/src/app/shared/shared-main/users/user-notification.service.ts6
-rw-r--r--client/src/app/shared/shared-main/users/user-quota.component.ts2
-rw-r--r--client/src/app/shared/shared-main/video-channel/video-channel.model.ts5
-rw-r--r--client/src/app/shared/shared-main/video-channel/video-channel.service.ts12
-rw-r--r--client/src/app/shared/shared-main/video/redundancy.service.ts4
-rw-r--r--client/src/app/shared/shared-main/video/video-edit.model.ts12
-rw-r--r--client/src/app/shared/shared-main/video/video.model.ts2
-rw-r--r--client/src/app/shared/shared-main/video/video.service.ts18
-rw-r--r--client/src/app/shared/shared-moderation/abuse.service.ts13
-rw-r--r--client/src/app/shared/shared-moderation/account-blocklist.component.ts7
-rw-r--r--client/src/app/shared/shared-moderation/blocklist.service.ts8
-rw-r--r--client/src/app/shared/shared-moderation/server-blocklist.component.ts10
-rw-r--r--client/src/app/shared/shared-moderation/video-block.component.ts4
-rw-r--r--client/src/app/shared/shared-support-modal/support-modal.component.ts4
-rw-r--r--client/src/app/shared/shared-user-settings/user-video-settings.component.ts2
-rw-r--r--client/src/app/shared/shared-user-subscription/remote-subscribe.component.ts16
-rw-r--r--client/src/app/shared/shared-user-subscription/subscribe-button.component.ts4
-rw-r--r--client/src/app/shared/shared-user-subscription/user-subscription.service.ts20
-rw-r--r--client/src/app/shared/shared-video-comment/video-comment.model.ts8
-rw-r--r--client/src/app/shared/shared-video-comment/video-comment.service.ts14
-rw-r--r--client/src/app/shared/shared-video-miniature/abstract-video-list.ts16
-rw-r--r--client/src/app/shared/shared-video-miniature/video-download.component.ts26
-rw-r--r--client/src/app/shared/shared-video-miniature/video-list-header.component.ts2
-rw-r--r--client/src/app/shared/shared-video-miniature/videos-selection.component.ts2
-rw-r--r--client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts2
-rw-r--r--client/src/app/shared/shared-video-playlist/video-playlist-element.model.ts2
-rw-r--r--client/src/app/shared/shared-video-playlist/video-playlist.model.ts2
-rw-r--r--client/src/app/shared/shared-video-playlist/video-playlist.service.ts10
-rw-r--r--client/src/assets/player/p2p-media-loader/hls-plugin.ts94
-rw-r--r--client/src/assets/player/p2p-media-loader/segment-validator.ts5
-rw-r--r--client/src/assets/player/peertube-player-manager.ts42
-rw-r--r--client/src/assets/player/peertube-plugin.ts2
-rw-r--r--client/src/assets/player/peertube-videojs-typings.ts9
-rw-r--r--client/src/assets/player/stats/stats-card.ts9
-rw-r--r--client/src/assets/player/translations-manager.ts6
-rw-r--r--client/src/assets/player/upnext/end-card.ts14
-rw-r--r--client/src/assets/player/utils.ts2
-rw-r--r--client/src/assets/player/videojs-components/p2p-info-button.ts8
-rw-r--r--client/src/assets/player/videojs-components/resolution-menu-item.ts4
-rw-r--r--client/src/assets/player/videojs-components/settings-dialog.ts4
-rw-r--r--client/src/assets/player/videojs-components/settings-menu-item.ts21
-rw-r--r--client/src/assets/player/videojs-components/settings-panel-child.ts4
-rw-r--r--client/src/assets/player/videojs-components/settings-panel.ts4
-rw-r--r--client/src/assets/player/webtorrent/peertube-chunk-store.ts8
-rw-r--r--client/src/assets/player/webtorrent/video-renderer.ts8
-rw-r--r--client/src/assets/player/webtorrent/webtorrent-plugin.ts24
-rw-r--r--client/src/polyfills.ts2
-rw-r--r--client/src/root-helpers/bytes.ts2
-rw-r--r--client/src/root-helpers/peertube-web-storage.ts4
-rw-r--r--client/src/root-helpers/plugins-manager.ts6
-rw-r--r--client/src/standalone/player/definitions.ts2
-rw-r--r--client/src/standalone/player/events.ts14
-rw-r--r--client/src/standalone/player/player.ts31
-rw-r--r--client/src/standalone/videos/embed-api.ts19
-rw-r--r--client/src/standalone/videos/embed.ts47
-rw-r--r--client/src/standalone/videos/test-embed.ts20
-rw-r--r--client/src/types/register-client-option.model.ts12
-rw-r--r--client/src/typings.d.ts1
-rw-r--r--client/tsconfig.json3
-rw-r--r--client/tslint.json39
-rw-r--r--client/yarn.lock1076
215 files changed, 2051 insertions, 1195 deletions
diff --git a/client/.eslintrc.json b/client/.eslintrc.json
new file mode 100644
index 000000000..81b50378a
--- /dev/null
+++ b/client/.eslintrc.json
@@ -0,0 +1,169 @@
1{
2 "root": true,
3 "ignorePatterns": [
4 "projects/**/*",
5 "node_modules/"
6 ],
7 "overrides": [
8 {
9 "files": [
10 "*.ts"
11 ],
12 "parserOptions": {
13 "project": [
14 "tsconfig.json",
15 "e2e/tsconfig.json"
16 ],
17 "createDefaultProgram": true
18 },
19 "extends": [
20 "../.eslintrc.json",
21 "plugin:@angular-eslint/ng-cli-compat",
22 "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
23 "plugin:@angular-eslint/template/process-inline-templates"
24 ],
25 "rules": {
26 "lines-between-class-members": "off",
27 "@typescript-eslint/lines-between-class-members": [ "off" ],
28 "arrow-body-style": "off",
29 "import/no-webpack-loader-syntax": "off",
30 "no-underscore-dangle": "off",
31 "node/no-callback-literal": "off",
32 "@angular-eslint/component-selector": [
33 "error",
34 {
35 "type": [ "element", "attribute" ],
36 "prefix": "my",
37 "style": "kebab-case"
38 }
39 ],
40 "@angular-eslint/directive-selector": [
41 "error",
42 {
43 "type": [ "element", "attribute" ],
44 "prefix": "my",
45 "style": "camelCase"
46 }
47 ],
48 "@typescript-eslint/no-this-alias": [
49 "error",
50 {
51 "allowDestructuring": true,
52 "allowedNames": ["self", "player"]
53 }
54 ],
55 "@typescript-eslint/prefer-readonly": "off",
56 "@angular-eslint/use-component-view-encapsulation": "error",
57 "prefer-arrow/prefer-arrow-functions": "off",
58 "@typescript-eslint/await-thenable": "error",
59 "@typescript-eslint/consistent-type-definitions": "off",
60 "@typescript-eslint/dot-notation": "off",
61 "@typescript-eslint/explicit-member-accessibility": [
62 "off",
63 {
64 "accessibility": "explicit"
65 }
66 ],
67 "@typescript-eslint/member-ordering": [
68 "off"
69 ],
70 "@typescript-eslint/member-delimiter-style": [
71 "error",
72 {
73 "multiline": {
74 "delimiter": "none",
75 "requireLast": true
76 },
77 "singleline": {
78 "delimiter": "comma",
79 "requireLast": false
80 }
81 }
82 ],
83 "@typescript-eslint/prefer-for-of": "off",
84 "@typescript-eslint/no-empty-function": "error",
85 "@typescript-eslint/no-floating-promises": "off",
86 "@typescript-eslint/no-inferrable-types": "error",
87 "@typescript-eslint/no-shadow": [
88 "off",
89 {
90 "hoist": "all"
91 }
92 ],
93 "@typescript-eslint/no-unnecessary-qualifier": "error",
94 "@typescript-eslint/no-unnecessary-type-assertion": "error",
95 "@typescript-eslint/no-unused-expressions": [
96 "error",
97 {
98 "allowTaggedTemplates": true,
99 "allowShortCircuit": true
100 }
101 ],
102 "@typescript-eslint/quotes": [
103 "error",
104 "single",
105 {
106 "avoidEscape": true,
107 "allowTemplateLiterals": true
108 }
109 ],
110 "@typescript-eslint/semi": [
111 "error",
112 "never"
113 ],
114 "brace-style": [
115 "error",
116 "1tbs"
117 ],
118 "comma-dangle": "error",
119 "curly": [
120 "error",
121 "multi-line"
122 ],
123 "dot-notation": "off",
124 "no-useless-return": "off",
125 "indent": "off",
126 "no-bitwise": "off",
127 "no-console": "off",
128 "no-return-assign": "off",
129 "no-constant-condition": "error",
130 "no-control-regex": "error",
131 "no-duplicate-imports": "error",
132 "no-empty": "error",
133 "no-empty-function": [
134 "error",
135 { "allow": [ "constructors" ] }
136 ],
137 "no-invalid-regexp": "error",
138 "no-multiple-empty-lines": "error",
139 "no-redeclare": "error",
140 "no-regex-spaces": "error",
141 "no-return-await": "error",
142 "no-shadow": "off",
143 "no-unused-expressions": "error",
144 "semi": "error",
145 "space-before-function-paren": [
146 "error",
147 "always"
148 ],
149 "space-in-parens": [
150 "error",
151 "never"
152 ],
153 "object-shorthand": [
154 "error",
155 "properties"
156 ]
157 }
158 },
159 {
160 "files": [
161 "*.html"
162 ],
163 "extends": [
164 "plugin:@angular-eslint/template/recommended"
165 ],
166 "rules": {}
167 }
168 ]
169}
diff --git a/client/angular.json b/client/angular.json
index 60a630c89..556df6bbd 100644
--- a/client/angular.json
+++ b/client/angular.json
@@ -203,7 +203,9 @@
203 ] 203 ]
204 }, 204 },
205 "ar-locale": { 205 "ar-locale": {
206 "localize": ["ar"], 206 "localize": [
207 "ar"
208 ],
207 "budgets": [ 209 "budgets": [
208 { 210 {
209 "type": "anyComponentStyle", 211 "type": "anyComponentStyle",
@@ -295,13 +297,11 @@
295 } 297 }
296 }, 298 },
297 "lint": { 299 "lint": {
298 "builder": "@angular-devkit/build-angular:tslint", 300 "builder": "@angular-eslint/builder:lint",
299 "options": { 301 "options": {
300 "tsConfig": [ 302 "lintFilePatterns": [
301 "tsconfig.json" 303 "src/**/*.ts",
302 ], 304 "src/**/*.html"
303 "exclude": [
304 "**/node_modules/**"
305 ] 305 ]
306 } 306 }
307 }, 307 },
@@ -378,17 +378,6 @@
378 "protractorConfig": "e2e/local-protractor.conf.js" 378 "protractorConfig": "e2e/local-protractor.conf.js"
379 } 379 }
380 } 380 }
381 },
382 "lint": {
383 "builder": "@angular-devkit/build-angular:tslint",
384 "options": {
385 "tsConfig": [
386 "e2e/tsconfig.e2e.json"
387 ],
388 "exclude": [
389 "**/node_modules/**"
390 ]
391 }
392 } 381 }
393 } 382 }
394 } 383 }
diff --git a/client/e2e/local-protractor.conf.js b/client/e2e/local-protractor.conf.js
index 5080f2528..d0d4ae9a3 100644
--- a/client/e2e/local-protractor.conf.js
+++ b/client/e2e/local-protractor.conf.js
@@ -49,7 +49,7 @@ exports.config = {
49 49
50 onPrepare() { 50 onPrepare() {
51 require('ts-node').register({ 51 require('ts-node').register({
52 project: require('path').join(__dirname, './tsconfig.e2e.json') 52 project: require('path').join(__dirname, './tsconfig.json')
53 }) 53 })
54 jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })) 54 jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }))
55 } 55 }
diff --git a/client/e2e/protractor.conf.js b/client/e2e/protractor.conf.js
index e5a23e16a..ff0ae83e7 100644
--- a/client/e2e/protractor.conf.js
+++ b/client/e2e/protractor.conf.js
@@ -83,7 +83,7 @@ exports.config = {
83 83
84 onPrepare() { 84 onPrepare() {
85 require('ts-node').register({ 85 require('ts-node').register({
86 project: require('path').join(__dirname, './tsconfig.e2e.json') 86 project: require('path').join(__dirname, './tsconfig.json')
87 }) 87 })
88 jasmine.getEnv().addReporter(new SpecReporter({ 88 jasmine.getEnv().addReporter(new SpecReporter({
89 spec: { displayStacktrace: 'raw' } 89 spec: { displayStacktrace: 'raw' }
diff --git a/client/e2e/tsconfig.e2e.json b/client/e2e/tsconfig.json
index 77d311e88..77d311e88 100644
--- a/client/e2e/tsconfig.e2e.json
+++ b/client/e2e/tsconfig.json
diff --git a/client/package.json b/client/package.json
index 1a04106f4..bfbb99dba 100644
--- a/client/package.json
+++ b/client/package.json
@@ -14,10 +14,10 @@
14 }, 14 },
15 "scripts": { 15 "scripts": {
16 "lint": "npm run lint-ts && npm run lint-scss", 16 "lint": "npm run lint-ts && npm run lint-scss",
17 "lint-ts": "tslint --project ./tsconfig.json -c ./tslint.json 'src/app/**/*.ts' 'src/standalone/**/*.ts'", 17 "lint-ts": "eslint --ext .ts src/standalone/**/*.ts && npm run ng lint",
18 "lint-scss": "stylelint 'src/**/*.scss'", 18 "lint-scss": "stylelint 'src/**/*.scss'",
19 "webpack": "webpack", 19 "webpack": "webpack",
20 "tslint": "tslint", 20 "eslint": "eslint",
21 "ng": "ng", 21 "ng": "ng",
22 "webpack-bundle-analyzer": "webpack-bundle-analyzer", 22 "webpack-bundle-analyzer": "webpack-bundle-analyzer",
23 "webdriver-manager": "webdriver-manager", 23 "webdriver-manager": "webdriver-manager",
@@ -27,6 +27,11 @@
27 "typings": "*.d.ts", 27 "typings": "*.d.ts",
28 "devDependencies": { 28 "devDependencies": {
29 "@angular-devkit/build-angular": "^12.0.0", 29 "@angular-devkit/build-angular": "^12.0.0",
30 "@angular-eslint/builder": "12.3.1",
31 "@angular-eslint/eslint-plugin": "12.3.1",
32 "@angular-eslint/eslint-plugin-template": "12.3.1",
33 "@angular-eslint/schematics": "12.3.1",
34 "@angular-eslint/template-parser": "12.3.1",
30 "@angular/animations": "^12.0.0", 35 "@angular/animations": "^12.0.0",
31 "@angular/cdk": "^12.0.0", 36 "@angular/cdk": "^12.0.0",
32 "@angular/cli": "^12.0.0", 37 "@angular/cli": "^12.0.0",
@@ -64,17 +69,22 @@
64 "@types/sha.js": "^2.4.0", 69 "@types/sha.js": "^2.4.0",
65 "@types/video.js": "^7.3.8", 70 "@types/video.js": "^7.3.8",
66 "@types/webtorrent": "^0.109.0", 71 "@types/webtorrent": "^0.109.0",
72 "@typescript-eslint/eslint-plugin": "4.28.2",
73 "@typescript-eslint/parser": "4.28.2",
67 "angular2-hotkeys": "^2.1.2", 74 "angular2-hotkeys": "^2.1.2",
68 "angularx-qrcode": "11.0.0", 75 "angularx-qrcode": "11.0.0",
69 "bootstrap": "^4.1.3", 76 "bootstrap": "^4.1.3",
70 "buffer": "^6.0.3", 77 "buffer": "^6.0.3",
71 "cache-chunk-store": "^3.0.0", 78 "cache-chunk-store": "^3.0.0",
72 "chart.js": "^2.9.3", 79 "chart.js": "^2.9.3",
73 "codelyzer": "^6.0.0",
74 "core-js": "^3.1.4", 80 "core-js": "^3.1.4",
75 "css-loader": "^6.2.0", 81 "css-loader": "^6.2.0",
76 "debug": "^4.3.1", 82 "debug": "^4.3.1",
77 "dexie": "^3.0.0", 83 "dexie": "^3.0.0",
84 "eslint": "^7.26.0",
85 "eslint-plugin-import": "latest",
86 "eslint-plugin-jsdoc": "latest",
87 "eslint-plugin-prefer-arrow": "latest",
78 "focus-visible": "^5.0.2", 88 "focus-visible": "^5.0.2",
79 "hls.js": "^1.0.7", 89 "hls.js": "^1.0.7",
80 "html-loader": "^2.1.2", 90 "html-loader": "^2.1.2",
@@ -112,9 +122,6 @@
112 "terser-webpack-plugin": "^5.1.2", 122 "terser-webpack-plugin": "^5.1.2",
113 "ts-loader": "^9.2.2", 123 "ts-loader": "^9.2.2",
114 "tslib": "^2.0.0", 124 "tslib": "^2.0.0",
115 "tslint": "~6.1.0",
116 "tslint-angular": "^3.0.2",
117 "tslint-config-standard": "^9.0.0",
118 "typescript": "~4.3.4", 125 "typescript": "~4.3.4",
119 "video.js": "^7", 126 "video.js": "^7",
120 "videojs-contextmenu-pt": "^5.4.1", 127 "videojs-contextmenu-pt": "^5.4.1",
diff --git a/client/src/app/+about/about-follows/about-follows.component.ts b/client/src/app/+about/about-follows/about-follows.component.ts
index 1dcb6396c..a35272681 100644
--- a/client/src/app/+about/about-follows/about-follows.component.ts
+++ b/client/src/app/+about/about-follows/about-follows.component.ts
@@ -90,7 +90,7 @@ export class AboutFollowsComponent implements OnInit {
90 private loadMoreFollowers (reset = false) { 90 private loadMoreFollowers (reset = false) {
91 const pagination = this.restService.componentPaginationToRestPagination(this.followersPagination) 91 const pagination = this.restService.componentPaginationToRestPagination(this.followersPagination)
92 92
93 this.followService.getFollowers({ pagination: pagination, sort: this.sort, state: 'accepted' }) 93 this.followService.getFollowers({ pagination, sort: this.sort, state: 'accepted' })
94 .subscribe({ 94 .subscribe({
95 next: resultList => { 95 next: resultList => {
96 if (reset) this.followers = [] 96 if (reset) this.followers = []
diff --git a/client/src/app/+about/about-instance/about-instance.component.ts b/client/src/app/+about/about-instance/about-instance.component.ts
index f86df5b67..0826bbc5a 100644
--- a/client/src/app/+about/about-instance/about-instance.component.ts
+++ b/client/src/app/+about/about-instance/about-instance.component.ts
@@ -95,6 +95,6 @@ export class AboutInstanceComponent implements OnInit, AfterViewChecked {
95 onClickCopyLink (anchor: HTMLAnchorElement) { 95 onClickCopyLink (anchor: HTMLAnchorElement) {
96 const link = anchor.href 96 const link = anchor.href
97 copyToClipboard(link) 97 copyToClipboard(link)
98 this.notifier.success(link, $localize `Link copied`) 98 this.notifier.success(link, $localize`Link copied`)
99 } 99 }
100} 100}
diff --git a/client/src/app/+about/about-instance/contact-admin-modal.component.ts b/client/src/app/+about/about-instance/contact-admin-modal.component.ts
index cbc759881..fab9cfc4b 100644
--- a/client/src/app/+about/about-instance/contact-admin-modal.component.ts
+++ b/client/src/app/+about/about-instance/contact-admin-modal.component.ts
@@ -77,10 +77,10 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit {
77 } 77 }
78 78
79 sendForm () { 79 sendForm () {
80 const fromName = this.form.value[ 'fromName' ] 80 const fromName = this.form.value['fromName']
81 const fromEmail = this.form.value[ 'fromEmail' ] 81 const fromEmail = this.form.value['fromEmail']
82 const subject = this.form.value[ 'subject' ] 82 const subject = this.form.value['subject']
83 const body = this.form.value[ 'body' ] 83 const body = this.form.value['body']
84 84
85 this.instanceService.contactAdministrator(fromEmail, fromName, subject, body) 85 this.instanceService.contactAdministrator(fromEmail, fromName, subject, body)
86 .subscribe({ 86 .subscribe({
diff --git a/client/src/app/+about/about-routing.module.ts b/client/src/app/+about/about-routing.module.ts
index 3974231e3..cf5570d31 100644
--- a/client/src/app/+about/about-routing.module.ts
+++ b/client/src/app/+about/about-routing.module.ts
@@ -3,7 +3,6 @@ import { RouterModule, Routes } from '@angular/router'
3import { AboutFollowsComponent } from '@app/+about/about-follows/about-follows.component' 3import { AboutFollowsComponent } from '@app/+about/about-follows/about-follows.component'
4import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component' 4import { AboutInstanceComponent } from '@app/+about/about-instance/about-instance.component'
5import { AboutInstanceResolver } from '@app/+about/about-instance/about-instance.resolver' 5import { AboutInstanceResolver } from '@app/+about/about-instance/about-instance.resolver'
6import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component'
7import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component' 6import { AboutPeertubeComponent } from '@app/+about/about-peertube/about-peertube.component'
8import { AboutComponent } from './about.component' 7import { AboutComponent } from './about.component'
9 8
diff --git a/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts b/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
index e146a5cd2..f6df38857 100644
--- a/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
+++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
@@ -1,10 +1,10 @@
1import { from, Subject, Subscription } from 'rxjs' 1import { from, Subject, Subscription } from 'rxjs'
2import { concatMap, map, switchMap, tap } from 'rxjs/operators' 2import { concatMap, map, switchMap, tap } from 'rxjs/operators'
3import { Component, OnDestroy, OnInit } from '@angular/core' 3import { Component, OnDestroy, OnInit } from '@angular/core'
4import { ComponentPagination, hasMoreItems, MarkdownService, ScreenService, User, UserService } from '@app/core' 4import { ComponentPagination, hasMoreItems, MarkdownService, User, UserService } from '@app/core'
5import { Account, AccountService, Video, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main' 5import { Account, AccountService, Video, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
6import { NSFWPolicyType, VideoSortField } from '@shared/models'
7import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature' 6import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature'
7import { NSFWPolicyType, VideoSortField } from '@shared/models'
8 8
9@Component({ 9@Component({
10 selector: 'my-account-video-channels', 10 selector: 'my-account-video-channels',
@@ -87,7 +87,9 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
87 87
88 this.videoChannelService.listAccountVideoChannels(options) 88 this.videoChannelService.listAccountVideoChannels(options)
89 .pipe( 89 .pipe(
90 tap(res => this.channelPagination.totalItems = res.total), 90 tap(res => {
91 this.channelPagination.totalItems = res.total
92 }),
91 switchMap(res => from(res.data)), 93 switchMap(res => from(res.data)),
92 concatMap(videoChannel => { 94 concatMap(videoChannel => {
93 const options = { 95 const options = {
@@ -113,14 +115,14 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
113 } 115 }
114 116
115 getVideosOf (videoChannel: VideoChannel) { 117 getVideosOf (videoChannel: VideoChannel) {
116 const obj = this.videos[ videoChannel.id ] 118 const obj = this.videos[videoChannel.id]
117 if (!obj) return [] 119 if (!obj) return []
118 120
119 return obj.videos 121 return obj.videos
120 } 122 }
121 123
122 getTotalVideosOf (videoChannel: VideoChannel) { 124 getTotalVideosOf (videoChannel: VideoChannel) {
123 const obj = this.videos[ videoChannel.id ] 125 const obj = this.videos[videoChannel.id]
124 if (!obj) return undefined 126 if (!obj) return undefined
125 127
126 return obj.total 128 return obj.total
diff --git a/client/src/app/+accounts/account-videos/account-videos.component.ts b/client/src/app/+accounts/account-videos/account-videos.component.ts
index 75af45e90..4ab6d2147 100644
--- a/client/src/app/+accounts/account-videos/account-videos.component.ts
+++ b/client/src/app/+accounts/account-videos/account-videos.component.ts
@@ -1,5 +1,5 @@
1import { forkJoin, Subscription } from 'rxjs' 1import { forkJoin, Subscription } from 'rxjs'
2import { first, tap } from 'rxjs/operators' 2import { first } from 'rxjs/operators'
3import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core' 3import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core'
4import { ActivatedRoute, Router } from '@angular/router' 4import { ActivatedRoute, Router } from '@angular/router'
5import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core' 5import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'
diff --git a/client/src/app/+accounts/accounts.component.html b/client/src/app/+accounts/accounts.component.html
index cb3e79a18..0906992fe 100644
--- a/client/src/app/+accounts/accounts.component.html
+++ b/client/src/app/+accounts/accounts.component.html
@@ -71,14 +71,14 @@
71 <a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a> 71 <a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
72 </ng-template> 72 </ng-template>
73 73
74 <list-overflow [hidden]="hideMenu" [items]="links" [itemTemplate]="linkTemplate"></list-overflow> 74 <my-list-overflow [hidden]="hideMenu" [items]="links" [itemTemplate]="linkTemplate"></my-list-overflow>
75 75
76 <simple-search-input 76 <my-simple-search-input
77 [alwaysShow]="!isInSmallView()" (searchChanged)="searchChanged($event)" 77 [alwaysShow]="!isInSmallView()" (searchChanged)="searchChanged($event)"
78 (inputDisplayChanged)="onSearchInputDisplayChanged($event)" name="search-videos" 78 (inputDisplayChanged)="onSearchInputDisplayChanged($event)" name="search-videos"
79 i18n-iconTitle icon-title="Search account videos" 79 i18n-iconTitle icon-title="Search account videos"
80 i18n-placeholder placeholder="Search account videos" 80 i18n-placeholder placeholder="Search account videos"
81 ></simple-search-input> 81 ></my-simple-search-input>
82 </div> 82 </div>
83 83
84 <router-outlet (activate)="onOutletLoaded($event)"></router-outlet> 84 <router-outlet (activate)="onOutletLoaded($event)"></router-outlet>
diff --git a/client/src/app/+accounts/accounts.component.ts b/client/src/app/+accounts/accounts.component.ts
index 25eb13588..733cff8d5 100644
--- a/client/src/app/+accounts/accounts.component.ts
+++ b/client/src/app/+accounts/accounts.component.ts
@@ -61,7 +61,7 @@ export class AccountsComponent implements OnInit, OnDestroy {
61 ngOnInit () { 61 ngOnInit () {
62 this.routeSub = this.route.params 62 this.routeSub = this.route.params
63 .pipe( 63 .pipe(
64 map(params => params[ 'accountId' ]), 64 map(params => params['accountId']),
65 distinctUntilChanged(), 65 distinctUntilChanged(),
66 switchMap(accountId => this.accountService.getAccount(accountId)), 66 switchMap(accountId => this.accountService.getAccount(accountId)),
67 tap(account => this.onAccount(account)), 67 tap(account => this.onAccount(account)),
@@ -72,7 +72,9 @@ export class AccountsComponent implements OnInit, OnDestroy {
72 ])) 72 ]))
73 ) 73 )
74 .subscribe({ 74 .subscribe({
75 next: videoChannels => this.videoChannels = videoChannels.data, 75 next: videoChannels => {
76 this.videoChannels = videoChannels.data
77 },
76 78
77 error: err => this.notifier.error(err.message) 79 error: err => this.notifier.error(err.message)
78 }) 80 })
@@ -176,7 +178,9 @@ export class AccountsComponent implements OnInit, OnDestroy {
176 if (user.hasRight(UserRight.MANAGE_USERS)) { 178 if (user.hasRight(UserRight.MANAGE_USERS)) {
177 this.userService.getUser(account.userId) 179 this.userService.getUser(account.userId)
178 .subscribe({ 180 .subscribe({
179 next: accountUser => this.accountUser = accountUser, 181 next: accountUser => {
182 this.accountUser = accountUser
183 },
180 184
181 error: err => this.notifier.error(err.message) 185 error: err => this.notifier.error(err.message)
182 }) 186 })
@@ -209,6 +213,8 @@ export class AccountsComponent implements OnInit, OnDestroy {
209 itemsPerPage: 0 213 itemsPerPage: 0
210 }, 214 },
211 sort: '-publishedAt' 215 sort: '-publishedAt'
212 }).subscribe(res => this.accountVideosCount = res.total) 216 }).subscribe(res => {
217 this.accountVideosCount = res.total
218 })
213 } 219 }
214} 220}
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.ts
index 671e734ac..7a8258820 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.ts
+++ b/client/src/app/+admin/config/edit-custom-config/edit-basic-configuration.component.ts
@@ -97,7 +97,7 @@ export class EditBasicConfigurationComponent implements OnInit, OnChanges {
97 .pipe(pairwise()) 97 .pipe(pairwise())
98 .subscribe(([ oldValue, newValue ]) => { 98 .subscribe(([ oldValue, newValue ]) => {
99 if (oldValue !== true && newValue === true) { 99 if (oldValue !== true && newValue === true) {
100 // tslint:disable:max-line-length 100 /* eslint-disable max-len */
101 this.signupAlertMessage = $localize`You enabled signup: we automatically enabled the "Block new videos automatically" checkbox of the "Videos" section just below.` 101 this.signupAlertMessage = $localize`You enabled signup: we automatically enabled the "Block new videos automatically" checkbox of the "Videos" section just below.`
102 102
103 this.form.patchValue({ 103 this.form.patchValue({
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
index 538fa6f14..be1a99289 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
@@ -277,7 +277,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
277 277
278 // Reload general configuration 278 // Reload general configuration
279 this.serverService.resetConfig() 279 this.serverService.resetConfig()
280 .subscribe(config => this.serverConfig = config) 280 .subscribe(config => {
281 this.serverConfig = config
282 })
281 283
282 this.updateForm() 284 this.updateForm()
283 285
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-homepage.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-homepage.component.ts
index 1923ede39..dc834da14 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-homepage.component.ts
+++ b/client/src/app/+admin/config/edit-custom-config/edit-homepage.component.ts
@@ -1,4 +1,4 @@
1import { Component, Input, OnInit } from '@angular/core' 1import { Component, Input } from '@angular/core'
2import { FormGroup } from '@angular/forms' 2import { FormGroup } from '@angular/forms'
3import { CustomMarkupService } from '@app/shared/shared-custom-markup' 3import { CustomMarkupService } from '@app/shared/shared-custom-markup'
4 4
diff --git a/client/src/app/+admin/follows/following-list/following-list.component.ts b/client/src/app/+admin/follows/following-list/following-list.component.ts
index cf0225098..383f66ffd 100644
--- a/client/src/app/+admin/follows/following-list/following-list.component.ts
+++ b/client/src/app/+admin/follows/following-list/following-list.component.ts
@@ -2,7 +2,6 @@ import { SortMeta } from 'primeng/api'
2import { Component, OnInit, ViewChild } from '@angular/core' 2import { Component, OnInit, ViewChild } from '@angular/core'
3import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core' 3import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
4import { InstanceFollowService } from '@app/shared/shared-instance' 4import { InstanceFollowService } from '@app/shared/shared-instance'
5import { BatchDomainsModalComponent } from '@app/shared/shared-moderation'
6import { ActorFollow } from '@shared/models' 5import { ActorFollow } from '@shared/models'
7import { FollowModalComponent } from './follow-modal.component' 6import { FollowModalComponent } from './follow-modal.component'
8 7
@@ -22,7 +21,7 @@ export class FollowingListComponent extends RestTable implements OnInit {
22 private notifier: Notifier, 21 private notifier: Notifier,
23 private confirmService: ConfirmService, 22 private confirmService: ConfirmService,
24 private followService: InstanceFollowService 23 private followService: InstanceFollowService
25 ) { 24 ) {
26 super() 25 super()
27 } 26 }
28 27
diff --git a/client/src/app/+admin/follows/shared/redundancy-checkbox.component.ts b/client/src/app/+admin/follows/shared/redundancy-checkbox.component.ts
index 47c402510..95f8473db 100644
--- a/client/src/app/+admin/follows/shared/redundancy-checkbox.component.ts
+++ b/client/src/app/+admin/follows/shared/redundancy-checkbox.component.ts
@@ -14,7 +14,7 @@ export class RedundancyCheckboxComponent {
14 constructor ( 14 constructor (
15 private notifier: Notifier, 15 private notifier: Notifier,
16 private redundancyService: RedundancyService 16 private redundancyService: RedundancyService
17 ) { } 17 ) { }
18 18
19 updateRedundancyState () { 19 updateRedundancyState () {
20 this.redundancyService.updateRedundancy(this.host, this.redundancyAllowed) 20 this.redundancyService.updateRedundancy(this.host, this.redundancyAllowed)
diff --git a/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.ts b/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.ts
index 4c691269a..7ffed83e8 100644
--- a/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.ts
+++ b/client/src/app/+admin/follows/video-redundancies-list/video-redundancies-list.component.ts
@@ -21,7 +21,7 @@ export class VideoRedundanciesListComponent extends RestTable implements OnInit
21 pagination: RestPagination = { count: this.rowsPerPage, start: 0 } 21 pagination: RestPagination = { count: this.rowsPerPage, start: 0 }
22 displayType: VideoRedundanciesTarget = 'my-videos' 22 displayType: VideoRedundanciesTarget = 'my-videos'
23 23
24 redundanciesGraphsData: { stats: VideosRedundancyStats, graphData: object, options: object }[] = [] 24 redundanciesGraphsData: { stats: VideosRedundancyStats, graphData: any, options: any }[] = []
25 25
26 noRedundancies = false 26 noRedundancies = false
27 27
@@ -32,7 +32,7 @@ export class VideoRedundanciesListComponent extends RestTable implements OnInit
32 private confirmService: ConfirmService, 32 private confirmService: ConfirmService,
33 private redundancyService: RedundancyService, 33 private redundancyService: RedundancyService,
34 private serverService: ServerService 34 private serverService: ServerService
35 ) { 35 ) {
36 super() 36 super()
37 37
38 this.bytesPipe = new BytesPipe() 38 this.bytesPipe = new BytesPipe()
diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html
index d89c8f244..3a8df1f07 100644
--- a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html
+++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.html
@@ -21,7 +21,7 @@
21 21
22 <ng-template pTemplate="header"> 22 <ng-template pTemplate="header">
23 <tr> 23 <tr>
24 <th style="width: 40px"></th> 24 <th style="width: 40px;"></th>
25 <th style="width: 150px;"></th> 25 <th style="width: 150px;"></th>
26 <th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th> 26 <th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th>
27 <th style="width: 100px;" i18n>Sensitive</th> 27 <th style="width: 100px;" i18n>Sensitive</th>
@@ -54,7 +54,7 @@
54 </div> 54 </div>
55 <div class="table-video-text"> 55 <div class="table-video-text">
56 <div> 56 <div>
57 <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> 57 <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>
58 {{ videoBlock.video.name }} 58 {{ videoBlock.video.name }}
59 </div> 59 </div>
60 <div class="text-muted">by {{ videoBlock.video.channel?.displayName }} on {{ videoBlock.video.channel?.host }} </div> 60 <div class="text-muted">by {{ videoBlock.video.channel?.displayName }} on {{ videoBlock.video.channel?.host }} </div>
diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts
index adef16975..3edcb1c63 100644
--- a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts
+++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts
@@ -28,11 +28,11 @@ export class VideoBlockListComponent extends RestTable implements OnInit {
28 28
29 inputFilters: AdvancedInputFilter[] = [ 29 inputFilters: AdvancedInputFilter[] = [
30 { 30 {
31 queryParams: { 'search': 'type:auto' }, 31 queryParams: { search: 'type:auto' },
32 label: $localize`Automatic blocks` 32 label: $localize`Automatic blocks`
33 }, 33 },
34 { 34 {
35 queryParams: { 'search': 'type:manual' }, 35 queryParams: { search: 'type:manual' },
36 label: $localize`Manual blocks` 36 label: $localize`Manual blocks`
37 } 37 }
38 ] 38 ]
diff --git a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts b/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts
index 4904bcc25..512ceffd9 100644
--- a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts
+++ b/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.ts
@@ -44,11 +44,11 @@ export class VideoCommentListComponent extends RestTable implements OnInit {
44 44
45 inputFilters: AdvancedInputFilter[] = [ 45 inputFilters: AdvancedInputFilter[] = [
46 { 46 {
47 queryParams: { 'search': 'local:true' }, 47 queryParams: { search: 'local:true' },
48 label: $localize`Local comments` 48 label: $localize`Local comments`
49 }, 49 },
50 { 50 {
51 queryParams: { 'search': 'local:false' }, 51 queryParams: { search: 'local:false' },
52 label: $localize`Remote comments` 52 label: $localize`Remote comments`
53 } 53 }
54 ] 54 ]
@@ -66,7 +66,7 @@ export class VideoCommentListComponent extends RestTable implements OnInit {
66 private videoCommentService: VideoCommentService, 66 private videoCommentService: VideoCommentService,
67 private markdownRenderer: MarkdownService, 67 private markdownRenderer: MarkdownService,
68 private bulkService: BulkService 68 private bulkService: BulkService
69 ) { 69 ) {
70 super() 70 super()
71 71
72 this.videoCommentActions = [ 72 this.videoCommentActions = [
diff --git a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html
index 8d8f12c48..a41c7d700 100644
--- a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html
+++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html
@@ -3,7 +3,7 @@
3</div> 3</div>
4 4
5<div class="search-bar"> 5<div class="search-bar">
6 <input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..." autofocus /> 6 <input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..." myAutofocus />
7</div> 7</div>
8 8
9<div class="alert alert-info" i18n *ngIf="pluginInstalled"> 9<div class="alert alert-info" i18n *ngIf="pluginInstalled">
diff --git a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts
index 10fb52911..402bef1ea 100644
--- a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts
+++ b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts
@@ -103,8 +103,8 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
103 const settingsValues: any = {} 103 const settingsValues: any = {}
104 104
105 for (const setting of this.registeredSettings) { 105 for (const setting of this.registeredSettings) {
106 buildOptions[ setting.name ] = null 106 buildOptions[setting.name] = null
107 settingsValues[ setting.name ] = this.getSetting(setting.name) 107 settingsValues[setting.name] = this.getSetting(setting.name)
108 } 108 }
109 109
110 this.buildForm(buildOptions) 110 this.buildForm(buildOptions)
@@ -117,7 +117,7 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit
117 private getSetting (name: string) { 117 private getSetting (name: string) {
118 const settings = this.plugin.settings 118 const settings = this.plugin.settings
119 119
120 if (settings && settings[name] !== undefined) return settings[name] 120 if (settings?.[name] !== undefined) return settings[name]
121 121
122 const registered = this.registeredSettings.find(r => r.name === name) 122 const registered = this.registeredSettings.find(r => r.name === name)
123 123
diff --git a/client/src/app/+admin/plugins/shared/plugin-api.service.ts b/client/src/app/+admin/plugins/shared/plugin-api.service.ts
index d91fccc09..c4f480cae 100644
--- a/client/src/app/+admin/plugins/shared/plugin-api.service.ts
+++ b/client/src/app/+admin/plugins/shared/plugin-api.service.ts
@@ -1,10 +1,8 @@
1import { Observable } from 'rxjs' 1import { catchError } from 'rxjs/operators'
2import { catchError, map, switchMap } from 'rxjs/operators'
3import { HttpClient, HttpParams } from '@angular/common/http' 2import { HttpClient, HttpParams } from '@angular/common/http'
4import { Injectable } from '@angular/core' 3import { Injectable } from '@angular/core'
5import { ComponentPagination, RestExtractor, RestService } from '@app/core' 4import { ComponentPagination, RestExtractor, RestService } from '@app/core'
6import { PluginService } from '@app/core/plugins/plugin.service' 5import { PluginService } from '@app/core/plugins/plugin.service'
7import { peertubeTranslate } from '@shared/core-utils/i18n'
8import { 6import {
9 InstallOrUpdatePlugin, 7 InstallOrUpdatePlugin,
10 ManagePlugin, 8 ManagePlugin,
diff --git a/client/src/app/+admin/system/jobs/job.service.ts b/client/src/app/+admin/system/jobs/job.service.ts
index 4b4a8914f..6c4a07469 100644
--- a/client/src/app/+admin/system/jobs/job.service.ts
+++ b/client/src/app/+admin/system/jobs/job.service.ts
@@ -20,9 +20,9 @@ export class JobService {
20 ) {} 20 ) {}
21 21
22 getJobs (options: { 22 getJobs (options: {
23 jobState?: JobStateClient, 23 jobState?: JobStateClient
24 jobType: JobTypeClient, 24 jobType: JobTypeClient
25 pagination: RestPagination, 25 pagination: RestPagination
26 sort: SortMeta 26 sort: SortMeta
27 }): Observable<ResultList<Job>> { 27 }): Observable<ResultList<Job>> {
28 const { jobState, jobType, pagination, sort } = options 28 const { jobState, jobType, pagination, sort } = options
@@ -32,7 +32,7 @@ export class JobService {
32 32
33 if (jobType !== 'all') params = params.append('jobType', jobType) 33 if (jobType !== 'all') params = params.append('jobType', jobType)
34 34
35 return this.authHttp.get<ResultList<Job>>(JobService.BASE_JOB_URL + `/${jobState ? jobState : ''}`, { params }) 35 return this.authHttp.get<ResultList<Job>>(JobService.BASE_JOB_URL + `/${jobState || ''}`, { params })
36 .pipe( 36 .pipe(
37 map(res => { 37 map(res => {
38 return this.restExtractor.convertResultListDateToHuman(res, [ 'createdAt', 'processedOn', 'finishedOn' ]) 38 return this.restExtractor.convertResultListDateToHuman(res, [ 'createdAt', 'processedOn', 'finishedOn' ])
diff --git a/client/src/app/+admin/system/logs/logs.service.ts b/client/src/app/+admin/system/logs/logs.service.ts
index 69439a179..0c222cad2 100644
--- a/client/src/app/+admin/system/logs/logs.service.ts
+++ b/client/src/app/+admin/system/logs/logs.service.ts
@@ -18,9 +18,9 @@ export class LogsService {
18 ) {} 18 ) {}
19 19
20 getLogs (options: { 20 getLogs (options: {
21 isAuditLog: boolean, 21 isAuditLog: boolean
22 startDate: string, 22 startDate: string
23 level?: LogLevel, 23 level?: LogLevel
24 endDate?: string 24 endDate?: string
25 }): Observable<any[]> { 25 }): Observable<any[]> {
26 const { isAuditLog, startDate } = options 26 const { isAuditLog, startDate } = options
diff --git a/client/src/app/+admin/users/user-edit/user-create.component.ts b/client/src/app/+admin/users/user-edit/user-create.component.ts
index 8403db91a..b61b22fd0 100644
--- a/client/src/app/+admin/users/user-edit/user-create.component.ts
+++ b/client/src/app/+admin/users/user-edit/user-create.component.ts
@@ -33,7 +33,7 @@ export class UserCreateComponent extends UserEdit implements OnInit {
33 private router: Router, 33 private router: Router,
34 private notifier: Notifier, 34 private notifier: Notifier,
35 private userService: UserService 35 private userService: UserService
36 ) { 36 ) {
37 super() 37 super()
38 38
39 this.buildQuotaOptions() 39 this.buildQuotaOptions()
@@ -78,7 +78,9 @@ export class UserCreateComponent extends UserEdit implements OnInit {
78 this.router.navigate([ '/admin/users/list' ]) 78 this.router.navigate([ '/admin/users/list' ])
79 }, 79 },
80 80
81 error: err => this.error = err.message 81 error: err => {
82 this.error = err.message
83 }
82 }) 84 })
83 } 85 }
84 86
diff --git a/client/src/app/+admin/users/user-edit/user-edit.ts b/client/src/app/+admin/users/user-edit/user-edit.ts
index ae1f79ba0..af5e674a7 100644
--- a/client/src/app/+admin/users/user-edit/user-edit.ts
+++ b/client/src/app/+admin/users/user-edit/user-edit.ts
@@ -7,7 +7,7 @@ import { HTMLServerConfig, UserAdminFlag, UserRole, VideoResolution } from '@sha
7import { SelectOptionsItem } from '../../../../types/select-options-item.model' 7import { SelectOptionsItem } from '../../../../types/select-options-item.model'
8 8
9@Directive() 9@Directive()
10// tslint:disable-next-line: directive-class-suffix 10// eslint-disable-next-line @angular-eslint/directive-class-suffix
11export abstract class UserEdit extends FormReactive implements OnInit { 11export abstract class UserEdit extends FormReactive implements OnInit {
12 videoQuotaOptions: SelectOptionsItem[] = [] 12 videoQuotaOptions: SelectOptionsItem[] = []
13 videoQuotaDailyOptions: SelectOptionsItem[] = [] 13 videoQuotaDailyOptions: SelectOptionsItem[] = []
diff --git a/client/src/app/+admin/users/user-edit/user-password.component.ts b/client/src/app/+admin/users/user-edit/user-password.component.ts
index 7c42b9241..42bf20de1 100644
--- a/client/src/app/+admin/users/user-edit/user-password.component.ts
+++ b/client/src/app/+admin/users/user-edit/user-password.component.ts
@@ -20,7 +20,7 @@ export class UserPasswordComponent extends FormReactive implements OnInit {
20 protected formValidatorService: FormValidatorService, 20 protected formValidatorService: FormValidatorService,
21 private notifier: Notifier, 21 private notifier: Notifier,
22 private userService: UserService 22 private userService: UserService
23 ) { 23 ) {
24 super() 24 super()
25 } 25 }
26 26
@@ -39,7 +39,9 @@ export class UserPasswordComponent extends FormReactive implements OnInit {
39 .subscribe({ 39 .subscribe({
40 next: () => this.notifier.success($localize`Password changed for user ${this.username}.`), 40 next: () => this.notifier.success($localize`Password changed for user ${this.username}.`),
41 41
42 error: err => this.error = err.message 42 error: err => {
43 this.error = err.message
44 }
43 }) 45 })
44 } 46 }
45 47
diff --git a/client/src/app/+admin/users/user-edit/user-update.component.ts b/client/src/app/+admin/users/user-edit/user-update.component.ts
index 2128ba4fd..42599a17e 100644
--- a/client/src/app/+admin/users/user-edit/user-update.component.ts
+++ b/client/src/app/+admin/users/user-edit/user-update.component.ts
@@ -33,7 +33,7 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
33 private router: Router, 33 private router: Router,
34 private notifier: Notifier, 34 private notifier: Notifier,
35 private userService: UserService 35 private userService: UserService
36 ) { 36 ) {
37 super() 37 super()
38 38
39 this.buildQuotaOptions() 39 this.buildQuotaOptions()
@@ -63,7 +63,9 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
63 .subscribe({ 63 .subscribe({
64 next: user => this.onUserFetched(user), 64 next: user => this.onUserFetched(user),
65 65
66 error: err => this.error = err.message 66 error: err => {
67 this.error = err.message
68 }
67 }) 69 })
68 }) 70 })
69 } 71 }
@@ -91,7 +93,9 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
91 this.router.navigate([ '/admin/users/list' ]) 93 this.router.navigate([ '/admin/users/list' ])
92 }, 94 },
93 95
94 error: err => this.error = err.message 96 error: err => {
97 this.error = err.message
98 }
95 }) 99 })
96 } 100 }
97 101
@@ -114,7 +118,9 @@ export class UserUpdateComponent extends UserEdit implements OnInit, OnDestroy {
114 this.notifier.success($localize`An email asking for password reset has been sent to ${this.user.username}.`) 118 this.notifier.success($localize`An email asking for password reset has been sent to ${this.user.username}.`)
115 }, 119 },
116 120
117 error: err => this.error = err.message 121 error: err => {
122 this.error = err.message
123 }
118 }) 124 })
119 } 125 }
120 126
diff --git a/client/src/app/+admin/users/user-list/user-list.component.ts b/client/src/app/+admin/users/user-list/user-list.component.ts
index d4406549a..39caf5ed5 100644
--- a/client/src/app/+admin/users/user-list/user-list.component.ts
+++ b/client/src/app/+admin/users/user-list/user-list.component.ts
@@ -36,7 +36,7 @@ export class UserListComponent extends RestTable implements OnInit {
36 36
37 inputFilters: AdvancedInputFilter[] = [ 37 inputFilters: AdvancedInputFilter[] = [
38 { 38 {
39 queryParams: { 'search': 'banned:true' }, 39 queryParams: { search: 'banned:true' },
40 label: $localize`Banned users` 40 label: $localize`Banned users`
41 } 41 }
42 ] 42 ]
diff --git a/client/src/app/+login/login.component.html b/client/src/app/+login/login.component.html
index 27793ff0c..0be67368e 100644
--- a/client/src/app/+login/login.component.html
+++ b/client/src/app/+login/login.component.html
@@ -21,7 +21,7 @@
21 <label i18n for="username">User</label> 21 <label i18n for="username">User</label>
22 <input 22 <input
23 type="text" id="username" i18n-placeholder placeholder="Username or email address" required tabindex="1" 23 type="text" id="username" i18n-placeholder placeholder="Username or email address" required tabindex="1"
24 formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" autofocus 24 formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }" myAutofocus
25 > 25 >
26 </div> 26 </div>
27 27
diff --git a/client/src/app/+login/login.component.ts b/client/src/app/+login/login.component.ts
index 16876afd6..1fa4bd3b5 100644
--- a/client/src/app/+login/login.component.ts
+++ b/client/src/app/+login/login.component.ts
@@ -46,7 +46,7 @@ export class LoginComponent extends FormReactive implements OnInit, AfterViewIni
46 private redirectService: RedirectService, 46 private redirectService: RedirectService,
47 private notifier: Notifier, 47 private notifier: Notifier,
48 private hooks: HooksService 48 private hooks: HooksService
49 ) { 49 ) {
50 super() 50 super()
51 } 51 }
52 52
diff --git a/client/src/app/+my-account/my-account-applications/my-account-applications.component.ts b/client/src/app/+my-account/my-account-applications/my-account-applications.component.ts
index 6873c7d40..e88cdd228 100644
--- a/client/src/app/+my-account/my-account-applications/my-account-applications.component.ts
+++ b/client/src/app/+my-account/my-account-applications/my-account-applications.component.ts
@@ -36,6 +36,7 @@ export class MyAccountApplicationsComponent implements OnInit {
36 36
37 async renewToken () { 37 async renewToken () {
38 const res = await this.confirmService.confirm( 38 const res = await this.confirmService.confirm(
39 // eslint-disable-next-line max-len
39 $localize`Renewing the token will disallow previously configured clients from retrieving the feed until they use the new token. Proceed?`, 40 $localize`Renewing the token will disallow previously configured clients from retrieving the feed until they use the new token. Proceed?`,
40 $localize`Renew token` 41 $localize`Renew token`
41 ) 42 )
diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts b/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts
index 08bc5b425..9b87daa40 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts
+++ b/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
28 ngOnInit () { 28 ngOnInit () {
29 this.buildForm({ 29 this.buildForm({
30 'new-email': USER_EMAIL_VALIDATOR, 30 'new-email': USER_EMAIL_VALIDATOR,
31 'password': USER_PASSWORD_VALIDATOR 31 password: USER_PASSWORD_VALIDATOR
32 }) 32 })
33 33
34 this.user = this.authService.getUser() 34 this.user = this.authService.getUser()
@@ -38,8 +38,8 @@ export class MyAccountChangeEmailComponent extends FormReactive implements OnIni
38 this.error = null 38 this.error = null
39 this.success = null 39 this.success = null
40 40
41 const password = this.form.value[ 'password' ] 41 const password = this.form.value['password']
42 const email = this.form.value[ 'new-email' ] 42 const email = this.form.value['new-email']
43 43
44 forkJoin([ 44 forkJoin([
45 this.serverService.getConfig(), 45 this.serverService.getConfig(),
diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts
index f91b2f37b..47e54dc23 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts
@@ -1,7 +1,11 @@
1import { filter } from 'rxjs/operators' 1import { filter } from 'rxjs/operators'
2import { Component, OnInit } from '@angular/core' 2import { Component, OnInit } from '@angular/core'
3import { AuthService, Notifier, UserService } from '@app/core' 3import { AuthService, Notifier, UserService } from '@app/core'
4import { USER_CONFIRM_PASSWORD_VALIDATOR, USER_PASSWORD_VALIDATOR, USER_EXISTING_PASSWORD_VALIDATOR } from '@app/shared/form-validators/user-validators' 4import {
5 USER_CONFIRM_PASSWORD_VALIDATOR,
6 USER_EXISTING_PASSWORD_VALIDATOR,
7 USER_PASSWORD_VALIDATOR
8} from '@app/shared/form-validators/user-validators'
5import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' 9import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
6import { User } from '@shared/models' 10import { User } from '@shared/models'
7 11
@@ -19,7 +23,7 @@ export class MyAccountChangePasswordComponent extends FormReactive implements On
19 private notifier: Notifier, 23 private notifier: Notifier,
20 private authService: AuthService, 24 private authService: AuthService,
21 private userService: UserService 25 private userService: UserService
22 ) { 26 ) {
23 super() 27 super()
24 } 28 }
25 29
@@ -35,13 +39,13 @@ export class MyAccountChangePasswordComponent extends FormReactive implements On
35 const confirmPasswordControl = this.form.get('new-confirmed-password') 39 const confirmPasswordControl = this.form.get('new-confirmed-password')
36 40
37 confirmPasswordControl.valueChanges 41 confirmPasswordControl.valueChanges
38 .pipe(filter(v => v !== this.form.value[ 'new-password' ])) 42 .pipe(filter(v => v !== this.form.value['new-password']))
39 .subscribe(() => confirmPasswordControl.setErrors({ matchPassword: true })) 43 .subscribe(() => confirmPasswordControl.setErrors({ matchPassword: true }))
40 } 44 }
41 45
42 changePassword () { 46 changePassword () {
43 const currentPassword = this.form.value[ 'current-password' ] 47 const currentPassword = this.form.value['current-password']
44 const newPassword = this.form.value[ 'new-password' ] 48 const newPassword = this.form.value['new-password']
45 49
46 this.userService.changePassword(currentPassword, newPassword) 50 this.userService.changePassword(currentPassword, newPassword)
47 .subscribe({ 51 .subscribe({
diff --git a/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts b/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts
index 5005cb630..4a46f1ad9 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts
+++ b/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 {
15 private userService: UserService, 15 private userService: UserService,
16 private confirmService: ConfirmService, 16 private confirmService: ConfirmService,
17 private redirectService: RedirectService 17 private redirectService: RedirectService
18 ) { } 18 ) { }
19 19
20 async deleteMe () { 20 async deleteMe () {
21 const res = await this.confirmService.confirmWithInput( 21 const res = await this.confirmService.confirmWithInput(
22 // eslint-disable-next-line max-len
22 $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.`, 23 $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.`,
23 $localize`Type your username to confirm`, 24 $localize`Type your username to confirm`,
24 this.user.username, 25 this.user.username,
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
index fc7635f38..a5bcb6496 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
@@ -19,7 +19,7 @@ export class MyAccountSettingsComponent implements OnInit, AfterViewChecked {
19 private userService: UserService, 19 private userService: UserService,
20 private authService: AuthService, 20 private authService: AuthService,
21 private notifier: Notifier 21 private notifier: Notifier
22 ) {} 22 ) {}
23 23
24 get userInformationLoaded () { 24 get userInformationLoaded () {
25 return this.authService.userInformationLoaded 25 return this.authService.userInformationLoaded
diff --git a/client/src/app/+my-account/my-account.component.ts b/client/src/app/+my-account/my-account.component.ts
index eaf8a72e9..450454ca2 100644
--- a/client/src/app/+my-account/my-account.component.ts
+++ b/client/src/app/+my-account/my-account.component.ts
@@ -13,7 +13,7 @@ export class MyAccountComponent implements OnInit {
13 13
14 constructor ( 14 constructor (
15 private screenService: ScreenService 15 private screenService: ScreenService
16 ) { } 16 ) { }
17 17
18 get isBroadcastMessageDisplayed () { 18 get isBroadcastMessageDisplayed () {
19 return this.screenService.isBroadcastMessageDisplayed 19 return this.screenService.isBroadcastMessageDisplayed
diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts b/client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts
index d983aacd9..fd00720d8 100644
--- a/client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts
+++ b/client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts
@@ -31,7 +31,7 @@ export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements
31 private notifier: Notifier, 31 private notifier: Notifier,
32 private router: Router, 32 private router: Router,
33 private videoChannelService: VideoChannelService 33 private videoChannelService: VideoChannelService
34 ) { 34 ) {
35 super() 35 super()
36 } 36 }
37 37
@@ -64,7 +64,7 @@ export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements
64 this.authService.refreshUserInformation() 64 this.authService.refreshUserInformation()
65 65
66 this.notifier.success($localize`Video channel ${videoChannelCreate.displayName} created.`) 66 this.notifier.success($localize`Video channel ${videoChannelCreate.displayName} created.`)
67 this.router.navigate(['/my-library', 'video-channels']) 67 this.router.navigate([ '/my-library', 'video-channels' ])
68 }, 68 },
69 69
70 error: err => { 70 error: err => {
diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts b/client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts
index e8bfbf9ce..f9521b8b5 100644
--- a/client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts
+++ b/client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts
@@ -66,7 +66,9 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
66 }) 66 })
67 }, 67 },
68 68
69 error: err => this.error = err.message 69 error: err => {
70 this.error = err.message
71 }
70 }) 72 })
71 }) 73 })
72 } 74 }
@@ -96,7 +98,9 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
96 this.router.navigate([ '/my-library', 'video-channels' ]) 98 this.router.navigate([ '/my-library', 'video-channels' ])
97 }, 99 },
98 100
99 error: err => this.error = err.message 101 error: err => {
102 this.error = err.message
103 }
100 }) 104 })
101 } 105 }
102 106
diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts b/client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts
index 8b665fd58..303f783fd 100644
--- a/client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts
+++ b/client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts
@@ -121,16 +121,16 @@ channel with the same name (${videoChannel.name})!`,
121 display: false 121 display: false
122 }, 122 },
123 scales: { 123 scales: {
124 xAxes: [{ 124 xAxes: [ {
125 display: false 125 display: false
126 }], 126 } ],
127 yAxes: [{ 127 yAxes: [ {
128 display: false, 128 display: false,
129 ticks: { 129 ticks: {
130 min: Math.max(0, this.videoChannelsMinimumDailyViews - (3 * this.videoChannelsMaximumDailyViews / 100)), 130 min: Math.max(0, this.videoChannelsMinimumDailyViews - (3 * this.videoChannelsMaximumDailyViews / 100)),
131 max: Math.max(1, this.videoChannelsMaximumDailyViews) 131 max: Math.max(1, this.videoChannelsMaximumDailyViews)
132 } 132 }
133 }] 133 } ]
134 }, 134 },
135 layout: { 135 layout: {
136 padding: { 136 padding: {
diff --git a/client/src/app/+my-library/my-history/my-history.component.ts b/client/src/app/+my-library/my-history/my-history.component.ts
index fe6e86346..a72d22e1c 100644
--- a/client/src/app/+my-library/my-history/my-history.component.ts
+++ b/client/src/app/+my-library/my-history/my-history.component.ts
@@ -1,4 +1,3 @@
1import { Subject } from 'rxjs'
2import { tap } from 'rxjs/operators' 1import { tap } from 'rxjs/operators'
3import { Component, ComponentFactoryResolver, OnInit, ViewChild } from '@angular/core' 2import { Component, ComponentFactoryResolver, OnInit, ViewChild } from '@angular/core'
4import { ActivatedRoute, Router } from '@angular/router' 3import { ActivatedRoute, Router } from '@angular/router'
@@ -109,9 +108,9 @@ export class MyHistoryComponent implements OnInit, DisableForReuseHook {
109 this.userService.updateMyProfile({ videosHistoryEnabled: this.videosHistoryEnabled }) 108 this.userService.updateMyProfile({ videosHistoryEnabled: this.videosHistoryEnabled })
110 .subscribe({ 109 .subscribe({
111 next: () => { 110 next: () => {
112 const message = this.videosHistoryEnabled === true ? 111 const message = this.videosHistoryEnabled === true
113 $localize`Videos history is enabled` : 112 ? $localize`Videos history is enabled`
114 $localize`Videos history is disabled` 113 : $localize`Videos history is disabled`
115 114
116 this.notifier.success(message) 115 this.notifier.success(message)
117 116
diff --git a/client/src/app/+my-library/my-library.component.ts b/client/src/app/+my-library/my-library.component.ts
index 2ee3559a7..16a7f63e3 100644
--- a/client/src/app/+my-library/my-library.component.ts
+++ b/client/src/app/+my-library/my-library.component.ts
@@ -17,7 +17,7 @@ export class MyLibraryComponent implements OnInit {
17 private serverService: ServerService, 17 private serverService: ServerService,
18 private authService: AuthService, 18 private authService: AuthService,
19 private screenService: ScreenService 19 private screenService: ScreenService
20 ) { } 20 ) { }
21 21
22 get isBroadcastMessageDisplayed () { 22 get isBroadcastMessageDisplayed () {
23 return this.screenService.isBroadcastMessageDisplayed 23 return this.screenService.isBroadcastMessageDisplayed
diff --git a/client/src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.ts b/client/src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.ts
index b92377bca..764da2369 100644
--- a/client/src/app/+my-library/my-ownership/my-accept-ownership/my-accept-ownership.component.ts
+++ b/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 {
29 private notifier: Notifier, 29 private notifier: Notifier,
30 private authService: AuthService, 30 private authService: AuthService,
31 private modalService: NgbModal 31 private modalService: NgbModal
32 ) { 32 ) {
33 super() 33 super()
34 } 34 }
35 35
diff --git a/client/src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts b/client/src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts
index 3e3c3c878..8bc78b2db 100644
--- a/client/src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts
+++ b/client/src/app/+my-library/my-video-playlists/my-video-playlist-create.component.ts
@@ -29,7 +29,7 @@ export class MyVideoPlaylistCreateComponent extends MyVideoPlaylistEdit implemen
29 private router: Router, 29 private router: Router,
30 private videoPlaylistService: VideoPlaylistService, 30 private videoPlaylistService: VideoPlaylistService,
31 private serverService: ServerService 31 private serverService: ServerService
32 ) { 32 ) {
33 super() 33 super()
34 } 34 }
35 35
@@ -78,7 +78,9 @@ export class MyVideoPlaylistCreateComponent extends MyVideoPlaylistEdit implemen
78 this.router.navigate([ '/my-library', 'video-playlists' ]) 78 this.router.navigate([ '/my-library', 'video-playlists' ])
79 }, 79 },
80 80
81 error: err => this.error = err.message 81 error: err => {
82 this.error = err.message
83 }
82 }) 84 })
83 } 85 }
84 86
diff --git a/client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts b/client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts
index 6aff5dbd7..d6959a50e 100644
--- a/client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts
+++ b/client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts
@@ -57,7 +57,7 @@ export class MyVideoPlaylistElementsComponent implements OnInit, OnDestroy {
57 ] 57 ]
58 58
59 this.paramsSub = this.route.params.subscribe(routeParams => { 59 this.paramsSub = this.route.params.subscribe(routeParams => {
60 this.videoPlaylistId = routeParams[ 'videoPlaylistId' ] 60 this.videoPlaylistId = routeParams['videoPlaylistId']
61 this.loadElements() 61 this.loadElements()
62 62
63 this.loadPlaylistInfo() 63 this.loadPlaylistInfo()
@@ -145,8 +145,6 @@ export class MyVideoPlaylistElementsComponent implements OnInit, OnDestroy {
145 * we add a delay to prevent unwanted drag&drop. 145 * we add a delay to prevent unwanted drag&drop.
146 * 146 *
147 * @see {@link https://github.com/Chocobozzz/PeerTube/issues/2078} 147 * @see {@link https://github.com/Chocobozzz/PeerTube/issues/2078}
148 *
149 * @returns {null|number} Null for no delay, or a number in milliseconds.
150 */ 148 */
151 getDragStartDelay (): null | number { 149 getDragStartDelay (): null | number {
152 if (this.screenService.isInTouchScreen()) { 150 if (this.screenService.isInTouchScreen()) {
diff --git a/client/src/app/+my-library/my-video-playlists/my-video-playlist-update.component.ts b/client/src/app/+my-library/my-video-playlists/my-video-playlist-update.component.ts
index a3f54279b..06ac3ad50 100644
--- a/client/src/app/+my-library/my-video-playlists/my-video-playlist-update.component.ts
+++ b/client/src/app/+my-library/my-video-playlists/my-video-playlist-update.component.ts
@@ -65,14 +65,16 @@ export class MyVideoPlaylistUpdateComponent extends MyVideoPlaylistEdit implemen
65 }) 65 })
66 ) 66 )
67 .subscribe({ 67 .subscribe({
68 next: ([ videoPlaylistToUpdate, videoPlaylistPrivacies]) => { 68 next: ([ videoPlaylistToUpdate, videoPlaylistPrivacies ]) => {
69 this.videoPlaylistToUpdate = videoPlaylistToUpdate 69 this.videoPlaylistToUpdate = videoPlaylistToUpdate
70 this.videoPlaylistPrivacies = videoPlaylistPrivacies 70 this.videoPlaylistPrivacies = videoPlaylistPrivacies
71 71
72 this.hydrateFormFromPlaylist() 72 this.hydrateFormFromPlaylist()
73 }, 73 },
74 74
75 error: err => this.error = err.message 75 error: err => {
76 this.error = err.message
77 }
76 }) 78 })
77 } 79 }
78 80
@@ -99,7 +101,9 @@ export class MyVideoPlaylistUpdateComponent extends MyVideoPlaylistEdit implemen
99 this.router.navigate([ '/my-library', 'video-playlists' ]) 101 this.router.navigate([ '/my-library', 'video-playlists' ])
100 }, 102 },
101 103
102 error: err => this.error = err.message 104 error: err => {
105 this.error = err.message
106 }
103 }) 107 })
104 } 108 }
105 109
diff --git a/client/src/app/+my-library/my-videos/modals/video-change-ownership.component.ts b/client/src/app/+my-library/my-videos/modals/video-change-ownership.component.ts
index 8c1f94bf3..960c9a4f7 100644
--- a/client/src/app/+my-library/my-videos/modals/video-change-ownership.component.ts
+++ b/client/src/app/+my-library/my-videos/modals/video-change-ownership.component.ts
@@ -25,7 +25,7 @@ export class VideoChangeOwnershipComponent extends FormReactive implements OnIni
25 private notifier: Notifier, 25 private notifier: Notifier,
26 private userService: UserService, 26 private userService: UserService,
27 private modalService: NgbModal 27 private modalService: NgbModal
28 ) { 28 ) {
29 super() 29 super()
30 } 30 }
31 31
@@ -49,7 +49,9 @@ export class VideoChangeOwnershipComponent extends FormReactive implements OnIni
49 const query = event.query 49 const query = event.query
50 this.userService.autocomplete(query) 50 this.userService.autocomplete(query)
51 .subscribe({ 51 .subscribe({
52 next: usernames => this.usernamePropositions = usernames, 52 next: usernames => {
53 this.usernamePropositions = usernames
54 },
53 55
54 error: err => this.notifier.error(err.message) 56 error: err => this.notifier.error(err.message)
55 }) 57 })
diff --git a/client/src/app/+my-library/my-videos/my-videos.component.ts b/client/src/app/+my-library/my-videos/my-videos.component.ts
index 4f9b71cc6..edb9392dd 100644
--- a/client/src/app/+my-library/my-videos/my-videos.component.ts
+++ b/client/src/app/+my-library/my-videos/my-videos.component.ts
@@ -49,7 +49,7 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
49 49
50 inputFilters: AdvancedInputFilter[] = [ 50 inputFilters: AdvancedInputFilter[] = [
51 { 51 {
52 queryParams: { 'search': 'isLive:true' }, 52 queryParams: { search: 'isLive:true' },
53 label: $localize`Only live videos` 53 label: $localize`Only live videos`
54 } 54 }
55 ] 55 ]
@@ -107,7 +107,7 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
107 107
108 async deleteSelectedVideos () { 108 async deleteSelectedVideos () {
109 const toDeleteVideosIds = Object.keys(this.selection) 109 const toDeleteVideosIds = Object.keys(this.selection)
110 .filter(k => this.selection[ k ] === true) 110 .filter(k => this.selection[k] === true)
111 .map(k => parseInt(k, 10)) 111 .map(k => parseInt(k, 10))
112 112
113 const res = await this.confirmService.confirm( 113 const res = await this.confirmService.confirm(
diff --git a/client/src/app/+remote-interaction/remote-interaction.component.ts b/client/src/app/+remote-interaction/remote-interaction.component.ts
index 293f7edad..775cc580c 100644
--- a/client/src/app/+remote-interaction/remote-interaction.component.ts
+++ b/client/src/app/+remote-interaction/remote-interaction.component.ts
@@ -7,7 +7,7 @@ import { SearchService } from '@app/shared/shared-search'
7@Component({ 7@Component({
8 selector: 'my-remote-interaction', 8 selector: 'my-remote-interaction',
9 templateUrl: './remote-interaction.component.html', 9 templateUrl: './remote-interaction.component.html',
10 styleUrls: ['./remote-interaction.component.scss'] 10 styleUrls: [ './remote-interaction.component.scss' ]
11}) 11})
12export class RemoteInteractionComponent implements OnInit { 12export class RemoteInteractionComponent implements OnInit {
13 error = '' 13 error = ''
diff --git a/client/src/app/+reset-password/reset-password.component.ts b/client/src/app/+reset-password/reset-password.component.ts
index a1c04147b..11c5110fd 100644
--- a/client/src/app/+reset-password/reset-password.component.ts
+++ b/client/src/app/+reset-password/reset-password.component.ts
@@ -21,7 +21,7 @@ export class ResetPasswordComponent extends FormReactive implements OnInit {
21 private notifier: Notifier, 21 private notifier: Notifier,
22 private router: Router, 22 private router: Router,
23 private route: ActivatedRoute 23 private route: ActivatedRoute
24 ) { 24 ) {
25 super() 25 super()
26 } 26 }
27 27
diff --git a/client/src/app/+signup/+register/custom-stepper.component.ts b/client/src/app/+signup/+register/custom-stepper.component.ts
index 5a80895f9..3b7ba40e8 100644
--- a/client/src/app/+signup/+register/custom-stepper.component.ts
+++ b/client/src/app/+signup/+register/custom-stepper.component.ts
@@ -1,5 +1,5 @@
1import { Component } from '@angular/core'
2import { CdkStep, CdkStepper } from '@angular/cdk/stepper' 1import { CdkStep, CdkStepper } from '@angular/cdk/stepper'
2import { Component } from '@angular/core'
3 3
4@Component({ 4@Component({
5 selector: 'my-custom-stepper', 5 selector: 'my-custom-stepper',
@@ -14,13 +14,13 @@ export class CustomStepperComponent extends CdkStepper {
14 } 14 }
15 15
16 isCompleted (step: CdkStep) { 16 isCompleted (step: CdkStep) {
17 return step.stepControl && step.stepControl.dirty && step.stepControl.valid 17 return step.stepControl?.dirty && step.stepControl.valid
18 } 18 }
19 19
20 isAccessible (index: number) { 20 isAccessible (index: number) {
21 const stepsCompletedMap = this.steps.map(step => this.isCompleted(step)) 21 const stepsCompletedMap = this.steps.map(step => this.isCompleted(step))
22 return index === 0 22 return index === 0
23 ? true 23 ? true
24 : stepsCompletedMap[ index - 1 ] 24 : stepsCompletedMap[index - 1]
25 } 25 }
26} 26}
diff --git a/client/src/app/+signup/+register/register.component.ts b/client/src/app/+signup/+register/register.component.ts
index 056442107..d8ac39c7c 100644
--- a/client/src/app/+signup/+register/register.component.ts
+++ b/client/src/app/+signup/+register/register.component.ts
@@ -49,8 +49,7 @@ export class RegisterComponent implements OnInit {
49 private authService: AuthService, 49 private authService: AuthService,
50 private userService: UserService, 50 private userService: UserService,
51 private hooks: HooksService 51 private hooks: HooksService
52 ) { 52 ) { }
53 }
54 53
55 get requiresEmailVerification () { 54 get requiresEmailVerification () {
56 return this.serverConfig.signup.requiresEmailVerification 55 return this.serverConfig.signup.requiresEmailVerification
@@ -138,11 +137,15 @@ export class RegisterComponent implements OnInit {
138 this.success = $localize`You are now logged in as ${body.username}!` 137 this.success = $localize`You are now logged in as ${body.username}!`
139 }, 138 },
140 139
141 error: err => this.error = err.message 140 error: err => {
141 this.error = err.message
142 }
142 }) 143 })
143 }, 144 },
144 145
145 error: err => this.error = err.message 146 error: err => {
147 this.error = err.message
148 }
146 }) 149 })
147 } 150 }
148} 151}
diff --git a/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts b/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts
index 457a0abe0..827ec7652 100644
--- a/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts
+++ b/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts
@@ -20,7 +20,7 @@ export class VerifyAccountEmailComponent implements OnInit {
20 private authService: AuthService, 20 private authService: AuthService,
21 private notifier: Notifier, 21 private notifier: Notifier,
22 private route: ActivatedRoute 22 private route: ActivatedRoute
23 ) { 23 ) {
24 } 24 }
25 25
26 ngOnInit () { 26 ngOnInit () {
diff --git a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
index d83fc1324..ef8fd79b9 100644
--- a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
+++ b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
@@ -1,5 +1,5 @@
1import { forkJoin, Subscription } from 'rxjs' 1import { forkJoin, Subscription } from 'rxjs'
2import { first, tap } from 'rxjs/operators' 2import { first } from 'rxjs/operators'
3import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core' 3import { Component, ComponentFactoryResolver, OnDestroy, OnInit } from '@angular/core'
4import { ActivatedRoute, Router } from '@angular/router' 4import { ActivatedRoute, Router } from '@angular/router'
5import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core' 5import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'
diff --git a/client/src/app/+video-channels/video-channels.component.html b/client/src/app/+video-channels/video-channels.component.html
index b4d81fe39..064fbb6f5 100644
--- a/client/src/app/+video-channels/video-channels.component.html
+++ b/client/src/app/+video-channels/video-channels.component.html
@@ -114,7 +114,7 @@
114 <a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a> 114 <a [routerLink]="item.routerLink" routerLinkActive="active" class="title-page">{{ item.label }}</a>
115 </ng-template> 115 </ng-template>
116 116
117 <list-overflow [items]="links" [itemTemplate]="linkTemplate"></list-overflow> 117 <my-list-overflow [items]="links" [itemTemplate]="linkTemplate"></my-list-overflow>
118 </div> 118 </div>
119 119
120 <router-outlet></router-outlet> 120 <router-outlet></router-outlet>
diff --git a/client/src/app/+video-channels/video-channels.component.ts b/client/src/app/+video-channels/video-channels.component.ts
index 6479644f1..272fc41d9 100644
--- a/client/src/app/+video-channels/video-channels.component.ts
+++ b/client/src/app/+video-channels/video-channels.component.ts
@@ -44,7 +44,7 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
44 ngOnInit () { 44 ngOnInit () {
45 this.routeSub = this.route.params 45 this.routeSub = this.route.params
46 .pipe( 46 .pipe(
47 map(params => params[ 'videoChannelName' ]), 47 map(params => params['videoChannelName']),
48 distinctUntilChanged(), 48 distinctUntilChanged(),
49 switchMap(videoChannelName => this.videoChannelService.getVideoChannel(videoChannelName)), 49 switchMap(videoChannelName => this.videoChannelService.getVideoChannel(videoChannelName)),
50 catchError(err => this.restExtractor.redirectTo404IfNotFound(err, 'other', [ 50 catchError(err => this.restExtractor.redirectTo404IfNotFound(err, 'other', [
@@ -64,9 +64,9 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
64 64
65 this.hotkeys = [ 65 this.hotkeys = [
66 new Hotkey('S', (event: KeyboardEvent): boolean => { 66 new Hotkey('S', (event: KeyboardEvent): boolean => {
67 this.subscribeButton.subscribed ? 67 if (this.subscribeButton.subscribed) this.subscribeButton.unsubscribe()
68 this.subscribeButton.unsubscribe() : 68 else this.subscribeButton.subscribe()
69 this.subscribeButton.subscribe() 69
70 return false 70 return false
71 }, undefined, $localize`Subscribe to the account`) 71 }, undefined, $localize`Subscribe to the account`)
72 ] 72 ]
diff --git a/client/src/app/+videos/+video-edit/shared/i18n-primeng-calendar.service.ts b/client/src/app/+videos/+video-edit/shared/i18n-primeng-calendar.service.ts
index 34848b036..4b201ac74 100644
--- a/client/src/app/+videos/+video-edit/shared/i18n-primeng-calendar.service.ts
+++ b/client/src/app/+videos/+video-edit/shared/i18n-primeng-calendar.service.ts
@@ -73,7 +73,7 @@ export class I18nPrimengCalendarService {
73 } 73 }
74 74
75 getTimezone () { 75 getTimezone () {
76 const gmt = new Date().toString().match(/([A-Z]+[\+-][0-9]+)/)[1] 76 const gmt = new Date().toString().match(/([A-Z]+[+-][0-9]+)/)[1]
77 const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone 77 const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
78 78
79 return `${timezone} - ${gmt}` 79 return `${timezone} - ${gmt}`
diff --git a/client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.ts b/client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.ts
index 875911b91..98d66ff00 100644
--- a/client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.ts
+++ b/client/src/app/+videos/+video-edit/shared/video-caption-add-modal.component.ts
@@ -66,18 +66,18 @@ export class VideoCaptionAddModalComponent extends FormReactive implements OnIni
66 isReplacingExistingCaption () { 66 isReplacingExistingCaption () {
67 if (this.closingModal === true) return false 67 if (this.closingModal === true) return false
68 68
69 const languageId = this.form.value[ 'language' ] 69 const languageId = this.form.value['language']
70 70
71 return languageId && this.existingCaptions.indexOf(languageId) !== -1 71 return languageId && this.existingCaptions.includes(languageId)
72 } 72 }
73 73
74 async addCaption () { 74 async addCaption () {
75 const languageId = this.form.value[ 'language' ] 75 const languageId = this.form.value['language']
76 const languageObject = this.videoCaptionLanguages.find(l => l.id === languageId) 76 const languageObject = this.videoCaptionLanguages.find(l => l.id === languageId)
77 77
78 this.captionAdded.emit({ 78 this.captionAdded.emit({
79 language: languageObject, 79 language: languageObject,
80 captionfile: this.form.value[ 'captionfile' ] 80 captionfile: this.form.value['captionfile']
81 }) 81 })
82 82
83 this.hide() 83 this.hide()
diff --git a/client/src/app/+videos/+video-edit/shared/video-edit-utils.ts b/client/src/app/+videos/+video-edit/shared/video-edit-utils.ts
index 3a7dbed36..db1ef8d73 100644
--- a/client/src/app/+videos/+video-edit/shared/video-edit-utils.ts
+++ b/client/src/app/+videos/+video-edit/shared/video-edit-utils.ts
@@ -24,7 +24,7 @@ function hydrateFormFromVideo (formGroup: FormGroup, video: VideoEdit, thumbnail
24 .then(response => response.blob()) 24 .then(response => response.blob())
25 .then(data => { 25 .then(data => {
26 formGroup.patchValue({ 26 formGroup.patchValue({
27 [ obj.name ]: data 27 [obj.name]: data
28 }) 28 })
29 }) 29 })
30 } 30 }
diff --git a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts
index 90a0e8f52..366c93a79 100644
--- a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts
+++ b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts
@@ -233,7 +233,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
233 233
234 async deleteCaption (caption: VideoCaptionEdit) { 234 async deleteCaption (caption: VideoCaptionEdit) {
235 // Caption recovers his former state 235 // Caption recovers his former state
236 if (caption.action && this.initialVideoCaptions.indexOf(caption.language.id) !== -1) { 236 if (caption.action && this.initialVideoCaptions.includes(caption.language.id)) {
237 caption.action = undefined 237 caption.action = undefined
238 return 238 return
239 } 239 }
@@ -297,7 +297,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
297 297
298 private trackPrivacyChange () { 298 private trackPrivacyChange () {
299 // We will update the schedule input and the wait transcoding checkbox validators 299 // We will update the schedule input and the wait transcoding checkbox validators
300 this.form.controls[ 'privacy' ] 300 this.form.controls['privacy']
301 .valueChanges 301 .valueChanges
302 .pipe(map(res => parseInt(res.toString(), 10))) 302 .pipe(map(res => parseInt(res.toString(), 10)))
303 .subscribe( 303 .subscribe(
@@ -336,12 +336,12 @@ export class VideoEditComponent implements OnInit, OnDestroy {
336 336
337 private trackChannelChange () { 337 private trackChannelChange () {
338 // We will update the "support" field depending on the channel 338 // We will update the "support" field depending on the channel
339 this.form.controls[ 'channelId' ] 339 this.form.controls['channelId']
340 .valueChanges 340 .valueChanges
341 .pipe(map(res => parseInt(res.toString(), 10))) 341 .pipe(map(res => parseInt(res.toString(), 10)))
342 .subscribe( 342 .subscribe(
343 newChannelId => { 343 newChannelId => {
344 const oldChannelId = parseInt(this.form.value[ 'channelId' ], 10) 344 const oldChannelId = parseInt(this.form.value['channelId'], 10)
345 345
346 // Not initialized yet 346 // Not initialized yet
347 if (isNaN(newChannelId)) return 347 if (isNaN(newChannelId)) return
@@ -350,7 +350,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
350 350
351 // Wait support field update 351 // Wait support field update
352 setTimeout(() => { 352 setTimeout(() => {
353 const currentSupport = this.form.value[ 'support' ] 353 const currentSupport = this.form.value['support']
354 354
355 // First time we set the channel? 355 // First time we set the channel?
356 if (isNaN(oldChannelId)) { 356 if (isNaN(oldChannelId)) {
diff --git a/client/src/app/+videos/+video-edit/video-add-components/drag-drop.directive.ts b/client/src/app/+videos/+video-edit/video-add-components/drag-drop.directive.ts
index 7b1a38c62..7c35e6b84 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/drag-drop.directive.ts
+++ b/client/src/app/+videos/+video-edit/video-add-components/drag-drop.directive.ts
@@ -1,26 +1,26 @@
1import { Directive, Output, EventEmitter, HostBinding, HostListener } from '@angular/core' 1import { Directive, Output, EventEmitter, HostBinding, HostListener } from '@angular/core'
2 2
3@Directive({ 3@Directive({
4 selector: '[dragDrop]' 4 selector: '[myDragDrop]'
5}) 5})
6export class DragDropDirective { 6export class DragDropDirective {
7 @Output() fileDropped = new EventEmitter<FileList>() 7 @Output() fileDropped = new EventEmitter<FileList>()
8 8
9 @HostBinding('class.dragover') dragover = false 9 @HostBinding('class.dragover') dragover = false
10 10
11 @HostListener('dragover', ['$event']) onDragOver (e: Event) { 11 @HostListener('dragover', [ '$event' ]) onDragOver (e: Event) {
12 e.preventDefault() 12 e.preventDefault()
13 e.stopPropagation() 13 e.stopPropagation()
14 this.dragover = true 14 this.dragover = true
15 } 15 }
16 16
17 @HostListener('dragleave', ['$event']) public onDragLeave (e: Event) { 17 @HostListener('dragleave', [ '$event' ]) public onDragLeave (e: Event) {
18 e.preventDefault() 18 e.preventDefault()
19 e.stopPropagation() 19 e.stopPropagation()
20 this.dragover = false 20 this.dragover = false
21 } 21 }
22 22
23 @HostListener('drop', ['$event']) public ondrop (e: DragEvent) { 23 @HostListener('drop', [ '$event' ]) public ondrop (e: DragEvent) {
24 e.preventDefault() 24 e.preventDefault()
25 e.stopPropagation() 25 e.stopPropagation()
26 this.dragover = false 26 this.dragover = false
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts
index 30c79594d..1b9447e03 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts
+++ b/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
41 private liveVideoService: LiveVideoService, 41 private liveVideoService: LiveVideoService,
42 private router: Router, 42 private router: Router,
43 private hooks: HooksService 43 private hooks: HooksService
44 ) { 44 ) {
45 super() 45 super()
46 } 46 }
47 47
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.html b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.html
index 20a7538db..0f1a94c84 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.html
+++ b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.html
@@ -1,4 +1,4 @@
1<div *ngIf="!hasImportedVideo" class="upload-video-container" dragDrop (fileDropped)="setTorrentFile($event)"> 1<div *ngIf="!hasImportedVideo" class="upload-video-container" myDragDrop (fileDropped)="setTorrentFile($event)">
2 <div class="first-step-block"> 2 <div class="first-step-block">
3 <my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon> 3 <my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
4 4
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts
index fef1f5d65..87e47683f 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts
+++ b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts
@@ -5,7 +5,7 @@ import { scrollToTop } from '@app/helpers'
5import { FormValidatorService } from '@app/shared/shared-forms' 5import { FormValidatorService } from '@app/shared/shared-forms'
6import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' 6import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main'
7import { LoadingBarService } from '@ngx-loading-bar/core' 7import { LoadingBarService } from '@ngx-loading-bar/core'
8import { PeerTubeProblemDocument, ServerErrorCode, VideoPrivacy, VideoUpdate } from '@shared/models' 8import { PeerTubeProblemDocument, ServerErrorCode, VideoUpdate } from '@shared/models'
9import { hydrateFormFromVideo } from '../shared/video-edit-utils' 9import { hydrateFormFromVideo } from '../shared/video-edit-utils'
10import { VideoSend } from './video-send' 10import { VideoSend } from './video-send'
11 11
@@ -43,7 +43,7 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Af
43 private router: Router, 43 private router: Router,
44 private videoImportService: VideoImportService, 44 private videoImportService: VideoImportService,
45 private hooks: HooksService 45 private hooks: HooksService
46 ) { 46 ) {
47 super() 47 super()
48 } 48 }
49 49
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts
index e1893b28f..3487c1adf 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts
+++ b/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
59 } 59 }
60 60
61 isTargetUrlValid () { 61 isTargetUrlValid () {
62 return this.targetUrl && this.targetUrl.match(/https?:\/\//) 62 return this.targetUrl?.match(/https?:\/\//)
63 } 63 }
64 64
65 importVideo () { 65 importVideo () {
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-send.ts b/client/src/app/+videos/+video-edit/video-add-components/video-send.ts
index ce8de049d..efa8c85a3 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/video-send.ts
+++ b/client/src/app/+videos/+video-edit/video-add-components/video-send.ts
@@ -9,7 +9,7 @@ import { LoadingBarService } from '@ngx-loading-bar/core'
9import { HTMLServerConfig, VideoConstant, VideoPrivacy } from '@shared/models' 9import { HTMLServerConfig, VideoConstant, VideoPrivacy } from '@shared/models'
10 10
11@Directive() 11@Directive()
12// tslint:disable-next-line: directive-class-suffix 12// eslint-disable-next-line @angular-eslint/directive-class-suffix
13export abstract class VideoSend extends FormReactive implements OnInit { 13export abstract class VideoSend extends FormReactive implements OnInit {
14 userVideoChannels: SelectChannelItem[] = [] 14 userVideoChannels: SelectChannelItem[] = []
15 videoPrivacies: VideoConstant<VideoPrivacy>[] = [] 15 videoPrivacies: VideoConstant<VideoPrivacy>[] = []
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.html b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.html
index 14cd06fcf..db494a02f 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.html
+++ b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.html
@@ -1,4 +1,4 @@
1<div *ngIf="!isUploadingVideo" class="upload-video-container" dragDrop (fileDropped)="onFileDropped($event)"> 1<div *ngIf="!isUploadingVideo" class="upload-video-container" myDragDrop (fileDropped)="onFileDropped($event)">
2 <div class="first-step-block"> 2 <div class="first-step-block">
3 <my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon> 3 <my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
4 4
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
index b8cb4fa1e..dee2bb57a 100644
--- a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
+++ b/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
128 128
129 onUploadVideoOngoing (state: UploadState) { 129 onUploadVideoOngoing (state: UploadState) {
130 switch (state.status) { 130 switch (state.status) {
131 case 'error': 131 case 'error': {
132 const error = state.response?.error || 'Unknow error' 132 const error = state.response?.error || 'Unknow error'
133 133
134 this.handleUploadError({ 134 this.handleUploadError({
@@ -143,6 +143,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
143 url: state.url 143 url: state.url
144 }) 144 })
145 break 145 break
146 }
146 147
147 case 'cancelled': 148 case 'cancelled':
148 this.isUploadingVideo = false 149 this.isUploadingVideo = false
@@ -323,6 +324,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
323 const videoQuotaUsedBytes = bytePipes.transform(this.userVideoQuotaUsed, 0) 324 const videoQuotaUsedBytes = bytePipes.transform(this.userVideoQuotaUsed, 0)
324 const videoQuotaBytes = bytePipes.transform(videoQuota, 0) 325 const videoQuotaBytes = bytePipes.transform(videoQuota, 0)
325 326
327 // eslint-disable-next-line max-len
326 const msg = $localize`Your video quota is exceeded with this video (video size: ${videoSizeBytes}, used: ${videoQuotaUsedBytes}, quota: ${videoQuotaBytes})` 328 const msg = $localize`Your video quota is exceeded with this video (video size: ${videoSizeBytes}, used: ${videoQuotaUsedBytes}, quota: ${videoQuotaBytes})`
327 this.notifier.error(msg) 329 this.notifier.error(msg)
328 330
@@ -341,6 +343,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
341 const videoSizeBytes = bytePipes.transform(videofile.size, 0) 343 const videoSizeBytes = bytePipes.transform(videofile.size, 0)
342 const quotaUsedDailyBytes = bytePipes.transform(this.userVideoQuotaUsedDaily, 0) 344 const quotaUsedDailyBytes = bytePipes.transform(this.userVideoQuotaUsedDaily, 0)
343 const quotaDailyBytes = bytePipes.transform(videoQuotaDaily, 0) 345 const quotaDailyBytes = bytePipes.transform(videoQuotaDaily, 0)
346 // eslint-disable-next-line max-len
344 const msg = $localize`Your daily video quota is exceeded with this video (video size: ${videoSizeBytes}, used: ${quotaUsedDailyBytes}, quota: ${quotaDailyBytes})` 347 const msg = $localize`Your daily video quota is exceeded with this video (video size: ${videoSizeBytes}, used: ${quotaUsedDailyBytes}, quota: ${quotaDailyBytes})`
345 this.notifier.error(msg) 348 this.notifier.error(msg)
346 349
diff --git a/client/src/app/+videos/+video-edit/video-update.component.ts b/client/src/app/+videos/+video-edit/video-update.component.ts
index 95336dc75..9bef60133 100644
--- a/client/src/app/+videos/+video-edit/video-update.component.ts
+++ b/client/src/app/+videos/+video-edit/video-update.component.ts
@@ -38,7 +38,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
38 private loadingBar: LoadingBarService, 38 private loadingBar: LoadingBarService,
39 private videoCaptionService: VideoCaptionService, 39 private videoCaptionService: VideoCaptionService,
40 private liveVideoService: LiveVideoService 40 private liveVideoService: LiveVideoService
41 ) { 41 ) {
42 super() 42 super()
43 } 43 }
44 44
@@ -119,8 +119,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
119 } 119 }
120 120
121 update () { 121 update () {
122 if (this.checkForm() === false 122 if (this.checkForm() === false || this.isUpdatingVideo === true) {
123 || this.isUpdatingVideo === true) {
124 return 123 return
125 } 124 }
126 125
diff --git a/client/src/app/+videos/+video-edit/video-update.resolver.ts b/client/src/app/+videos/+video-edit/video-update.resolver.ts
index 9172b78a8..91e76b7fe 100644
--- a/client/src/app/+videos/+video-edit/video-update.resolver.ts
+++ b/client/src/app/+videos/+video-edit/video-update.resolver.ts
@@ -18,7 +18,7 @@ export class VideoUpdateResolver implements Resolve<any> {
18 } 18 }
19 19
20 resolve (route: ActivatedRouteSnapshot) { 20 resolve (route: ActivatedRouteSnapshot) {
21 const uuid: string = route.params[ 'uuid' ] 21 const uuid: string = route.params['uuid']
22 22
23 return this.videoService.getVideo({ videoId: uuid }) 23 return this.videoService.getVideo({ videoId: uuid })
24 .pipe( 24 .pipe(
@@ -42,8 +42,8 @@ export class VideoUpdateResolver implements Resolve<any> {
42 ), 42 ),
43 43
44 video.isLive 44 video.isLive
45 ? this.liveVideoService.getVideoLive(video.id) 45 ? this.liveVideoService.getVideoLive(video.id)
46 : of(undefined) 46 : of(undefined)
47 ] 47 ]
48 } 48 }
49} 49}
diff --git a/client/src/app/+videos/+video-watch/player-styles.component.ts b/client/src/app/+videos/+video-watch/player-styles.component.ts
index 9b1672a8c..448a0ee96 100644
--- a/client/src/app/+videos/+video-watch/player-styles.component.ts
+++ b/client/src/app/+videos/+video-watch/player-styles.component.ts
@@ -8,7 +8,7 @@ import { Component, ViewEncapsulation } from '@angular/core'
8 selector: 'my-player-styles', 8 selector: 'my-player-styles',
9 template: '', 9 template: '',
10 styleUrls: [ './player-styles.component.scss' ], 10 styleUrls: [ './player-styles.component.scss' ],
11 // tslint:disable:use-component-view-encapsulation 11 /* eslint-disable @angular-eslint/use-component-view-encapsulation */
12 encapsulation: ViewEncapsulation.None 12 encapsulation: ViewEncapsulation.None
13}) 13})
14export class PlayerStylesComponent { 14export class PlayerStylesComponent {
diff --git a/client/src/app/+videos/+video-watch/shared/comment/video-comment-add.component.ts b/client/src/app/+videos/+video-watch/shared/comment/video-comment-add.component.ts
index ac65f7260..71fb127f6 100644
--- a/client/src/app/+videos/+video-watch/shared/comment/video-comment-add.component.ts
+++ b/client/src/app/+videos/+video-watch/shared/comment/video-comment-add.component.ts
@@ -25,7 +25,7 @@ import { VideoCommentCreate } from '@shared/models'
25@Component({ 25@Component({
26 selector: 'my-video-comment-add', 26 selector: 'my-video-comment-add',
27 templateUrl: './video-comment-add.component.html', 27 templateUrl: './video-comment-add.component.html',
28 styleUrls: ['./video-comment-add.component.scss'] 28 styleUrls: [ './video-comment-add.component.scss' ]
29}) 29})
30export class VideoCommentAddComponent extends FormReactive implements OnChanges, OnInit { 30export class VideoCommentAddComponent extends FormReactive implements OnChanges, OnInit {
31 @Input() user: User 31 @Input() user: User
@@ -64,7 +64,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnChanges,
64 for (const emojiMarkupName in emojiMarkupObjectList) { 64 for (const emojiMarkupName in emojiMarkupObjectList) {
65 if (emojiMarkupName) { 65 if (emojiMarkupName) {
66 const emoji = emojiMarkupObjectList[emojiMarkupName] 66 const emoji = emojiMarkupObjectList[emojiMarkupName]
67 emojiMarkupArrayList.push([emoji, emojiMarkupName]) 67 emojiMarkupArrayList.push([ emoji, emojiMarkupName ])
68 } 68 }
69 } 69 }
70 70
@@ -91,7 +91,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnChanges,
91 // Not initialized yet 91 // Not initialized yet
92 if (!this.form) return 92 if (!this.form) return
93 93
94 if (changes.textValue && changes.textValue.currentValue && changes.textValue.currentValue !== changes.textValue.previousValue) { 94 if (changes.textValue?.currentValue && changes.textValue.currentValue !== changes.textValue.previousValue) {
95 this.patchTextValue(changes.textValue.currentValue, true) 95 this.patchTextValue(changes.textValue.currentValue, true)
96 } 96 }
97 } 97 }
diff --git a/client/src/app/+videos/+video-watch/shared/comment/video-comment.component.html b/client/src/app/+videos/+video-watch/shared/comment/video-comment.component.html
index d8b944b35..d0e9bcd29 100644
--- a/client/src/app/+videos/+video-watch/shared/comment/video-comment.component.html
+++ b/client/src/app/+videos/+video-watch/shared/comment/video-comment.component.html
@@ -29,7 +29,7 @@
29 class="comment-html" 29 class="comment-html"
30 [innerHTML]="sanitizedCommentHTML" 30 [innerHTML]="sanitizedCommentHTML"
31 (timestampClicked)="handleTimestampClicked($event)" 31 (timestampClicked)="handleTimestampClicked($event)"
32 timestampRouteTransformer 32 myTimestampRouteTransformer
33 ></div> 33 ></div>
34 34
35 <div class="comment-actions"> 35 <div class="comment-actions">
diff --git a/client/src/app/+videos/+video-watch/shared/comment/video-comment.component.ts b/client/src/app/+videos/+video-watch/shared/comment/video-comment.component.ts
index f858f4750..5bbcffe82 100644
--- a/client/src/app/+videos/+video-watch/shared/comment/video-comment.component.ts
+++ b/client/src/app/+videos/+video-watch/shared/comment/video-comment.component.ts
@@ -10,7 +10,7 @@ import { User, UserRight } from '@shared/models'
10@Component({ 10@Component({
11 selector: 'my-video-comment', 11 selector: 'my-video-comment',
12 templateUrl: './video-comment.component.html', 12 templateUrl: './video-comment.component.html',
13 styleUrls: ['./video-comment.component.scss'] 13 styleUrls: [ './video-comment.component.scss' ]
14}) 14})
15export class VideoCommentComponent implements OnInit, OnChanges { 15export class VideoCommentComponent implements OnInit, OnChanges {
16 @ViewChild('commentReportModal') commentReportModal: CommentReportComponent 16 @ViewChild('commentReportModal') commentReportModal: CommentReportComponent
diff --git a/client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts b/client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts
index 72866b874..17e0af3bc 100644
--- a/client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts
+++ b/client/src/app/+videos/+video-watch/shared/comment/video-comments.component.ts
@@ -9,7 +9,7 @@ import { VideoComment, VideoCommentService, VideoCommentThreadTree } from '@app/
9@Component({ 9@Component({
10 selector: 'my-video-comments', 10 selector: 'my-video-comments',
11 templateUrl: './video-comments.component.html', 11 templateUrl: './video-comments.component.html',
12 styleUrls: ['./video-comments.component.scss'] 12 styleUrls: [ './video-comments.component.scss' ]
13}) 13})
14export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy { 14export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
15 @ViewChild('commentHighlightBlock') commentHighlightBlock: ElementRef 15 @ViewChild('commentHighlightBlock') commentHighlightBlock: ElementRef
@@ -200,7 +200,11 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
200 } 200 }
201 201
202 async onWantedToRedraft (commentToRedraft: VideoComment) { 202 async onWantedToRedraft (commentToRedraft: VideoComment) {
203 const confirm = await this.onWantedToDelete(commentToRedraft, $localize`Delete and re-draft`, $localize`Do you really want to delete and re-draft this comment?`) 203 const confirm = await this.onWantedToDelete(
204 commentToRedraft,
205 $localize`Delete and re-draft`,
206 $localize`Do you really want to delete and re-draft this comment?`
207 )
204 208
205 if (confirm) { 209 if (confirm) {
206 this.inReplyToCommentId = commentToRedraft.inReplyToCommentId 210 this.inReplyToCommentId = commentToRedraft.inReplyToCommentId
diff --git a/client/src/app/+videos/+video-watch/shared/information/video-alert.component.ts b/client/src/app/+videos/+video-watch/shared/information/video-alert.component.ts
index 0072492ac..257d463b4 100644
--- a/client/src/app/+videos/+video-watch/shared/information/video-alert.component.ts
+++ b/client/src/app/+videos/+video-watch/shared/information/video-alert.component.ts
@@ -23,7 +23,7 @@ export class VideoAlertComponent {
23 } 23 }
24 24
25 hasVideoScheduledPublication () { 25 hasVideoScheduledPublication () {
26 return this.video && this.video.scheduledUpdate !== undefined 26 return this.video?.scheduledUpdate !== undefined
27 } 27 }
28 28
29 isWaitingForLive () { 29 isWaitingForLive () {
diff --git a/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.html b/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.html
index 57f682899..2cfaad8f6 100644
--- a/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.html
+++ b/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.html
@@ -3,7 +3,7 @@
3 class="video-info-description-html" 3 class="video-info-description-html"
4 [innerHTML]="videoHTMLDescription" 4 [innerHTML]="videoHTMLDescription"
5 (timestampClicked)="onTimestampClicked($event)" 5 (timestampClicked)="onTimestampClicked($event)"
6 timestampRouteTransformer 6 myTimestampRouteTransformer
7 ></div> 7 ></div>
8 8
9 <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()"> 9 <div class="video-info-description-more" *ngIf="completeDescriptionShown === false && video.description?.length >= 250" (click)="showMoreDescription()">
diff --git a/client/src/app/+videos/+video-watch/shared/playlist/video-watch-playlist.component.ts b/client/src/app/+videos/+video-watch/shared/playlist/video-watch-playlist.component.ts
index f0f7966b1..78b3af4a7 100644
--- a/client/src/app/+videos/+video-watch/shared/playlist/video-watch-playlist.component.ts
+++ b/client/src/app/+videos/+video-watch/shared/playlist/video-watch-playlist.component.ts
@@ -39,7 +39,7 @@ export class VideoWatchPlaylistComponent {
39 private notifier: Notifier, 39 private notifier: Notifier,
40 private videoPlaylist: VideoPlaylistService, 40 private videoPlaylist: VideoPlaylistService,
41 private localStorageService: LocalStorageService, 41 private localStorageService: LocalStorageService,
42 private sessionStorageService: SessionStorageService, 42 private sessionStorage: SessionStorageService,
43 private router: Router 43 private router: Router
44 ) { 44 ) {
45 // defaults to true 45 // defaults to true
@@ -50,7 +50,7 @@ export class VideoWatchPlaylistComponent {
50 this.setAutoPlayNextVideoPlaylistSwitchText() 50 this.setAutoPlayNextVideoPlaylistSwitchText()
51 51
52 // defaults to false 52 // defaults to false
53 this.loopPlaylist = this.sessionStorageService.getItem(VideoWatchPlaylistComponent.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) === 'true' 53 this.loopPlaylist = this.sessionStorage.getItem(VideoWatchPlaylistComponent.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO_PLAYLIST) === 'true'
54 this.setLoopPlaylistSwitchText() 54 this.setLoopPlaylistSwitchText()
55 } 55 }
56 56
@@ -145,7 +145,7 @@ export class VideoWatchPlaylistComponent {
145 145
146 const start = previous.startTimestamp 146 const start = previous.startTimestamp
147 const stop = previous.stopTimestamp 147 const stop = previous.stopTimestamp
148 this.router.navigate([],{ queryParams: { playlistPosition: previous.position, start, stop } }) 148 this.router.navigate([], { queryParams: { playlistPosition: previous.position, start, stop } })
149 } 149 }
150 150
151 findPlaylistVideo (position: number, type: 'previous' | 'next'): VideoPlaylistElement { 151 findPlaylistVideo (position: number, type: 'previous' | 'next'): VideoPlaylistElement {
@@ -163,7 +163,7 @@ export class VideoWatchPlaylistComponent {
163 } 163 }
164 164
165 const found = this.playlistElements.find(e => e.position === position) 165 const found = this.playlistElements.find(e => e.position === position)
166 if (found && found.video) return found 166 if (found?.video) return found
167 167
168 const newPosition = type === 'previous' 168 const newPosition = type === 'previous'
169 ? position - 1 169 ? position - 1
@@ -178,7 +178,7 @@ export class VideoWatchPlaylistComponent {
178 178
179 const start = next.startTimestamp 179 const start = next.startTimestamp
180 const stop = next.stopTimestamp 180 const stop = next.stopTimestamp
181 this.router.navigate([],{ queryParams: { playlistPosition: next.position, start, stop } }) 181 this.router.navigate([], { queryParams: { playlistPosition: next.position, start, stop } })
182 } 182 }
183 183
184 switchAutoPlayNextVideoPlaylist () { 184 switchAutoPlayNextVideoPlaylist () {
diff --git a/client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.html b/client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.html
index e1040fead..bbfcab2ae 100644
--- a/client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.html
+++ b/client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.html
@@ -20,7 +20,7 @@
20 > 20 >
21 </my-video-miniature> 21 </my-video-miniature>
22 22
23 <hr *ngIf="!playlist && i == 0 && length > 1" /> 23 <hr *ngIf="!playlist && i === 0 && length > 1" />
24 </ng-container> 24 </ng-container>
25 </ng-container> 25 </ng-container>
26</div> 26</div>
diff --git a/client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.ts b/client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.ts
index 7f3703c08..dfc296d15 100644
--- a/client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.ts
+++ b/client/src/app/+videos/+video-watch/shared/recommendations/recommended-videos.component.ts
@@ -51,7 +51,7 @@ export class RecommendedVideosComponent implements OnInit, OnChanges {
51 } else { 51 } else {
52 this.autoPlayNextVideo = this.sessionStorageService.getItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true' 52 this.autoPlayNextVideo = this.sessionStorageService.getItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true'
53 53
54 this.sessionStorageService.watch([UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO]).subscribe( 54 this.sessionStorageService.watch([ UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO ]).subscribe(
55 () => { 55 () => {
56 this.autoPlayNextVideo = this.sessionStorageService.getItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true' 56 this.autoPlayNextVideo = this.sessionStorageService.getItem(UserLocalStorageKeys.SESSION_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true'
57 } 57 }
diff --git a/client/src/app/+videos/+video-watch/shared/timestamp-route-transformer.directive.ts b/client/src/app/+videos/+video-watch/shared/timestamp-route-transformer.directive.ts
index 45e023695..91fe5bf5d 100644
--- a/client/src/app/+videos/+video-watch/shared/timestamp-route-transformer.directive.ts
+++ b/client/src/app/+videos/+video-watch/shared/timestamp-route-transformer.directive.ts
@@ -1,12 +1,12 @@
1import { Directive, EventEmitter, HostListener, Output } from '@angular/core' 1import { Directive, EventEmitter, HostListener, Output } from '@angular/core'
2 2
3@Directive({ 3@Directive({
4 selector: '[timestampRouteTransformer]' 4 selector: '[myTimestampRouteTransformer]'
5}) 5})
6export class TimestampRouteTransformerDirective { 6export class TimestampRouteTransformerDirective {
7 @Output() timestampClicked = new EventEmitter<number>() 7 @Output() timestampClicked = new EventEmitter<number>()
8 8
9 @HostListener('click', ['$event']) 9 @HostListener('click', [ '$event' ])
10 public onClick ($event: Event) { 10 public onClick ($event: Event) {
11 const target = $event.target as HTMLLinkElement 11 const target = $event.target as HTMLLinkElement
12 12
@@ -21,10 +21,10 @@ export class TimestampRouteTransformerDirective {
21 const ngxLinkParams = new URLSearchParams(ngxLink.search) 21 const ngxLinkParams = new URLSearchParams(ngxLink.search)
22 if (ngxLinkParams.has('start') !== true) return 22 if (ngxLinkParams.has('start') !== true) return
23 23
24 const separators = ['h', 'm', 's'] 24 const separators = [ 'h', 'm', 's' ]
25 const start = ngxLinkParams 25 const start = ngxLinkParams
26 .get('start') 26 .get('start')
27 .match(new RegExp('(\\d{1,9}[' + separators.join('') + '])','g')) // match digits before any given separator 27 .match(new RegExp('(\\d{1,9}[' + separators.join('') + '])', 'g')) // match digits before any given separator
28 .map(t => { 28 .map(t => {
29 if (t.includes('h')) return parseInt(t, 10) * 3600 29 if (t.includes('h')) return parseInt(t, 10) * 3600
30 if (t.includes('m')) return parseInt(t, 10) * 60 30 if (t.includes('m')) return parseInt(t, 10) * 60
diff --git a/client/src/app/+videos/+video-watch/video-watch.component.ts b/client/src/app/+videos/+video-watch/video-watch.component.ts
index 85100b653..2007bdecb 100644
--- a/client/src/app/+videos/+video-watch/video-watch.component.ts
+++ b/client/src/app/+videos/+video-watch/video-watch.component.ts
@@ -195,10 +195,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
195 195
196 private loadRouteParams () { 196 private loadRouteParams () {
197 this.paramsSub = this.route.params.subscribe(routeParams => { 197 this.paramsSub = this.route.params.subscribe(routeParams => {
198 const videoId = routeParams[ 'videoId' ] 198 const videoId = routeParams['videoId']
199 if (videoId) return this.loadVideo(videoId) 199 if (videoId) return this.loadVideo(videoId)
200 200
201 const playlistId = routeParams[ 'playlistId' ] 201 const playlistId = routeParams['playlistId']
202 if (playlistId) return this.loadPlaylist(playlistId) 202 if (playlistId) return this.loadPlaylist(playlistId)
203 }) 203 })
204 } 204 }
@@ -206,7 +206,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
206 private loadRouteQuery () { 206 private loadRouteQuery () {
207 this.queryParamsSub = this.route.queryParams.subscribe(queryParams => { 207 this.queryParamsSub = this.route.queryParams.subscribe(queryParams => {
208 // Handle the ?playlistPosition 208 // Handle the ?playlistPosition
209 const positionParam = queryParams[ 'playlistPosition' ] ?? 1 209 const positionParam = queryParams['playlistPosition'] ?? 1
210 210
211 this.playlistPosition = positionParam === 'last' 211 this.playlistPosition = positionParam === 'last'
212 ? -1 // Handle the "last" index 212 ? -1 // Handle the "last" index
@@ -219,7 +219,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
219 219
220 this.videoWatchPlaylist.updatePlaylistIndex(this.playlistPosition) 220 this.videoWatchPlaylist.updatePlaylistIndex(this.playlistPosition)
221 221
222 const start = queryParams[ 'start' ] 222 const start = queryParams['start']
223 if (this.player && start) this.player.currentTime(parseInt(start, 10)) 223 if (this.player && start) this.player.currentTime(parseInt(start, 10))
224 }) 224 })
225 } 225 }
@@ -237,7 +237,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
237 'filter:api.video-watch.video.get.result' 237 'filter:api.video-watch.video.get.result'
238 ) 238 )
239 239
240 forkJoin([ videoObs, this.videoCaptionService.listCaptions(videoId)]) 240 forkJoin([ videoObs, this.videoCaptionService.listCaptions(videoId) ])
241 .subscribe({ 241 .subscribe({
242 next: ([ video, captionsResult ]) => { 242 next: ([ video, captionsResult ]) => {
243 const queryParams = this.route.snapshot.queryParams 243 const queryParams = this.route.snapshot.queryParams
@@ -292,6 +292,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
292 const originUrl = errorBody.originUrl + (window.location.search ?? '') 292 const originUrl = errorBody.originUrl + (window.location.search ?? '')
293 293
294 const res = await this.confirmService.confirm( 294 const res = await this.confirmService.confirm(
295 // eslint-disable-next-line max-len
295 $localize`This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="${originUrl}">${originUrl}</a>?`, 296 $localize`This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="${originUrl}">${originUrl}</a>?`,
296 $localize`Redirection` 297 $localize`Redirection`
297 ) 298 )
@@ -312,7 +313,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
312 if (!errorMessage) return 313 if (!errorMessage) return
313 314
314 // Display a message in the video player instead of a notification 315 // Display a message in the video player instead of a notification
315 if (errorMessage.indexOf('from xs param') !== -1) { 316 if (errorMessage.includes('from xs param')) {
316 this.flushPlayer() 317 this.flushPlayer()
317 this.remoteServerDown = true 318 this.remoteServerDown = true
318 319
@@ -466,7 +467,6 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
466 467
467 if (this.nextVideoUUID) { 468 if (this.nextVideoUUID) {
468 this.router.navigate([ '/w', this.nextVideoUUID ]) 469 this.router.navigate([ '/w', this.nextVideoUUID ])
469 return
470 } 470 }
471 } 471 }
472 472
@@ -483,14 +483,14 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
483 483
484 private isAutoPlayNext () { 484 private isAutoPlayNext () {
485 return ( 485 return (
486 (this.user && this.user.autoPlayNextVideo) || 486 (this.user?.autoPlayNextVideo) ||
487 this.anonymousUser.autoPlayNextVideo 487 this.anonymousUser.autoPlayNextVideo
488 ) 488 )
489 } 489 }
490 490
491 private isPlaylistAutoPlayNext () { 491 private isPlaylistAutoPlayNext () {
492 return ( 492 return (
493 (this.user && this.user.autoPlayNextVideoPlaylist) || 493 (this.user?.autoPlayNextVideoPlaylist) ||
494 this.anonymousUser.autoPlayNextVideoPlaylist 494 this.anonymousUser.autoPlayNextVideoPlaylist
495 ) 495 )
496 } 496 }
@@ -508,9 +508,9 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
508 } 508 }
509 509
510 private buildPlayerManagerOptions (params: { 510 private buildPlayerManagerOptions (params: {
511 video: VideoDetails, 511 video: VideoDetails
512 videoCaptions: VideoCaption[], 512 videoCaptions: VideoCaption[]
513 urlOptions: CustomizationOptions & { playerMode: PlayerMode }, 513 urlOptions: CustomizationOptions & { playerMode: PlayerMode }
514 user?: AuthUser 514 user?: AuthUser
515 }) { 515 }) {
516 const { video, videoCaptions, urlOptions, user } = params 516 const { video, videoCaptions, urlOptions, user } = params
@@ -573,10 +573,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
573 573
574 language: this.localeId, 574 language: this.localeId,
575 575
576 userWatching: user && user.videosHistoryEnabled === true ? { 576 userWatching: user && user.videosHistoryEnabled === true
577 url: this.videoService.getUserWatchingVideoUrl(video.uuid), 577 ? {
578 authorizationHeader: this.authService.getRequestHeaderValue() 578 url: this.videoService.getUserWatchingVideoUrl(video.uuid),
579 } : undefined, 579 authorizationHeader: this.authService.getRequestHeaderValue()
580 }
581 : undefined,
580 582
581 serverUrl: environment.apiUrl, 583 serverUrl: environment.apiUrl,
582 584
@@ -704,9 +706,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
704 if (this.isUserLoggedIn()) { 706 if (this.isUserLoggedIn()) {
705 this.hotkeys = this.hotkeys.concat([ 707 this.hotkeys = this.hotkeys.concat([
706 new Hotkey('shift+s', () => { 708 new Hotkey('shift+s', () => {
707 this.subscribeButton.isSubscribedToAll() 709 if (this.subscribeButton.isSubscribedToAll()) this.subscribeButton.unsubscribe()
708 ? this.subscribeButton.unsubscribe() 710 else this.subscribeButton.subscribe()
709 : this.subscribeButton.subscribe()
710 711
711 return false 712 return false
712 }, undefined, $localize`Subscribe to the account`) 713 }, undefined, $localize`Subscribe to the account`)
diff --git a/client/src/app/+videos/video-list/overview/overview.service.ts b/client/src/app/+videos/video-list/overview/overview.service.ts
index 3aa64ebc8..12d2aa1cb 100644
--- a/client/src/app/+videos/video-list/overview/overview.service.ts
+++ b/client/src/app/+videos/video-list/overview/overview.service.ts
@@ -43,7 +43,7 @@ export class OverviewService {
43 43
44 // Build videos objects 44 // Build videos objects
45 for (const key of Object.keys(serverVideosOverview)) { 45 for (const key of Object.keys(serverVideosOverview)) {
46 for (const object of serverVideosOverview[ key ]) { 46 for (const object of serverVideosOverview[key]) {
47 observables.push( 47 observables.push(
48 of(object.videos) 48 of(object.videos)
49 .pipe( 49 .pipe(
diff --git a/client/src/app/+videos/video-list/trending/video-trending-header.component.ts b/client/src/app/+videos/video-list/trending/video-trending-header.component.ts
index 6c2b32a4f..c94655c74 100644
--- a/client/src/app/+videos/video-list/trending/video-trending-header.component.ts
+++ b/client/src/app/+videos/video-list/trending/video-trending-header.component.ts
@@ -15,7 +15,7 @@ interface VideoTrendingHeaderItem {
15} 15}
16 16
17@Component({ 17@Component({
18 selector: 'video-trending-title-page', 18 selector: 'my-video-trending-title-page',
19 styleUrls: [ './video-trending-header.component.scss' ], 19 styleUrls: [ './video-trending-header.component.scss' ],
20 templateUrl: './video-trending-header.component.html' 20 templateUrl: './video-trending-header.component.html'
21}) 21})
diff --git a/client/src/app/+videos/video-list/trending/video-trending.component.ts b/client/src/app/+videos/video-list/trending/video-trending.component.ts
index ebec672f3..085f29a8b 100644
--- a/client/src/app/+videos/video-list/trending/video-trending.component.ts
+++ b/client/src/app/+videos/video-list/trending/video-trending.component.ts
@@ -63,7 +63,7 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
63 63
64 if (oldSort !== this.sort) this.reloadVideos() 64 if (oldSort !== this.sort) this.reloadVideos()
65 } 65 }
66 ) 66 )
67 } 67 }
68 68
69 ngOnDestroy () { 69 ngOnDestroy () {
@@ -97,12 +97,12 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
97 97
98 getInjector () { 98 getInjector () {
99 return Injector.create({ 99 return Injector.create({
100 providers: [{ 100 providers: [ {
101 provide: 'data', 101 provide: 'data',
102 useValue: { 102 useValue: {
103 model: this.defaultSort 103 model: this.defaultSort
104 } 104 }
105 }] 105 } ]
106 }) 106 })
107 } 107 }
108 108
diff --git a/client/src/app/+videos/video-list/video-local.component.ts b/client/src/app/+videos/video-list/video-local.component.ts
index 4be8cd6b5..b576883d1 100644
--- a/client/src/app/+videos/video-list/video-local.component.ts
+++ b/client/src/app/+videos/video-list/video-local.component.ts
@@ -5,7 +5,7 @@ import { HooksService } from '@app/core/plugins/hooks.service'
5import { immutableAssign } from '@app/helpers' 5import { immutableAssign } from '@app/helpers'
6import { VideoService } from '@app/shared/shared-main' 6import { VideoService } from '@app/shared/shared-main'
7import { AbstractVideoList } from '@app/shared/shared-video-miniature' 7import { AbstractVideoList } from '@app/shared/shared-video-miniature'
8import { UserRight, VideoFilter, VideoSortField } from '@shared/models' 8import { VideoFilter, VideoSortField } from '@shared/models'
9 9
10@Component({ 10@Component({
11 selector: 'my-videos-local', 11 selector: 'my-videos-local',
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts
index c1e296182..ed5cc53d9 100644
--- a/client/src/app/app.component.ts
+++ b/client/src/app/app.component.ts
@@ -243,7 +243,7 @@ export class AppComponent implements OnInit, AfterViewInit {
243 // Inject JS 243 // Inject JS
244 if (this.serverConfig.instance.customizations.javascript) { 244 if (this.serverConfig.instance.customizations.javascript) {
245 try { 245 try {
246 // tslint:disable:no-eval 246 /* eslint-disable no-eval */
247 eval(this.serverConfig.instance.customizations.javascript) 247 eval(this.serverConfig.instance.customizations.javascript)
248 } catch (err) { 248 } catch (err) {
249 console.error('Cannot eval custom JavaScript.', err) 249 console.error('Cannot eval custom JavaScript.', err)
@@ -294,7 +294,7 @@ export class AppComponent implements OnInit, AfterViewInit {
294 294
295 private initHotkeys () { 295 private initHotkeys () {
296 this.hotkeysService.add([ 296 this.hotkeysService.add([
297 new Hotkey(['/', 's'], (event: KeyboardEvent): boolean => { 297 new Hotkey([ '/', 's' ], (event: KeyboardEvent): boolean => {
298 document.getElementById('search-video').focus() 298 document.getElementById('search-video').focus()
299 return false 299 return false
300 }, undefined, $localize`Focus the search bar`), 300 }, undefined, $localize`Focus the search bar`),
diff --git a/client/src/app/core/auth/auth.service.ts b/client/src/app/core/auth/auth.service.ts
index 5da66c981..79239a17a 100644
--- a/client/src/app/core/auth/auth.service.ts
+++ b/client/src/app/core/auth/auth.service.ts
@@ -48,7 +48,7 @@ export class AuthService {
48 private hotkeysService: HotkeysService, 48 private hotkeysService: HotkeysService,
49 private restExtractor: RestExtractor, 49 private restExtractor: RestExtractor,
50 private router: Router 50 private router: Router
51 ) { 51 ) {
52 this.loginChanged = new Subject<AuthStatus>() 52 this.loginChanged = new Subject<AuthStatus>()
53 this.loginChangedSource = this.loginChanged.asObservable() 53 this.loginChangedSource = this.loginChanged.asObservable()
54 54
@@ -206,7 +206,9 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular
206 this.refreshingTokenObservable = this.http.post<UserRefreshToken>(AuthService.BASE_TOKEN_URL, body, { headers }) 206 this.refreshingTokenObservable = this.http.post<UserRefreshToken>(AuthService.BASE_TOKEN_URL, body, { headers })
207 .pipe( 207 .pipe(
208 map(res => this.handleRefreshToken(res)), 208 map(res => this.handleRefreshToken(res)),
209 tap(() => { this.refreshingTokenObservable = null }), 209 tap(() => {
210 this.refreshingTokenObservable = null
211 }),
210 catchError(err => { 212 catchError(err => {
211 this.refreshingTokenObservable = null 213 this.refreshingTokenObservable = null
212 214
diff --git a/client/src/app/core/hotkeys/hotkeys.component.ts b/client/src/app/core/hotkeys/hotkeys.component.ts
index 315e1a25e..60b7516aa 100644
--- a/client/src/app/core/hotkeys/hotkeys.component.ts
+++ b/client/src/app/core/hotkeys/hotkeys.component.ts
@@ -3,8 +3,8 @@ import { Subscription } from 'rxjs'
3import { Component, Input, OnDestroy, OnInit } from '@angular/core' 3import { Component, Input, OnDestroy, OnInit } from '@angular/core'
4 4
5@Component({ 5@Component({
6 selector : 'my-hotkeys-cheatsheet', 6 selector: 'my-hotkeys-cheatsheet',
7 templateUrl : './hotkeys.component.html', 7 templateUrl: './hotkeys.component.html',
8 styleUrls: [ './hotkeys.component.scss' ] 8 styleUrls: [ './hotkeys.component.scss' ]
9}) 9})
10export class CheatSheetComponent implements OnInit, OnDestroy { 10export class CheatSheetComponent implements OnInit, OnDestroy {
@@ -16,7 +16,7 @@ export class CheatSheetComponent implements OnInit, OnDestroy {
16 16
17 constructor ( 17 constructor (
18 private hotkeysService: HotkeysService 18 private hotkeysService: HotkeysService
19 ) {} 19 ) {}
20 20
21 public ngOnInit (): void { 21 public ngOnInit (): void {
22 this.subscription = this.hotkeysService.cheatSheetToggle.subscribe((isOpen) => { 22 this.subscription = this.hotkeysService.cheatSheetToggle.subscribe((isOpen) => {
diff --git a/client/src/app/core/menu/menu.service.ts b/client/src/app/core/menu/menu.service.ts
index 0b8d0191e..f0dc4fcaa 100644
--- a/client/src/app/core/menu/menu.service.ts
+++ b/client/src/app/core/menu/menu.service.ts
@@ -25,7 +25,7 @@ export type MenuSection = {
25export class MenuService { 25export class MenuService {
26 isMenuDisplayed = true 26 isMenuDisplayed = true
27 isMenuChangedByUser = false 27 isMenuChangedByUser = false
28 menuWidth = 240 // should be kept equal to $menu-width 28 menuWidth = 240 // should be kept equal to $menu-width
29 29
30 constructor ( 30 constructor (
31 private screenService: ScreenService 31 private screenService: ScreenService
@@ -55,7 +55,7 @@ export class MenuService {
55 // On touch screens, lock body scroll and display content overlay when memu is opened 55 // On touch screens, lock body scroll and display content overlay when memu is opened
56 if (this.isMenuDisplayed) { 56 if (this.isMenuDisplayed) {
57 document.body.classList.add('menu-open') 57 document.body.classList.add('menu-open')
58 this.screenService.onFingerSwipe('left', () => { this.setMenuDisplay(false) }) 58 this.screenService.onFingerSwipe('left', () => this.setMenuDisplay(false))
59 return 59 return
60 } 60 }
61 61
diff --git a/client/src/app/core/plugins/hooks.service.ts b/client/src/app/core/plugins/hooks.service.ts
index ddde198d2..062083fd1 100644
--- a/client/src/app/core/plugins/hooks.service.ts
+++ b/client/src/app/core/plugins/hooks.service.ts
@@ -27,9 +27,8 @@ export class HooksService {
27 }) 27 })
28 } 28 }
29 29
30 wrapObsFun 30 wrapObsFun <P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName>
31 <P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName> 31 (fun: ObservableFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
32 (fun: ObservableFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
33 return from(this.pluginService.ensurePluginsAreLoaded(scope)) 32 return from(this.pluginService.ensurePluginsAreLoaded(scope))
34 .pipe( 33 .pipe(
35 mergeMap(() => this.wrapObjectWithoutScopeLoad(params, hookParamName)), 34 mergeMap(() => this.wrapObjectWithoutScopeLoad(params, hookParamName)),
@@ -38,9 +37,8 @@ export class HooksService {
38 ) 37 )
39 } 38 }
40 39
41 async wrapFun 40 async wrapFun <P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName>
42 <P, R, H1 extends ClientFilterHookName, H2 extends ClientFilterHookName> 41 (fun: RawFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
43 (fun: RawFunction<P, R>, params: P, scope: PluginClientScope, hookParamName: H1, hookResultName: H2) {
44 await this.pluginService.ensurePluginsAreLoaded(scope) 42 await this.pluginService.ensurePluginsAreLoaded(scope)
45 43
46 const newParams = await this.wrapObjectWithoutScopeLoad(params, hookParamName) 44 const newParams = await this.wrapObjectWithoutScopeLoad(params, hookParamName)
diff --git a/client/src/app/core/plugins/plugin.service.ts b/client/src/app/core/plugins/plugin.service.ts
index 774c03964..89391c2c5 100644
--- a/client/src/app/core/plugins/plugin.service.ts
+++ b/client/src/app/core/plugins/plugin.service.ts
@@ -188,7 +188,7 @@ export class PluginService implements ClientHook {
188 if (!this.authService.isLoggedIn()) return undefined 188 if (!this.authService.isLoggedIn()) return undefined
189 189
190 const value = this.authService.getRequestHeaderValue() 190 const value = this.authService.getRequestHeaderValue()
191 return { 'Authorization': value } 191 return { Authorization: value }
192 }, 192 },
193 193
194 notifier: { 194 notifier: {
@@ -198,10 +198,10 @@ export class PluginService implements ClientHook {
198 }, 198 },
199 199
200 showModal: (input: { 200 showModal: (input: {
201 title: string, 201 title: string
202 content: string, 202 content: string
203 close?: boolean, 203 close?: boolean
204 cancel?: { value: string, action?: () => void }, 204 cancel?: { value: string, action?: () => void }
205 confirm?: { value: string, action?: () => void } 205 confirm?: { value: string, action?: () => void }
206 }) => { 206 }) => {
207 this.zone.run(() => this.customModal.show(input)) 207 this.zone.run(() => this.customModal.show(input))
diff --git a/client/src/app/core/renderer/markdown.service.ts b/client/src/app/core/renderer/markdown.service.ts
index 36258ca98..a81d99534 100644
--- a/client/src/app/core/renderer/markdown.service.ts
+++ b/client/src/app/core/renderer/markdown.service.ts
@@ -103,20 +103,20 @@ export class MarkdownService {
103 const { name, markdown, withEmoji, additionalAllowedTags } = options 103 const { name, markdown, withEmoji, additionalAllowedTags } = options
104 if (!markdown) return '' 104 if (!markdown) return ''
105 105
106 const config = this.parsersConfig[ name ] 106 const config = this.parsersConfig[name]
107 if (!this.markdownParsers[ name ]) { 107 if (!this.markdownParsers[name]) {
108 this.markdownParsers[ name ] = await this.createMarkdownIt(config) 108 this.markdownParsers[name] = await this.createMarkdownIt(config)
109 109
110 if (withEmoji) { 110 if (withEmoji) {
111 if (!this.emojiModule) { 111 if (!this.emojiModule) {
112 this.emojiModule = (await import('markdown-it-emoji/light')).default 112 this.emojiModule = (await import('markdown-it-emoji/light')).default
113 } 113 }
114 114
115 this.markdownParsers[ name ].use(this.emojiModule) 115 this.markdownParsers[name].use(this.emojiModule)
116 } 116 }
117 } 117 }
118 118
119 let html = this.markdownParsers[ name ].render(markdown) 119 let html = this.markdownParsers[name].render(markdown)
120 html = this.avoidTruncatedTags(html) 120 html = this.avoidTruncatedTags(html)
121 121
122 if (config.escape) return this.htmlRenderer.toSafeHtml(html, additionalAllowedTags) 122 if (config.escape) return this.htmlRenderer.toSafeHtml(html, additionalAllowedTags)
@@ -156,7 +156,7 @@ export class MarkdownService {
156 if (relIndex < 0) token.attrPush([ 'rel', 'noopener noreferrer' ]) 156 if (relIndex < 0) token.attrPush([ 'rel', 'noopener noreferrer' ])
157 else token.attrs[relIndex][1] = 'noopener noreferrer' 157 else token.attrs[relIndex][1] = 'noopener noreferrer'
158 158
159 // pass token to default renderer. 159 // pass token to default renderer.*
160 return defaultRender(tokens, index, options, env, self) 160 return defaultRender(tokens, index, options, env, self)
161 } 161 }
162 } 162 }
@@ -164,7 +164,7 @@ export class MarkdownService {
164 private avoidTruncatedTags (html: string) { 164 private avoidTruncatedTags (html: string) {
165 return html.replace(/\*\*?([^*]+)$/, '$1') 165 return html.replace(/\*\*?([^*]+)$/, '$1')
166 .replace(/<a[^>]+>([^<]+)<\/a>\s*...((<\/p>)|(<\/li>)|(<\/strong>))?$/mi, '$1...') 166 .replace(/<a[^>]+>([^<]+)<\/a>\s*...((<\/p>)|(<\/li>)|(<\/strong>))?$/mi, '$1...')
167 .replace(/\[[^\]]+\]\(([^\)]+)$/m, '$1') 167 .replace(/\[[^\]]+\]\(([^)]+)$/m, '$1')
168 .replace(/\s?\[[^\]]+\]?[.]{3}<\/p>$/m, '...</p>') 168 .replace(/\s?\[[^\]]+\]?[.]{3}<\/p>$/m, '...</p>')
169 } 169 }
170} 170}
diff --git a/client/src/app/core/rest/rest-extractor.service.ts b/client/src/app/core/rest/rest-extractor.service.ts
index 29a56ba39..dd4a78de5 100644
--- a/client/src/app/core/rest/rest-extractor.service.ts
+++ b/client/src/app/core/rest/rest-extractor.service.ts
@@ -13,15 +13,16 @@ export class RestExtractor {
13 return true 13 return true
14 } 14 }
15 15
16 applyToResultListData <T> (result: ResultList<T>, fun: Function, additionalArgs?: any[]): ResultList<T> { 16 applyToResultListData <T, A, U> (
17 result: ResultList<T>,
18 fun: (data: T, ...args: A[]) => U,
19 additionalArgs: A[] = []
20 ): ResultList<U> {
17 const data: T[] = result.data 21 const data: T[] = result.data
18 const newData: T[] = []
19
20 data.forEach(d => newData.push(fun.apply(this, [ d ].concat(additionalArgs))))
21 22
22 return { 23 return {
23 total: result.total, 24 total: result.total,
24 data: newData 25 data: data.map(d => fun.apply(this, [ d, ...additionalArgs ]))
25 } 26 }
26 } 27 }
27 28
@@ -29,8 +30,10 @@ export class RestExtractor {
29 return this.applyToResultListData(result, this.convertDateToHuman, [ fieldsToConvert ]) 30 return this.applyToResultListData(result, this.convertDateToHuman, [ fieldsToConvert ])
30 } 31 }
31 32
32 convertDateToHuman (target: { [ id: string ]: string }, fieldsToConvert: string[]) { 33 convertDateToHuman (target: any, fieldsToConvert: string[]) {
33 fieldsToConvert.forEach(field => target[field] = dateToHuman(target[field])) 34 fieldsToConvert.forEach(field => {
35 target[field] = dateToHuman(target[field])
36 })
34 37
35 return target 38 return target
36 } 39 }
@@ -46,7 +49,7 @@ export class RestExtractor {
46 errorMessage = err.error 49 errorMessage = err.error
47 } else if (err.status !== undefined) { 50 } else if (err.status !== undefined) {
48 // A server-side error occurred. 51 // A server-side error occurred.
49 if (err.error && err.error.errors) { 52 if (err.error?.errors) {
50 const errors = err.error.errors 53 const errors = err.error.errors
51 const errorsArray: string[] = [] 54 const errorsArray: string[] = []
52 55
@@ -55,9 +58,10 @@ export class RestExtractor {
55 }) 58 })
56 59
57 errorMessage = errorsArray.join('. ') 60 errorMessage = errorsArray.join('. ')
58 } else if (err.error && err.error.error) { 61 } else if (err.error?.error) {
59 errorMessage = err.error.error 62 errorMessage = err.error.error
60 } else if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413) { 63 } else if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413) {
64 // eslint-disable-next-line max-len
61 errorMessage = $localize`Media is too large for the server. Please contact you administrator if you want to increase the limit size.` 65 errorMessage = $localize`Media is too large for the server. Please contact you administrator if you want to increase the limit size.`
62 } else if (err.status === HttpStatusCode.TOO_MANY_REQUESTS_429) { 66 } else if (err.status === HttpStatusCode.TOO_MANY_REQUESTS_429) {
63 const secondsLeft = err.headers.get('retry-after') 67 const secondsLeft = err.headers.get('retry-after')
@@ -71,7 +75,7 @@ export class RestExtractor {
71 errorMessage = $localize`Server error. Please retry later.` 75 errorMessage = $localize`Server error. Please retry later.`
72 } 76 }
73 77
74 errorMessage = errorMessage ? errorMessage : 'Unknown error.' 78 errorMessage = errorMessage || 'Unknown error.'
75 console.error(`Backend returned code ${err.status}, errorMessage is: ${errorMessage}`) 79 console.error(`Backend returned code ${err.status}, errorMessage is: ${errorMessage}`)
76 } else { 80 } else {
77 console.error(err) 81 console.error(err)
@@ -93,7 +97,7 @@ export class RestExtractor {
93 } 97 }
94 98
95 redirectTo404IfNotFound (obj: { status: number }, type: 'video' | 'other', status = [ HttpStatusCode.NOT_FOUND_404 ]) { 99 redirectTo404IfNotFound (obj: { status: number }, type: 'video' | 'other', status = [ HttpStatusCode.NOT_FOUND_404 ]) {
96 if (obj && obj.status && status.indexOf(obj.status) !== -1) { 100 if (obj?.status && status.includes(obj.status)) {
97 // Do not use redirectService to avoid circular dependencies 101 // Do not use redirectService to avoid circular dependencies
98 this.router.navigate([ '/404' ], { state: { type, obj }, skipLocationChange: true }) 102 this.router.navigate([ '/404' ], { state: { type, obj }, skipLocationChange: true })
99 } 103 }
diff --git a/client/src/app/core/routing/custom-reuse-strategy.ts b/client/src/app/core/routing/custom-reuse-strategy.ts
index c0f9f04e0..c2510f1df 100644
--- a/client/src/app/core/routing/custom-reuse-strategy.ts
+++ b/client/src/app/core/routing/custom-reuse-strategy.ts
@@ -1,5 +1,5 @@
1import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router'
2import { Injectable } from '@angular/core' 1import { Injectable } from '@angular/core'
2import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router'
3 3
4@Injectable() 4@Injectable()
5export class CustomReuseStrategy implements RouteReuseStrategy { 5export class CustomReuseStrategy implements RouteReuseStrategy {
@@ -78,6 +78,6 @@ export class CustomReuseStrategy implements RouteReuseStrategy {
78 } 78 }
79 79
80 private isReuseEnabled (route: ActivatedRouteSnapshot) { 80 private isReuseEnabled (route: ActivatedRouteSnapshot) {
81 return route.data.reuse && route.data.reuse.enabled && route.queryParams[ 'a-state' ] 81 return route.data.reuse?.enabled && route.queryParams['a-state']
82 } 82 }
83} 83}
diff --git a/client/src/app/core/routing/menu-guard.service.ts b/client/src/app/core/routing/menu-guard.service.ts
index c4e64d434..8c5bbfde9 100644
--- a/client/src/app/core/routing/menu-guard.service.ts
+++ b/client/src/app/core/routing/menu-guard.service.ts
@@ -17,33 +17,43 @@ abstract class MenuGuard implements CanActivate, CanDeactivate<any> {
17 if (!this.screen.isInMobileView() && this.screen.isInMediumView()) { 17 if (!this.screen.isInMobileView() && this.screen.isInMediumView()) {
18 this.menu.setMenuDisplay(this.display) 18 this.menu.setMenuDisplay(this.display)
19 } 19 }
20
20 return true 21 return true
21 } 22 }
22} 23}
23 24
24@Injectable() 25@Injectable()
25export class OpenMenuGuard extends MenuGuard { 26export class OpenMenuGuard extends MenuGuard {
26 constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, true) } 27 constructor (menu: MenuService, screen: ScreenService) {
28 super(menu, screen, true)
29 }
27} 30}
28 31
29@Injectable() 32@Injectable()
30export class OpenMenuAlwaysGuard extends MenuGuard { 33export class OpenMenuAlwaysGuard extends MenuGuard {
31 constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, true) } 34 constructor (menu: MenuService, screen: ScreenService) {
35 super(menu, screen, true)
36 }
32 37
33 canActivate (): boolean { 38 canActivate (): boolean {
34 this.menu.setMenuDisplay(this.display) 39 this.menu.setMenuDisplay(this.display)
40
35 return true 41 return true
36 } 42 }
37} 43}
38 44
39@Injectable() 45@Injectable()
40export class CloseMenuGuard extends MenuGuard { 46export class CloseMenuGuard extends MenuGuard {
41 constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, false) } 47 constructor (menu: MenuService, screen: ScreenService) {
48 super(menu, screen, false)
49 }
42} 50}
43 51
44@Injectable() 52@Injectable()
45export class CloseMenuAlwaysGuard extends MenuGuard { 53export class CloseMenuAlwaysGuard extends MenuGuard {
46 constructor (menu: MenuService, screen: ScreenService) { super(menu, screen, false) } 54 constructor (menu: MenuService, screen: ScreenService) {
55 super(menu, screen, false)
56 }
47 57
48 canActivate (): boolean { 58 canActivate (): boolean {
49 this.menu.setMenuDisplay(this.display) 59 this.menu.setMenuDisplay(this.display)
diff --git a/client/src/app/core/routing/meta-guard.service.ts b/client/src/app/core/routing/meta-guard.service.ts
index bedb3450e..851404959 100644
--- a/client/src/app/core/routing/meta-guard.service.ts
+++ b/client/src/app/core/routing/meta-guard.service.ts
@@ -1,5 +1,5 @@
1import { Injectable } from '@angular/core' 1import { Injectable } from '@angular/core'
2import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, RouterStateSnapshot } from '@angular/router' 2import { ActivatedRouteSnapshot, CanActivate, CanActivateChild } from '@angular/router'
3import { MetaService } from './meta.service' 3import { MetaService } from './meta.service'
4 4
5@Injectable() 5@Injectable()
diff --git a/client/src/app/core/routing/preload-selected-modules-list.ts b/client/src/app/core/routing/preload-selected-modules-list.ts
index b494a40bc..b5c3195b0 100644
--- a/client/src/app/core/routing/preload-selected-modules-list.ts
+++ b/client/src/app/core/routing/preload-selected-modules-list.ts
@@ -6,7 +6,7 @@ import { Injectable } from '@angular/core'
6@Injectable() 6@Injectable()
7export class PreloadSelectedModulesList implements PreloadingStrategy { 7export class PreloadSelectedModulesList implements PreloadingStrategy {
8 8
9 preload (route: Route, load: Function): Observable<any> { 9 preload (route: Route, load: () => Observable<any>): Observable<any> {
10 if (!route.data || !route.data.preload) return ofObservable(null) 10 if (!route.data || !route.data.preload) return ofObservable(null)
11 11
12 if (typeof route.data.preload === 'number') { 12 if (typeof route.data.preload === 'number') {
diff --git a/client/src/app/core/scoped-tokens/scoped-tokens.service.ts b/client/src/app/core/scoped-tokens/scoped-tokens.service.ts
index 8e3697c31..038e5031c 100644
--- a/client/src/app/core/scoped-tokens/scoped-tokens.service.ts
+++ b/client/src/app/core/scoped-tokens/scoped-tokens.service.ts
@@ -1,9 +1,8 @@
1import { Injectable } from '@angular/core' 1import { catchError } from 'rxjs/operators'
2import { HttpClient } from '@angular/common/http' 2import { HttpClient } from '@angular/common/http'
3import { environment } from '../../../environments/environment' 3import { Injectable } from '@angular/core'
4import { AuthService } from '../auth'
5import { ScopedToken } from '@shared/models/users/user-scoped-token' 4import { ScopedToken } from '@shared/models/users/user-scoped-token'
6import { catchError } from 'rxjs/operators' 5import { environment } from '../../../environments/environment'
7import { RestExtractor } from '../rest' 6import { RestExtractor } from '../rest'
8 7
9@Injectable() 8@Injectable()
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts
index 8f041a147..d01942139 100644
--- a/client/src/app/core/server/server.service.ts
+++ b/client/src/app/core/server/server.service.ts
@@ -4,7 +4,7 @@ import { HttpClient } from '@angular/common/http'
4import { Inject, Injectable, LOCALE_ID } from '@angular/core' 4import { Inject, Injectable, LOCALE_ID } from '@angular/core'
5import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers' 5import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers'
6import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n' 6import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n'
7import { HTMLServerConfig, SearchTargetType, ServerConfig, ServerStats, VideoConstant } from '@shared/models' 7import { HTMLServerConfig, ServerConfig, ServerStats, VideoConstant } from '@shared/models'
8import { environment } from '../../../environments/environment' 8import { environment } from '../../../environments/environment'
9 9
10@Injectable() 10@Injectable()
@@ -171,7 +171,7 @@ export class ServerService {
171 map(({ data, translations }) => { 171 map(({ data, translations }) => {
172 const hashToPopulate: VideoConstant<T>[] = Object.keys(data) 172 const hashToPopulate: VideoConstant<T>[] = Object.keys(data)
173 .map(dataKey => { 173 .map(dataKey => {
174 const label = data[ dataKey ] 174 const label = data[dataKey]
175 175
176 const id = attributeName === 'languages' 176 const id = attributeName === 'languages'
177 ? dataKey as T 177 ? dataKey as T
diff --git a/client/src/app/core/theme/theme.service.ts b/client/src/app/core/theme/theme.service.ts
index c35548798..c9e6fa700 100644
--- a/client/src/app/core/theme/theme.service.ts
+++ b/client/src/app/core/theme/theme.service.ts
@@ -95,8 +95,8 @@ export class ThemeService {
95 private loadTheme (name: string) { 95 private loadTheme (name: string) {
96 const links = document.getElementsByTagName('link') 96 const links = document.getElementsByTagName('link')
97 for (let i = 0; i < links.length; i++) { 97 for (let i = 0; i < links.length; i++) {
98 const link = links[ i ] 98 const link = links[i]
99 if (link.getAttribute('rel').indexOf('style') !== -1 && link.getAttribute('title')) { 99 if (link.getAttribute('rel').includes('style') && link.getAttribute('title')) {
100 link.disabled = link.getAttribute('title') !== name 100 link.disabled = link.getAttribute('title') !== name
101 } 101 }
102 } 102 }
diff --git a/client/src/app/core/users/user.service.ts b/client/src/app/core/users/user.service.ts
index 47db985e1..a8a774eca 100644
--- a/client/src/app/core/users/user.service.ts
+++ b/client/src/app/core/users/user.service.ts
@@ -35,7 +35,7 @@ export class UserService {
35 private restService: RestService, 35 private restService: RestService,
36 private localStorageService: LocalStorageService, 36 private localStorageService: LocalStorageService,
37 private sessionStorageService: SessionStorageService 37 private sessionStorageService: SessionStorageService
38 ) { } 38 ) { }
39 39
40 changePassword (currentPassword: string, newPassword: string) { 40 changePassword (currentPassword: string, newPassword: string) {
41 const url = UserService.BASE_USERS_URL + 'me' 41 const url = UserService.BASE_USERS_URL + 'me'
@@ -266,7 +266,7 @@ export class UserService {
266 266
267 getUserWithCache (userId: number) { 267 getUserWithCache (userId: number) {
268 if (!this.userCache[userId]) { 268 if (!this.userCache[userId]) {
269 this.userCache[ userId ] = this.getUser(userId).pipe(shareReplay()) 269 this.userCache[userId] = this.getUser(userId).pipe(shareReplay())
270 } 270 }
271 271
272 return this.userCache[userId] 272 return this.userCache[userId]
diff --git a/client/src/app/header/search-typeahead.component.ts b/client/src/app/header/search-typeahead.component.ts
index b5d76c70e..e10baea2b 100644
--- a/client/src/app/header/search-typeahead.component.ts
+++ b/client/src/app/header/search-typeahead.component.ts
@@ -199,7 +199,7 @@ export class SearchTypeaheadComponent implements OnInit, AfterViewChecked, OnDes
199 } 199 }
200 200
201 private loadUserLanguagesIfNeeded (queryParams: any) { 201 private loadUserLanguagesIfNeeded (queryParams: any) {
202 if (queryParams && queryParams.languageOneOf) return of(queryParams) 202 if (queryParams?.languageOneOf) return of(queryParams)
203 203
204 return this.authService.userInformationLoaded 204 return this.authService.userInformationLoaded
205 .pipe( 205 .pipe(
diff --git a/client/src/app/helpers/locales/oc.ts b/client/src/app/helpers/locales/oc.ts
index d3b2e8407..716b76df1 100644
--- a/client/src/app/helpers/locales/oc.ts
+++ b/client/src/app/helpers/locales/oc.ts
@@ -12,16 +12,16 @@ function plural (n: number): number {
12 12
13export default [ 13export default [
14 'oc', 14 'oc',
15 [['a. m.', 'p. m.'], u, u], 15 [ [ 'a. m.', 'p. m.' ], u, u ],
16 u, 16 u,
17 [ 17 [
18 ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'], ['dg.', 'dl.', 'dm.', 'dc.', 'dj.', 'dv.', 'ds.'], 18 [ 'dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds' ], [ 'dg.', 'dl.', 'dm.', 'dc.', 'dj.', 'dv.', 'ds.' ],
19 ['dimenge', 'diluns', 'dimars', 'dimècres', 'dijòus', 'divendres', 'dissabte'], 19 [ 'dimenge', 'diluns', 'dimars', 'dimècres', 'dijòus', 'divendres', 'dissabte' ],
20 ['dg.', 'dl.', 'dm.', 'dc.', 'dj.', 'dv.', 'ds.'] 20 [ 'dg.', 'dl.', 'dm.', 'dc.', 'dj.', 'dv.', 'ds.' ]
21 ], 21 ],
22 u, 22 u,
23 [ 23 [
24 ['GN', 'FB', 'MÇ', 'AB', 'MA', 'JN', 'JL', 'AG', 'ST', 'OC', 'NV', 'DC'], 24 [ 'GN', 'FB', 'MÇ', 'AB', 'MA', 'JN', 'JL', 'AG', 'ST', 'OC', 'NV', 'DC' ],
25 [ 25 [
26 'de gen.', 'de febr.', 'de març', 'd’abr.', 'de mai', 'de junh', 'de jul.', 'd’ag.', 26 'de gen.', 'de febr.', 'de març', 'd’abr.', 'de mai', 'de junh', 'de jul.', 'd’ag.',
27 'de set.', 'd’oct.', 'de nov.', 'de dec.' 27 'de set.', 'd’oct.', 'de nov.', 'de dec.'
@@ -32,7 +32,7 @@ export default [
32 ] 32 ]
33 ], 33 ],
34 [ 34 [
35 ['GN', 'FB', 'MÇ', 'AB', 'MA', 'JN', 'JL', 'AG', 'ST', 'OC', 'NV', 'DC'], 35 [ 'GN', 'FB', 'MÇ', 'AB', 'MA', 'JN', 'JL', 'AG', 'ST', 'OC', 'NV', 'DC' ],
36 [ 36 [
37 'gen.', 'febr.', 'març', 'abr.', 'mai', 'junh', 'jul.', 'ag.', 'set.', 'oct.', 'nov.', 37 'gen.', 'febr.', 'març', 'abr.', 'mai', 'junh', 'jul.', 'ag.', 'set.', 'oct.', 'nov.',
38 'dec.' 38 'dec.'
@@ -42,62 +42,62 @@ export default [
42 'novembre', 'decembre' 42 'novembre', 'decembre'
43 ] 43 ]
44 ], 44 ],
45 [['aC', 'dC'], u, ['abans Jèsus-Crist', 'aprèp Jèsus-Crist']], 45 [ [ 'aC', 'dC' ], u, [ 'abans Jèsus-Crist', 'aprèp Jèsus-Crist' ] ],
46 1, 46 1,
47 [6, 0], 47 [ 6, 0 ],
48 ['d/M/yy', 'd MMM y', 'd MMMM \'de\' y', 'EEEE, d MMMM \'de\' y'], 48 [ 'd/M/yy', 'd MMM y', 'd MMMM \'de\' y', 'EEEE, d MMMM \'de\' y' ],
49 ['H:mm', 'H:mm:ss', 'H:mm:ss z', 'H:mm:ss zzzz'], 49 [ 'H:mm', 'H:mm:ss', 'H:mm:ss z', 'H:mm:ss zzzz' ],
50 ['{1} {0}', '{1}, {0}', '{1} \'a\' \'les\' {0}', u], 50 [ '{1} {0}', '{1}, {0}', '{1} \'a\' \'les\' {0}', u ],
51 [',', '.', ';', '%', '+', '-', 'E', '×', '‰', '∞', 'NaN', ':'], 51 [ ',', '.', ';', '%', '+', '-', 'E', '×', '‰', '∞', 'NaN', ':' ],
52 ['#,##0.###', '#,##0%', '#,##0.00 ¤', '#E0'], 52 [ '#,##0.###', '#,##0%', '#,##0.00 ¤', '#E0' ],
53 'EUR', 53 'EUR',
54 '€', 54 '€',
55 'euro', 55 'euro',
56 { 56 {
57 'ARS': ['$AR', '$'], 57 ARS: [ '$AR', '$' ],
58 'AUD': ['$AU', '$'], 58 AUD: [ '$AU', '$' ],
59 'BEF': ['FB'], 59 BEF: [ 'FB' ],
60 'BMD': ['$BM', '$'], 60 BMD: [ '$BM', '$' ],
61 'BND': ['$BN', '$'], 61 BND: [ '$BN', '$' ],
62 'BZD': ['$BZ', '$'], 62 BZD: [ '$BZ', '$' ],
63 'CAD': ['$CA', '$'], 63 CAD: [ '$CA', '$' ],
64 'CLP': ['$CL', '$'], 64 CLP: [ '$CL', '$' ],
65 'CNY': [u, 'Â¥'], 65 CNY: [ u, 'Â¥' ],
66 'COP': ['$CO', '$'], 66 COP: [ '$CO', '$' ],
67 'CYP': ['£CY'], 67 CYP: [ '£CY' ],
68 'EGP': [u, '£E'], 68 EGP: [ u, '£E' ],
69 'FJD': ['$FJ', '$'], 69 FJD: [ '$FJ', '$' ],
70 'FKP': ['£FK', '£'], 70 FKP: [ '£FK', '£' ],
71 'FRF': ['F'], 71 FRF: [ 'F' ],
72 'GBP': ['£GB', '£'], 72 GBP: [ '£GB', '£' ],
73 'GIP': ['£GI', '£'], 73 GIP: [ '£GI', '£' ],
74 'HKD': [u, '$'], 74 HKD: [ u, '$' ],
75 'IEP': ['£IE'], 75 IEP: [ '£IE' ],
76 'ILP': ['£IL'], 76 ILP: [ '£IL' ],
77 'ITL': ['₤IT'], 77 ITL: [ '₤IT' ],
78 'JPY': [u, 'Â¥'], 78 JPY: [ u, 'Â¥' ],
79 'KMF': [u, 'FC'], 79 KMF: [ u, 'FC' ],
80 'LBP': ['£LB', '£L'], 80 LBP: [ '£LB', '£L' ],
81 'MTP': ['£MT'], 81 MTP: [ '£MT' ],
82 'MXN': ['$MX', '$'], 82 MXN: [ '$MX', '$' ],
83 'NAD': ['$NA', '$'], 83 NAD: [ '$NA', '$' ],
84 'NIO': [u, '$C'], 84 NIO: [ u, '$C' ],
85 'NZD': ['$NZ', '$'], 85 NZD: [ '$NZ', '$' ],
86 'RHD': ['$RH'], 86 RHD: [ '$RH' ],
87 'RON': [u, 'L'], 87 RON: [ u, 'L' ],
88 'RWF': [u, 'FR'], 88 RWF: [ u, 'FR' ],
89 'SBD': ['$SB', '$'], 89 SBD: [ '$SB', '$' ],
90 'SGD': ['$SG', '$'], 90 SGD: [ '$SG', '$' ],
91 'SRD': ['$SR', '$'], 91 SRD: [ '$SR', '$' ],
92 'TOP': [u, '$T'], 92 TOP: [ u, '$T' ],
93 'TTD': ['$TT', '$'], 93 TTD: [ '$TT', '$' ],
94 'TWD': [u, 'NT$'], 94 TWD: [ u, 'NT$' ],
95 'USD': ['$US', '$'], 95 USD: [ '$US', '$' ],
96 'UYU': ['$UY', '$'], 96 UYU: [ '$UY', '$' ],
97 'WST': ['$WS'], 97 WST: [ '$WS' ],
98 'XCD': [u, '$'], 98 XCD: [ u, '$' ],
99 'XPF': ['FCFP'], 99 XPF: [ 'FCFP' ],
100 'ZMW': [u, 'Kw'] 100 ZMW: [ u, 'Kw' ]
101 }, 101 },
102 'ltr', 102 'ltr',
103 plural 103 plural
diff --git a/client/src/app/helpers/utils.ts b/client/src/app/helpers/utils.ts
index edcaf50e0..8636f3a55 100644
--- a/client/src/app/helpers/utils.ts
+++ b/client/src/app/helpers/utils.ts
@@ -10,7 +10,7 @@ import { AuthService } from '../core/auth'
10// Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript 10// Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
11function getParameterByName (name: string, url: string) { 11function getParameterByName (name: string, url: string) {
12 if (!url) url = window.location.href 12 if (!url) url = window.location.href
13 name = name.replace(/[\[\]]/g, '\\$&') 13 name = name.replace(/[[\]]/g, '\\$&')
14 14
15 const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)') 15 const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)')
16 const results = regex.exec(url) 16 const results = regex.exec(url)
@@ -110,10 +110,10 @@ function objectToFormData (obj: any, form?: FormData, namespace?: string) {
110 continue 110 continue
111 } 111 }
112 112
113 if (obj[key] !== null && typeof obj[ key ] === 'object' && !(obj[ key ] instanceof File)) { 113 if (obj[key] !== null && typeof obj[key] === 'object' && !(obj[key] instanceof File)) {
114 objectToFormData(obj[ key ], fd, formKey) 114 objectToFormData(obj[key], fd, formKey)
115 } else { 115 } else {
116 fd.append(formKey, obj[ key ]) 116 fd.append(formKey, obj[key])
117 } 117 }
118 } 118 }
119 119
@@ -159,7 +159,7 @@ function scrollToTop (behavior: 'auto' | 'smooth' = 'auto') {
159function isInViewport (el: HTMLElement) { 159function isInViewport (el: HTMLElement) {
160 const bounding = el.getBoundingClientRect() 160 const bounding = el.getBoundingClientRect()
161 return ( 161 return (
162 bounding.top >= 0 && 162 bounding.top >= 0 &&
163 bounding.left >= 0 && 163 bounding.left >= 0 &&
164 bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) && 164 bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
165 bounding.right <= (window.innerWidth || document.documentElement.clientWidth) 165 bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
diff --git a/client/src/app/menu/language-chooser.component.ts b/client/src/app/menu/language-chooser.component.ts
index e15aeff20..b42e41855 100644
--- a/client/src/app/menu/language-chooser.component.ts
+++ b/client/src/app/menu/language-chooser.component.ts
@@ -18,7 +18,7 @@ export class LanguageChooserComponent {
18 @Inject(LOCALE_ID) private localeId: string 18 @Inject(LOCALE_ID) private localeId: string
19 ) { 19 ) {
20 const l = Object.keys(I18N_LOCALES) 20 const l = Object.keys(I18N_LOCALES)
21 .map(k => ({ id: k, label: I18N_LOCALES[k] , iso: getShortLocale(k) })) 21 .map(k => ({ id: k, label: I18N_LOCALES[k], iso: getShortLocale(k) }))
22 22
23 this.languages = sortBy(l, 'label') 23 this.languages = sortBy(l, 'label')
24 } 24 }
diff --git a/client/src/app/menu/menu.component.ts b/client/src/app/menu/menu.component.ts
index 627a8712f..97f07c956 100644
--- a/client/src/app/menu/menu.component.ts
+++ b/client/src/app/menu/menu.component.ts
@@ -28,7 +28,7 @@ const logger = debug('peertube:menu:MenuComponent')
28@Component({ 28@Component({
29 selector: 'my-menu', 29 selector: 'my-menu',
30 templateUrl: './menu.component.html', 30 templateUrl: './menu.component.html',
31 styleUrls: ['./menu.component.scss'] 31 styleUrls: [ './menu.component.scss' ]
32}) 32})
33export class MenuComponent implements OnInit { 33export class MenuComponent implements OnInit {
34 @ViewChild('languageChooserModal', { static: true }) languageChooserModal: LanguageChooserComponent 34 @ViewChild('languageChooserModal', { static: true }) languageChooserModal: LanguageChooserComponent
diff --git a/client/src/app/modal/custom-modal.component.ts b/client/src/app/modal/custom-modal.component.ts
index a98579085..559230e04 100644
--- a/client/src/app/modal/custom-modal.component.ts
+++ b/client/src/app/modal/custom-modal.component.ts
@@ -22,10 +22,10 @@ export class CustomModalComponent {
22 ) { } 22 ) { }
23 23
24 show (input: { 24 show (input: {
25 title: string, 25 title: string
26 content: string, 26 content: string
27 close?: boolean, 27 close?: boolean
28 cancel?: { value: string, action?: () => void }, 28 cancel?: { value: string, action?: () => void }
29 confirm?: { value: string, action?: () => void } 29 confirm?: { value: string, action?: () => void }
30 }) { 30 }) {
31 if (this.modalRef instanceof NgbModalRef && this.modalService.hasOpenModals()) { 31 if (this.modalRef instanceof NgbModalRef && this.modalService.hasOpenModals()) {
diff --git a/client/src/app/shared/form-validators/abuse-validators.ts b/client/src/app/shared/form-validators/abuse-validators.ts
index 75bfacf01..8d3c411b4 100644
--- a/client/src/app/shared/form-validators/abuse-validators.ts
+++ b/client/src/app/shared/form-validators/abuse-validators.ts
@@ -2,28 +2,28 @@ import { Validators } from '@angular/forms'
2import { BuildFormValidator } from './form-validator.model' 2import { BuildFormValidator } from './form-validator.model'
3 3
4export const ABUSE_REASON_VALIDATOR: BuildFormValidator = { 4export const ABUSE_REASON_VALIDATOR: BuildFormValidator = {
5 VALIDATORS: [Validators.required, Validators.minLength(2), Validators.maxLength(3000)], 5 VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ],
6 MESSAGES: { 6 MESSAGES: {
7 'required': $localize`Report reason is required.`, 7 required: $localize`Report reason is required.`,
8 'minlength': $localize`Report reason must be at least 2 characters long.`, 8 minlength: $localize`Report reason must be at least 2 characters long.`,
9 'maxlength': $localize`Report reason cannot be more than 3000 characters long.` 9 maxlength: $localize`Report reason cannot be more than 3000 characters long.`
10 } 10 }
11} 11}
12 12
13export const ABUSE_MODERATION_COMMENT_VALIDATOR: BuildFormValidator = { 13export const ABUSE_MODERATION_COMMENT_VALIDATOR: BuildFormValidator = {
14 VALIDATORS: [Validators.required, Validators.minLength(2), Validators.maxLength(3000)], 14 VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ],
15 MESSAGES: { 15 MESSAGES: {
16 'required': $localize`Moderation comment is required.`, 16 required: $localize`Moderation comment is required.`,
17 'minlength': $localize`Moderation comment must be at least 2 characters long.`, 17 minlength: $localize`Moderation comment must be at least 2 characters long.`,
18 'maxlength': $localize`Moderation comment cannot be more than 3000 characters long.` 18 maxlength: $localize`Moderation comment cannot be more than 3000 characters long.`
19 } 19 }
20} 20}
21 21
22export const ABUSE_MESSAGE_VALIDATOR: BuildFormValidator = { 22export const ABUSE_MESSAGE_VALIDATOR: BuildFormValidator = {
23 VALIDATORS: [Validators.required, Validators.minLength(2), Validators.maxLength(3000)], 23 VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(3000) ],
24 MESSAGES: { 24 MESSAGES: {
25 'required': $localize`Abuse message is required.`, 25 required: $localize`Abuse message is required.`,
26 'minlength': $localize`Abuse message must be at least 2 characters long.`, 26 minlength: $localize`Abuse message must be at least 2 characters long.`,
27 'maxlength': $localize`Abuse message cannot be more than 3000 characters long.` 27 maxlength: $localize`Abuse message cannot be more than 3000 characters long.`
28 } 28 }
29} 29}
diff --git a/client/src/app/shared/form-validators/custom-config-validators.ts b/client/src/app/shared/form-validators/custom-config-validators.ts
index 1ed5700ff..fbf423d08 100644
--- a/client/src/app/shared/form-validators/custom-config-validators.ts
+++ b/client/src/app/shared/form-validators/custom-config-validators.ts
@@ -2,120 +2,120 @@ import { Validators } from '@angular/forms'
2import { BuildFormValidator } from './form-validator.model' 2import { BuildFormValidator } from './form-validator.model'
3 3
4export const INSTANCE_NAME_VALIDATOR: BuildFormValidator = { 4export const INSTANCE_NAME_VALIDATOR: BuildFormValidator = {
5 VALIDATORS: [Validators.required], 5 VALIDATORS: [ Validators.required ],
6 MESSAGES: { 6 MESSAGES: {
7 'required': $localize`Instance name is required.` 7 required: $localize`Instance name is required.`
8 } 8 }
9} 9}
10 10
11export const INSTANCE_SHORT_DESCRIPTION_VALIDATOR: BuildFormValidator = { 11export const INSTANCE_SHORT_DESCRIPTION_VALIDATOR: BuildFormValidator = {
12 VALIDATORS: [Validators.max(250)], 12 VALIDATORS: [ Validators.max(250) ],
13 MESSAGES: { 13 MESSAGES: {
14 'max': $localize`Short description should not be longer than 250 characters.` 14 max: $localize`Short description should not be longer than 250 characters.`
15 } 15 }
16} 16}
17 17
18export const SERVICES_TWITTER_USERNAME_VALIDATOR: BuildFormValidator = { 18export const SERVICES_TWITTER_USERNAME_VALIDATOR: BuildFormValidator = {
19 VALIDATORS: [Validators.required], 19 VALIDATORS: [ Validators.required ],
20 MESSAGES: { 20 MESSAGES: {
21 'required': $localize`Twitter username is required.` 21 required: $localize`Twitter username is required.`
22 } 22 }
23} 23}
24 24
25export const CACHE_PREVIEWS_SIZE_VALIDATOR: BuildFormValidator = { 25export const CACHE_PREVIEWS_SIZE_VALIDATOR: BuildFormValidator = {
26 VALIDATORS: [Validators.required, Validators.min(1), Validators.pattern('[0-9]+')], 26 VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
27 MESSAGES: { 27 MESSAGES: {
28 'required': $localize`Previews cache size is required.`, 28 required: $localize`Previews cache size is required.`,
29 'min': $localize`Previews cache size must be greater than 1.`, 29 min: $localize`Previews cache size must be greater than 1.`,
30 'pattern': $localize`Previews cache size must be a number.` 30 pattern: $localize`Previews cache size must be a number.`
31 } 31 }
32} 32}
33 33
34export const CACHE_CAPTIONS_SIZE_VALIDATOR: BuildFormValidator = { 34export const CACHE_CAPTIONS_SIZE_VALIDATOR: BuildFormValidator = {
35 VALIDATORS: [Validators.required, Validators.min(1), Validators.pattern('[0-9]+')], 35 VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
36 MESSAGES: { 36 MESSAGES: {
37 'required': $localize`Captions cache size is required.`, 37 required: $localize`Captions cache size is required.`,
38 'min': $localize`Captions cache size must be greater than 1.`, 38 min: $localize`Captions cache size must be greater than 1.`,
39 'pattern': $localize`Captions cache size must be a number.` 39 pattern: $localize`Captions cache size must be a number.`
40 } 40 }
41} 41}
42 42
43export const SIGNUP_LIMIT_VALIDATOR: BuildFormValidator = { 43export const SIGNUP_LIMIT_VALIDATOR: BuildFormValidator = {
44 VALIDATORS: [Validators.required, Validators.min(-1), Validators.pattern('-?[0-9]+')], 44 VALIDATORS: [ Validators.required, Validators.min(-1), Validators.pattern('-?[0-9]+') ],
45 MESSAGES: { 45 MESSAGES: {
46 'required': $localize`Signup limit is required.`, 46 required: $localize`Signup limit is required.`,
47 'min': $localize`Signup limit must be greater than 1. Use -1 to disable it.`, 47 min: $localize`Signup limit must be greater than 1. Use -1 to disable it.`,
48 'pattern': $localize`Signup limit must be a number.` 48 pattern: $localize`Signup limit must be a number.`
49 } 49 }
50} 50}
51 51
52export const SIGNUP_MINIMUM_AGE_VALIDATOR: BuildFormValidator = { 52export const SIGNUP_MINIMUM_AGE_VALIDATOR: BuildFormValidator = {
53 VALIDATORS: [Validators.required, Validators.min(1), Validators.pattern('[0-9]+')], 53 VALIDATORS: [ Validators.required, Validators.min(1), Validators.pattern('[0-9]+') ],
54 MESSAGES: { 54 MESSAGES: {
55 'required': $localize`Signup minimum age is required.`, 55 required: $localize`Signup minimum age is required.`,
56 'min': $localize`Signup minimum age must be greater than 1.`, 56 min: $localize`Signup minimum age must be greater than 1.`,
57 'pattern': $localize`Signup minimum age must be a number.` 57 pattern: $localize`Signup minimum age must be a number.`
58 } 58 }
59} 59}
60 60
61export const ADMIN_EMAIL_VALIDATOR: BuildFormValidator = { 61export const ADMIN_EMAIL_VALIDATOR: BuildFormValidator = {
62 VALIDATORS: [Validators.required, Validators.email], 62 VALIDATORS: [ Validators.required, Validators.email ],
63 MESSAGES: { 63 MESSAGES: {
64 'required': $localize`Admin email is required.`, 64 required: $localize`Admin email is required.`,
65 'email': $localize`Admin email must be valid.` 65 email: $localize`Admin email must be valid.`
66 } 66 }
67} 67}
68 68
69export const TRANSCODING_THREADS_VALIDATOR: BuildFormValidator = { 69export const TRANSCODING_THREADS_VALIDATOR: BuildFormValidator = {
70 VALIDATORS: [Validators.required, Validators.min(0)], 70 VALIDATORS: [ Validators.required, Validators.min(0) ],
71 MESSAGES: { 71 MESSAGES: {
72 'required': $localize`Transcoding threads is required.`, 72 required: $localize`Transcoding threads is required.`,
73 'min': $localize`Transcoding threads must be greater or equal to 0.` 73 min: $localize`Transcoding threads must be greater or equal to 0.`
74 } 74 }
75} 75}
76 76
77export const MAX_LIVE_DURATION_VALIDATOR: BuildFormValidator = { 77export const MAX_LIVE_DURATION_VALIDATOR: BuildFormValidator = {
78 VALIDATORS: [Validators.required, Validators.min(-1)], 78 VALIDATORS: [ Validators.required, Validators.min(-1) ],
79 MESSAGES: { 79 MESSAGES: {
80 'required': $localize`Max live duration is required.`, 80 required: $localize`Max live duration is required.`,
81 'min': $localize`Max live duration should be greater or equal to -1.` 81 min: $localize`Max live duration should be greater or equal to -1.`
82 } 82 }
83} 83}
84 84
85export const MAX_INSTANCE_LIVES_VALIDATOR: BuildFormValidator = { 85export const MAX_INSTANCE_LIVES_VALIDATOR: BuildFormValidator = {
86 VALIDATORS: [Validators.required, Validators.min(-1)], 86 VALIDATORS: [ Validators.required, Validators.min(-1) ],
87 MESSAGES: { 87 MESSAGES: {
88 'required': $localize`Max instance lives is required.`, 88 required: $localize`Max instance lives is required.`,
89 'min': $localize`Max instance lives should be greater or equal to -1.` 89 min: $localize`Max instance lives should be greater or equal to -1.`
90 } 90 }
91} 91}
92 92
93export const MAX_USER_LIVES_VALIDATOR: BuildFormValidator = { 93export const MAX_USER_LIVES_VALIDATOR: BuildFormValidator = {
94 VALIDATORS: [Validators.required, Validators.min(-1)], 94 VALIDATORS: [ Validators.required, Validators.min(-1) ],
95 MESSAGES: { 95 MESSAGES: {
96 'required': $localize`Max user lives is required.`, 96 required: $localize`Max user lives is required.`,
97 'min': $localize`Max user lives should be greater or equal to -1.` 97 min: $localize`Max user lives should be greater or equal to -1.`
98 } 98 }
99} 99}
100 100
101export const CONCURRENCY_VALIDATOR: BuildFormValidator = { 101export const CONCURRENCY_VALIDATOR: BuildFormValidator = {
102 VALIDATORS: [Validators.required, Validators.min(1)], 102 VALIDATORS: [ Validators.required, Validators.min(1) ],
103 MESSAGES: { 103 MESSAGES: {
104 'required': $localize`Concurrency is required.`, 104 required: $localize`Concurrency is required.`,
105 'min': $localize`Concurrency should be greater or equal to 1.` 105 min: $localize`Concurrency should be greater or equal to 1.`
106 } 106 }
107} 107}
108 108
109export const INDEX_URL_VALIDATOR: BuildFormValidator = { 109export const INDEX_URL_VALIDATOR: BuildFormValidator = {
110 VALIDATORS: [Validators.pattern(/^https:\/\//)], 110 VALIDATORS: [ Validators.pattern(/^https:\/\//) ],
111 MESSAGES: { 111 MESSAGES: {
112 'pattern': $localize`Index URL should be a URL` 112 pattern: $localize`Index URL should be a URL`
113 } 113 }
114} 114}
115 115
116export const SEARCH_INDEX_URL_VALIDATOR: BuildFormValidator = { 116export const SEARCH_INDEX_URL_VALIDATOR: BuildFormValidator = {
117 VALIDATORS: [Validators.pattern(/^https?:\/\//)], 117 VALIDATORS: [ Validators.pattern(/^https?:\/\//) ],
118 MESSAGES: { 118 MESSAGES: {
119 'pattern': $localize`Search index URL should be a URL` 119 pattern: $localize`Search index URL should be a URL`
120 } 120 }
121} 121}
diff --git a/client/src/app/shared/form-validators/form-validator.model.ts b/client/src/app/shared/form-validators/form-validator.model.ts
index 07b1ea075..6f2472ccd 100644
--- a/client/src/app/shared/form-validators/form-validator.model.ts
+++ b/client/src/app/shared/form-validators/form-validator.model.ts
@@ -1,7 +1,7 @@
1import { ValidatorFn } from '@angular/forms' 1import { ValidatorFn } from '@angular/forms'
2 2
3export type BuildFormValidator = { 3export type BuildFormValidator = {
4 VALIDATORS: ValidatorFn[], 4 VALIDATORS: ValidatorFn[]
5 MESSAGES: { [ name: string ]: string } 5 MESSAGES: { [ name: string ]: string }
6} 6}
7 7
diff --git a/client/src/app/shared/form-validators/host-validators.ts b/client/src/app/shared/form-validators/host-validators.ts
index 6f410a50a..3d9c476b5 100644
--- a/client/src/app/shared/form-validators/host-validators.ts
+++ b/client/src/app/shared/form-validators/host-validators.ts
@@ -4,7 +4,7 @@ import { BuildFormValidator } from './form-validator.model'
4export function validateHost (value: string) { 4export function validateHost (value: string) {
5 // Thanks to http://stackoverflow.com/a/106223 5 // Thanks to http://stackoverflow.com/a/106223
6 const HOST_REGEXP = new RegExp( 6 const HOST_REGEXP = new RegExp(
7 '^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$' 7 '^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$'
8 ) 8 )
9 9
10 return HOST_REGEXP.test(value) 10 return HOST_REGEXP.test(value)
@@ -32,7 +32,7 @@ const validHosts: ValidatorFn = (control: AbstractControl) => {
32 if (errors.length === 0) return null 32 if (errors.length === 0) return null
33 33
34 return { 34 return {
35 'validHosts': { 35 validHosts: {
36 reason: 'invalid', 36 reason: 'invalid',
37 value: errors.join('. ') + '.' 37 value: errors.join('. ') + '.'
38 } 38 }
@@ -55,7 +55,7 @@ const validHostsOrHandles: ValidatorFn = (control: AbstractControl) => {
55 if (errors.length === 0) return null 55 if (errors.length === 0) return null
56 56
57 return { 57 return {
58 'validHostsOrHandles': { 58 validHostsOrHandles: {
59 reason: 'invalid', 59 reason: 'invalid',
60 value: errors.join('. ') + '.' 60 value: errors.join('. ') + '.'
61 } 61 }
@@ -80,7 +80,7 @@ export const unique: ValidatorFn = (control: AbstractControl) => {
80 } 80 }
81 81
82 return { 82 return {
83 'unique': { 83 unique: {
84 reason: 'invalid' 84 reason: 'invalid'
85 } 85 }
86 } 86 }
@@ -89,17 +89,17 @@ export const unique: ValidatorFn = (control: AbstractControl) => {
89export const UNIQUE_HOSTS_VALIDATOR: BuildFormValidator = { 89export const UNIQUE_HOSTS_VALIDATOR: BuildFormValidator = {
90 VALIDATORS: [ Validators.required, validHosts, unique ], 90 VALIDATORS: [ Validators.required, validHosts, unique ],
91 MESSAGES: { 91 MESSAGES: {
92 'required': $localize`Domain is required.`, 92 required: $localize`Domain is required.`,
93 'validHosts': $localize`Hosts entered are invalid.`, 93 validHosts: $localize`Hosts entered are invalid.`,
94 'unique': $localize`Hosts entered contain duplicates.` 94 unique: $localize`Hosts entered contain duplicates.`
95 } 95 }
96} 96}
97 97
98export const UNIQUE_HOSTS_OR_HANDLE_VALIDATOR: BuildFormValidator = { 98export const UNIQUE_HOSTS_OR_HANDLE_VALIDATOR: BuildFormValidator = {
99 VALIDATORS: [ Validators.required, validHostsOrHandles, unique ], 99 VALIDATORS: [ Validators.required, validHostsOrHandles, unique ],
100 MESSAGES: { 100 MESSAGES: {
101 'required': $localize`Domain is required.`, 101 required: $localize`Domain is required.`,
102 'validHostsOrHandles': $localize`Hosts or handles are invalid.`, 102 validHostsOrHandles: $localize`Hosts or handles are invalid.`,
103 'unique': $localize`Hosts or handles contain duplicates.` 103 unique: $localize`Hosts or handles contain duplicates.`
104 } 104 }
105} 105}
diff --git a/client/src/app/shared/form-validators/instance-validators.ts b/client/src/app/shared/form-validators/instance-validators.ts
index a72e28ba0..4b1f0d048 100644
--- a/client/src/app/shared/form-validators/instance-validators.ts
+++ b/client/src/app/shared/form-validators/instance-validators.ts
@@ -2,10 +2,10 @@ import { Validators } from '@angular/forms'
2import { BuildFormValidator } from './form-validator.model' 2import { BuildFormValidator } from './form-validator.model'
3 3
4export const FROM_EMAIL_VALIDATOR: BuildFormValidator = { 4export const FROM_EMAIL_VALIDATOR: BuildFormValidator = {
5 VALIDATORS: [Validators.required, Validators.email], 5 VALIDATORS: [ Validators.required, Validators.email ],
6 MESSAGES: { 6 MESSAGES: {
7 'required': $localize`Email is required.`, 7 required: $localize`Email is required.`,
8 'email': $localize`Email must be valid.` 8 email: $localize`Email must be valid.`
9 } 9 }
10} 10}
11 11
@@ -16,9 +16,9 @@ export const FROM_NAME_VALIDATOR: BuildFormValidator = {
16 Validators.maxLength(120) 16 Validators.maxLength(120)
17 ], 17 ],
18 MESSAGES: { 18 MESSAGES: {
19 'required': $localize`Your name is required.`, 19 required: $localize`Your name is required.`,
20 'minlength': $localize`Your name must be at least 1 character long.`, 20 minlength: $localize`Your name must be at least 1 character long.`,
21 'maxlength': $localize`Your name cannot be more than 120 characters long.` 21 maxlength: $localize`Your name cannot be more than 120 characters long.`
22 } 22 }
23} 23}
24 24
@@ -29,9 +29,9 @@ export const SUBJECT_VALIDATOR: BuildFormValidator = {
29 Validators.maxLength(120) 29 Validators.maxLength(120)
30 ], 30 ],
31 MESSAGES: { 31 MESSAGES: {
32 'required': $localize`A subject is required.`, 32 required: $localize`A subject is required.`,
33 'minlength': $localize`The subject must be at least 1 character long.`, 33 minlength: $localize`The subject must be at least 1 character long.`,
34 'maxlength': $localize`The subject cannot be more than 120 characters long.` 34 maxlength: $localize`The subject cannot be more than 120 characters long.`
35 } 35 }
36} 36}
37 37
@@ -42,8 +42,8 @@ export const BODY_VALIDATOR: BuildFormValidator = {
42 Validators.maxLength(5000) 42 Validators.maxLength(5000)
43 ], 43 ],
44 MESSAGES: { 44 MESSAGES: {
45 'required': $localize`A message is required.`, 45 required: $localize`A message is required.`,
46 'minlength': $localize`The message must be at least 3 characters long.`, 46 minlength: $localize`The message must be at least 3 characters long.`,
47 'maxlength': $localize`The message cannot be more than 5000 characters long.` 47 maxlength: $localize`The message cannot be more than 5000 characters long.`
48 } 48 }
49} 49}
diff --git a/client/src/app/shared/form-validators/login-validators.ts b/client/src/app/shared/form-validators/login-validators.ts
index 1ceae1be3..5b911ac47 100644
--- a/client/src/app/shared/form-validators/login-validators.ts
+++ b/client/src/app/shared/form-validators/login-validators.ts
@@ -6,7 +6,7 @@ export const LOGIN_USERNAME_VALIDATOR: BuildFormValidator = {
6 Validators.required 6 Validators.required
7 ], 7 ],
8 MESSAGES: { 8 MESSAGES: {
9 'required': $localize`Username is required.` 9 required: $localize`Username is required.`
10 } 10 }
11} 11}
12 12
@@ -15,6 +15,6 @@ export const LOGIN_PASSWORD_VALIDATOR: BuildFormValidator = {
15 Validators.required 15 Validators.required
16 ], 16 ],
17 MESSAGES: { 17 MESSAGES: {
18 'required': $localize`Password is required.` 18 required: $localize`Password is required.`
19 } 19 }
20} 20}
diff --git a/client/src/app/shared/form-validators/reset-password-validators.ts b/client/src/app/shared/form-validators/reset-password-validators.ts
index b87f2eab9..70617a562 100644
--- a/client/src/app/shared/form-validators/reset-password-validators.ts
+++ b/client/src/app/shared/form-validators/reset-password-validators.ts
@@ -6,6 +6,6 @@ export const RESET_PASSWORD_CONFIRM_VALIDATOR: BuildFormValidator = {
6 Validators.required 6 Validators.required
7 ], 7 ],
8 MESSAGES: { 8 MESSAGES: {
9 'required': $localize`Confirmation of the password is required.` 9 required: $localize`Confirmation of the password is required.`
10 } 10 }
11} 11}
diff --git a/client/src/app/shared/form-validators/user-validators.ts b/client/src/app/shared/form-validators/user-validators.ts
index 976c97b87..6d0dea64e 100644
--- a/client/src/app/shared/form-validators/user-validators.ts
+++ b/client/src/app/shared/form-validators/user-validators.ts
@@ -11,10 +11,10 @@ export const USER_USERNAME_VALIDATOR: BuildFormValidator = {
11 Validators.pattern(new RegExp(`^${USER_USERNAME_REGEX_CHARACTERS}*$`)) 11 Validators.pattern(new RegExp(`^${USER_USERNAME_REGEX_CHARACTERS}*$`))
12 ], 12 ],
13 MESSAGES: { 13 MESSAGES: {
14 'required': $localize`Username is required.`, 14 required: $localize`Username is required.`,
15 'minlength': $localize`Username must be at least 1 character long.`, 15 minlength: $localize`Username must be at least 1 character long.`,
16 'maxlength': $localize`Username cannot be more than 50 characters long.`, 16 maxlength: $localize`Username cannot be more than 50 characters long.`,
17 'pattern': $localize`Username should be lowercase alphanumeric; dots and underscores are allowed.` 17 pattern: $localize`Username should be lowercase alphanumeric; dots and underscores are allowed.`
18 } 18 }
19} 19}
20 20
@@ -26,18 +26,18 @@ export const USER_CHANNEL_NAME_VALIDATOR: BuildFormValidator = {
26 Validators.pattern(/^[a-z0-9][a-z0-9._]*$/) 26 Validators.pattern(/^[a-z0-9][a-z0-9._]*$/)
27 ], 27 ],
28 MESSAGES: { 28 MESSAGES: {
29 'required': $localize`Channel name is required.`, 29 required: $localize`Channel name is required.`,
30 'minlength': $localize`Channel name must be at least 1 character long.`, 30 minlength: $localize`Channel name must be at least 1 character long.`,
31 'maxlength': $localize`Channel name cannot be more than 50 characters long.`, 31 maxlength: $localize`Channel name cannot be more than 50 characters long.`,
32 'pattern': $localize`Channel name should be lowercase, and can contain only alphanumeric characters, dots and underscores.` 32 pattern: $localize`Channel name should be lowercase, and can contain only alphanumeric characters, dots and underscores.`
33 } 33 }
34} 34}
35 35
36export const USER_EMAIL_VALIDATOR: BuildFormValidator = { 36export const USER_EMAIL_VALIDATOR: BuildFormValidator = {
37 VALIDATORS: [ Validators.required, Validators.email ], 37 VALIDATORS: [ Validators.required, Validators.email ],
38 MESSAGES: { 38 MESSAGES: {
39 'required': $localize`Email is required.`, 39 required: $localize`Email is required.`,
40 'email': $localize`Email must be valid.` 40 email: $localize`Email must be valid.`
41 } 41 }
42} 42}
43 43
@@ -47,8 +47,8 @@ export const USER_HANDLE_VALIDATOR: BuildFormValidator = {
47 Validators.pattern(/@.+/) 47 Validators.pattern(/@.+/)
48 ], 48 ],
49 MESSAGES: { 49 MESSAGES: {
50 'required': $localize`Handle is required.`, 50 required: $localize`Handle is required.`,
51 'pattern': $localize`Handle must be valid (eg. chocobozzz@example.com).` 51 pattern: $localize`Handle must be valid (eg. chocobozzz@example.com).`
52 } 52 }
53} 53}
54 54
@@ -57,7 +57,7 @@ export const USER_EXISTING_PASSWORD_VALIDATOR: BuildFormValidator = {
57 Validators.required 57 Validators.required
58 ], 58 ],
59 MESSAGES: { 59 MESSAGES: {
60 'required': $localize`Password is required.` 60 required: $localize`Password is required.`
61 } 61 }
62} 62}
63 63
@@ -68,9 +68,9 @@ export const USER_PASSWORD_VALIDATOR: BuildFormValidator = {
68 Validators.maxLength(255) 68 Validators.maxLength(255)
69 ], 69 ],
70 MESSAGES: { 70 MESSAGES: {
71 'required': $localize`Password is required.`, 71 required: $localize`Password is required.`,
72 'minlength': $localize`Password must be at least 6 characters long.`, 72 minlength: $localize`Password must be at least 6 characters long.`,
73 'maxlength': $localize`Password cannot be more than 255 characters long.` 73 maxlength: $localize`Password cannot be more than 255 characters long.`
74 } 74 }
75} 75}
76 76
@@ -80,37 +80,37 @@ export const USER_PASSWORD_OPTIONAL_VALIDATOR: BuildFormValidator = {
80 Validators.maxLength(255) 80 Validators.maxLength(255)
81 ], 81 ],
82 MESSAGES: { 82 MESSAGES: {
83 'minlength': $localize`Password must be at least 6 characters long.`, 83 minlength: $localize`Password must be at least 6 characters long.`,
84 'maxlength': $localize`Password cannot be more than 255 characters long.` 84 maxlength: $localize`Password cannot be more than 255 characters long.`
85 } 85 }
86} 86}
87 87
88export const USER_CONFIRM_PASSWORD_VALIDATOR: BuildFormValidator = { 88export const USER_CONFIRM_PASSWORD_VALIDATOR: BuildFormValidator = {
89 VALIDATORS: [], 89 VALIDATORS: [],
90 MESSAGES: { 90 MESSAGES: {
91 'matchPassword': $localize`The new password and the confirmed password do not correspond.` 91 matchPassword: $localize`The new password and the confirmed password do not correspond.`
92 } 92 }
93} 93}
94 94
95export const USER_VIDEO_QUOTA_VALIDATOR: BuildFormValidator = { 95export const USER_VIDEO_QUOTA_VALIDATOR: BuildFormValidator = {
96 VALIDATORS: [ Validators.required, Validators.min(-1) ], 96 VALIDATORS: [ Validators.required, Validators.min(-1) ],
97 MESSAGES: { 97 MESSAGES: {
98 'required': $localize`Video quota is required.`, 98 required: $localize`Video quota is required.`,
99 'min': $localize`Quota must be greater than -1.` 99 min: $localize`Quota must be greater than -1.`
100 } 100 }
101} 101}
102export const USER_VIDEO_QUOTA_DAILY_VALIDATOR: BuildFormValidator = { 102export const USER_VIDEO_QUOTA_DAILY_VALIDATOR: BuildFormValidator = {
103 VALIDATORS: [ Validators.required, Validators.min(-1) ], 103 VALIDATORS: [ Validators.required, Validators.min(-1) ],
104 MESSAGES: { 104 MESSAGES: {
105 'required': $localize`Daily upload limit is required.`, 105 required: $localize`Daily upload limit is required.`,
106 'min': $localize`Daily upload limit must be greater than -1.` 106 min: $localize`Daily upload limit must be greater than -1.`
107 } 107 }
108} 108}
109 109
110export const USER_ROLE_VALIDATOR: BuildFormValidator = { 110export const USER_ROLE_VALIDATOR: BuildFormValidator = {
111 VALIDATORS: [ Validators.required ], 111 VALIDATORS: [ Validators.required ],
112 MESSAGES: { 112 MESSAGES: {
113 'required': $localize`User role is required.` 113 required: $localize`User role is required.`
114 } 114 }
115} 115}
116 116
@@ -122,15 +122,15 @@ export const USER_DESCRIPTION_VALIDATOR: BuildFormValidator = {
122 Validators.maxLength(1000) 122 Validators.maxLength(1000)
123 ], 123 ],
124 MESSAGES: { 124 MESSAGES: {
125 'minlength': $localize`Description must be at least 3 characters long.`, 125 minlength: $localize`Description must be at least 3 characters long.`,
126 'maxlength': $localize`Description cannot be more than 1000 characters long.` 126 maxlength: $localize`Description cannot be more than 1000 characters long.`
127 } 127 }
128} 128}
129 129
130export const USER_TERMS_VALIDATOR: BuildFormValidator = { 130export const USER_TERMS_VALIDATOR: BuildFormValidator = {
131 VALIDATORS: [ Validators.requiredTrue ], 131 VALIDATORS: [ Validators.requiredTrue ],
132 MESSAGES: { 132 MESSAGES: {
133 'required': $localize`You must agree with the instance terms in order to register on it.` 133 required: $localize`You must agree with the instance terms in order to register on it.`
134 } 134 }
135} 135}
136 136
@@ -140,8 +140,8 @@ export const USER_BAN_REASON_VALIDATOR: BuildFormValidator = {
140 Validators.maxLength(250) 140 Validators.maxLength(250)
141 ], 141 ],
142 MESSAGES: { 142 MESSAGES: {
143 'minlength': $localize`Ban reason must be at least 3 characters long.`, 143 minlength: $localize`Ban reason must be at least 3 characters long.`,
144 'maxlength': $localize`Ban reason cannot be more than 250 characters long.` 144 maxlength: $localize`Ban reason cannot be more than 250 characters long.`
145 } 145 }
146} 146}
147 147
@@ -152,9 +152,9 @@ function buildDisplayNameValidator (required: boolean) {
152 Validators.maxLength(120) 152 Validators.maxLength(120)
153 ], 153 ],
154 MESSAGES: { 154 MESSAGES: {
155 'required': $localize`Display name is required.`, 155 required: $localize`Display name is required.`,
156 'minlength': $localize`Display name must be at least 1 character long.`, 156 minlength: $localize`Display name must be at least 1 character long.`,
157 'maxlength': $localize`Display name cannot be more than 50 characters long.` 157 maxlength: $localize`Display name cannot be more than 50 characters long.`
158 } 158 }
159 } 159 }
160 160
diff --git a/client/src/app/shared/form-validators/video-block-validators.ts b/client/src/app/shared/form-validators/video-block-validators.ts
index d3974aefe..cd2791b76 100644
--- a/client/src/app/shared/form-validators/video-block-validators.ts
+++ b/client/src/app/shared/form-validators/video-block-validators.ts
@@ -4,7 +4,7 @@ import { BuildFormValidator } from './form-validator.model'
4export const VIDEO_BLOCK_REASON_VALIDATOR: BuildFormValidator = { 4export const VIDEO_BLOCK_REASON_VALIDATOR: BuildFormValidator = {
5 VALIDATORS: [ Validators.minLength(2), Validators.maxLength(300) ], 5 VALIDATORS: [ Validators.minLength(2), Validators.maxLength(300) ],
6 MESSAGES: { 6 MESSAGES: {
7 'minlength': $localize`Block reason must be at least 2 characters long.`, 7 minlength: $localize`Block reason must be at least 2 characters long.`,
8 'maxlength': $localize`Block reason cannot be more than 300 characters long.` 8 maxlength: $localize`Block reason cannot be more than 300 characters long.`
9 } 9 }
10} 10}
diff --git a/client/src/app/shared/form-validators/video-captions-validators.ts b/client/src/app/shared/form-validators/video-captions-validators.ts
index 9742d2925..a16216422 100644
--- a/client/src/app/shared/form-validators/video-captions-validators.ts
+++ b/client/src/app/shared/form-validators/video-captions-validators.ts
@@ -4,13 +4,13 @@ import { BuildFormValidator } from './form-validator.model'
4export const VIDEO_CAPTION_LANGUAGE_VALIDATOR: BuildFormValidator = { 4export const VIDEO_CAPTION_LANGUAGE_VALIDATOR: BuildFormValidator = {
5 VALIDATORS: [ Validators.required ], 5 VALIDATORS: [ Validators.required ],
6 MESSAGES: { 6 MESSAGES: {
7 'required': $localize`Video caption language is required.` 7 required: $localize`Video caption language is required.`
8 } 8 }
9} 9}
10 10
11export const VIDEO_CAPTION_FILE_VALIDATOR: BuildFormValidator = { 11export const VIDEO_CAPTION_FILE_VALIDATOR: BuildFormValidator = {
12 VALIDATORS: [ Validators.required ], 12 VALIDATORS: [ Validators.required ],
13 MESSAGES: { 13 MESSAGES: {
14 'required': $localize`Video caption file is required.` 14 required: $localize`Video caption file is required.`
15 } 15 }
16} 16}
diff --git a/client/src/app/shared/form-validators/video-channel-validators.ts b/client/src/app/shared/form-validators/video-channel-validators.ts
index ba502ed01..48f5b1a2c 100644
--- a/client/src/app/shared/form-validators/video-channel-validators.ts
+++ b/client/src/app/shared/form-validators/video-channel-validators.ts
@@ -7,10 +7,10 @@ export const VIDEO_CHANNEL_NAME_VALIDATOR: BuildFormValidator = {
7 VALIDATORS: USER_USERNAME_VALIDATOR.VALIDATORS, 7 VALIDATORS: USER_USERNAME_VALIDATOR.VALIDATORS,
8 8
9 MESSAGES: { 9 MESSAGES: {
10 'required': $localize`Name is required.`, 10 required: $localize`Name is required.`,
11 'minlength': $localize`Name must be at least 1 character long.`, 11 minlength: $localize`Name must be at least 1 character long.`,
12 'maxlength': $localize`Name cannot be more than 50 characters long.`, 12 maxlength: $localize`Name cannot be more than 50 characters long.`,
13 'pattern': $localize`Name should be lowercase alphanumeric; dots and underscores are allowed.` 13 pattern: $localize`Name should be lowercase alphanumeric; dots and underscores are allowed.`
14 } 14 }
15} 15}
16 16
@@ -21,9 +21,9 @@ export const VIDEO_CHANNEL_DISPLAY_NAME_VALIDATOR: BuildFormValidator = {
21 Validators.maxLength(50) 21 Validators.maxLength(50)
22 ], 22 ],
23 MESSAGES: { 23 MESSAGES: {
24 'required': $localize`Display name is required.`, 24 required: $localize`Display name is required.`,
25 'minlength': $localize`Display name must be at least 1 character long.`, 25 minlength: $localize`Display name must be at least 1 character long.`,
26 'maxlength': $localize`Display name cannot be more than 50 characters long.` 26 maxlength: $localize`Display name cannot be more than 50 characters long.`
27 } 27 }
28} 28}
29 29
@@ -33,8 +33,8 @@ export const VIDEO_CHANNEL_DESCRIPTION_VALIDATOR: BuildFormValidator = {
33 Validators.maxLength(1000) 33 Validators.maxLength(1000)
34 ], 34 ],
35 MESSAGES: { 35 MESSAGES: {
36 'minlength': $localize`Description must be at least 3 characters long.`, 36 minlength: $localize`Description must be at least 3 characters long.`,
37 'maxlength': $localize`Description cannot be more than 1000 characters long.` 37 maxlength: $localize`Description cannot be more than 1000 characters long.`
38 } 38 }
39} 39}
40 40
@@ -44,7 +44,7 @@ export const VIDEO_CHANNEL_SUPPORT_VALIDATOR: BuildFormValidator = {
44 Validators.maxLength(1000) 44 Validators.maxLength(1000)
45 ], 45 ],
46 MESSAGES: { 46 MESSAGES: {
47 'minlength': $localize`Support text must be at least 3 characters long.`, 47 minlength: $localize`Support text must be at least 3 characters long.`,
48 'maxlength': $localize`Support text cannot be more than 1000 characters long` 48 maxlength: $localize`Support text cannot be more than 1000 characters long`
49 } 49 }
50} 50}
diff --git a/client/src/app/shared/form-validators/video-comment-validators.ts b/client/src/app/shared/form-validators/video-comment-validators.ts
index c56564d34..9e8f95e7c 100644
--- a/client/src/app/shared/form-validators/video-comment-validators.ts
+++ b/client/src/app/shared/form-validators/video-comment-validators.ts
@@ -4,8 +4,8 @@ import { BuildFormValidator } from './form-validator.model'
4export const VIDEO_COMMENT_TEXT_VALIDATOR: BuildFormValidator = { 4export const VIDEO_COMMENT_TEXT_VALIDATOR: BuildFormValidator = {
5 VALIDATORS: [ Validators.required, Validators.minLength(1), Validators.maxLength(3000) ], 5 VALIDATORS: [ Validators.required, Validators.minLength(1), Validators.maxLength(3000) ],
6 MESSAGES: { 6 MESSAGES: {
7 'required': $localize`Comment is required.`, 7 required: $localize`Comment is required.`,
8 'minlength': $localize`Comment must be at least 2 characters long.`, 8 minlength: $localize`Comment must be at least 2 characters long.`,
9 'maxlength': $localize`Comment cannot be more than 3000 characters long.` 9 maxlength: $localize`Comment cannot be more than 3000 characters long.`
10 } 10 }
11} 11}
diff --git a/client/src/app/shared/form-validators/video-ownership-change-validators.ts b/client/src/app/shared/form-validators/video-ownership-change-validators.ts
index e1a2df8a6..3e7823c49 100644
--- a/client/src/app/shared/form-validators/video-ownership-change-validators.ts
+++ b/client/src/app/shared/form-validators/video-ownership-change-validators.ts
@@ -4,21 +4,21 @@ import { BuildFormValidator } from './form-validator.model'
4export const OWNERSHIP_CHANGE_CHANNEL_VALIDATOR: BuildFormValidator = { 4export const OWNERSHIP_CHANGE_CHANNEL_VALIDATOR: BuildFormValidator = {
5 VALIDATORS: [ Validators.required ], 5 VALIDATORS: [ Validators.required ],
6 MESSAGES: { 6 MESSAGES: {
7 'required': $localize`The channel is required.` 7 required: $localize`The channel is required.`
8 } 8 }
9} 9}
10 10
11export const OWNERSHIP_CHANGE_USERNAME_VALIDATOR: BuildFormValidator = { 11export const OWNERSHIP_CHANGE_USERNAME_VALIDATOR: BuildFormValidator = {
12 VALIDATORS: [ Validators.required, localAccountValidator ], 12 VALIDATORS: [ Validators.required, localAccountValidator ],
13 MESSAGES: { 13 MESSAGES: {
14 'required': $localize`The username is required.`, 14 required: $localize`The username is required.`,
15 'localAccountOnly': $localize`You can only transfer ownership to a local account` 15 localAccountOnly: $localize`You can only transfer ownership to a local account`
16 } 16 }
17} 17}
18 18
19function localAccountValidator (control: AbstractControl): ValidationErrors { 19function localAccountValidator (control: AbstractControl): ValidationErrors {
20 if (control.value.includes('@')) { 20 if (control.value.includes('@')) {
21 return { 'localAccountOnly': true } 21 return { localAccountOnly: true }
22 } 22 }
23 23
24 return null 24 return null
diff --git a/client/src/app/shared/form-validators/video-playlist-validators.ts b/client/src/app/shared/form-validators/video-playlist-validators.ts
index 7e3d29458..63af637a3 100644
--- a/client/src/app/shared/form-validators/video-playlist-validators.ts
+++ b/client/src/app/shared/form-validators/video-playlist-validators.ts
@@ -9,9 +9,9 @@ export const VIDEO_PLAYLIST_DISPLAY_NAME_VALIDATOR: BuildFormValidator = {
9 Validators.maxLength(120) 9 Validators.maxLength(120)
10 ], 10 ],
11 MESSAGES: { 11 MESSAGES: {
12 'required': $localize`Display name is required.`, 12 required: $localize`Display name is required.`,
13 'minlength': $localize`Display name must be at least 1 character long.`, 13 minlength: $localize`Display name must be at least 1 character long.`,
14 'maxlength': $localize`Display name cannot be more than 120 characters long.` 14 maxlength: $localize`Display name cannot be more than 120 characters long.`
15 } 15 }
16} 16}
17 17
@@ -20,7 +20,7 @@ export const VIDEO_PLAYLIST_PRIVACY_VALIDATOR: BuildFormValidator = {
20 Validators.required 20 Validators.required
21 ], 21 ],
22 MESSAGES: { 22 MESSAGES: {
23 'required': $localize`Privacy is required.` 23 required: $localize`Privacy is required.`
24 } 24 }
25} 25}
26 26
@@ -30,21 +30,21 @@ export const VIDEO_PLAYLIST_DESCRIPTION_VALIDATOR: BuildFormValidator = {
30 Validators.maxLength(1000) 30 Validators.maxLength(1000)
31 ], 31 ],
32 MESSAGES: { 32 MESSAGES: {
33 'minlength': $localize`Description must be at least 3 characters long.`, 33 minlength: $localize`Description must be at least 3 characters long.`,
34 'maxlength': $localize`Description cannot be more than 1000 characters long.` 34 maxlength: $localize`Description cannot be more than 1000 characters long.`
35 } 35 }
36} 36}
37 37
38export const VIDEO_PLAYLIST_CHANNEL_ID_VALIDATOR: BuildFormValidator = { 38export const VIDEO_PLAYLIST_CHANNEL_ID_VALIDATOR: BuildFormValidator = {
39 VALIDATORS: [], 39 VALIDATORS: [],
40 MESSAGES: { 40 MESSAGES: {
41 'required': $localize`The channel is required when the playlist is public.` 41 required: $localize`The channel is required when the playlist is public.`
42 } 42 }
43} 43}
44 44
45export function setPlaylistChannelValidator (channelControl: AbstractControl, privacy: VideoPlaylistPrivacy) { 45export function setPlaylistChannelValidator (channelControl: AbstractControl, privacy: VideoPlaylistPrivacy) {
46 if (privacy.toString() === VideoPlaylistPrivacy.PUBLIC.toString()) { 46 if (privacy.toString() === VideoPlaylistPrivacy.PUBLIC.toString()) {
47 channelControl.setValidators([Validators.required]) 47 channelControl.setValidators([ Validators.required ])
48 } else { 48 } else {
49 channelControl.setValidators(null) 49 channelControl.setValidators(null)
50 } 50 }
diff --git a/client/src/app/shared/form-validators/video-validators.ts b/client/src/app/shared/form-validators/video-validators.ts
index 1382a7747..f96189aa2 100644
--- a/client/src/app/shared/form-validators/video-validators.ts
+++ b/client/src/app/shared/form-validators/video-validators.ts
@@ -12,17 +12,17 @@ export const trimValidator: ValidatorFn = (control: FormControl) => {
12export const VIDEO_NAME_VALIDATOR: BuildFormValidator = { 12export const VIDEO_NAME_VALIDATOR: BuildFormValidator = {
13 VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(120) ], 13 VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(120) ],
14 MESSAGES: { 14 MESSAGES: {
15 'required': $localize`Video name is required.`, 15 required: $localize`Video name is required.`,
16 'minlength': $localize`Video name must be at least 3 characters long.`, 16 minlength: $localize`Video name must be at least 3 characters long.`,
17 'maxlength': $localize`Video name cannot be more than 120 characters long.`, 17 maxlength: $localize`Video name cannot be more than 120 characters long.`,
18 'spaces': $localize`Video name has leading or trailing whitespace.` 18 spaces: $localize`Video name has leading or trailing whitespace.`
19 } 19 }
20} 20}
21 21
22export const VIDEO_PRIVACY_VALIDATOR: BuildFormValidator = { 22export const VIDEO_PRIVACY_VALIDATOR: BuildFormValidator = {
23 VALIDATORS: [ Validators.required ], 23 VALIDATORS: [ Validators.required ],
24 MESSAGES: { 24 MESSAGES: {
25 'required': $localize`Video privacy is required.` 25 required: $localize`Video privacy is required.`
26 } 26 }
27} 27}
28 28
@@ -49,46 +49,46 @@ export const VIDEO_IMAGE_VALIDATOR: BuildFormValidator = {
49export const VIDEO_CHANNEL_VALIDATOR: BuildFormValidator = { 49export const VIDEO_CHANNEL_VALIDATOR: BuildFormValidator = {
50 VALIDATORS: [ Validators.required ], 50 VALIDATORS: [ Validators.required ],
51 MESSAGES: { 51 MESSAGES: {
52 'required': $localize`Video channel is required.` 52 required: $localize`Video channel is required.`
53 } 53 }
54} 54}
55 55
56export const VIDEO_DESCRIPTION_VALIDATOR: BuildFormValidator = { 56export const VIDEO_DESCRIPTION_VALIDATOR: BuildFormValidator = {
57 VALIDATORS: [ Validators.minLength(3), Validators.maxLength(10000) ], 57 VALIDATORS: [ Validators.minLength(3), Validators.maxLength(10000) ],
58 MESSAGES: { 58 MESSAGES: {
59 'minlength': $localize`Video description must be at least 3 characters long.`, 59 minlength: $localize`Video description must be at least 3 characters long.`,
60 'maxlength': $localize`Video description cannot be more than 10000 characters long.` 60 maxlength: $localize`Video description cannot be more than 10000 characters long.`
61 } 61 }
62} 62}
63 63
64export const VIDEO_TAG_VALIDATOR: BuildFormValidator = { 64export const VIDEO_TAG_VALIDATOR: BuildFormValidator = {
65 VALIDATORS: [ Validators.minLength(2), Validators.maxLength(30) ], 65 VALIDATORS: [ Validators.minLength(2), Validators.maxLength(30) ],
66 MESSAGES: { 66 MESSAGES: {
67 'minlength': $localize`A tag should be more than 2 characters long.`, 67 minlength: $localize`A tag should be more than 2 characters long.`,
68 'maxlength': $localize`A tag should be less than 30 characters long.` 68 maxlength: $localize`A tag should be less than 30 characters long.`
69 } 69 }
70} 70}
71 71
72export const VIDEO_TAGS_ARRAY_VALIDATOR: BuildFormValidator = { 72export const VIDEO_TAGS_ARRAY_VALIDATOR: BuildFormValidator = {
73 VALIDATORS: [ Validators.maxLength(5), arrayTagLengthValidator() ], 73 VALIDATORS: [ Validators.maxLength(5), arrayTagLengthValidator() ],
74 MESSAGES: { 74 MESSAGES: {
75 'maxlength': $localize`A maximum of 5 tags can be used on a video.`, 75 maxlength: $localize`A maximum of 5 tags can be used on a video.`,
76 'arrayTagLength': $localize`A tag should be more than 1 and less than 30 characters long.` 76 arrayTagLength: $localize`A tag should be more than 1 and less than 30 characters long.`
77 } 77 }
78} 78}
79 79
80export const VIDEO_SUPPORT_VALIDATOR: BuildFormValidator = { 80export const VIDEO_SUPPORT_VALIDATOR: BuildFormValidator = {
81 VALIDATORS: [ Validators.minLength(3), Validators.maxLength(1000) ], 81 VALIDATORS: [ Validators.minLength(3), Validators.maxLength(1000) ],
82 MESSAGES: { 82 MESSAGES: {
83 'minlength': $localize`Video support must be at least 3 characters long.`, 83 minlength: $localize`Video support must be at least 3 characters long.`,
84 'maxlength': $localize`Video support cannot be more than 1000 characters long.` 84 maxlength: $localize`Video support cannot be more than 1000 characters long.`
85 } 85 }
86} 86}
87 87
88export const VIDEO_SCHEDULE_PUBLICATION_AT_VALIDATOR: BuildFormValidator = { 88export const VIDEO_SCHEDULE_PUBLICATION_AT_VALIDATOR: BuildFormValidator = {
89 VALIDATORS: [ ], 89 VALIDATORS: [ ],
90 MESSAGES: { 90 MESSAGES: {
91 'required': $localize`A date is required to schedule video update.` 91 required: $localize`A date is required to schedule video update.`
92 } 92 }
93} 93}
94 94
@@ -105,6 +105,6 @@ function arrayTagLengthValidator (min = 2, max = 30): ValidatorFn {
105 return null 105 return null
106 } 106 }
107 107
108 return { 'arrayTagLength': true } 108 return { arrayTagLength: true }
109 } 109 }
110} 110}
diff --git a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
index e3bf9e1fb..33e9fd8de 100644
--- a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
+++ b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts
@@ -39,23 +39,23 @@ export class AbuseListTableComponent extends RestTable implements OnInit {
39 39
40 inputFilters: AdvancedInputFilter[] = [ 40 inputFilters: AdvancedInputFilter[] = [
41 { 41 {
42 queryParams: { 'search': 'state:pending' }, 42 queryParams: { search: 'state:pending' },
43 label: $localize`Unsolved reports` 43 label: $localize`Unsolved reports`
44 }, 44 },
45 { 45 {
46 queryParams: { 'search': 'state:accepted' }, 46 queryParams: { search: 'state:accepted' },
47 label: $localize`Accepted reports` 47 label: $localize`Accepted reports`
48 }, 48 },
49 { 49 {
50 queryParams: { 'search': 'state:rejected' }, 50 queryParams: { search: 'state:rejected' },
51 label: $localize`Refused reports` 51 label: $localize`Refused reports`
52 }, 52 },
53 { 53 {
54 queryParams: { 'search': 'videoIs:blacklisted' }, 54 queryParams: { search: 'videoIs:blacklisted' },
55 label: $localize`Reports with blocked videos` 55 label: $localize`Reports with blocked videos`
56 }, 56 },
57 { 57 {
58 queryParams: { 'search': 'videoIs:deleted' }, 58 queryParams: { search: 'videoIs:deleted' },
59 label: $localize`Reports with deleted videos` 59 label: $localize`Reports with deleted videos`
60 } 60 }
61 ] 61 ]
diff --git a/client/src/app/shared/shared-abuse-list/moderation-comment-modal.component.ts b/client/src/app/shared/shared-abuse-list/moderation-comment-modal.component.ts
index 06f1555ea..ccb0c5262 100644
--- a/client/src/app/shared/shared-abuse-list/moderation-comment-modal.component.ts
+++ b/client/src/app/shared/shared-abuse-list/moderation-comment-modal.component.ts
@@ -50,7 +50,7 @@ export class ModerationCommentModalComponent extends FormReactive implements OnI
50 } 50 }
51 51
52 async banUser () { 52 async banUser () {
53 const moderationComment: string = this.form.value[ 'moderationComment' ] 53 const moderationComment: string = this.form.value['moderationComment']
54 54
55 this.abuseService.updateAbuse(this.abuseToComment, { moderationComment }) 55 this.abuseService.updateAbuse(this.abuseToComment, { moderationComment })
56 .subscribe({ 56 .subscribe({
diff --git a/client/src/app/shared/shared-abuse-list/processed-abuse.model.ts b/client/src/app/shared/shared-abuse-list/processed-abuse.model.ts
index fce1a8db3..194d52a33 100644
--- a/client/src/app/shared/shared-abuse-list/processed-abuse.model.ts
+++ b/client/src/app/shared/shared-abuse-list/processed-abuse.model.ts
@@ -5,7 +5,7 @@ import { Account } from '@app/shared/shared-main'
5// Don't use an abuse model because we need external services to compute some properties 5// Don't use an abuse model because we need external services to compute some properties
6// And this model is only used in this component 6// And this model is only used in this component
7export type ProcessedAbuse = AdminAbuse & { 7export type ProcessedAbuse = AdminAbuse & {
8 moderationCommentHtml?: string, 8 moderationCommentHtml?: string
9 reasonHtml?: string 9 reasonHtml?: string
10 embedHtml?: SafeHtml 10 embedHtml?: SafeHtml
11 updatedAt?: Date 11 updatedAt?: Date
diff --git a/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts b/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts
index dc9b72ddb..2c0e45e20 100644
--- a/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts
+++ b/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts
@@ -51,7 +51,7 @@ export class ActorAvatarEditComponent implements OnInit {
51 onAvatarChange (input: HTMLInputElement) { 51 onAvatarChange (input: HTMLInputElement) {
52 this.avatarfileInput = new ElementRef(input) 52 this.avatarfileInput = new ElementRef(input)
53 53
54 const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ] 54 const avatarfile = this.avatarfileInput.nativeElement.files[0]
55 if (avatarfile.size > this.maxAvatarSize) { 55 if (avatarfile.size > this.maxAvatarSize) {
56 this.notifier.error('Error', $localize`This image is too large.`) 56 this.notifier.error('Error', $localize`This image is too large.`)
57 return 57 return
diff --git a/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts b/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts
index c3f10c055..cba2c5db3 100644
--- a/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts
+++ b/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts
@@ -40,14 +40,14 @@ export class ActorBannerEditComponent implements OnInit {
40 this.maxBannerSize = config.banner.file.size.max 40 this.maxBannerSize = config.banner.file.size.max
41 this.bannerExtensions = config.banner.file.extensions.join(', ') 41 this.bannerExtensions = config.banner.file.extensions.join(', ')
42 42
43 // tslint:disable:max-line-length 43 /* eslint-disable max-len */
44 this.bannerFormat = $localize`ratio 6/1, recommended size: 1920x317, max size: ${getBytes(this.maxBannerSize)}, extensions: ${this.bannerExtensions}` 44 this.bannerFormat = $localize`ratio 6/1, recommended size: 1920x317, max size: ${getBytes(this.maxBannerSize)}, extensions: ${this.bannerExtensions}`
45 } 45 }
46 46
47 onBannerChange (input: HTMLInputElement) { 47 onBannerChange (input: HTMLInputElement) {
48 this.bannerfileInput = new ElementRef(input) 48 this.bannerfileInput = new ElementRef(input)
49 49
50 const bannerfile = this.bannerfileInput.nativeElement.files[ 0 ] 50 const bannerfile = this.bannerfileInput.nativeElement.files[0]
51 if (bannerfile.size > this.maxBannerSize) { 51 if (bannerfile.size > this.maxBannerSize) {
52 this.notifier.error('Error', $localize`This image is too large.`) 52 this.notifier.error('Error', $localize`This image is too large.`)
53 return 53 return
diff --git a/client/src/app/shared/shared-actor-image/actor-avatar.component.ts b/client/src/app/shared/shared-actor-image/actor-avatar.component.ts
index b06c2bae6..a4adfd1b7 100644
--- a/client/src/app/shared/shared-actor-image/actor-avatar.component.ts
+++ b/client/src/app/shared/shared-actor-image/actor-avatar.component.ts
@@ -17,6 +17,8 @@ export type ActorAvatarSize = '18' | '25' | '32' | '34' | '36' | '40' | '100' |
17 templateUrl: './actor-avatar.component.html' 17 templateUrl: './actor-avatar.component.html'
18}) 18})
19export class ActorAvatarComponent { 19export class ActorAvatarComponent {
20 private _title: string
21
20 @Input() account: ActorInput 22 @Input() account: ActorInput
21 @Input() channel: ActorInput 23 @Input() channel: ActorInput
22 24
@@ -33,8 +35,6 @@ export class ActorAvatarComponent {
33 this._title = value 35 this._title = value
34 } 36 }
35 37
36 private _title: string
37
38 get title () { 38 get title () {
39 if (this._title) return this._title 39 if (this._title) return this._title
40 if (this.account) return $localize`${this.account.name} (account page)` 40 if (this.account) return $localize`${this.account.name} (account page)`
@@ -50,22 +50,6 @@ export class ActorAvatarComponent {
50 return '' 50 return ''
51 } 51 }
52 52
53 getClass (type: 'avatar' | 'initial') {
54 const base = [ 'avatar' ]
55
56 if (this.size) base.push(`avatar-${this.size}`)
57
58 if (this.channel) base.push('channel')
59 else base.push('account')
60
61 if (type === 'initial' && this.initial) {
62 base.push('initial')
63 base.push(this.getColorTheme())
64 }
65
66 return base
67 }
68
69 get defaultAvatarUrl () { 53 get defaultAvatarUrl () {
70 if (this.channel) return VideoChannel.GET_DEFAULT_AVATAR_URL() 54 if (this.channel) return VideoChannel.GET_DEFAULT_AVATAR_URL()
71 55
@@ -86,6 +70,22 @@ export class ActorAvatarComponent {
86 return name.slice(0, 1) 70 return name.slice(0, 1)
87 } 71 }
88 72
73 getClass (type: 'avatar' | 'initial') {
74 const base = [ 'avatar' ]
75
76 if (this.size) base.push(`avatar-${this.size}`)
77
78 if (this.channel) base.push('channel')
79 else base.push('account')
80
81 if (type === 'initial' && this.initial) {
82 base.push('initial')
83 base.push(this.getColorTheme())
84 }
85
86 return base
87 }
88
89 hasActor () { 89 hasActor () {
90 return !!this.account || !!this.channel 90 return !!this.account || !!this.channel
91 } 91 }
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts
index 8c1357d7a..35b413b60 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts
@@ -39,9 +39,13 @@ export class ChannelMiniatureMarkupComponent implements CustomMarkupComponent, O
39 ngOnInit () { 39 ngOnInit () {
40 this.findInBulk.getChannel(this.name) 40 this.findInBulk.getChannel(this.name)
41 .pipe( 41 .pipe(
42 tap(channel => this.channel = channel), 42 tap(channel => {
43 this.channel = channel
44 }),
43 switchMap(() => from(this.markdown.textMarkdownToHTML(this.channel.description))), 45 switchMap(() => from(this.markdown.textMarkdownToHTML(this.channel.description))),
44 tap(html => this.descriptionHTML = html), 46 tap(html => {
47 this.descriptionHTML = html
48 }),
45 switchMap(() => this.loadVideosObservable()), 49 switchMap(() => this.loadVideosObservable()),
46 finalize(() => this.loaded.emit(true)) 50 finalize(() => this.loaded.emit(true))
47 ).subscribe({ 51 ).subscribe({
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts
index 56b43d85e..7315126e0 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts
@@ -1,10 +1,10 @@
1import { finalize } from 'rxjs/operators' 1import { finalize } from 'rxjs/operators'
2import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core' 2import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
3import { AuthService, Notifier } from '@app/core' 3import { AuthService, Notifier } from '@app/core'
4import { Video, VideoService } from '../../shared-main' 4import { FindInBulkService } from '@app/shared/shared-search'
5import { Video } from '../../shared-main'
5import { MiniatureDisplayOptions } from '../../shared-video-miniature' 6import { MiniatureDisplayOptions } from '../../shared-video-miniature'
6import { CustomMarkupComponent } from './shared' 7import { CustomMarkupComponent } from './shared'
7import { FindInBulkService } from '@app/shared/shared-search'
8 8
9/* 9/*
10 * Markup component that creates a video miniature only 10 * Markup component that creates a video miniature only
diff --git a/client/src/app/shared/shared-forms/form-reactive.ts b/client/src/app/shared/shared-forms/form-reactive.ts
index adf6cb894..f2ce82360 100644
--- a/client/src/app/shared/shared-forms/form-reactive.ts
+++ b/client/src/app/shared/shared-forms/form-reactive.ts
@@ -51,7 +51,7 @@ export abstract class FormReactive {
51 } 51 }
52 52
53 // clear previous error message (if any) 53 // clear previous error message (if any)
54 formErrors[ field ] = '' 54 formErrors[field] = ''
55 const control = form.get(field) 55 const control = form.get(field)
56 56
57 if (control.dirty) this.formChanged = true 57 if (control.dirty) this.formChanged = true
@@ -59,9 +59,9 @@ export abstract class FormReactive {
59 // Don't care if dirty on force check 59 // Don't care if dirty on force check
60 const isDirty = control.dirty || forceCheck === true 60 const isDirty = control.dirty || forceCheck === true
61 if (control && isDirty && control.enabled && !control.valid) { 61 if (control && isDirty && control.enabled && !control.valid) {
62 const messages = validationMessages[ field ] 62 const messages = validationMessages[field]
63 for (const key of Object.keys(control.errors)) { 63 for (const key of Object.keys(control.errors)) {
64 formErrors[ field ] += messages[ key ] + ' ' 64 formErrors[field] += messages[key] + ' '
65 } 65 }
66 } 66 }
67 } 67 }
diff --git a/client/src/app/shared/shared-forms/form-validator.service.ts b/client/src/app/shared/shared-forms/form-validator.service.ts
index 41c8b76bd..c0664de5f 100644
--- a/client/src/app/shared/shared-forms/form-validator.service.ts
+++ b/client/src/app/shared/shared-forms/form-validator.service.ts
@@ -28,11 +28,11 @@ export class FormValidatorService {
28 continue 28 continue
29 } 29 }
30 30
31 if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string } 31 if (field?.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string }
32 32
33 const defaultValue = defaultValues[name] || '' 33 const defaultValue = defaultValues[name] || ''
34 34
35 if (field && field.VALIDATORS) group[name] = [ defaultValue, field.VALIDATORS ] 35 if (field?.VALIDATORS) group[name] = [ defaultValue, field.VALIDATORS ]
36 else group[name] = [ defaultValue ] 36 else group[name] = [ defaultValue ]
37 } 37 }
38 38
@@ -62,11 +62,11 @@ export class FormValidatorService {
62 continue 62 continue
63 } 63 }
64 64
65 if (field && field.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string } 65 if (field?.MESSAGES) validationMessages[name] = field.MESSAGES as { [ name: string ]: string }
66 66
67 const defaultValue = defaultValues[name] || '' 67 const defaultValue = defaultValues[name] || ''
68 68
69 if (field && field.VALIDATORS) form.addControl(name, new FormControl(defaultValue, field.VALIDATORS as ValidatorFn[])) 69 if (field?.VALIDATORS) form.addControl(name, new FormControl(defaultValue, field.VALIDATORS as ValidatorFn[]))
70 else form.addControl(name, new FormControl(defaultValue)) 70 else form.addControl(name, new FormControl(defaultValue))
71 } 71 }
72 } 72 }
diff --git a/client/src/app/shared/shared-forms/reactive-file.component.ts b/client/src/app/shared/shared-forms/reactive-file.component.ts
index fac3dfb3a..9d27ad07a 100644
--- a/client/src/app/shared/shared-forms/reactive-file.component.ts
+++ b/client/src/app/shared/shared-forms/reactive-file.component.ts
@@ -43,7 +43,7 @@ export class ReactiveFileComponent implements OnInit, ControlValueAccessor {
43 } 43 }
44 44
45 fileChange (event: any) { 45 fileChange (event: any) {
46 if (event.target.files && event.target.files.length) { 46 if (event.target.files?.length) {
47 const [ file ] = event.target.files 47 const [ file ] = event.target.files
48 48
49 if (file.size > this.maxFileSize) { 49 if (file.size > this.maxFileSize) {
diff --git a/client/src/app/shared/shared-icons/global-icon.component.ts b/client/src/app/shared/shared-icons/global-icon.component.ts
index a47f07fc3..cb5f31c8e 100644
--- a/client/src/app/shared/shared-icons/global-icon.component.ts
+++ b/client/src/app/shared/shared-icons/global-icon.component.ts
@@ -3,77 +3,77 @@ import { HooksService } from '@app/core/plugins/hooks.service'
3 3
4const icons = { 4const icons = {
5 // misc icons 5 // misc icons
6 'npm': require('!!raw-loader?!../../../assets/images/misc/npm.svg').default, 6 npm: require('!!raw-loader?!../../../assets/images/misc/npm.svg').default,
7 'markdown': require('!!raw-loader?!../../../assets/images/misc/markdown.svg').default, 7 markdown: require('!!raw-loader?!../../../assets/images/misc/markdown.svg').default,
8 'language': require('!!raw-loader?!../../../assets/images/misc/language.svg').default, 8 language: require('!!raw-loader?!../../../assets/images/misc/language.svg').default,
9 'video-lang': require('!!raw-loader?!../../../assets/images/misc/video-lang.svg').default, 9 'video-lang': require('!!raw-loader?!../../../assets/images/misc/video-lang.svg').default,
10 'support': require('!!raw-loader?!../../../assets/images/misc/support.svg').default, 10 support: require('!!raw-loader?!../../../assets/images/misc/support.svg').default,
11 'peertube-x': require('!!raw-loader?!../../../assets/images/misc/peertube-x.svg').default, 11 'peertube-x': require('!!raw-loader?!../../../assets/images/misc/peertube-x.svg').default,
12 'robot': require('!!raw-loader?!../../../assets/images/misc/miscellaneous-services.svg').default, // material ui 12 robot: require('!!raw-loader?!../../../assets/images/misc/miscellaneous-services.svg').default, // material ui
13 'videos': require('!!raw-loader?!../../../assets/images/misc/video-library.svg').default, // material ui 13 videos: require('!!raw-loader?!../../../assets/images/misc/video-library.svg').default, // material ui
14 'history': require('!!raw-loader?!../../../assets/images/misc/history.svg').default, // material ui 14 history: require('!!raw-loader?!../../../assets/images/misc/history.svg').default, // material ui
15 'subscriptions': require('!!raw-loader?!../../../assets/images/misc/subscriptions.svg').default, // material ui 15 subscriptions: require('!!raw-loader?!../../../assets/images/misc/subscriptions.svg').default, // material ui
16 'playlist-add': require('!!raw-loader?!../../../assets/images/misc/playlist-add.svg').default, // material ui 16 'playlist-add': require('!!raw-loader?!../../../assets/images/misc/playlist-add.svg').default, // material ui
17 'follower': require('!!raw-loader?!../../../assets/images/misc/account-arrow-left.svg').default, // material ui 17 follower: require('!!raw-loader?!../../../assets/images/misc/account-arrow-left.svg').default, // material ui
18 'following': require('!!raw-loader?!../../../assets/images/misc/account-arrow-right.svg').default, // material ui 18 following: require('!!raw-loader?!../../../assets/images/misc/account-arrow-right.svg').default, // material ui
19 'flame': require('!!raw-loader?!../../../assets/images/misc/flame.svg').default, 19 flame: require('!!raw-loader?!../../../assets/images/misc/flame.svg').default,
20 'local': require('!!raw-loader?!../../../assets/images/misc/local.svg').default, 20 local: require('!!raw-loader?!../../../assets/images/misc/local.svg').default,
21 21
22 // feather icons 22 // feather icons
23 'flag': require('!!raw-loader?!../../../assets/images/feather/flag.svg').default, 23 flag: require('!!raw-loader?!../../../assets/images/feather/flag.svg').default,
24 'playlists': require('!!raw-loader?!../../../assets/images/feather/list.svg').default, 24 playlists: require('!!raw-loader?!../../../assets/images/feather/list.svg').default,
25 'syndication': require('!!raw-loader?!../../../assets/images/feather/syndication.svg').default, 25 syndication: require('!!raw-loader?!../../../assets/images/feather/syndication.svg').default,
26 'help': require('!!raw-loader?!../../../assets/images/feather/help.svg').default, 26 help: require('!!raw-loader?!../../../assets/images/feather/help.svg').default,
27 'alert': require('!!raw-loader?!../../../assets/images/feather/alert.svg').default, 27 alert: require('!!raw-loader?!../../../assets/images/feather/alert.svg').default,
28 'globe': require('!!raw-loader?!../../../assets/images/feather/globe.svg').default, 28 globe: require('!!raw-loader?!../../../assets/images/feather/globe.svg').default,
29 'home': require('!!raw-loader?!../../../assets/images/feather/home.svg').default, 29 home: require('!!raw-loader?!../../../assets/images/feather/home.svg').default,
30 'recently-added': require('!!raw-loader?!../../../assets/images/feather/recently-added.svg').default, 30 'recently-added': require('!!raw-loader?!../../../assets/images/feather/recently-added.svg').default,
31 'trending': require('!!raw-loader?!../../../assets/images/feather/trending.svg').default, 31 trending: require('!!raw-loader?!../../../assets/images/feather/trending.svg').default,
32 'search': require('!!raw-loader?!../../../assets/images/feather/search.svg').default, 32 search: require('!!raw-loader?!../../../assets/images/feather/search.svg').default,
33 'upload': require('!!raw-loader?!../../../assets/images/feather/upload.svg').default, 33 upload: require('!!raw-loader?!../../../assets/images/feather/upload.svg').default,
34 'dislike': require('!!raw-loader?!../../../assets/images/feather/dislike.svg').default, 34 dislike: require('!!raw-loader?!../../../assets/images/feather/dislike.svg').default,
35 'like': require('!!raw-loader?!../../../assets/images/feather/like.svg').default, 35 like: require('!!raw-loader?!../../../assets/images/feather/like.svg').default,
36 'no': require('!!raw-loader?!../../../assets/images/feather/no.svg').default, 36 no: require('!!raw-loader?!../../../assets/images/feather/no.svg').default,
37 'cloud-download': require('!!raw-loader?!../../../assets/images/feather/cloud-download.svg').default, 37 'cloud-download': require('!!raw-loader?!../../../assets/images/feather/cloud-download.svg').default,
38 'clock': require('!!raw-loader?!../../../assets/images/feather/clock.svg').default, 38 clock: require('!!raw-loader?!../../../assets/images/feather/clock.svg').default,
39 'cog': require('!!raw-loader?!../../../assets/images/feather/cog.svg').default, 39 cog: require('!!raw-loader?!../../../assets/images/feather/cog.svg').default,
40 'delete': require('!!raw-loader?!../../../assets/images/feather/delete.svg').default, 40 delete: require('!!raw-loader?!../../../assets/images/feather/delete.svg').default,
41 'bell': require('!!raw-loader?!../../../assets/images/feather/bell.svg').default, 41 bell: require('!!raw-loader?!../../../assets/images/feather/bell.svg').default,
42 'sign-out': require('!!raw-loader?!../../../assets/images/feather/log-out.svg').default, 42 'sign-out': require('!!raw-loader?!../../../assets/images/feather/log-out.svg').default,
43 'sign-in': require('!!raw-loader?!../../../assets/images/feather/log-in.svg').default, 43 'sign-in': require('!!raw-loader?!../../../assets/images/feather/log-in.svg').default,
44 'download': require('!!raw-loader?!../../../assets/images/feather/download.svg').default, 44 download: require('!!raw-loader?!../../../assets/images/feather/download.svg').default,
45 'ownership-change': require('!!raw-loader?!../../../assets/images/feather/share.svg').default, 45 'ownership-change': require('!!raw-loader?!../../../assets/images/feather/share.svg').default,
46 'share': require('!!raw-loader?!../../../assets/images/feather/share-2.svg').default, 46 share: require('!!raw-loader?!../../../assets/images/feather/share-2.svg').default,
47 'channel': require('!!raw-loader?!../../../assets/images/feather/tv.svg').default, 47 channel: require('!!raw-loader?!../../../assets/images/feather/tv.svg').default,
48 'user': require('!!raw-loader?!../../../assets/images/feather/user.svg').default, 48 user: require('!!raw-loader?!../../../assets/images/feather/user.svg').default,
49 'user-x': require('!!raw-loader?!../../../assets/images/feather/user-x.svg').default, 49 'user-x': require('!!raw-loader?!../../../assets/images/feather/user-x.svg').default,
50 'users': require('!!raw-loader?!../../../assets/images/feather/users.svg').default, 50 users: require('!!raw-loader?!../../../assets/images/feather/users.svg').default,
51 'user-add': require('!!raw-loader?!../../../assets/images/feather/user-plus.svg').default, 51 'user-add': require('!!raw-loader?!../../../assets/images/feather/user-plus.svg').default,
52 'add': require('!!raw-loader?!../../../assets/images/feather/plus-circle.svg').default, 52 add: require('!!raw-loader?!../../../assets/images/feather/plus-circle.svg').default,
53 'cloud-error': require('!!raw-loader?!../../../assets/images/feather/cloud-off.svg').default, 53 'cloud-error': require('!!raw-loader?!../../../assets/images/feather/cloud-off.svg').default,
54 'undo': require('!!raw-loader?!../../../assets/images/feather/corner-up-left.svg').default, 54 undo: require('!!raw-loader?!../../../assets/images/feather/corner-up-left.svg').default,
55 'circle-tick': require('!!raw-loader?!../../../assets/images/feather/check-circle.svg').default, 55 'circle-tick': require('!!raw-loader?!../../../assets/images/feather/check-circle.svg').default,
56 'more-horizontal': require('!!raw-loader?!../../../assets/images/feather/more-horizontal.svg').default, 56 'more-horizontal': require('!!raw-loader?!../../../assets/images/feather/more-horizontal.svg').default,
57 'more-vertical': require('!!raw-loader?!../../../assets/images/feather/more-vertical.svg').default, 57 'more-vertical': require('!!raw-loader?!../../../assets/images/feather/more-vertical.svg').default,
58 'play': require('!!raw-loader?!../../../assets/images/feather/play.svg').default, 58 play: require('!!raw-loader?!../../../assets/images/feather/play.svg').default,
59 'p2p': require('!!raw-loader?!../../../assets/images/feather/airplay.svg').default, 59 p2p: require('!!raw-loader?!../../../assets/images/feather/airplay.svg').default,
60 'fullscreen': require('!!raw-loader?!../../../assets/images/feather/maximize.svg').default, 60 fullscreen: require('!!raw-loader?!../../../assets/images/feather/maximize.svg').default,
61 'exit-fullscreen': require('!!raw-loader?!../../../assets/images/feather/minimize.svg').default, 61 'exit-fullscreen': require('!!raw-loader?!../../../assets/images/feather/minimize.svg').default,
62 'film': require('!!raw-loader?!../../../assets/images/feather/film.svg').default, 62 film: require('!!raw-loader?!../../../assets/images/feather/film.svg').default,
63 'edit': require('!!raw-loader?!../../../assets/images/feather/edit-2.svg').default, 63 edit: require('!!raw-loader?!../../../assets/images/feather/edit-2.svg').default,
64 'sensitive': require('!!raw-loader?!../../../assets/images/feather/eye.svg').default, 64 sensitive: require('!!raw-loader?!../../../assets/images/feather/eye.svg').default,
65 'unsensitive': require('!!raw-loader?!../../../assets/images/feather/eye-off.svg').default, 65 unsensitive: require('!!raw-loader?!../../../assets/images/feather/eye-off.svg').default,
66 'refresh': require('!!raw-loader?!../../../assets/images/feather/refresh-cw.svg').default, 66 refresh: require('!!raw-loader?!../../../assets/images/feather/refresh-cw.svg').default,
67 'command': require('!!raw-loader?!../../../assets/images/feather/command.svg').default, 67 command: require('!!raw-loader?!../../../assets/images/feather/command.svg').default,
68 'go': require('!!raw-loader?!../../../assets/images/feather/arrow-up-right.svg').default, 68 go: require('!!raw-loader?!../../../assets/images/feather/arrow-up-right.svg').default,
69 'cross': require('!!raw-loader?!../../../assets/images/feather/x.svg').default, 69 cross: require('!!raw-loader?!../../../assets/images/feather/x.svg').default,
70 'tick': require('!!raw-loader?!../../../assets/images/feather/check.svg').default, 70 tick: require('!!raw-loader?!../../../assets/images/feather/check.svg').default,
71 'columns': require('!!raw-loader?!../../../assets/images/feather/columns.svg').default, 71 columns: require('!!raw-loader?!../../../assets/images/feather/columns.svg').default,
72 'live': require('!!raw-loader?!../../../assets/images/feather/live.svg').default, 72 live: require('!!raw-loader?!../../../assets/images/feather/live.svg').default,
73 'repeat': require('!!raw-loader?!../../../assets/images/feather/repeat.svg').default, 73 repeat: require('!!raw-loader?!../../../assets/images/feather/repeat.svg').default,
74 'message-circle': require('!!raw-loader?!../../../assets/images/feather/message-circle.svg').default, 74 'message-circle': require('!!raw-loader?!../../../assets/images/feather/message-circle.svg').default,
75 'codesandbox': require('!!raw-loader?!../../../assets/images/feather/codesandbox.svg').default, 75 codesandbox: require('!!raw-loader?!../../../assets/images/feather/codesandbox.svg').default,
76 'award': require('!!raw-loader?!../../../assets/images/feather/award.svg').default 76 award: require('!!raw-loader?!../../../assets/images/feather/award.svg').default
77} 77}
78 78
79export type GlobalIconName = keyof typeof icons 79export type GlobalIconName = keyof typeof icons
diff --git a/client/src/app/shared/shared-instance/instance-about-accordion.component.ts b/client/src/app/shared/shared-instance/instance-about-accordion.component.ts
index 855c06aa1..1eb7b49b6 100644
--- a/client/src/app/shared/shared-instance/instance-about-accordion.component.ts
+++ b/client/src/app/shared/shared-instance/instance-about-accordion.component.ts
@@ -7,7 +7,7 @@ import { About } from '@shared/models/server'
7@Component({ 7@Component({
8 selector: 'my-instance-about-accordion', 8 selector: 'my-instance-about-accordion',
9 templateUrl: './instance-about-accordion.component.html', 9 templateUrl: './instance-about-accordion.component.html',
10 styleUrls: ['./instance-about-accordion.component.scss'] 10 styleUrls: [ './instance-about-accordion.component.scss' ]
11}) 11})
12export class InstanceAboutAccordionComponent implements OnInit { 12export class InstanceAboutAccordionComponent implements OnInit {
13 @ViewChild('accordion', { static: true }) accordion: NgbAccordion 13 @ViewChild('accordion', { static: true }) accordion: NgbAccordion
diff --git a/client/src/app/shared/shared-instance/instance-follow.service.ts b/client/src/app/shared/shared-instance/instance-follow.service.ts
index af44020cf..a6799d3e1 100644
--- a/client/src/app/shared/shared-instance/instance-follow.service.ts
+++ b/client/src/app/shared/shared-instance/instance-follow.service.ts
@@ -19,10 +19,10 @@ export class InstanceFollowService {
19 } 19 }
20 20
21 getFollowing (options: { 21 getFollowing (options: {
22 pagination: RestPagination, 22 pagination: RestPagination
23 sort: SortMeta, 23 sort: SortMeta
24 search?: string, 24 search?: string
25 actorType?: ActivityPubActorType, 25 actorType?: ActivityPubActorType
26 state?: FollowState 26 state?: FollowState
27 }): Observable<ResultList<ActorFollow>> { 27 }): Observable<ResultList<ActorFollow>> {
28 const { pagination, sort, search, state, actorType } = options 28 const { pagination, sort, search, state, actorType } = options
@@ -42,10 +42,10 @@ export class InstanceFollowService {
42 } 42 }
43 43
44 getFollowers (options: { 44 getFollowers (options: {
45 pagination: RestPagination, 45 pagination: RestPagination
46 sort: SortMeta, 46 sort: SortMeta
47 search?: string, 47 search?: string
48 actorType?: ActivityPubActorType, 48 actorType?: ActivityPubActorType
49 state?: FollowState 49 state?: FollowState
50 }): Observable<ResultList<ActorFollow>> { 50 }): Observable<ResultList<ActorFollow>> {
51 const { pagination, sort, search, state, actorType } = options 51 const { pagination, sort, search, state, actorType } = options
diff --git a/client/src/app/shared/shared-instance/instance-statistics.component.ts b/client/src/app/shared/shared-instance/instance-statistics.component.ts
index 40aa8a4c0..0618efe69 100644
--- a/client/src/app/shared/shared-instance/instance-statistics.component.ts
+++ b/client/src/app/shared/shared-instance/instance-statistics.component.ts
@@ -17,6 +17,8 @@ export class InstanceStatisticsComponent implements OnInit {
17 17
18 ngOnInit () { 18 ngOnInit () {
19 this.serverService.getServerStats() 19 this.serverService.getServerStats()
20 .subscribe(res => this.serverStats = res) 20 .subscribe(res => {
21 this.serverStats = res
22 })
21 } 23 }
22} 24}
diff --git a/client/src/app/shared/shared-instance/instance.service.ts b/client/src/app/shared/shared-instance/instance.service.ts
index 70e022178..0241f56ef 100644
--- a/client/src/app/shared/shared-instance/instance.service.ts
+++ b/client/src/app/shared/shared-instance/instance.service.ts
@@ -51,7 +51,7 @@ export class InstanceService {
51 } 51 }
52 52
53 for (const key of Object.keys(html)) { 53 for (const key of Object.keys(html)) {
54 html[ key ] = await this.markdownService.textMarkdownToHTML(about.instance[ key ]) 54 html[key] = await this.markdownService.textMarkdownToHTML(about.instance[key])
55 } 55 }
56 56
57 return html 57 return html
diff --git a/client/src/app/shared/shared-instance/shared-instance.module.ts b/client/src/app/shared/shared-instance/shared-instance.module.ts
index 5efb95a7d..13c681ab8 100644
--- a/client/src/app/shared/shared-instance/shared-instance.module.ts
+++ b/client/src/app/shared/shared-instance/shared-instance.module.ts
@@ -1,7 +1,6 @@
1 1
2import { NgModule } from '@angular/core' 2import { NgModule } from '@angular/core'
3import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap' 3import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap'
4import { SharedCustomMarkupModule } from '../shared-custom-markup'
5import { SharedMainModule } from '../shared-main/shared-main.module' 4import { SharedMainModule } from '../shared-main/shared-main.module'
6import { FeatureBooleanComponent } from './feature-boolean.component' 5import { FeatureBooleanComponent } from './feature-boolean.component'
7import { InstanceAboutAccordionComponent } from './instance-about-accordion.component' 6import { InstanceAboutAccordionComponent } from './instance-about-accordion.component'
diff --git a/client/src/app/shared/shared-main/account/account.model.ts b/client/src/app/shared/shared-main/account/account.model.ts
index 7b5611f35..92606e7fa 100644
--- a/client/src/app/shared/shared-main/account/account.model.ts
+++ b/client/src/app/shared/shared-main/account/account.model.ts
@@ -1,4 +1,4 @@
1import { Account as ServerAccount, Actor as ServerActor, ActorImage } from '@shared/models' 1import { Account as ServerAccount, ActorImage } from '@shared/models'
2import { Actor } from './actor.model' 2import { Actor } from './actor.model'
3 3
4export class Account extends Actor implements ServerAccount { 4export class Account extends Actor implements ServerAccount {
diff --git a/client/src/app/shared/shared-main/account/actor.model.ts b/client/src/app/shared/shared-main/account/actor.model.ts
index 2fccc472a..082f44fb9 100644
--- a/client/src/app/shared/shared-main/account/actor.model.ts
+++ b/client/src/app/shared/shared-main/account/actor.model.ts
@@ -20,7 +20,7 @@ export abstract class Actor implements ServerActor {
20 static GET_ACTOR_AVATAR_URL (actor: { avatar?: { url?: string, path: string } }) { 20 static GET_ACTOR_AVATAR_URL (actor: { avatar?: { url?: string, path: string } }) {
21 if (actor?.avatar?.url) return actor.avatar.url 21 if (actor?.avatar?.url) return actor.avatar.url
22 22
23 if (actor && actor.avatar) { 23 if (actor?.avatar) {
24 const absoluteAPIUrl = getAbsoluteAPIUrl() 24 const absoluteAPIUrl = getAbsoluteAPIUrl()
25 25
26 return absoluteAPIUrl + actor.avatar.path 26 return absoluteAPIUrl + actor.avatar.path
diff --git a/client/src/app/shared/shared-main/angular/autofocus.directive.ts b/client/src/app/shared/shared-main/angular/autofocus.directive.ts
index 5f087d79d..2da492ea1 100644
--- a/client/src/app/shared/shared-main/angular/autofocus.directive.ts
+++ b/client/src/app/shared/shared-main/angular/autofocus.directive.ts
@@ -1,7 +1,7 @@
1import { AfterViewInit, Directive, ElementRef } from '@angular/core' 1import { AfterViewInit, Directive, ElementRef } from '@angular/core'
2 2
3@Directive({ 3@Directive({
4 selector: '[autofocus]' 4 selector: '[myAutofocus]'
5}) 5})
6export class AutofocusDirective implements AfterViewInit { 6export class AutofocusDirective implements AfterViewInit {
7 constructor (private host: ElementRef) { } 7 constructor (private host: ElementRef) { }
diff --git a/client/src/app/shared/shared-main/angular/link.component.ts b/client/src/app/shared/shared-main/angular/link.component.ts
index 597a16871..ecbd9151c 100644
--- a/client/src/app/shared/shared-main/angular/link.component.ts
+++ b/client/src/app/shared/shared-main/angular/link.component.ts
@@ -1,4 +1,4 @@
1import { Component, Input, ViewEncapsulation } from '@angular/core' 1import { Component, Input } from '@angular/core'
2 2
3@Component({ 3@Component({
4 selector: 'my-link', 4 selector: 'my-link',
diff --git a/client/src/app/shared/shared-main/angular/peertube-template.directive.ts b/client/src/app/shared/shared-main/angular/peertube-template.directive.ts
index e04c25d9a..dc0cde12d 100644
--- a/client/src/app/shared/shared-main/angular/peertube-template.directive.ts
+++ b/client/src/app/shared/shared-main/angular/peertube-template.directive.ts
@@ -1,6 +1,7 @@
1import { Directive, Input, TemplateRef } from '@angular/core' 1import { Directive, Input, TemplateRef } from '@angular/core'
2 2
3@Directive({ 3@Directive({
4 // eslint-disable-next-line @angular-eslint/directive-selector
4 selector: '[ptTemplate]' 5 selector: '[ptTemplate]'
5}) 6})
6export class PeerTubeTemplateDirective <T extends string> { 7export class PeerTubeTemplateDirective <T extends string> {
diff --git a/client/src/app/shared/shared-main/feeds/syndication.model.ts b/client/src/app/shared/shared-main/feeds/syndication.model.ts
index 2466ae7c6..cd6fbdb48 100644
--- a/client/src/app/shared/shared-main/feeds/syndication.model.ts
+++ b/client/src/app/shared/shared-main/feeds/syndication.model.ts
@@ -1,7 +1,7 @@
1import { FeedFormat } from '@shared/models' 1import { FeedFormat } from '@shared/models'
2 2
3export interface Syndication { 3export interface Syndication {
4 format: FeedFormat, 4 format: FeedFormat
5 label: string, 5 label: string
6 url: string 6 url: string
7} 7}
diff --git a/client/src/app/shared/shared-main/misc/help.component.ts b/client/src/app/shared/shared-main/misc/help.component.ts
index 76e255d99..37e2abd97 100644
--- a/client/src/app/shared/shared-main/misc/help.component.ts
+++ b/client/src/app/shared/shared-main/misc/help.component.ts
@@ -71,18 +71,18 @@ export class HelpComponent implements OnInit, OnChanges, AfterContentInit {
71 } 71 }
72 72
73 private formatMarkdownSupport (rules: string[]) { 73 private formatMarkdownSupport (rules: string[]) {
74 // tslint:disable:max-line-length 74 /* eslint-disable max-len */
75 return $localize`<a href="https://en.wikipedia.org/wiki/Markdown#Example" target="_blank" rel="noopener noreferrer">Markdown</a> compatible that supports:` + 75 return $localize`<a href="https://en.wikipedia.org/wiki/Markdown#Example" target="_blank" rel="noopener noreferrer">Markdown</a> compatible that supports:` +
76 this.createMarkdownList(rules) 76 this.createMarkdownList(rules)
77 } 77 }
78 78
79 private createMarkdownList (rules: string[]) { 79 private createMarkdownList (rules: string[]) {
80 const rulesToText = { 80 const rulesToText = {
81 'emphasis': $localize`Emphasis`, 81 emphasis: $localize`Emphasis`,
82 'link': $localize`Links`, 82 link: $localize`Links`,
83 'newline': $localize`New lines`, 83 newline: $localize`New lines`,
84 'list': $localize`Lists`, 84 list: $localize`Lists`,
85 'image': $localize`Images` 85 image: $localize`Images`
86 } 86 }
87 87
88 const bullets = rules.map(r => rulesToText[r]) 88 const bullets = rules.map(r => rulesToText[r])
diff --git a/client/src/app/shared/shared-main/misc/list-overflow.component.ts b/client/src/app/shared/shared-main/misc/list-overflow.component.ts
index 144e0f156..fbc481093 100644
--- a/client/src/app/shared/shared-main/misc/list-overflow.component.ts
+++ b/client/src/app/shared/shared-main/misc/list-overflow.component.ts
@@ -22,7 +22,7 @@ export interface ListOverflowItem {
22} 22}
23 23
24@Component({ 24@Component({
25 selector: 'list-overflow', 25 selector: 'my-list-overflow',
26 templateUrl: './list-overflow.component.html', 26 templateUrl: './list-overflow.component.html',
27 styleUrls: [ './list-overflow.component.scss' ], 27 styleUrls: [ './list-overflow.component.scss' ],
28 changeDetection: ChangeDetectionStrategy.OnPush 28 changeDetection: ChangeDetectionStrategy.OnPush
@@ -65,7 +65,7 @@ export class ListOverflowComponent<T extends ListOverflowItem> implements AfterV
65 let showItemsUntilIndexExcluded: number 65 let showItemsUntilIndexExcluded: number
66 let accWidth = 0 66 let accWidth = 0
67 67
68 for (const [index, el] of this.itemsRendered.toArray().entries()) { 68 for (const [ index, el ] of this.itemsRendered.toArray().entries()) {
69 accWidth += el.nativeElement.getBoundingClientRect().width 69 accWidth += el.nativeElement.getBoundingClientRect().width
70 if (showItemsUntilIndexExcluded === undefined) { 70 if (showItemsUntilIndexExcluded === undefined) {
71 showItemsUntilIndexExcluded = (parentWidth < accWidth) ? index : undefined 71 showItemsUntilIndexExcluded = (parentWidth < accWidth) ? index : undefined
diff --git a/client/src/app/shared/shared-main/misc/simple-search-input.component.ts b/client/src/app/shared/shared-main/misc/simple-search-input.component.ts
index 224d71134..292ec4c82 100644
--- a/client/src/app/shared/shared-main/misc/simple-search-input.component.ts
+++ b/client/src/app/shared/shared-main/misc/simple-search-input.component.ts
@@ -4,7 +4,7 @@ import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild }
4import { ActivatedRoute, Router } from '@angular/router' 4import { ActivatedRoute, Router } from '@angular/router'
5 5
6@Component({ 6@Component({
7 selector: 'simple-search-input', 7 selector: 'my-simple-search-input',
8 templateUrl: './simple-search-input.component.html', 8 templateUrl: './simple-search-input.component.html',
9 styleUrls: [ './simple-search-input.component.scss' ] 9 styleUrls: [ './simple-search-input.component.scss' ]
10}) 10})
diff --git a/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts b/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts
index 2cafb6c55..e7e34ce1e 100644
--- a/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts
+++ b/client/src/app/shared/shared-main/misc/top-menu-dropdown.component.ts
@@ -66,7 +66,7 @@ export class TopMenuDropdownComponent implements OnInit, OnDestroy {
66 .subscribe(() => this.updateChildLabels(window.location.pathname)) 66 .subscribe(() => this.updateChildLabels(window.location.pathname))
67 67
68 this.hasIcons = this.menuEntries.some( 68 this.hasIcons = this.menuEntries.some(
69 e => e.children && e.children.some(c => !!c.iconName) 69 e => e.children?.some(c => !!c.iconName)
70 ) 70 )
71 } 71 }
72 72
diff --git a/client/src/app/shared/shared-main/users/user-notification.service.ts b/client/src/app/shared/shared-main/users/user-notification.service.ts
index 9014b48a8..09fee87a3 100644
--- a/client/src/app/shared/shared-main/users/user-notification.service.ts
+++ b/client/src/app/shared/shared-main/users/user-notification.service.ts
@@ -1,11 +1,11 @@
1import { SortMeta } from 'primeng/api'
1import { catchError, map, tap } from 'rxjs/operators' 2import { catchError, map, tap } from 'rxjs/operators'
2import { HttpClient, HttpParams } from '@angular/common/http' 3import { HttpClient, HttpParams } from '@angular/common/http'
3import { Injectable } from '@angular/core' 4import { Injectable } from '@angular/core'
4import { ComponentPaginationLight, RestExtractor, RestService, User, PeerTubeSocket, AuthService } from '@app/core' 5import { AuthService, ComponentPaginationLight, PeerTubeSocket, RestExtractor, RestService } from '@app/core'
5import { ResultList, UserNotification as UserNotificationServer, UserNotificationSetting } from '@shared/models' 6import { ResultList, UserNotification as UserNotificationServer, UserNotificationSetting } from '@shared/models'
6import { environment } from '../../../../environments/environment' 7import { environment } from '../../../../environments/environment'
7import { UserNotification } from './user-notification.model' 8import { UserNotification } from './user-notification.model'
8import { SortMeta } from 'primeng/api'
9 9
10@Injectable() 10@Injectable()
11export class UserNotificationService { 11export class UserNotificationService {
@@ -23,7 +23,7 @@ export class UserNotificationService {
23 listMyNotifications (parameters: { 23 listMyNotifications (parameters: {
24 pagination: ComponentPaginationLight 24 pagination: ComponentPaginationLight
25 ignoreLoadingBar?: boolean 25 ignoreLoadingBar?: boolean
26 unread?: boolean, 26 unread?: boolean
27 sort?: SortMeta 27 sort?: SortMeta
28 }) { 28 }) {
29 const { pagination, ignoreLoadingBar, unread, sort } = parameters 29 const { pagination, ignoreLoadingBar, unread, sort } = parameters
diff --git a/client/src/app/shared/shared-main/users/user-quota.component.ts b/client/src/app/shared/shared-main/users/user-quota.component.ts
index b38619186..5a95f1209 100644
--- a/client/src/app/shared/shared-main/users/user-quota.component.ts
+++ b/client/src/app/shared/shared-main/users/user-quota.component.ts
@@ -6,7 +6,7 @@ import { BytesPipe } from '../angular'
6@Component({ 6@Component({
7 selector: 'my-user-quota', 7 selector: 'my-user-quota',
8 templateUrl: './user-quota.component.html', 8 templateUrl: './user-quota.component.html',
9 styleUrls: ['./user-quota.component.scss'] 9 styleUrls: [ './user-quota.component.scss' ]
10}) 10})
11 11
12export class UserQuotaComponent implements OnInit { 12export class UserQuotaComponent implements OnInit {
diff --git a/client/src/app/shared/shared-main/video-channel/video-channel.model.ts b/client/src/app/shared/shared-main/video-channel/video-channel.model.ts
index a9dcf2fa2..66d4cac68 100644
--- a/client/src/app/shared/shared-main/video-channel/video-channel.model.ts
+++ b/client/src/app/shared/shared-main/video-channel/video-channel.model.ts
@@ -1,6 +1,5 @@
1import { getAbsoluteAPIUrl } from '@app/helpers' 1import { getAbsoluteAPIUrl } from '@app/helpers'
2import { Account as ServerAccount, ActorImage, VideoChannel as ServerVideoChannel, ViewsPerDate } from '@shared/models' 2import { Account as ServerAccount, ActorImage, VideoChannel as ServerVideoChannel, ViewsPerDate } from '@shared/models'
3import { Account } from '../account/account.model'
4import { Actor } from '../account/actor.model' 3import { Actor } from '../account/actor.model'
5 4
6export class VideoChannel extends Actor implements ServerVideoChannel { 5export class VideoChannel extends Actor implements ServerVideoChannel {
@@ -25,14 +24,14 @@ export class VideoChannel extends Actor implements ServerVideoChannel {
25 24
26 viewsPerDay?: ViewsPerDate[] 25 viewsPerDay?: ViewsPerDate[]
27 26
28 static GET_ACTOR_AVATAR_URL (actor: object) { 27 static GET_ACTOR_AVATAR_URL (actor: { avatar?: { url?: string, path: string } }) {
29 return Actor.GET_ACTOR_AVATAR_URL(actor) 28 return Actor.GET_ACTOR_AVATAR_URL(actor)
30 } 29 }
31 30
32 static GET_ACTOR_BANNER_URL (channel: ServerVideoChannel) { 31 static GET_ACTOR_BANNER_URL (channel: ServerVideoChannel) {
33 if (channel?.banner?.url) return channel.banner.url 32 if (channel?.banner?.url) return channel.banner.url
34 33
35 if (channel && channel.banner) { 34 if (channel?.banner) {
36 const absoluteAPIUrl = getAbsoluteAPIUrl() 35 const absoluteAPIUrl = getAbsoluteAPIUrl()
37 36
38 return absoluteAPIUrl + channel.banner.path 37 return absoluteAPIUrl + channel.banner.path
diff --git a/client/src/app/shared/shared-main/video-channel/video-channel.service.ts b/client/src/app/shared/shared-main/video-channel/video-channel.service.ts
index a89f1065a..7560a35a8 100644
--- a/client/src/app/shared/shared-main/video-channel/video-channel.service.ts
+++ b/client/src/app/shared/shared-main/video-channel/video-channel.service.ts
@@ -15,6 +15,12 @@ export class VideoChannelService {
15 15
16 videoChannelLoaded = new ReplaySubject<VideoChannel>(1) 16 videoChannelLoaded = new ReplaySubject<VideoChannel>(1)
17 17
18 constructor (
19 private authHttp: HttpClient,
20 private restService: RestService,
21 private restExtractor: RestExtractor
22 ) { }
23
18 static extractVideoChannels (result: ResultList<VideoChannelServer>) { 24 static extractVideoChannels (result: ResultList<VideoChannelServer>) {
19 const videoChannels: VideoChannel[] = [] 25 const videoChannels: VideoChannel[] = []
20 26
@@ -25,12 +31,6 @@ export class VideoChannelService {
25 return { data: videoChannels, total: result.total } 31 return { data: videoChannels, total: result.total }
26 } 32 }
27 33
28 constructor (
29 private authHttp: HttpClient,
30 private restService: RestService,
31 private restExtractor: RestExtractor
32 ) { }
33
34 getVideoChannel (videoChannelName: string) { 34 getVideoChannel (videoChannelName: string) {
35 return this.authHttp.get<VideoChannel>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannelName) 35 return this.authHttp.get<VideoChannel>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannelName)
36 .pipe( 36 .pipe(
diff --git a/client/src/app/shared/shared-main/video/redundancy.service.ts b/client/src/app/shared/shared-main/video/redundancy.service.ts
index 6e839e655..966d7fafd 100644
--- a/client/src/app/shared/shared-main/video/redundancy.service.ts
+++ b/client/src/app/shared/shared-main/video/redundancy.service.ts
@@ -30,8 +30,8 @@ export class RedundancyService {
30 } 30 }
31 31
32 listVideoRedundancies (options: { 32 listVideoRedundancies (options: {
33 pagination: RestPagination, 33 pagination: RestPagination
34 sort: SortMeta, 34 sort: SortMeta
35 target?: VideoRedundanciesTarget 35 target?: VideoRedundanciesTarget
36 }): Observable<ResultList<VideoRedundancy>> { 36 }): Observable<ResultList<VideoRedundancy>> {
37 const { pagination, sort, target } = options 37 const { pagination, sort, target } = options
diff --git a/client/src/app/shared/shared-main/video/video-edit.model.ts b/client/src/app/shared/shared-main/video/video-edit.model.ts
index 757b686c0..ea0456942 100644
--- a/client/src/app/shared/shared-main/video/video-edit.model.ts
+++ b/client/src/app/shared/shared-main/video/video-edit.model.ts
@@ -29,11 +29,11 @@ export class VideoEdit implements VideoUpdate {
29 29
30 constructor ( 30 constructor (
31 video?: Video & { 31 video?: Video & {
32 tags: string[], 32 tags: string[]
33 commentsEnabled: boolean, 33 commentsEnabled: boolean
34 downloadEnabled: boolean, 34 downloadEnabled: boolean
35 support: string, 35 support: string
36 thumbnailUrl: string, 36 thumbnailUrl: string
37 previewUrl: string 37 previewUrl: string
38 }) { 38 }) {
39 if (video) { 39 if (video) {
@@ -64,7 +64,7 @@ export class VideoEdit implements VideoUpdate {
64 64
65 patch (values: { [ id: string ]: any }) { 65 patch (values: { [ id: string ]: any }) {
66 Object.keys(values).forEach((key) => { 66 Object.keys(values).forEach((key) => {
67 this[ key ] = values[ key ] 67 this[key] = values[key]
68 }) 68 })
69 69
70 // If schedule publication, the video is private and will be changed to public privacy 70 // If schedule publication, the video is private and will be changed to public privacy
diff --git a/client/src/app/shared/shared-main/video/video.model.ts b/client/src/app/shared/shared-main/video/video.model.ts
index b7720c8d2..7471a933b 100644
--- a/client/src/app/shared/shared-main/video/video.model.ts
+++ b/client/src/app/shared/shared-main/video/video.model.ts
@@ -100,7 +100,7 @@ export class Video implements VideoServerModel {
100 return '/videos/update/' + video.uuid 100 return '/videos/update/' + video.uuid
101 } 101 }
102 102
103 constructor (hash: VideoServerModel, translations = {}) { 103 constructor (hash: VideoServerModel, translations: { [ id: string ]: string } = {}) {
104 const absoluteAPIUrl = getAbsoluteAPIUrl() 104 const absoluteAPIUrl = getAbsoluteAPIUrl()
105 105
106 this.createdAt = new Date(hash.createdAt.toString()) 106 this.createdAt = new Date(hash.createdAt.toString())
diff --git a/client/src/app/shared/shared-main/video/video.service.ts b/client/src/app/shared/shared-main/video/video.service.ts
index 4a97719fa..60cc9d160 100644
--- a/client/src/app/shared/shared-main/video/video.service.ts
+++ b/client/src/app/shared/shared-main/video/video.service.ts
@@ -30,10 +30,10 @@ import { Video } from './video.model'
30 30
31export interface VideosProvider { 31export interface VideosProvider {
32 getVideos (parameters: { 32 getVideos (parameters: {
33 videoPagination: ComponentPaginationLight, 33 videoPagination: ComponentPaginationLight
34 sort: VideoSortField, 34 sort: VideoSortField
35 filter?: VideoFilter, 35 filter?: VideoFilter
36 categoryOneOf?: number[], 36 categoryOneOf?: number[]
37 languageOneOf?: string[] 37 languageOneOf?: string[]
38 nsfwPolicy: NSFWPolicyType 38 nsfwPolicy: NSFWPolicyType
39 }): Observable<ResultList<Video>> 39 }): Observable<ResultList<Video>>
@@ -145,8 +145,8 @@ export class VideoService implements VideosProvider {
145 } 145 }
146 146
147 getAccountVideos (parameters: { 147 getAccountVideos (parameters: {
148 account: Pick<Account, 'nameWithHost'>, 148 account: Pick<Account, 'nameWithHost'>
149 videoPagination: ComponentPaginationLight, 149 videoPagination: ComponentPaginationLight
150 sort: VideoSortField 150 sort: VideoSortField
151 nsfwPolicy?: NSFWPolicyType 151 nsfwPolicy?: NSFWPolicyType
152 videoFilter?: VideoFilter 152 videoFilter?: VideoFilter
@@ -180,9 +180,9 @@ export class VideoService implements VideosProvider {
180 } 180 }
181 181
182 getVideoChannelVideos (parameters: { 182 getVideoChannelVideos (parameters: {
183 videoChannel: Pick<VideoChannel, 'nameWithHost'>, 183 videoChannel: Pick<VideoChannel, 'nameWithHost'>
184 videoPagination: ComponentPaginationLight, 184 videoPagination: ComponentPaginationLight
185 sort: VideoSortField, 185 sort: VideoSortField
186 nsfwPolicy?: NSFWPolicyType 186 nsfwPolicy?: NSFWPolicyType
187 videoFilter?: VideoFilter 187 videoFilter?: VideoFilter
188 }): Observable<ResultList<Video>> { 188 }): Observable<ResultList<Video>> {
diff --git a/client/src/app/shared/shared-moderation/abuse.service.ts b/client/src/app/shared/shared-moderation/abuse.service.ts
index bf98d4b36..f45b5c8e8 100644
--- a/client/src/app/shared/shared-moderation/abuse.service.ts
+++ b/client/src/app/shared/shared-moderation/abuse.service.ts
@@ -30,8 +30,8 @@ export class AbuseService {
30 ) { } 30 ) { }
31 31
32 getAdminAbuses (options: { 32 getAdminAbuses (options: {
33 pagination: RestPagination, 33 pagination: RestPagination
34 sort: SortMeta, 34 sort: SortMeta
35 search?: string 35 search?: string
36 }): Observable<ResultList<AdminAbuse>> { 36 }): Observable<ResultList<AdminAbuse>> {
37 const { pagination, sort, search } = options 37 const { pagination, sort, search } = options
@@ -51,8 +51,8 @@ export class AbuseService {
51 } 51 }
52 52
53 getUserAbuses (options: { 53 getUserAbuses (options: {
54 pagination: RestPagination, 54 pagination: RestPagination
55 sort: SortMeta, 55 sort: SortMeta
56 search?: string 56 search?: string
57 }): Observable<ResultList<UserAbuse>> { 57 }): Observable<ResultList<UserAbuse>> {
58 const { pagination, sort, search } = options 58 const { pagination, sort, search } = options
@@ -74,7 +74,7 @@ export class AbuseService {
74 reportVideo (parameters: AbuseCreate) { 74 reportVideo (parameters: AbuseCreate) {
75 const url = AbuseService.BASE_ABUSE_URL 75 const url = AbuseService.BASE_ABUSE_URL
76 76
77 const body = omit(parameters, ['id']) 77 const body = omit(parameters, [ 'id' ])
78 78
79 return this.authHttp.post(url, body) 79 return this.authHttp.post(url, body)
80 .pipe( 80 .pipe(
@@ -147,11 +147,13 @@ export class AbuseService {
147 { 147 {
148 id: 'spamOrMisleading', 148 id: 'spamOrMisleading',
149 label: $localize`Spam, ad or false news`, 149 label: $localize`Spam, ad or false news`,
150 // eslint-disable-next-line max-len
150 help: $localize`Contains marketing, spam, purposefully deceitful news, or otherwise misleading thumbnail/text/tags. Please provide reputable sources to report hoaxes.` 151 help: $localize`Contains marketing, spam, purposefully deceitful news, or otherwise misleading thumbnail/text/tags. Please provide reputable sources to report hoaxes.`
151 }, 152 },
152 { 153 {
153 id: 'privacy', 154 id: 'privacy',
154 label: $localize`Privacy breach or doxxing`, 155 label: $localize`Privacy breach or doxxing`,
156 // eslint-disable-next-line max-len
155 help: $localize`Contains personal information that could be used to track, identify, contact or impersonate someone (e.g. name, address, phone number, email, or credit card details).` 157 help: $localize`Contains personal information that could be used to track, identify, contact or impersonate someone (e.g. name, address, phone number, email, or credit card details).`
156 }, 158 },
157 { 159 {
@@ -162,6 +164,7 @@ export class AbuseService {
162 { 164 {
163 id: 'serverRules', 165 id: 'serverRules',
164 label: $localize`Breaks server rules`, 166 label: $localize`Breaks server rules`,
167 // eslint-disable-next-line max-len
165 description: $localize`Anything not included in the above that breaks the terms of service, code of conduct, or general rules in place on the server.` 168 description: $localize`Anything not included in the above that breaks the terms of service, code of conduct, or general rules in place on the server.`
166 } 169 }
167 ] 170 ]
diff --git a/client/src/app/shared/shared-moderation/account-blocklist.component.ts b/client/src/app/shared/shared-moderation/account-blocklist.component.ts
index 36f2a591b..9ed00bc12 100644
--- a/client/src/app/shared/shared-moderation/account-blocklist.component.ts
+++ b/client/src/app/shared/shared-moderation/account-blocklist.component.ts
@@ -1,14 +1,13 @@
1import { SortMeta } from 'primeng/api' 1import { SortMeta } from 'primeng/api'
2import { Directive, OnInit } from '@angular/core' 2import { Directive, OnInit } from '@angular/core'
3import { Notifier, RestPagination, RestTable } from '@app/core' 3import { Notifier, RestPagination, RestTable } from '@app/core'
4import { Account } from '@app/shared/shared-main'
5import { AccountBlock } from './account-block.model' 4import { AccountBlock } from './account-block.model'
6import { BlocklistComponentType, BlocklistService } from './blocklist.service' 5import { BlocklistComponentType, BlocklistService } from './blocklist.service'
7 6
8@Directive() 7@Directive()
9// tslint:disable-next-line: directive-class-suffix 8// eslint-disable-next-line @angular-eslint/directive-class-suffix
10export class GenericAccountBlocklistComponent extends RestTable implements OnInit { 9export class GenericAccountBlocklistComponent extends RestTable implements OnInit {
11 // @ts-ignore: "Abstract methods can only appear within an abstract class" 10 // @ts-expect-error: "Abstract methods can only appear within an abstract class"
12 abstract mode: BlocklistComponentType 11 abstract mode: BlocklistComponentType
13 12
14 blockedAccounts: AccountBlock[] = [] 13 blockedAccounts: AccountBlock[] = []
@@ -23,7 +22,7 @@ export class GenericAccountBlocklistComponent extends RestTable implements OnIni
23 super() 22 super()
24 } 23 }
25 24
26 // @ts-ignore: "Abstract methods can only appear within an abstract class" 25 // @ts-expect-error: "Abstract methods can only appear within an abstract class"
27 abstract getIdentifier (): string 26 abstract getIdentifier (): string
28 27
29 ngOnInit () { 28 ngOnInit () {
diff --git a/client/src/app/shared/shared-moderation/blocklist.service.ts b/client/src/app/shared/shared-moderation/blocklist.service.ts
index de677a77b..db2a8c584 100644
--- a/client/src/app/shared/shared-moderation/blocklist.service.ts
+++ b/client/src/app/shared/shared-moderation/blocklist.service.ts
@@ -21,7 +21,7 @@ export class BlocklistService {
21 private restService: RestService 21 private restService: RestService
22 ) { } 22 ) { }
23 23
24 /*********************** User -> Account blocklist ***********************/ 24 /** ********************* User -> Account blocklist ***********************/
25 25
26 getUserAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) { 26 getUserAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) {
27 const { pagination, sort, search } = options 27 const { pagination, sort, search } = options
@@ -53,7 +53,7 @@ export class BlocklistService {
53 .pipe(catchError(err => this.restExtractor.handleError(err))) 53 .pipe(catchError(err => this.restExtractor.handleError(err)))
54 } 54 }
55 55
56 /*********************** User -> Server blocklist ***********************/ 56 /** ********************* User -> Server blocklist ***********************/
57 57
58 getUserServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) { 58 getUserServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) {
59 const { pagination, sort, search } = options 59 const { pagination, sort, search } = options
@@ -84,7 +84,7 @@ export class BlocklistService {
84 .pipe(catchError(err => this.restExtractor.handleError(err))) 84 .pipe(catchError(err => this.restExtractor.handleError(err)))
85 } 85 }
86 86
87 /*********************** Instance -> Account blocklist ***********************/ 87 /** ********************* Instance -> Account blocklist ***********************/
88 88
89 getInstanceAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) { 89 getInstanceAccountBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) {
90 const { pagination, sort, search } = options 90 const { pagination, sort, search } = options
@@ -116,7 +116,7 @@ export class BlocklistService {
116 .pipe(catchError(err => this.restExtractor.handleError(err))) 116 .pipe(catchError(err => this.restExtractor.handleError(err)))
117 } 117 }
118 118
119 /*********************** Instance -> Server blocklist ***********************/ 119 /** ********************* Instance -> Server blocklist ***********************/
120 120
121 getInstanceServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) { 121 getInstanceServerBlocklist (options: { pagination: RestPagination, sort: SortMeta, search?: string }) {
122 const { pagination, sort, search } = options 122 const { pagination, sort, search } = options
diff --git a/client/src/app/shared/shared-moderation/server-blocklist.component.ts b/client/src/app/shared/shared-moderation/server-blocklist.component.ts
index da09b1d0e..1ba7a1b4d 100644
--- a/client/src/app/shared/shared-moderation/server-blocklist.component.ts
+++ b/client/src/app/shared/shared-moderation/server-blocklist.component.ts
@@ -6,11 +6,11 @@ import { ServerBlock } from '@shared/models'
6import { BlocklistComponentType, BlocklistService } from './blocklist.service' 6import { BlocklistComponentType, BlocklistService } from './blocklist.service'
7 7
8@Directive() 8@Directive()
9// tslint:disable-next-line: directive-class-suffix 9// eslint-disable-next-line @angular-eslint/directive-class-suffix
10export class GenericServerBlocklistComponent extends RestTable implements OnInit { 10export class GenericServerBlocklistComponent extends RestTable implements OnInit {
11 @ViewChild('batchDomainsModal') batchDomainsModal: BatchDomainsModalComponent 11 @ViewChild('batchDomainsModal') batchDomainsModal: BatchDomainsModalComponent
12 12
13 // @ts-ignore: "Abstract methods can only appear within an abstract class" 13 // @ts-expect-error: "Abstract methods can only appear within an abstract class"
14 public abstract mode: BlocklistComponentType 14 public abstract mode: BlocklistComponentType
15 15
16 blockedServers: ServerBlock[] = [] 16 blockedServers: ServerBlock[] = []
@@ -25,7 +25,7 @@ export class GenericServerBlocklistComponent extends RestTable implements OnInit
25 super() 25 super()
26 } 26 }
27 27
28 // @ts-ignore: "Abstract methods can only appear within an abstract class" 28 // @ts-expect-error: "Abstract methods can only appear within an abstract class"
29 public abstract getIdentifier (): string 29 public abstract getIdentifier (): string
30 30
31 ngOnInit () { 31 ngOnInit () {
@@ -34,8 +34,8 @@ export class GenericServerBlocklistComponent extends RestTable implements OnInit
34 34
35 unblockServer (serverBlock: ServerBlock) { 35 unblockServer (serverBlock: ServerBlock) {
36 const operation = (host: string) => this.mode === BlocklistComponentType.Account 36 const operation = (host: string) => this.mode === BlocklistComponentType.Account
37 ? this.blocklistService.unblockServerByUser(host) 37 ? this.blocklistService.unblockServerByUser(host)
38 : this.blocklistService.unblockServerByInstance(host) 38 : this.blocklistService.unblockServerByInstance(host)
39 const host = serverBlock.blockedServer.host 39 const host = serverBlock.blockedServer.host
40 40
41 operation(host).subscribe( 41 operation(host).subscribe(
diff --git a/client/src/app/shared/shared-moderation/video-block.component.ts b/client/src/app/shared/shared-moderation/video-block.component.ts
index bc6952620..f6c29dcfa 100644
--- a/client/src/app/shared/shared-moderation/video-block.component.ts
+++ b/client/src/app/shared/shared-moderation/video-block.component.ts
@@ -51,8 +51,8 @@ export class VideoBlockComponent extends FormReactive implements OnInit {
51 } 51 }
52 52
53 block () { 53 block () {
54 const reason = this.form.value[ 'reason' ] || undefined 54 const reason = this.form.value['reason'] || undefined
55 const unfederate = this.video.isLocal ? this.form.value[ 'unfederate' ] : undefined 55 const unfederate = this.video.isLocal ? this.form.value['unfederate'] : undefined
56 56
57 this.videoBlocklistService.blockVideo(this.video.id, reason, unfederate) 57 this.videoBlocklistService.blockVideo(this.video.id, reason, unfederate)
58 .subscribe({ 58 .subscribe({
diff --git a/client/src/app/shared/shared-support-modal/support-modal.component.ts b/client/src/app/shared/shared-support-modal/support-modal.component.ts
index a0b9fada6..08e997f7b 100644
--- a/client/src/app/shared/shared-support-modal/support-modal.component.ts
+++ b/client/src/app/shared/shared-support-modal/support-modal.component.ts
@@ -28,7 +28,9 @@ export class SupportModalComponent {
28 const support = this.video?.support || this.videoChannel.support 28 const support = this.video?.support || this.videoChannel.support
29 29
30 this.markdownService.enhancedMarkdownToHTML(support) 30 this.markdownService.enhancedMarkdownToHTML(support)
31 .then(r => this.htmlSupport = r) 31 .then(r => {
32 this.htmlSupport = r
33 })
32 34
33 this.displayName = this.video 35 this.displayName = this.video
34 ? this.video.channel.displayName 36 ? this.video.channel.displayName
diff --git a/client/src/app/shared/shared-user-settings/user-video-settings.component.ts b/client/src/app/shared/shared-user-settings/user-video-settings.component.ts
index 4aac60c2b..5d6e11c04 100644
--- a/client/src/app/shared/shared-user-settings/user-video-settings.component.ts
+++ b/client/src/app/shared/shared-user-settings/user-video-settings.component.ts
@@ -80,7 +80,7 @@ export class UserVideoSettingsComponent extends FormReactive implements OnInit,
80 } 80 }
81 81
82 updateDetails (onlyKeys?: string[]) { 82 updateDetails (onlyKeys?: string[]) {
83 const nsfwPolicy = this.form.value[ 'nsfwPolicy' ] 83 const nsfwPolicy = this.form.value['nsfwPolicy']
84 const webTorrentEnabled = this.form.value['webTorrentEnabled'] 84 const webTorrentEnabled = this.form.value['webTorrentEnabled']
85 const autoPlayVideo = this.form.value['autoPlayVideo'] 85 const autoPlayVideo = this.form.value['autoPlayVideo']
86 const autoPlayNextVideo = this.form.value['autoPlayNextVideo'] 86 const autoPlayNextVideo = this.form.value['autoPlayNextVideo']
diff --git a/client/src/app/shared/shared-user-subscription/remote-subscribe.component.ts b/client/src/app/shared/shared-user-subscription/remote-subscribe.component.ts
index 666199523..a951134eb 100644
--- a/client/src/app/shared/shared-user-subscription/remote-subscribe.component.ts
+++ b/client/src/app/shared/shared-user-subscription/remote-subscribe.component.ts
@@ -6,7 +6,7 @@ import { USER_HANDLE_VALIDATOR } from '../form-validators/user-validators'
6@Component({ 6@Component({
7 selector: 'my-remote-subscribe', 7 selector: 'my-remote-subscribe',
8 templateUrl: './remote-subscribe.component.html', 8 templateUrl: './remote-subscribe.component.html',
9 styleUrls: ['./remote-subscribe.component.scss'] 9 styleUrls: [ './remote-subscribe.component.scss' ]
10}) 10})
11export class RemoteSubscribeComponent extends FormReactive implements OnInit { 11export class RemoteSubscribeComponent extends FormReactive implements OnInit {
12 @Input() uri: string 12 @Input() uri: string
@@ -42,17 +42,21 @@ export class RemoteSubscribeComponent extends FormReactive implements OnInit {
42 // Should not have CORS error because https://tools.ietf.org/html/rfc7033#section-5 42 // Should not have CORS error because https://tools.ietf.org/html/rfc7033#section-5
43 fetch(`${protocol}//${hostname}/.well-known/webfinger?resource=acct:${username}@${hostname}`) 43 fetch(`${protocol}//${hostname}/.well-known/webfinger?resource=acct:${username}@${hostname}`)
44 .then(response => response.json()) 44 .then(response => response.json())
45 .then(data => new Promise((res, rej) => { 45 .then(data => {
46 if (!data || Array.isArray(data.links) === false) return rej() 46 if (!data || Array.isArray(data.links) === false) {
47 throw new Error('Not links in webfinger response')
48 }
47 49
48 const link: { template: string } = data.links.find((link: any) => { 50 const link: { template: string } = data.links.find((link: any) => {
49 return link && typeof link.template === 'string' && link.rel === 'http://ostatus.org/schema/1.0/subscribe' 51 return link && typeof link.template === 'string' && link.rel === 'http://ostatus.org/schema/1.0/subscribe'
50 }) 52 })
51 53
52 if (link && link.template.includes('{uri}')) { 54 if (link?.template.includes('{uri}')) {
53 res(link.template.replace('{uri}', encodeURIComponent(this.uri))) 55 return link.template.replace('{uri}', encodeURIComponent(this.uri))
54 } 56 }
55 })) 57
58 throw new Error('No subscribe template in webfinger response')
59 })
56 .then(window.open) 60 .then(window.open)
57 .catch(err => { 61 .catch(err => {
58 console.error(err) 62 console.error(err)
diff --git a/client/src/app/shared/shared-user-subscription/subscribe-button.component.ts b/client/src/app/shared/shared-user-subscription/subscribe-button.component.ts
index 796493bd9..180bc0565 100644
--- a/client/src/app/shared/shared-user-subscription/subscribe-button.component.ts
+++ b/client/src/app/shared/shared-user-subscription/subscribe-button.component.ts
@@ -137,7 +137,7 @@ export class SubscribeButtonComponent implements OnInit, OnChanges {
137 this.notifier.success( 137 this.notifier.success(
138 this.account 138 this.account
139 ? $localize`Unsubscribed from all channels of ${this.account.nameWithHost}` 139 ? $localize`Unsubscribed from all channels of ${this.account.nameWithHost}`
140 : $localize`Unsubscribed from ${this.videoChannels[ 0 ].nameWithHost}`, 140 : $localize`Unsubscribed from ${this.videoChannels[0].nameWithHost}`,
141 141
142 $localize`Unsubscribed` 142 $localize`Unsubscribed`
143 ) 143 )
@@ -157,7 +157,7 @@ export class SubscribeButtonComponent implements OnInit, OnChanges {
157 157
158 subscribeStatus (subscribed: boolean) { 158 subscribeStatus (subscribed: boolean) {
159 const accumulator: string[] = [] 159 const accumulator: string[] = []
160 for (const [key, value] of this.subscribed.entries()) { 160 for (const [ key, value ] of this.subscribed.entries()) {
161 if (value === subscribed) accumulator.push(key) 161 if (value === subscribed) accumulator.push(key)
162 } 162 }
163 163
diff --git a/client/src/app/shared/shared-user-subscription/user-subscription.service.ts b/client/src/app/shared/shared-user-subscription/user-subscription.service.ts
index bb44660d2..e4fc09b36 100644
--- a/client/src/app/shared/shared-user-subscription/user-subscription.service.ts
+++ b/client/src/app/shared/shared-user-subscription/user-subscription.service.ts
@@ -46,8 +46,8 @@ export class UserSubscriptionService {
46 } 46 }
47 47
48 getUserSubscriptionVideos (parameters: { 48 getUserSubscriptionVideos (parameters: {
49 videoPagination: ComponentPaginationLight, 49 videoPagination: ComponentPaginationLight
50 sort: VideoSortField, 50 sort: VideoSortField
51 skipCount?: boolean 51 skipCount?: boolean
52 }): Observable<ResultList<Video>> { 52 }): Observable<ResultList<Video>> {
53 const { videoPagination, sort, skipCount } = parameters 53 const { videoPagination, sort, skipCount } = parameters
@@ -131,16 +131,16 @@ export class UserSubscriptionService {
131 131
132 listenToSubscriptionCacheChange (nameWithHost: string) { 132 listenToSubscriptionCacheChange (nameWithHost: string) {
133 if (nameWithHost in this.myAccountSubscriptionCacheObservable) { 133 if (nameWithHost in this.myAccountSubscriptionCacheObservable) {
134 return this.myAccountSubscriptionCacheObservable[ nameWithHost ] 134 return this.myAccountSubscriptionCacheObservable[nameWithHost]
135 } 135 }
136 136
137 const obs = this.existsObservable 137 const obs = this.existsObservable
138 .pipe( 138 .pipe(
139 filter(existsResult => existsResult[ nameWithHost ] !== undefined), 139 filter(existsResult => existsResult[nameWithHost] !== undefined),
140 map(existsResult => existsResult[ nameWithHost ]) 140 map(existsResult => existsResult[nameWithHost])
141 ) 141 )
142 142
143 this.myAccountSubscriptionCacheObservable[ nameWithHost ] = obs 143 this.myAccountSubscriptionCacheObservable[nameWithHost] = obs
144 return obs 144 return obs
145 } 145 }
146 146
@@ -150,16 +150,16 @@ export class UserSubscriptionService {
150 if (nameWithHost in this.myAccountSubscriptionCache) { 150 if (nameWithHost in this.myAccountSubscriptionCache) {
151 logger('Found cache for %d.', nameWithHost) 151 logger('Found cache for %d.', nameWithHost)
152 152
153 return of(this.myAccountSubscriptionCache[ nameWithHost ]) 153 return of(this.myAccountSubscriptionCache[nameWithHost])
154 } 154 }
155 155
156 this.existsSubject.next(nameWithHost) 156 this.existsSubject.next(nameWithHost)
157 157
158 logger('Fetching from network for %d.', nameWithHost) 158 logger('Fetching from network for %d.', nameWithHost)
159 return this.existsObservable.pipe( 159 return this.existsObservable.pipe(
160 filter(existsResult => existsResult[ nameWithHost ] !== undefined), 160 filter(existsResult => existsResult[nameWithHost] !== undefined),
161 map(existsResult => existsResult[ nameWithHost ]), 161 map(existsResult => existsResult[nameWithHost]),
162 tap(result => this.myAccountSubscriptionCache[ nameWithHost ] = result) 162 tap(result => this.myAccountSubscriptionCache[nameWithHost] = result)
163 ) 163 )
164 } 164 }
165 165
diff --git a/client/src/app/shared/shared-video-comment/video-comment.model.ts b/client/src/app/shared/shared-video-comment/video-comment.model.ts
index ba0f57e8f..adab4cfbd 100644
--- a/client/src/app/shared/shared-video-comment/video-comment.model.ts
+++ b/client/src/app/shared/shared-video-comment/video-comment.model.ts
@@ -1,6 +1,10 @@
1import { getAbsoluteAPIUrl } from '@app/helpers' 1import { getAbsoluteAPIUrl } from '@app/helpers'
2import { Account, Actor, Video } from '@app/shared/shared-main' 2import { Actor, Video } from '@app/shared/shared-main'
3import { Account as AccountInterface, VideoComment as VideoCommentServerModel, VideoCommentAdmin as VideoCommentAdminServerModel } from '@shared/models' 3import {
4 Account as AccountInterface,
5 VideoComment as VideoCommentServerModel,
6 VideoCommentAdmin as VideoCommentAdminServerModel
7} from '@shared/models'
4 8
5export class VideoComment implements VideoCommentServerModel { 9export class VideoComment implements VideoCommentServerModel {
6 id: number 10 id: number
diff --git a/client/src/app/shared/shared-video-comment/video-comment.service.ts b/client/src/app/shared/shared-video-comment/video-comment.service.ts
index 4f1452116..5550c96e4 100644
--- a/client/src/app/shared/shared-video-comment/video-comment.service.ts
+++ b/client/src/app/shared/shared-video-comment/video-comment.service.ts
@@ -37,8 +37,8 @@ export class VideoCommentService {
37 37
38 return this.authHttp.post<{ comment: VideoCommentServerModel }>(url, normalizedComment) 38 return this.authHttp.post<{ comment: VideoCommentServerModel }>(url, normalizedComment)
39 .pipe( 39 .pipe(
40 map(data => this.extractVideoComment(data.comment)), 40 map(data => this.extractVideoComment(data.comment)),
41 catchError(err => this.restExtractor.handleError(err)) 41 catchError(err => this.restExtractor.handleError(err))
42 ) 42 )
43 } 43 }
44 44
@@ -54,8 +54,8 @@ export class VideoCommentService {
54 } 54 }
55 55
56 getAdminVideoComments (options: { 56 getAdminVideoComments (options: {
57 pagination: RestPagination, 57 pagination: RestPagination
58 sort: SortMeta, 58 sort: SortMeta
59 search?: string 59 search?: string
60 }): Observable<ResultList<VideoCommentAdmin>> { 60 }): Observable<ResultList<VideoCommentAdmin>> {
61 const { pagination, sort, search } = options 61 const { pagination, sort, search } = options
@@ -75,8 +75,8 @@ export class VideoCommentService {
75 } 75 }
76 76
77 getVideoCommentThreads (parameters: { 77 getVideoCommentThreads (parameters: {
78 videoId: number | string, 78 videoId: number | string
79 componentPagination: ComponentPaginationLight, 79 componentPagination: ComponentPaginationLight
80 sort: string 80 sort: string
81 }): Observable<ThreadsResultList<VideoComment>> { 81 }): Observable<ThreadsResultList<VideoComment>> {
82 const { videoId, componentPagination, sort } = parameters 82 const { videoId, componentPagination, sort } = parameters
@@ -95,7 +95,7 @@ export class VideoCommentService {
95 } 95 }
96 96
97 getVideoThreadComments (parameters: { 97 getVideoThreadComments (parameters: {
98 videoId: number | string, 98 videoId: number | string
99 threadId: number 99 threadId: number
100 }): Observable<VideoCommentThreadTree> { 100 }): Observable<VideoCommentThreadTree> {
101 const { videoId, threadId } = parameters 101 const { videoId, threadId } = parameters
diff --git a/client/src/app/shared/shared-video-miniature/abstract-video-list.ts b/client/src/app/shared/shared-video-miniature/abstract-video-list.ts
index d8b2ee17d..f12ae2ee5 100644
--- a/client/src/app/shared/shared-video-miniature/abstract-video-list.ts
+++ b/client/src/app/shared/shared-video-miniature/abstract-video-list.ts
@@ -42,7 +42,7 @@ enum GroupDate {
42} 42}
43 43
44@Directive() 44@Directive()
45// tslint:disable-next-line: directive-class-suffix 45// eslint-disable-next-line @angular-eslint/directive-class-suffix
46export abstract class AbstractVideoList implements OnInit, OnDestroy, AfterContentInit, DisableForReuseHook { 46export abstract class AbstractVideoList implements OnInit, OnDestroy, AfterContentInit, DisableForReuseHook {
47 @ViewChild('videoListHeader', { static: true, read: ViewContainerRef }) videoListHeader: ViewContainerRef 47 @ViewChild('videoListHeader', { static: true, read: ViewContainerRef }) videoListHeader: ViewContainerRef
48 48
@@ -174,7 +174,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, AfterConte
174 ngAfterContentInit () { 174 ngAfterContentInit () {
175 if (this.videoListHeader) { 175 if (this.videoListHeader) {
176 // some components don't use the header: they use their own template, like my-history.component.html 176 // some components don't use the header: they use their own template, like my-history.component.html
177 this.setHeader.apply(this, [ this.HeaderComponent, this.headerComponentInjector ]) 177 this.setHeader(this.HeaderComponent, this.headerComponentInjector)
178 } 178 }
179 } 179 }
180 180
@@ -278,7 +278,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, AfterConte
278 278
279 if (currentGroupedDate !== period.value) { 279 if (currentGroupedDate !== period.value) {
280 currentGroupedDate = period.value 280 currentGroupedDate = period.value
281 this.groupedDates[ video.id ] = currentGroupedDate 281 this.groupedDates[video.id] = currentGroupedDate
282 } 282 }
283 283
284 break 284 break
@@ -302,13 +302,13 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, AfterConte
302 i: Injector = this.headerComponentInjector 302 i: Injector = this.headerComponentInjector
303 ) { 303 ) {
304 const injector = i || Injector.create({ 304 const injector = i || Injector.create({
305 providers: [{ 305 providers: [ {
306 provide: 'data', 306 provide: 'data',
307 useValue: { 307 useValue: {
308 titlePage: this.titlePage, 308 titlePage: this.titlePage,
309 titleTooltip: this.titleTooltip 309 titleTooltip: this.titleTooltip
310 } 310 }
311 }] 311 } ]
312 }) 312 })
313 const viewContainerRef = this.videoListHeader 313 const viewContainerRef = this.videoListHeader
314 viewContainerRef.clear() 314 viewContainerRef.clear()
@@ -331,9 +331,9 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, AfterConte
331 protected loadPageRouteParams (_queryParams: Params) { /* empty */ } 331 protected loadPageRouteParams (_queryParams: Params) { /* empty */ }
332 332
333 protected loadRouteParams (queryParams: Params) { 333 protected loadRouteParams (queryParams: Params) {
334 this.sort = queryParams[ 'sort' ] as VideoSortField || this.defaultSort 334 this.sort = queryParams['sort'] as VideoSortField || this.defaultSort
335 this.categoryOneOf = queryParams[ 'categoryOneOf' ] 335 this.categoryOneOf = queryParams['categoryOneOf']
336 this.angularState = queryParams[ 'a-state' ] 336 this.angularState = queryParams['a-state']
337 337
338 this.loadPageRouteParams(queryParams) 338 this.loadPageRouteParams(queryParams)
339 } 339 }
diff --git a/client/src/app/shared/shared-video-miniature/video-download.component.ts b/client/src/app/shared/shared-video-miniature/video-download.component.ts
index 28fefb9dd..5328f5170 100644
--- a/client/src/app/shared/shared-video-miniature/video-download.component.ts
+++ b/client/src/app/shared/shared-video-miniature/video-download.component.ts
@@ -210,10 +210,10 @@ export class VideoDownloadComponent {
210 210
211 private getMetadataFormat (format: any) { 211 private getMetadataFormat (format: any) {
212 const keyToTranslateFunction = { 212 const keyToTranslateFunction = {
213 'encoder': (value: string) => ({ label: $localize`Encoder`, value }), 213 encoder: (value: string) => ({ label: $localize`Encoder`, value }),
214 'format_long_name': (value: string) => ({ label: $localize`Format name`, value }), 214 format_long_name: (value: string) => ({ label: $localize`Format name`, value }),
215 'size': (value: number) => ({ label: $localize`Size`, value: this.bytesPipe.transform(value, 2) }), 215 size: (value: number) => ({ label: $localize`Size`, value: this.bytesPipe.transform(value, 2) }),
216 'bit_rate': (value: number) => ({ 216 bit_rate: (value: number) => ({
217 label: $localize`Bitrate`, 217 label: $localize`Bitrate`,
218 value: `${this.numbersPipe.transform(value)}bps` 218 value: `${this.numbersPipe.transform(value)}bps`
219 }) 219 })
@@ -234,9 +234,9 @@ export class VideoDownloadComponent {
234 if (!stream) return undefined 234 if (!stream) return undefined
235 235
236 let keyToTranslateFunction = { 236 let keyToTranslateFunction = {
237 'codec_long_name': (value: string) => ({ label: $localize`Codec`, value }), 237 codec_long_name: (value: string) => ({ label: $localize`Codec`, value }),
238 'profile': (value: string) => ({ label: $localize`Profile`, value }), 238 profile: (value: string) => ({ label: $localize`Profile`, value }),
239 'bit_rate': (value: number) => ({ 239 bit_rate: (value: number) => ({
240 label: $localize`Bitrate`, 240 label: $localize`Bitrate`,
241 value: `${this.numbersPipe.transform(value)}bps` 241 value: `${this.numbersPipe.transform(value)}bps`
242 }) 242 })
@@ -244,15 +244,15 @@ export class VideoDownloadComponent {
244 244
245 if (type === 'video') { 245 if (type === 'video') {
246 keyToTranslateFunction = Object.assign(keyToTranslateFunction, { 246 keyToTranslateFunction = Object.assign(keyToTranslateFunction, {
247 'width': (value: number) => ({ label: $localize`Resolution`, value: `${value}x${stream.height}` }), 247 width: (value: number) => ({ label: $localize`Resolution`, value: `${value}x${stream.height}` }),
248 'display_aspect_ratio': (value: string) => ({ label: $localize`Aspect ratio`, value }), 248 display_aspect_ratio: (value: string) => ({ label: $localize`Aspect ratio`, value }),
249 'avg_frame_rate': (value: string) => ({ label: $localize`Average frame rate`, value }), 249 avg_frame_rate: (value: string) => ({ label: $localize`Average frame rate`, value }),
250 'pix_fmt': (value: string) => ({ label: $localize`Pixel format`, value }) 250 pix_fmt: (value: string) => ({ label: $localize`Pixel format`, value })
251 }) 251 })
252 } else { 252 } else {
253 keyToTranslateFunction = Object.assign(keyToTranslateFunction, { 253 keyToTranslateFunction = Object.assign(keyToTranslateFunction, {
254 'sample_rate': (value: number) => ({ label: $localize`Sample rate`, value }), 254 sample_rate: (value: number) => ({ label: $localize`Sample rate`, value }),
255 'channel_layout': (value: number) => ({ label: $localize`Channel Layout`, value }) 255 channel_layout: (value: number) => ({ label: $localize`Channel Layout`, value })
256 }) 256 })
257 } 257 }
258 258
diff --git a/client/src/app/shared/shared-video-miniature/video-list-header.component.ts b/client/src/app/shared/shared-video-miniature/video-list-header.component.ts
index 08a961be1..fed696672 100644
--- a/client/src/app/shared/shared-video-miniature/video-list-header.component.ts
+++ b/client/src/app/shared/shared-video-miniature/video-list-header.component.ts
@@ -11,7 +11,7 @@ export abstract class GenericHeaderComponent {
11 11
12@Component({ 12@Component({
13 selector: 'my-video-list-header', 13 selector: 'my-video-list-header',
14 // tslint:disable-next-line:use-component-view-encapsulation 14 // eslint-disable-next-line @angular-eslint/use-component-view-encapsulation
15 encapsulation: ViewEncapsulation.None, 15 encapsulation: ViewEncapsulation.None,
16 templateUrl: './video-list-header.component.html' 16 templateUrl: './video-list-header.component.html'
17}) 17})
diff --git a/client/src/app/shared/shared-video-miniature/videos-selection.component.ts b/client/src/app/shared/shared-video-miniature/videos-selection.component.ts
index d64ee9b98..456b36926 100644
--- a/client/src/app/shared/shared-video-miniature/videos-selection.component.ts
+++ b/client/src/app/shared/shared-video-miniature/videos-selection.component.ts
@@ -108,7 +108,7 @@ export class VideosSelectionComponent extends AbstractVideoList implements OnIni
108 } 108 }
109 109
110 isInSelectionMode () { 110 isInSelectionMode () {
111 return Object.keys(this._selection).some(k => this._selection[ k ] === true) 111 return Object.keys(this._selection).some(k => this._selection[k] === true)
112 } 112 }
113 113
114 generateSyndicationList () { 114 generateSyndicationList () {
diff --git a/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts b/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts
index df3aeddb7..553930595 100644
--- a/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts
+++ b/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts
@@ -191,7 +191,7 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
191 } 191 }
192 192
193 createPlaylist () { 193 createPlaylist () {
194 const displayName = this.form.value[ 'displayName' ] 194 const displayName = this.form.value['displayName']
195 195
196 const videoPlaylistCreate: VideoPlaylistCreate = { 196 const videoPlaylistCreate: VideoPlaylistCreate = {
197 displayName, 197 displayName,
diff --git a/client/src/app/shared/shared-video-playlist/video-playlist-element.model.ts b/client/src/app/shared/shared-video-playlist/video-playlist-element.model.ts
index f25f10ede..b661378bd 100644
--- a/client/src/app/shared/shared-video-playlist/video-playlist-element.model.ts
+++ b/client/src/app/shared/shared-video-playlist/video-playlist-element.model.ts
@@ -11,7 +11,7 @@ export class VideoPlaylistElement implements ServerVideoPlaylistElement {
11 11
12 video?: Video 12 video?: Video
13 13
14 constructor (hash: ServerVideoPlaylistElement, translations: {}) { 14 constructor (hash: ServerVideoPlaylistElement, translations: { [ id: string ]: string } = {}) {
15 this.id = hash.id 15 this.id = hash.id
16 this.position = hash.position 16 this.position = hash.position
17 this.startTimestamp = hash.startTimestamp 17 this.startTimestamp = hash.startTimestamp
diff --git a/client/src/app/shared/shared-video-playlist/video-playlist.model.ts b/client/src/app/shared/shared-video-playlist/video-playlist.model.ts
index fcc2ce705..6b38d9ca3 100644
--- a/client/src/app/shared/shared-video-playlist/video-playlist.model.ts
+++ b/client/src/app/shared/shared-video-playlist/video-playlist.model.ts
@@ -48,7 +48,7 @@ export class VideoPlaylist implements ServerVideoPlaylist {
48 return buildPlaylistWatchPath({ shortUUID: playlist.shortUUID || playlist.uuid }) 48 return buildPlaylistWatchPath({ shortUUID: playlist.shortUUID || playlist.uuid })
49 } 49 }
50 50
51 constructor (hash: ServerVideoPlaylist, translations: {}) { 51 constructor (hash: ServerVideoPlaylist, translations: { [ id: string ]: string }) {
52 const absoluteAPIUrl = getAbsoluteAPIUrl() 52 const absoluteAPIUrl = getAbsoluteAPIUrl()
53 53
54 this.id = hash.id 54 this.id = hash.id
diff --git a/client/src/app/shared/shared-video-playlist/video-playlist.service.ts b/client/src/app/shared/shared-video-playlist/video-playlist.service.ts
index a3f1393ff..0a01af593 100644
--- a/client/src/app/shared/shared-video-playlist/video-playlist.service.ts
+++ b/client/src/app/shared/shared-video-playlist/video-playlist.service.ts
@@ -279,18 +279,18 @@ export class VideoPlaylistService {
279 } 279 }
280 280
281 listenToVideoPlaylistChange (videoId: number) { 281 listenToVideoPlaylistChange (videoId: number) {
282 if (this.videoExistsObservableCache[ videoId ]) { 282 if (this.videoExistsObservableCache[videoId]) {
283 return this.videoExistsObservableCache[ videoId ] 283 return this.videoExistsObservableCache[videoId]
284 } 284 }
285 285
286 const obs = this.videoExistsInPlaylistObservable 286 const obs = this.videoExistsInPlaylistObservable
287 .pipe( 287 .pipe(
288 map(existsResult => existsResult[ videoId ]), 288 map(existsResult => existsResult[videoId]),
289 filter(r => !!r), 289 filter(r => !!r),
290 tap(result => this.videoExistsCache[ videoId ] = result) 290 tap(result => this.videoExistsCache[videoId] = result)
291 ) 291 )
292 292
293 this.videoExistsObservableCache[ videoId ] = obs 293 this.videoExistsObservableCache[videoId] = obs
294 return obs 294 return obs
295 } 295 }
296 296
diff --git a/client/src/assets/player/p2p-media-loader/hls-plugin.ts b/client/src/assets/player/p2p-media-loader/hls-plugin.ts
index 78f0944ef..a1b07aea6 100644
--- a/client/src/assets/player/p2p-media-loader/hls-plugin.ts
+++ b/client/src/assets/player/p2p-media-loader/hls-plugin.ts
@@ -13,6 +13,8 @@ type Metadata = {
13 levels: Level[] 13 levels: Level[]
14} 14}
15 15
16type HookFn = (player: videojs.Player, hljs: Hlsjs) => void
17
16const registerSourceHandler = function (vjs: typeof videojs) { 18const registerSourceHandler = function (vjs: typeof videojs) {
17 if (!Hlsjs.isSupported()) { 19 if (!Hlsjs.isSupported()) {
18 console.warn('Hls.js is not supported in this browser!') 20 console.warn('Hls.js is not supported in this browser!')
@@ -82,7 +84,7 @@ const registerConfigPlugin = function (vjs: typeof videojs) {
82} 84}
83 85
84class Html5Hlsjs { 86class Html5Hlsjs {
85 private static readonly hooks: { [id: string]: Function[] } = {} 87 private static readonly hooks: { [id: string]: HookFn[] } = {}
86 88
87 private readonly videoElement: HTMLVideoElement 89 private readonly videoElement: HTMLVideoElement
88 private readonly errorCounts: ErrorCounts = {} 90 private readonly errorCounts: ErrorCounts = {}
@@ -131,7 +133,8 @@ class Html5Hlsjs {
131 errorTxt = 'You aborted the video playback' 133 errorTxt = 'You aborted the video playback'
132 break 134 break
133 case mediaError.MEDIA_ERR_DECODE: 135 case mediaError.MEDIA_ERR_DECODE:
134 errorTxt = 'The video playback was aborted due to a corruption problem or because the video used features your browser did not support' 136 errorTxt = 'The video playback was aborted due to a corruption problem or because the video used features ' +
137 'your browser did not support'
135 this._handleMediaError(mediaError) 138 this._handleMediaError(mediaError)
136 break 139 break
137 case mediaError.MEDIA_ERR_NETWORK: 140 case mediaError.MEDIA_ERR_NETWORK:
@@ -182,58 +185,57 @@ class Html5Hlsjs {
182 this.hls.destroy() 185 this.hls.destroy()
183 } 186 }
184 187
185 static addHook (type: string, callback: Function) { 188 static addHook (type: string, callback: HookFn) {
186 Html5Hlsjs.hooks[ type ] = this.hooks[ type ] || [] 189 Html5Hlsjs.hooks[type] = this.hooks[type] || []
187 Html5Hlsjs.hooks[ type ].push(callback) 190 Html5Hlsjs.hooks[type].push(callback)
188 } 191 }
189 192
190 static removeHook (type: string, callback: Function) { 193 static removeHook (type: string, callback: HookFn) {
191 if (Html5Hlsjs.hooks[ type ] === undefined) return false 194 if (Html5Hlsjs.hooks[type] === undefined) return false
192 195
193 const index = Html5Hlsjs.hooks[ type ].indexOf(callback) 196 const index = Html5Hlsjs.hooks[type].indexOf(callback)
194 if (index === -1) return false 197 if (index === -1) return false
195 198
196 Html5Hlsjs.hooks[ type ].splice(index, 1) 199 Html5Hlsjs.hooks[type].splice(index, 1)
197 200
198 return true 201 return true
199 } 202 }
200 203
201 private _executeHooksFor (type: string) { 204 private _executeHooksFor (type: string) {
202 if (Html5Hlsjs.hooks[ type ] === undefined) { 205 if (Html5Hlsjs.hooks[type] === undefined) {
203 return 206 return
204 } 207 }
205 208
206 // ES3 and IE < 9 209 // ES3 and IE < 9
207 for (let i = 0; i < Html5Hlsjs.hooks[ type ].length; i++) { 210 for (let i = 0; i < Html5Hlsjs.hooks[type].length; i++) {
208 Html5Hlsjs.hooks[ type ][ i ](this.player, this.hls) 211 Html5Hlsjs.hooks[type][i](this.player, this.hls)
209 } 212 }
210 } 213 }
211 214
212 private _handleMediaError (error: any) { 215 private _handleMediaError (error: any) {
213 if (this.errorCounts[ Hlsjs.ErrorTypes.MEDIA_ERROR ] === 1) { 216 if (this.errorCounts[Hlsjs.ErrorTypes.MEDIA_ERROR] === 1) {
214 console.info('trying to recover media error') 217 console.info('trying to recover media error')
215 this.hls.recoverMediaError() 218 this.hls.recoverMediaError()
216 return 219 return
217 } 220 }
218 221
219 if (this.errorCounts[ Hlsjs.ErrorTypes.MEDIA_ERROR ] === 2) { 222 if (this.errorCounts[Hlsjs.ErrorTypes.MEDIA_ERROR] === 2) {
220 console.info('2nd try to recover media error (by swapping audio codec') 223 console.info('2nd try to recover media error (by swapping audio codec')
221 this.hls.swapAudioCodec() 224 this.hls.swapAudioCodec()
222 this.hls.recoverMediaError() 225 this.hls.recoverMediaError()
223 return 226 return
224 } 227 }
225 228
226 if (this.errorCounts[ Hlsjs.ErrorTypes.MEDIA_ERROR ] > 2) { 229 if (this.errorCounts[Hlsjs.ErrorTypes.MEDIA_ERROR] > 2) {
227 console.info('bubbling media error up to VIDEOJS') 230 console.info('bubbling media error up to VIDEOJS')
228 this.hls.destroy() 231 this.hls.destroy()
229 this.tech.error = () => error 232 this.tech.error = () => error
230 this.tech.trigger('error') 233 this.tech.trigger('error')
231 return
232 } 234 }
233 } 235 }
234 236
235 private _handleNetworkError (error: any) { 237 private _handleNetworkError (error: any) {
236 if (this.errorCounts[ Hlsjs.ErrorTypes.NETWORK_ERROR] <= 5) { 238 if (this.errorCounts[Hlsjs.ErrorTypes.NETWORK_ERROR] <= 5) {
237 console.info('trying to recover network error') 239 console.info('trying to recover network error')
238 240
239 // Wait 1 second and retry 241 // Wait 1 second and retry
@@ -241,7 +243,7 @@ class Html5Hlsjs {
241 243
242 // Reset error count on success 244 // Reset error count on success
243 this.hls.once(Hlsjs.Events.FRAG_LOADED, () => { 245 this.hls.once(Hlsjs.Events.FRAG_LOADED, () => {
244 this.errorCounts[ Hlsjs.ErrorTypes.NETWORK_ERROR] = 0 246 this.errorCounts[Hlsjs.ErrorTypes.NETWORK_ERROR] = 0
245 }) 247 })
246 248
247 return 249 return
@@ -259,8 +261,8 @@ class Html5Hlsjs {
259 } 261 }
260 262
261 // increment/set error count 263 // increment/set error count
262 if (this.errorCounts[ data.type ]) this.errorCounts[ data.type ] += 1 264 if (this.errorCounts[data.type]) this.errorCounts[data.type] += 1
263 else this.errorCounts[ data.type ] = 1 265 else this.errorCounts[data.type] = 1
264 266
265 if (data.fatal) console.warn(error.message) 267 if (data.fatal) console.warn(error.message)
266 else console.error(error.message, data) 268 else console.error(error.message, data)
@@ -300,7 +302,7 @@ class Html5Hlsjs {
300 let isAuto = true 302 let isAuto = true
301 303
302 for (let i = 0; i < qualityLevels.length; i++) { 304 for (let i = 0; i < qualityLevels.length; i++) {
303 if (!qualityLevels[ i ]._enabled) { 305 if (!qualityLevels[i]._enabled) {
304 isAuto = false 306 isAuto = false
305 break 307 break
306 } 308 }
@@ -316,7 +318,7 @@ class Html5Hlsjs {
316 let selectedTrack: number 318 let selectedTrack: number
317 319
318 for (selectedTrack = qualityLevels.length - 1; selectedTrack >= 0; selectedTrack--) { 320 for (selectedTrack = qualityLevels.length - 1; selectedTrack >= 0; selectedTrack--) {
319 if (qualityLevels[ selectedTrack ]._enabled) { 321 if (qualityLevels[selectedTrack]._enabled) {
320 break 322 break
321 } 323 }
322 } 324 }
@@ -327,11 +329,11 @@ class Html5Hlsjs {
327 private _handleQualityLevels () { 329 private _handleQualityLevels () {
328 if (!this.metadata) return 330 if (!this.metadata) return
329 331
330 const qualityLevels = this.player.qualityLevels && this.player.qualityLevels() 332 const qualityLevels = this.player.qualityLevels?.()
331 if (!qualityLevels) return 333 if (!qualityLevels) return
332 334
333 for (let i = 0; i < this.metadata.levels.length; i++) { 335 for (let i = 0; i < this.metadata.levels.length; i++) {
334 const details = this.metadata.levels[ i ] 336 const details = this.metadata.levels[i]
335 const representation: QualityLevelRepresentation = { 337 const representation: QualityLevelRepresentation = {
336 id: i, 338 id: i,
337 width: details.width, 339 width: details.width,
@@ -345,11 +347,11 @@ class Html5Hlsjs {
345 representation.enabled = function (this: QualityLevels, level: number, toggle?: boolean) { 347 representation.enabled = function (this: QualityLevels, level: number, toggle?: boolean) {
346 // Brightcove switcher works TextTracks-style (enable tracks that it wants to ABR on) 348 // Brightcove switcher works TextTracks-style (enable tracks that it wants to ABR on)
347 if (typeof toggle === 'boolean') { 349 if (typeof toggle === 'boolean') {
348 this[ level ]._enabled = toggle 350 this[level]._enabled = toggle
349 self._relayQualityChange(this) 351 self._relayQualityChange(this)
350 } 352 }
351 353
352 return this[ level ]._enabled 354 return this[level]._enabled
353 } 355 }
354 356
355 qualityLevels.addQualityLevel(representation) 357 qualityLevels.addQualityLevel(representation)
@@ -395,7 +397,7 @@ class Html5Hlsjs {
395 const playerAudioTracks = this.tech.audioTracks() 397 const playerAudioTracks = this.tech.audioTracks()
396 for (let j = 0; j < playerAudioTracks.length; j++) { 398 for (let j = 0; j < playerAudioTracks.length; j++) {
397 // FIXME: typings 399 // FIXME: typings
398 if ((playerAudioTracks[ j ] as any).enabled) { 400 if ((playerAudioTracks[j] as any).enabled) {
399 this.hls.audioTrack = j 401 this.hls.audioTrack = j
400 break 402 break
401 } 403 }
@@ -412,8 +414,8 @@ class Html5Hlsjs {
412 playerAudioTracks.addTrack(new this.vjs.AudioTrack({ 414 playerAudioTracks.addTrack(new this.vjs.AudioTrack({
413 id: i.toString(), 415 id: i.toString(),
414 kind: 'alternative', 416 kind: 'alternative',
415 label: hlsAudioTracks[ i ].name || hlsAudioTracks[ i ].lang, 417 label: hlsAudioTracks[i].name || hlsAudioTracks[i].lang,
416 language: hlsAudioTracks[ i ].lang, 418 language: hlsAudioTracks[i].lang,
417 enabled: i === this.hls.audioTrack 419 enabled: i === this.hls.audioTrack
418 })) 420 }))
419 } 421 }
@@ -430,8 +432,8 @@ class Html5Hlsjs {
430 } 432 }
431 433
432 private _isSameTextTrack (track1: TextTrack, track2: TextTrack) { 434 private _isSameTextTrack (track1: TextTrack, track2: TextTrack) {
433 return this._getTextTrackLabel(track1) === this._getTextTrackLabel(track2) 435 return this._getTextTrackLabel(track1) === this._getTextTrackLabel(track2) &&
434 && track1.kind === track2.kind 436 track1.kind === track2.kind
435 } 437 }
436 438
437 private _updateSelectedTextTrack () { 439 private _updateSelectedTextTrack () {
@@ -439,16 +441,16 @@ class Html5Hlsjs {
439 let activeTrack: TextTrack = null 441 let activeTrack: TextTrack = null
440 442
441 for (let j = 0; j < playerTextTracks.length; j++) { 443 for (let j = 0; j < playerTextTracks.length; j++) {
442 if (playerTextTracks[ j ].mode === 'showing') { 444 if (playerTextTracks[j].mode === 'showing') {
443 activeTrack = playerTextTracks[ j ] 445 activeTrack = playerTextTracks[j]
444 break 446 break
445 } 447 }
446 } 448 }
447 449
448 const hlsjsTracks = this.videoElement.textTracks 450 const hlsjsTracks = this.videoElement.textTracks
449 for (let k = 0; k < hlsjsTracks.length; k++) { 451 for (let k = 0; k < hlsjsTracks.length; k++) {
450 if (hlsjsTracks[ k ].kind === 'subtitles' || hlsjsTracks[ k ].kind === 'captions') { 452 if (hlsjsTracks[k].kind === 'subtitles' || hlsjsTracks[k].kind === 'captions') {
451 hlsjsTracks[ k ].mode = activeTrack && this._isSameTextTrack(hlsjsTracks[ k ], activeTrack) 453 hlsjsTracks[k].mode = activeTrack && this._isSameTextTrack(hlsjsTracks[k], activeTrack)
452 ? 'showing' 454 ? 'showing'
453 : 'disabled' 455 : 'disabled'
454 } 456 }
@@ -460,11 +462,11 @@ class Html5Hlsjs {
460 this.videoElement.removeEventListener('play', this.handlers.play) 462 this.videoElement.removeEventListener('play', this.handlers.play)
461 } 463 }
462 464
463 private _oneLevelObjClone (obj: object) { 465 private _oneLevelObjClone (obj: { [ id: string ]: any }) {
464 const result = {} 466 const result = {}
465 const objKeys = Object.keys(obj) 467 const objKeys = Object.keys(obj)
466 for (let i = 0; i < objKeys.length; i++) { 468 for (let i = 0; i < objKeys.length; i++) {
467 result[ objKeys[ i ] ] = obj[ objKeys[ i ] ] 469 result[objKeys[i]] = obj[objKeys[i]]
468 } 470 }
469 471
470 return result 472 return result
@@ -475,8 +477,8 @@ class Html5Hlsjs {
475 477
476 // Filter out tracks that is displayable (captions or subtitles) 478 // Filter out tracks that is displayable (captions or subtitles)
477 for (let idx = 0; idx < textTracks.length; idx++) { 479 for (let idx = 0; idx < textTracks.length; idx++) {
478 if (textTracks[ idx ].kind === 'subtitles' || textTracks[ idx ].kind === 'captions') { 480 if (textTracks[idx].kind === 'subtitles' || textTracks[idx].kind === 'captions') {
479 displayableTracks.push(textTracks[ idx ]) 481 displayableTracks.push(textTracks[idx])
480 } 482 }
481 } 483 }
482 484
@@ -493,14 +495,14 @@ class Html5Hlsjs {
493 let isAdded = false 495 let isAdded = false
494 496
495 for (let jdx = 0; jdx < playerTextTracks.length; jdx++) { 497 for (let jdx = 0; jdx < playerTextTracks.length; jdx++) {
496 if (this._isSameTextTrack(displayableTracks[ idx ], playerTextTracks[ jdx ])) { 498 if (this._isSameTextTrack(displayableTracks[idx], playerTextTracks[jdx])) {
497 isAdded = true 499 isAdded = true
498 break 500 break
499 } 501 }
500 } 502 }
501 503
502 if (!isAdded) { 504 if (!isAdded) {
503 const hlsjsTextTrack = displayableTracks[ idx ] 505 const hlsjsTextTrack = displayableTracks[idx]
504 this.player.addRemoteTextTrack({ 506 this.player.addRemoteTextTrack({
505 kind: hlsjsTextTrack.kind as videojs.TextTrack.Kind, 507 kind: hlsjsTextTrack.kind as videojs.TextTrack.Kind,
506 label: this._getTextTrackLabel(hlsjsTextTrack), 508 label: this._getTextTrackLabel(hlsjsTextTrack),
@@ -536,12 +538,12 @@ class Html5Hlsjs {
536 const VTTCue = (window as any).VTTCue || (window as any).TextTrackCue 538 const VTTCue = (window as any).VTTCue || (window as any).TextTrackCue
537 539
538 for (let r = 0; r < captionScreen.rows.length; r++) { 540 for (let r = 0; r < captionScreen.rows.length; r++) {
539 row = captionScreen.rows[ r ] 541 row = captionScreen.rows[r]
540 text = '' 542 text = ''
541 543
542 if (!row.isEmpty()) { 544 if (!row.isEmpty()) {
543 for (let c = 0; c < row.chars.length; c++) { 545 for (let c = 0; c < row.chars.length; c++) {
544 text += row.chars[ c ].ucharj 546 text += row.chars[c].ucharj
545 } 547 }
546 548
547 cue = new VTTCue(startTime, endTime, text.trim()) 549 cue = new VTTCue(startTime, endTime, text.trim())
@@ -552,7 +554,7 @@ class Html5Hlsjs {
552 const configKeys = Object.keys(captionConfig) 554 const configKeys = Object.keys(captionConfig)
553 555
554 for (let k = 0; k < configKeys.length; k++) { 556 for (let k = 0; k < configKeys.length; k++) {
555 cue[ configKeys[ k ] ] = captionConfig[ configKeys[ k ] ] 557 cue[configKeys[k]] = captionConfig[configKeys[k]]
556 } 558 }
557 } 559 }
558 track.addCue(cue) 560 track.addCue(cue)
@@ -567,7 +569,7 @@ class Html5Hlsjs {
567 const techOptions = this.tech.options_ as HlsjsConfigHandlerOptions 569 const techOptions = this.tech.options_ as HlsjsConfigHandlerOptions
568 const srOptions_ = this.player.srOptions_ 570 const srOptions_ = this.player.srOptions_
569 571
570 const hlsjsConfigRef = srOptions_ && srOptions_.hlsjsConfig || techOptions.hlsjsConfig 572 const hlsjsConfigRef = srOptions_?.hlsjsConfig || techOptions.hlsjsConfig
571 // Hls.js will write to the reference thus change the object for later streams 573 // Hls.js will write to the reference thus change the object for later streams
572 this.hlsjsConfig = hlsjsConfigRef ? this._oneLevelObjClone(hlsjsConfigRef) : {} 574 this.hlsjsConfig = hlsjsConfigRef ? this._oneLevelObjClone(hlsjsConfigRef) : {}
573 575
@@ -575,7 +577,7 @@ class Html5Hlsjs {
575 this.hlsjsConfig.autoStartLoad = false 577 this.hlsjsConfig.autoStartLoad = false
576 } 578 }
577 579
578 const captionConfig = srOptions_ && srOptions_.captionConfig || techOptions.captionConfig 580 const captionConfig = srOptions_?.captionConfig || techOptions.captionConfig
579 if (captionConfig) { 581 if (captionConfig) {
580 this.hlsjsConfig.cueHandler = this._createCueHandler(captionConfig) 582 this.hlsjsConfig.cueHandler = this._createCueHandler(captionConfig)
581 } 583 }
diff --git a/client/src/assets/player/p2p-media-loader/segment-validator.ts b/client/src/assets/player/p2p-media-loader/segment-validator.ts
index d0a4c4a3f..f7f83a8a4 100644
--- a/client/src/assets/player/p2p-media-loader/segment-validator.ts
+++ b/client/src/assets/player/p2p-media-loader/segment-validator.ts
@@ -86,6 +86,7 @@ async function sha256Hex (data?: ArrayBuffer) {
86 86
87 // Fallback for non HTTPS context 87 // Fallback for non HTTPS context
88 const shaModule = (await import('sha.js') as any).default 88 const shaModule = (await import('sha.js') as any).default
89 // eslint-disable-next-line new-cap
89 return new shaModule.sha256().update(Buffer.from(data)).digest('hex') 90 return new shaModule.sha256().update(Buffer.from(data)).digest('hex')
90} 91}
91 92
@@ -97,7 +98,9 @@ function bufferToHex (buffer?: ArrayBuffer) {
97 const h = '0123456789abcdef' 98 const h = '0123456789abcdef'
98 const o = new Uint8Array(buffer) 99 const o = new Uint8Array(buffer)
99 100
100 o.forEach((v: any) => s += h[ v >> 4 ] + h[ v & 15 ]) 101 o.forEach((v: any) => {
102 s += h[v >> 4] + h[v & 15]
103 })
101 104
102 return s 105 return s
103} 106}
diff --git a/client/src/assets/player/peertube-player-manager.ts b/client/src/assets/player/peertube-player-manager.ts
index c45e8f53e..f3c21fc4c 100644
--- a/client/src/assets/player/peertube-player-manager.ts
+++ b/client/src/assets/player/peertube-player-manager.ts
@@ -435,8 +435,6 @@ export class PeertubePlayerManager {
435 const p2pMediaLoaderOptions = options.p2pMediaLoader 435 const p2pMediaLoaderOptions = options.p2pMediaLoader
436 436
437 const autoplay = this.getAutoPlayValue(commonOptions.autoplay) === 'play' 437 const autoplay = this.getAutoPlayValue(commonOptions.autoplay) === 'play'
438 ? true
439 : false
440 438
441 const webtorrent = { 439 const webtorrent = {
442 autoplay, 440 autoplay,
@@ -459,10 +457,10 @@ export class PeertubePlayerManager {
459 theaterButton: boolean 457 theaterButton: boolean
460 captions: boolean 458 captions: boolean
461 459
462 nextVideo?: Function 460 nextVideo?: () => void
463 hasNextVideo?: () => boolean 461 hasNextVideo?: () => boolean
464 462
465 previousVideo?: Function 463 previousVideo?: () => void
466 hasPreviousVideo?: () => boolean 464 hasPreviousVideo?: () => boolean
467 }) { 465 }) {
468 const settingEntries = [] 466 const settingEntries = []
@@ -487,7 +485,7 @@ export class PeertubePlayerManager {
487 } 485 }
488 486
489 Object.assign(children, { 487 Object.assign(children, {
490 'previousVideoButton': buttonOptions 488 previousVideoButton: buttonOptions
491 }) 489 })
492 } 490 }
493 491
@@ -505,35 +503,35 @@ export class PeertubePlayerManager {
505 } 503 }
506 504
507 Object.assign(children, { 505 Object.assign(children, {
508 'nextVideoButton': buttonOptions 506 nextVideoButton: buttonOptions
509 }) 507 })
510 } 508 }
511 509
512 Object.assign(children, { 510 Object.assign(children, {
513 'currentTimeDisplay': {}, 511 currentTimeDisplay: {},
514 'timeDivider': {}, 512 timeDivider: {},
515 'durationDisplay': {}, 513 durationDisplay: {},
516 'liveDisplay': {}, 514 liveDisplay: {},
517 515
518 'flexibleWidthSpacer': {}, 516 flexibleWidthSpacer: {},
519 'progressControl': { 517 progressControl: {
520 children: { 518 children: {
521 'seekBar': { 519 seekBar: {
522 children: { 520 children: {
523 [loadProgressBar]: {}, 521 [loadProgressBar]: {},
524 'mouseTimeDisplay': {}, 522 mouseTimeDisplay: {},
525 'playProgressBar': {} 523 playProgressBar: {}
526 } 524 }
527 } 525 }
528 } 526 }
529 }, 527 },
530 528
531 'p2PInfoButton': {}, 529 p2PInfoButton: {},
532 530
533 'muteToggle': {}, 531 muteToggle: {},
534 'volumeControl': {}, 532 volumeControl: {},
535 533
536 'settingsButton': { 534 settingsButton: {
537 setup: { 535 setup: {
538 maxHeightOffset: 40 536 maxHeightOffset: 40
539 }, 537 },
@@ -543,18 +541,18 @@ export class PeertubePlayerManager {
543 541
544 if (options.peertubeLink === true) { 542 if (options.peertubeLink === true) {
545 Object.assign(children, { 543 Object.assign(children, {
546 'peerTubeLinkButton': { shortUUID: options.videoShortUUID } as PeerTubeLinkButtonOptions 544 peerTubeLinkButton: { shortUUID: options.videoShortUUID } as PeerTubeLinkButtonOptions
547 }) 545 })
548 } 546 }
549 547
550 if (options.theaterButton === true) { 548 if (options.theaterButton === true) {
551 Object.assign(children, { 549 Object.assign(children, {
552 'theaterButton': {} 550 theaterButton: {}
553 }) 551 })
554 } 552 }
555 553
556 Object.assign(children, { 554 Object.assign(children, {
557 'fullscreenToggle': {} 555 fullscreenToggle: {}
558 }) 556 })
559 557
560 return children 558 return children
diff --git a/client/src/assets/player/peertube-plugin.ts b/client/src/assets/player/peertube-plugin.ts
index ade8e2ee4..b4841b235 100644
--- a/client/src/assets/player/peertube-plugin.ts
+++ b/client/src/assets/player/peertube-plugin.ts
@@ -211,7 +211,7 @@ class PeerTubePlugin extends Plugin {
211 const body = new URLSearchParams() 211 const body = new URLSearchParams()
212 body.append('currentTime', currentTime.toString()) 212 body.append('currentTime', currentTime.toString())
213 213
214 const headers = new Headers({ 'Authorization': authorizationHeader }) 214 const headers = new Headers({ Authorization: authorizationHeader })
215 215
216 return fetch(url, { method: 'PUT', body, headers }) 216 return fetch(url, { method: 'PUT', body, headers })
217 } 217 }
diff --git a/client/src/assets/player/peertube-videojs-typings.ts b/client/src/assets/player/peertube-videojs-typings.ts
index f0eb129d4..97828c802 100644
--- a/client/src/assets/player/peertube-videojs-typings.ts
+++ b/client/src/assets/player/peertube-videojs-typings.ts
@@ -1,3 +1,6 @@
1// FIXME: lint
2/* eslint-disable @typescript-eslint/ban-types */
3
1import { HlsConfig, Level } from 'hls.js' 4import { HlsConfig, Level } from 'hls.js'
2import videojs from 'video.js' 5import videojs from 'video.js'
3import { VideoFile, VideoPlaylist, VideoPlaylistElement } from '@shared/models' 6import { VideoFile, VideoPlaylist, VideoPlaylistElement } from '@shared/models'
@@ -93,7 +96,7 @@ type VideoJSCaption = {
93} 96}
94 97
95type UserWatching = { 98type UserWatching = {
96 url: string, 99 url: string
97 authorizationHeader: string 100 authorizationHeader: string
98} 101}
99 102
@@ -166,7 +169,7 @@ type VideoJSPluginOptions = {
166} 169}
167 170
168type LoadedQualityData = { 171type LoadedQualityData = {
169 qualitySwitchCallback: Function, 172 qualitySwitchCallback: (resolutionId: number, type: 'video') => void
170 qualityData: { 173 qualityData: {
171 video: { 174 video: {
172 id: number 175 id: number
@@ -177,7 +180,7 @@ type LoadedQualityData = {
177} 180}
178 181
179type ResolutionUpdateData = { 182type ResolutionUpdateData = {
180 auto: boolean, 183 auto: boolean
181 resolutionId: number 184 resolutionId: number
182 id?: number 185 id?: number
183} 186}
diff --git a/client/src/assets/player/stats/stats-card.ts b/client/src/assets/player/stats/stats-card.ts
index b271d0526..a32f6fb97 100644
--- a/client/src/assets/player/stats/stats-card.ts
+++ b/client/src/assets/player/stats/stats-card.ts
@@ -39,10 +39,6 @@ class StatsCard extends Component {
39 intervalMs = 300 39 intervalMs = 300
40 playerNetworkInfo: PlayerNetworkInfo = {} 40 playerNetworkInfo: PlayerNetworkInfo = {}
41 41
42 constructor (player: videojs.Player, options: StatsCardOptions) {
43 super(player, options)
44 }
45
46 createEl () { 42 createEl () {
47 const container = super.createEl('div', { 43 const container = super.createEl('div', {
48 className: 'vjs-stats-content', 44 className: 'vjs-stats-content',
@@ -81,9 +77,8 @@ class StatsCard extends Component {
81 } 77 }
82 78
83 toggle () { 79 toggle () {
84 this.updateInterval 80 if (this.updateInterval) this.hide()
85 ? this.hide() 81 else this.show()
86 : this.show()
87 } 82 }
88 83
89 show () { 84 show () {
diff --git a/client/src/assets/player/translations-manager.ts b/client/src/assets/player/translations-manager.ts
index d5a09a31a..8a6e67dda 100644
--- a/client/src/assets/player/translations-manager.ts
+++ b/client/src/assets/player/translations-manager.ts
@@ -23,13 +23,13 @@ export class TranslationsManager {
23 23
24 let p: Promise<any> 24 let p: Promise<any>
25 25
26 if (TranslationsManager.videojsLocaleCache[ path ]) { 26 if (TranslationsManager.videojsLocaleCache[path]) {
27 p = Promise.resolve(TranslationsManager.videojsLocaleCache[ path ]) 27 p = Promise.resolve(TranslationsManager.videojsLocaleCache[path])
28 } else { 28 } else {
29 p = fetch(path + '/player.json') 29 p = fetch(path + '/player.json')
30 .then(res => res.json()) 30 .then(res => res.json())
31 .then(json => { 31 .then(json => {
32 TranslationsManager.videojsLocaleCache[ path ] = json 32 TranslationsManager.videojsLocaleCache[path] = json
33 return json 33 return json
34 }) 34 })
35 .catch(err => { 35 .catch(err => {
diff --git a/client/src/assets/player/upnext/end-card.ts b/client/src/assets/player/upnext/end-card.ts
index 8fabfc3fd..61668e407 100644
--- a/client/src/assets/player/upnext/end-card.ts
+++ b/client/src/assets/player/upnext/end-card.ts
@@ -9,7 +9,9 @@ function getMainTemplate (options: any) {
9 <div class="vjs-upnext-autoplay-icon"> 9 <div class="vjs-upnext-autoplay-icon">
10 <svg height="100%" version="1.1" viewbox="0 0 98 98" width="100%"> 10 <svg height="100%" version="1.1" viewbox="0 0 98 98" width="100%">
11 <circle class="vjs-upnext-svg-autoplay-circle" cx="49" cy="49" fill="#000" fill-opacity="0.8" r="48"></circle> 11 <circle class="vjs-upnext-svg-autoplay-circle" cx="49" cy="49" fill="#000" fill-opacity="0.8" r="48"></circle>
12 <circle class="vjs-upnext-svg-autoplay-ring" cx="-49" cy="49" fill-opacity="0" r="46.5" stroke="#FFFFFF" stroke-width="4" transform="rotate(-90)"></circle> 12 <circle class="vjs-upnext-svg-autoplay-ring" cx="-49" cy="49" fill-opacity="0" r="46.5"
13 stroke="#FFFFFF" stroke-width="4" transform="rotate(-90)"
14 ></circle>
13 <polygon class="vjs-upnext-svg-autoplay-triangle" fill="#fff" points="32,27 72,49 32,71"></polygon></svg> 15 <polygon class="vjs-upnext-svg-autoplay-triangle" fill="#fff" points="32,27 72,49 32,71"></polygon></svg>
14 </div> 16 </div>
15 <span class="vjs-upnext-bottom"> 17 <span class="vjs-upnext-bottom">
@@ -22,7 +24,7 @@ function getMainTemplate (options: any) {
22} 24}
23 25
24export interface EndCardOptions extends videojs.ComponentOptions { 26export interface EndCardOptions extends videojs.ComponentOptions {
25 next: Function, 27 next: () => void
26 getTitle: () => string 28 getTitle: () => string
27 timeout: number 29 timeout: number
28 cancelText: string 30 cancelText: string
@@ -99,11 +101,11 @@ class EndCard extends Component {
99 return container 101 return container
100 } 102 }
101 103
102 showCard (cb: Function) { 104 showCard (cb: (value: boolean) => void) {
103 let timeout: any 105 let timeout: any
104 106
105 this.autoplayRing.setAttribute('stroke-dasharray', '' + this.dashOffsetStart) 107 this.autoplayRing.setAttribute('stroke-dasharray', `${this.dashOffsetStart}`)
106 this.autoplayRing.setAttribute('stroke-dashoffset', '' + -this.dashOffsetStart) 108 this.autoplayRing.setAttribute('stroke-dashoffset', `${-this.dashOffsetStart}`)
107 109
108 this.title.innerHTML = this.options_.getTitle() 110 this.title.innerHTML = this.options_.getTitle()
109 111
@@ -123,7 +125,7 @@ class EndCard extends Component {
123 }) 125 })
124 126
125 const goToPercent = (percent: number) => { 127 const goToPercent = (percent: number) => {
126 const newOffset = Math.max(-this.dashOffsetTotal, - this.dashOffsetStart - percent * this.dashOffsetTotal / 2 / 100) 128 const newOffset = Math.max(-this.dashOffsetTotal, -this.dashOffsetStart - percent * this.dashOffsetTotal / 2 / 100)
127 this.autoplayRing.setAttribute('stroke-dashoffset', '' + newOffset) 129 this.autoplayRing.setAttribute('stroke-dashoffset', '' + newOffset)
128 } 130 }
129 131
diff --git a/client/src/assets/player/utils.ts b/client/src/assets/player/utils.ts
index f0a1b1aee..f2e9adb14 100644
--- a/client/src/assets/player/utils.ts
+++ b/client/src/assets/player/utils.ts
@@ -17,7 +17,7 @@ function isIOS () {
17 // Detect iPad Desktop mode 17 // Detect iPad Desktop mode
18 return !!(navigator.maxTouchPoints && 18 return !!(navigator.maxTouchPoints &&
19 navigator.maxTouchPoints > 2 && 19 navigator.maxTouchPoints > 2 &&
20 /MacIntel/.test(navigator.platform)) 20 navigator.platform.includes('MacIntel'))
21} 21}
22 22
23function isSafari () { 23function isSafari () {
diff --git a/client/src/assets/player/videojs-components/p2p-info-button.ts b/client/src/assets/player/videojs-components/p2p-info-button.ts
index 81f9544f4..07ed18989 100644
--- a/client/src/assets/player/videojs-components/p2p-info-button.ts
+++ b/client/src/assets/player/videojs-components/p2p-info-button.ts
@@ -96,11 +96,11 @@ class P2pInfoButton extends Button {
96 } 96 }
97 subDivWebtorrent.title += this.player().localize('Total uploaded: ') + totalUploaded.join(' ') 97 subDivWebtorrent.title += this.player().localize('Total uploaded: ') + totalUploaded.join(' ')
98 98
99 downloadSpeedNumber.textContent = downloadSpeed[ 0 ] 99 downloadSpeedNumber.textContent = downloadSpeed[0]
100 downloadSpeedUnit.textContent = ' ' + downloadSpeed[ 1 ] 100 downloadSpeedUnit.textContent = ' ' + downloadSpeed[1]
101 101
102 uploadSpeedNumber.textContent = uploadSpeed[ 0 ] 102 uploadSpeedNumber.textContent = uploadSpeed[0]
103 uploadSpeedUnit.textContent = ' ' + uploadSpeed[ 1 ] 103 uploadSpeedUnit.textContent = ' ' + uploadSpeed[1]
104 104
105 peersNumber.textContent = numPeers.toString() 105 peersNumber.textContent = numPeers.toString()
106 peersText.textContent = ' ' + (numPeers > 1 ? this.player().localize('peers') : this.player_.localize('peer')) 106 peersText.textContent = ' ' + (numPeers > 1 ? this.player().localize('peers') : this.player_.localize('peer'))
diff --git a/client/src/assets/player/videojs-components/resolution-menu-item.ts b/client/src/assets/player/videojs-components/resolution-menu-item.ts
index 73ad47d2b..c1f502600 100644
--- a/client/src/assets/player/videojs-components/resolution-menu-item.ts
+++ b/client/src/assets/player/videojs-components/resolution-menu-item.ts
@@ -6,7 +6,7 @@ const MenuItem = videojs.getComponent('MenuItem')
6export interface ResolutionMenuItemOptions extends videojs.MenuItemOptions { 6export interface ResolutionMenuItemOptions extends videojs.MenuItemOptions {
7 labels?: { [id: number]: string } 7 labels?: { [id: number]: string }
8 id: number 8 id: number
9 callback: Function 9 callback: (resolutionId: number, type: 'video') => void
10} 10}
11 11
12class ResolutionMenuItem extends MenuItem { 12class ResolutionMenuItem extends MenuItem {
@@ -14,7 +14,7 @@ class ResolutionMenuItem extends MenuItem {
14 private readonly label: string 14 private readonly label: string
15 // Only used for the automatic item 15 // Only used for the automatic item
16 private readonly labels: { [id: number]: string } 16 private readonly labels: { [id: number]: string }
17 private readonly callback: Function 17 private readonly callback: (resolutionId: number, type: 'video') => void
18 18
19 private autoResolutionPossible: boolean 19 private autoResolutionPossible: boolean
20 private currentResolutionLabel: string 20 private currentResolutionLabel: string
diff --git a/client/src/assets/player/videojs-components/settings-dialog.ts b/client/src/assets/player/videojs-components/settings-dialog.ts
index 41911e7e8..8cd98967f 100644
--- a/client/src/assets/player/videojs-components/settings-dialog.ts
+++ b/client/src/assets/player/videojs-components/settings-dialog.ts
@@ -12,8 +12,6 @@ class SettingsDialog extends Component {
12 /** 12 /**
13 * Create the component's DOM element 13 * Create the component's DOM element
14 * 14 *
15 * @return {Element}
16 * @method createEl
17 */ 15 */
18 createEl () { 16 createEl () {
19 const uniqueId = this.id() 17 const uniqueId = this.id()
@@ -25,7 +23,7 @@ class SettingsDialog extends Component {
25 innerHTML: '', 23 innerHTML: '',
26 tabIndex: -1 24 tabIndex: -1
27 }, { 25 }, {
28 'role': 'dialog', 26 role: 'dialog',
29 'aria-labelledby': dialogLabelId, 27 'aria-labelledby': dialogLabelId,
30 'aria-describedby': dialogDescriptionId 28 'aria-describedby': dialogDescriptionId
31 }) 29 })
diff --git a/client/src/assets/player/videojs-components/settings-menu-item.ts b/client/src/assets/player/videojs-components/settings-menu-item.ts
index f1342f179..1871d41f8 100644
--- a/client/src/assets/player/videojs-components/settings-menu-item.ts
+++ b/client/src/assets/player/videojs-components/settings-menu-item.ts
@@ -1,8 +1,8 @@
1import videojs from 'video.js'
1// Thanks to Yanko Shterev: https://github.com/yshterev/videojs-settings-menu 2// Thanks to Yanko Shterev: https://github.com/yshterev/videojs-settings-menu
2import { toTitleCase } from '../utils' 3import { toTitleCase } from '../utils'
3import videojs from 'video.js'
4import { SettingsButton } from './settings-menu-button'
5import { SettingsDialog } from './settings-dialog' 4import { SettingsDialog } from './settings-dialog'
5import { SettingsButton } from './settings-menu-button'
6import { SettingsPanel } from './settings-panel' 6import { SettingsPanel } from './settings-panel'
7import { SettingsPanelChild } from './settings-panel-child' 7import { SettingsPanelChild } from './settings-panel-child'
8 8
@@ -57,7 +57,7 @@ class SettingsMenuItem extends MenuItem {
57 const newOptions = Object.assign({}, options, { entry: options.menuButton, menuButton: this }) 57 const newOptions = Object.assign({}, options, { entry: options.menuButton, menuButton: this })
58 58
59 this.subMenu = new SubMenuComponent(this.player(), newOptions) as any // FIXME: typings 59 this.subMenu = new SubMenuComponent(this.player(), newOptions) as any // FIXME: typings
60 const subMenuClass = this.subMenu.buildCSSClass().split(' ')[ 0 ] 60 const subMenuClass = this.subMenu.buildCSSClass().split(' ')[0]
61 this.settingsSubMenuEl_.className += ' ' + subMenuClass 61 this.settingsSubMenuEl_.className += ' ' + subMenuClass
62 62
63 this.eventHandlers() 63 this.eventHandlers()
@@ -104,7 +104,7 @@ class SettingsMenuItem extends MenuItem {
104 target = event.currentTarget 104 target = event.currentTarget
105 } 105 }
106 106
107 if (target && target.classList.contains('vjs-back-button')) { 107 if (target?.classList.contains('vjs-back-button')) {
108 this.loadMainMenu() 108 this.loadMainMenu()
109 return 109 return
110 } 110 }
@@ -121,8 +121,6 @@ class SettingsMenuItem extends MenuItem {
121 /** 121 /**
122 * Create the component's DOM element 122 * Create the component's DOM element
123 * 123 *
124 * @return {Element}
125 * @method createEl
126 */ 124 */
127 createEl () { 125 createEl () {
128 const el = videojs.dom.createEl('li', { 126 const el = videojs.dom.createEl('li', {
@@ -198,14 +196,14 @@ class SettingsMenuItem extends MenuItem {
198 const prefix = [ 'webkit', 'moz', 'MS', 'o', '' ] 196 const prefix = [ 'webkit', 'moz', 'MS', 'o', '' ]
199 197
200 for (let p = 0; p < prefix.length; p++) { 198 for (let p = 0; p < prefix.length; p++) {
201 if (!prefix[ p ]) { 199 if (!prefix[p]) {
202 type = type.toLowerCase() 200 type = type.toLowerCase()
203 } 201 }
204 202
205 if (action === 'addEvent') { 203 if (action === 'addEvent') {
206 element.addEventListener(prefix[ p ] + type, callback, false) 204 element.addEventListener(prefix[p] + type, callback, false)
207 } else if (action === 'removeEvent') { 205 } else if (action === 'removeEvent') {
208 element.removeEventListener(prefix[ p ] + type, callback, false) 206 element.removeEventListener(prefix[p] + type, callback, false)
209 } 207 }
210 } 208 }
211 } 209 }
@@ -292,7 +290,10 @@ class SettingsMenuItem extends MenuItem {
292 // Thus we get the submenu value based on the labelEl of playbackRateMenuButton 290 // Thus we get the submenu value based on the labelEl of playbackRateMenuButton
293 if (subMenu === 'PlaybackRateMenuButton') { 291 if (subMenu === 'PlaybackRateMenuButton') {
294 const html = (this.subMenu as any).labelEl_.innerHTML 292 const html = (this.subMenu as any).labelEl_.innerHTML
295 setTimeout(() => this.settingsSubMenuValueEl_.innerHTML = html, 250) 293
294 setTimeout(() => {
295 this.settingsSubMenuValueEl_.innerHTML = html
296 }, 250)
296 } else { 297 } else {
297 // Loop trough the submenu items to find the selected child 298 // Loop trough the submenu items to find the selected child
298 for (const subMenuItem of this.subMenu.menu.children_) { 299 for (const subMenuItem of this.subMenu.menu.children_) {
diff --git a/client/src/assets/player/videojs-components/settings-panel-child.ts b/client/src/assets/player/videojs-components/settings-panel-child.ts
index d1582412c..161420c38 100644
--- a/client/src/assets/player/videojs-components/settings-panel-child.ts
+++ b/client/src/assets/player/videojs-components/settings-panel-child.ts
@@ -4,10 +4,6 @@ const Component = videojs.getComponent('Component')
4 4
5class SettingsPanelChild extends Component { 5class SettingsPanelChild extends Component {
6 6
7 constructor (player: videojs.Player, options?: videojs.ComponentOptions) {
8 super(player, options)
9 }
10
11 createEl () { 7 createEl () {
12 return super.createEl('div', { 8 return super.createEl('div', {
13 className: 'vjs-settings-panel-child', 9 className: 'vjs-settings-panel-child',
diff --git a/client/src/assets/player/videojs-components/settings-panel.ts b/client/src/assets/player/videojs-components/settings-panel.ts
index 1ad8bb1fc..28b579bdd 100644
--- a/client/src/assets/player/videojs-components/settings-panel.ts
+++ b/client/src/assets/player/videojs-components/settings-panel.ts
@@ -4,10 +4,6 @@ const Component = videojs.getComponent('Component')
4 4
5class SettingsPanel extends Component { 5class SettingsPanel extends Component {
6 6
7 constructor (player: videojs.Player, options?: videojs.ComponentOptions) {
8 super(player, options)
9 }
10
11 createEl () { 7 createEl () {
12 return super.createEl('div', { 8 return super.createEl('div', {
13 className: 'vjs-settings-panel', 9 className: 'vjs-settings-panel',
diff --git a/client/src/assets/player/webtorrent/peertube-chunk-store.ts b/client/src/assets/player/webtorrent/peertube-chunk-store.ts
index 66762bef8..93ca8e1d8 100644
--- a/client/src/assets/player/webtorrent/peertube-chunk-store.ts
+++ b/client/src/assets/player/webtorrent/peertube-chunk-store.ts
@@ -36,7 +36,7 @@ export class PeertubeChunkStore extends EventEmitter {
36 36
37 chunkLength: number 37 chunkLength: number
38 38
39 private pendingPut: { id: number, buf: Buffer, cb: Function }[] = [] 39 private pendingPut: { id: number, buf: Buffer, cb: (err?: Error) => void }[] = []
40 // If the store is full 40 // If the store is full
41 private memoryChunks: { [ id: number ]: Buffer | true } = {} 41 private memoryChunks: { [ id: number ]: Buffer | true } = {}
42 private databaseName: string 42 private databaseName: string
@@ -54,7 +54,7 @@ export class PeertubeChunkStore extends EventEmitter {
54 this.databaseName = 'webtorrent-chunks-' 54 this.databaseName = 'webtorrent-chunks-'
55 55
56 if (!opts) opts = {} 56 if (!opts) opts = {}
57 if (opts.torrent && opts.torrent.infoHash) this.databaseName += opts.torrent.infoHash 57 if (opts.torrent?.infoHash) this.databaseName += opts.torrent.infoHash
58 else this.databaseName += '-default' 58 else this.databaseName += '-default'
59 59
60 this.setMaxListeners(100) 60 this.setMaxListeners(100)
@@ -106,7 +106,9 @@ export class PeertubeChunkStore extends EventEmitter {
106 } catch (err) { 106 } catch (err) {
107 console.log('Cannot bulk insert chunks. Store them in memory.', { err }) 107 console.log('Cannot bulk insert chunks. Store them in memory.', { err })
108 108
109 processing.forEach(p => this.memoryChunks[ p.id ] = p.buf) 109 processing.forEach(p => {
110 this.memoryChunks[p.id] = p.buf
111 })
110 } finally { 112 } finally {
111 processing.forEach(p => p.cb()) 113 processing.forEach(p => p.cb())
112 } 114 }
diff --git a/client/src/assets/player/webtorrent/video-renderer.ts b/client/src/assets/player/webtorrent/video-renderer.ts
index c3cbea725..8fb3e9672 100644
--- a/client/src/assets/player/webtorrent/video-renderer.ts
+++ b/client/src/assets/player/webtorrent/video-renderer.ts
@@ -3,7 +3,7 @@
3 3
4const MediaElementWrapper = require('mediasource') 4const MediaElementWrapper = require('mediasource')
5import { extname } from 'path' 5import { extname } from 'path'
6const videostream = require('videostream') 6const Videostream = require('videostream')
7 7
8const VIDEOSTREAM_EXTS = [ 8const VIDEOSTREAM_EXTS = [
9 '.m4a', 9 '.m4a',
@@ -34,7 +34,7 @@ function renderMedia (file: any, elem: HTMLVideoElement, opts: RenderMediaOption
34 let renderer: any 34 let renderer: any
35 35
36 try { 36 try {
37 if (VIDEOSTREAM_EXTS.indexOf(extension) >= 0) { 37 if (VIDEOSTREAM_EXTS.includes(extension)) {
38 renderer = useVideostream() 38 renderer = useVideostream()
39 } else { 39 } else {
40 renderer = useMediaSource() 40 renderer = useMediaSource()
@@ -51,7 +51,7 @@ function renderMedia (file: any, elem: HTMLVideoElement, opts: RenderMediaOption
51 return callback(err) 51 return callback(err)
52 }) 52 })
53 preparedElem.addEventListener('loadstart', onLoadStart) 53 preparedElem.addEventListener('loadstart', onLoadStart)
54 return new videostream(file, preparedElem) 54 return new Videostream(file, preparedElem)
55 } 55 }
56 56
57 function useMediaSource (useVP9 = false) { 57 function useMediaSource (useVP9 = false) {
@@ -62,7 +62,7 @@ function renderMedia (file: any, elem: HTMLVideoElement, opts: RenderMediaOption
62 preparedElem.removeEventListener('error', onError) 62 preparedElem.removeEventListener('error', onError)
63 63
64 // Try with vp9 before returning an error 64 // Try with vp9 before returning an error
65 if (codecs.indexOf('vp8') !== -1) return fallbackToMediaSource(true) 65 if (codecs.includes('vp8')) return fallbackToMediaSource(true)
66 66
67 return callback(err) 67 return callback(err)
68 }) 68 })
diff --git a/client/src/assets/player/webtorrent/webtorrent-plugin.ts b/client/src/assets/player/webtorrent/webtorrent-plugin.ts
index 17d369c10..0587ddee6 100644
--- a/client/src/assets/player/webtorrent/webtorrent-plugin.ts
+++ b/client/src/assets/player/webtorrent/webtorrent-plugin.ts
@@ -17,8 +17,8 @@ import { renderVideo } from './video-renderer'
17const CacheChunkStore = require('cache-chunk-store') 17const CacheChunkStore = require('cache-chunk-store')
18 18
19type PlayOptions = { 19type PlayOptions = {
20 forcePlay?: boolean, 20 forcePlay?: boolean
21 seek?: number, 21 seek?: number
22 delay?: number 22 delay?: number
23} 23}
24 24
@@ -126,8 +126,8 @@ class WebTorrentPlugin extends Plugin {
126 updateVideoFile ( 126 updateVideoFile (
127 videoFile?: VideoFile, 127 videoFile?: VideoFile,
128 options: { 128 options: {
129 forcePlay?: boolean, 129 forcePlay?: boolean
130 seek?: number, 130 seek?: number
131 delay?: number 131 delay?: number
132 } = {}, 132 } = {},
133 done: () => void = () => { /* empty */ } 133 done: () => void = () => { /* empty */ }
@@ -248,7 +248,7 @@ class WebTorrentPlugin extends Plugin {
248 magnetOrTorrentUrl: string, 248 magnetOrTorrentUrl: string,
249 previousVideoFile: VideoFile, 249 previousVideoFile: VideoFile,
250 options: PlayOptions, 250 options: PlayOptions,
251 done: Function 251 done: (err?: Error) => void
252 ) { 252 ) {
253 if (!magnetOrTorrentUrl) return this.fallbackToHttp(options, done) 253 if (!magnetOrTorrentUrl) return this.fallbackToHttp(options, done)
254 254
@@ -272,7 +272,7 @@ class WebTorrentPlugin extends Plugin {
272 this.stopTorrent(oldTorrent) 272 this.stopTorrent(oldTorrent)
273 273
274 // We use a fake renderer so we download correct pieces of the next file 274 // We use a fake renderer so we download correct pieces of the next file
275 if (options.delay) this.renderFileInFakeElement(torrent.files[ 0 ], options.delay) 275 if (options.delay) this.renderFileInFakeElement(torrent.files[0], options.delay)
276 } 276 }
277 277
278 // Render the video in a few seconds? (on resolution change for example, we wait some seconds of the new video resolution) 278 // Render the video in a few seconds? (on resolution change for example, we wait some seconds of the new video resolution)
@@ -288,7 +288,7 @@ class WebTorrentPlugin extends Plugin {
288 if (options.seek) this.player.currentTime(options.seek) 288 if (options.seek) this.player.currentTime(options.seek)
289 289
290 const renderVideoOptions = { autoplay: false, controls: true } 290 const renderVideoOptions = { autoplay: false, controls: true }
291 renderVideo(torrent.files[ 0 ], this.playerElement, renderVideoOptions, (err, renderer) => { 291 renderVideo(torrent.files[0], this.playerElement, renderVideoOptions, (err, renderer) => {
292 this.renderer = renderer 292 this.renderer = renderer
293 293
294 if (err) return this.fallbackToHttp(options, done) 294 if (err) return this.fallbackToHttp(options, done)
@@ -321,7 +321,7 @@ class WebTorrentPlugin extends Plugin {
321 if (err.message.indexOf('incorrect info hash') !== -1) { 321 if (err.message.indexOf('incorrect info hash') !== -1) {
322 console.error('Incorrect info hash detected, falling back to torrent file.') 322 console.error('Incorrect info hash detected, falling back to torrent file.')
323 const newOptions = { forcePlay: true, seek: options.seek } 323 const newOptions = { forcePlay: true, seek: options.seek }
324 return this.addTorrent(this.torrent[ 'xs' ], previousVideoFile, newOptions, done) 324 return this.addTorrent(this.torrent['xs'], previousVideoFile, newOptions, done)
325 } 325 }
326 326
327 // Remote instance is down 327 // Remote instance is down
@@ -340,7 +340,7 @@ class WebTorrentPlugin extends Plugin {
340 if (playPromise !== undefined) { 340 if (playPromise !== undefined) {
341 return playPromise.then(() => done()) 341 return playPromise.then(() => done())
342 .catch((err: Error) => { 342 .catch((err: Error) => {
343 if (err.message.indexOf('The play() request was interrupted by a call to pause()') !== -1) { 343 if (err.message.includes('The play() request was interrupted by a call to pause()')) {
344 return 344 return
345 } 345 }
346 346
@@ -479,7 +479,7 @@ class WebTorrentPlugin extends Plugin {
479 } 479 }
480 480
481 private isPlayerWaiting () { 481 private isPlayerWaiting () {
482 return this.player && this.player.hasClass('vjs-waiting') 482 return this.player?.hasClass('vjs-waiting')
483 } 483 }
484 484
485 private runTorrentInfoScheduler () { 485 private runTorrentInfoScheduler () {
@@ -513,7 +513,7 @@ class WebTorrentPlugin extends Plugin {
513 }, this.CONSTANTS.INFO_SCHEDULER) 513 }, this.CONSTANTS.INFO_SCHEDULER)
514 } 514 }
515 515
516 private fallbackToHttp (options: PlayOptions, done?: Function) { 516 private fallbackToHttp (options: PlayOptions, done?: (err?: Error) => void) {
517 const paused = this.player.paused() 517 const paused = this.player.paused()
518 518
519 this.disableAutoResolution(true) 519 this.disableAutoResolution(true)
@@ -565,7 +565,7 @@ class WebTorrentPlugin extends Plugin {
565 private stopTorrent (torrent: WebTorrent.Torrent) { 565 private stopTorrent (torrent: WebTorrent.Torrent) {
566 torrent.pause() 566 torrent.pause()
567 // Pause does not remove actual peers (in particular the webseed peer) 567 // Pause does not remove actual peers (in particular the webseed peer)
568 torrent.removePeer(torrent[ 'ws' ]) 568 torrent.removePeer(torrent['ws'])
569 } 569 }
570 570
571 private renderFileInFakeElement (file: WebTorrent.TorrentFile, delay: number) { 571 private renderFileInFakeElement (file: WebTorrent.TorrentFile, delay: number) {
diff --git a/client/src/polyfills.ts b/client/src/polyfills.ts
index d862de8d8..bbba3f05c 100644
--- a/client/src/polyfills.ts
+++ b/client/src/polyfills.ts
@@ -57,7 +57,7 @@ import 'core-js/es/object'
57/*************************************************************************************************** 57/***************************************************************************************************
58 * Zone JS is required by default for Angular itself. 58 * Zone JS is required by default for Angular itself.
59 */ 59 */
60// tslint:disable 60/* eslint-disable */
61import 'zone.js' // Included with Angular CLI. 61import 'zone.js' // Included with Angular CLI.
62 62
63/*************************************************************************************************** 63/***************************************************************************************************
diff --git a/client/src/root-helpers/bytes.ts b/client/src/root-helpers/bytes.ts
index ec8b55faa..bda786cc6 100644
--- a/client/src/root-helpers/bytes.ts
+++ b/client/src/root-helpers/bytes.ts
@@ -1,4 +1,4 @@
1const dictionary: Array<{ max: number; type: string }> = [ 1const dictionary: Array<{ max: number, type: string }> = [
2 { max: 1024, type: 'B' }, 2 { max: 1024, type: 'B' },
3 { max: 1048576, type: 'KB' }, 3 { max: 1048576, type: 'KB' },
4 { max: 1073741824, type: 'MB' }, 4 { max: 1073741824, type: 'MB' },
diff --git a/client/src/root-helpers/peertube-web-storage.ts b/client/src/root-helpers/peertube-web-storage.ts
index d4cad8a20..68a2462de 100644
--- a/client/src/root-helpers/peertube-web-storage.ts
+++ b/client/src/root-helpers/peertube-web-storage.ts
@@ -5,7 +5,7 @@ const valuesMap = new Map()
5function proxify (instance: MemoryStorage) { 5function proxify (instance: MemoryStorage) {
6 return new Proxy(instance, { 6 return new Proxy(instance, {
7 set: function (obj, prop: string | symbol, value) { 7 set: function (obj, prop: string | symbol, value) {
8 if (MemoryStorage.prototype.hasOwnProperty(prop)) { 8 if (Object.prototype.hasOwnProperty.call(MemoryStorage, prop)) {
9 // FIXME: symbol typing issue https://github.com/microsoft/TypeScript/issues/1863 9 // FIXME: symbol typing issue https://github.com/microsoft/TypeScript/issues/1863
10 instance[prop as any] = value 10 instance[prop as any] = value
11 } else { 11 } else {
@@ -14,7 +14,7 @@ function proxify (instance: MemoryStorage) {
14 return true 14 return true
15 }, 15 },
16 get: function (target, name: string | symbol | number) { 16 get: function (target, name: string | symbol | number) {
17 if (MemoryStorage.prototype.hasOwnProperty(name)) { 17 if (Object.prototype.hasOwnProperty.call(MemoryStorage, name)) {
18 // FIXME: symbol typing issue https://github.com/microsoft/TypeScript/issues/1863 18 // FIXME: symbol typing issue https://github.com/microsoft/TypeScript/issues/1863
19 return instance[name as any] 19 return instance[name as any]
20 } 20 }
diff --git a/client/src/root-helpers/plugins-manager.ts b/client/src/root-helpers/plugins-manager.ts
index d14ac4acd..f1687d91d 100644
--- a/client/src/root-helpers/plugins-manager.ts
+++ b/client/src/root-helpers/plugins-manager.ts
@@ -155,7 +155,7 @@ class PluginsManager {
155 try { 155 try {
156 if (!isReload) this.loadedScopes.push(scope) 156 if (!isReload) this.loadedScopes.push(scope)
157 157
158 const toLoad = this.scopes[ scope ] 158 const toLoad = this.scopes[scope]
159 if (!Array.isArray(toLoad)) { 159 if (!Array.isArray(toLoad)) {
160 this.loadingScopes[scope] = false 160 this.loadingScopes[scope] = false
161 this.pluginsLoaded[scope].next(true) 161 this.pluginsLoaded[scope].next(true)
@@ -168,11 +168,11 @@ class PluginsManager {
168 for (const pluginInfo of toLoad) { 168 for (const pluginInfo of toLoad) {
169 const clientScript = pluginInfo.clientScript 169 const clientScript = pluginInfo.clientScript
170 170
171 if (this.loadedScripts[ clientScript.script ]) continue 171 if (this.loadedScripts[clientScript.script]) continue
172 172
173 promises.push(this.loadPlugin(pluginInfo)) 173 promises.push(this.loadPlugin(pluginInfo))
174 174
175 this.loadedScripts[ clientScript.script ] = true 175 this.loadedScripts[clientScript.script] = true
176 } 176 }
177 177
178 await Promise.all(promises) 178 await Promise.all(promises)
diff --git a/client/src/standalone/player/definitions.ts b/client/src/standalone/player/definitions.ts
index cc5203ed5..495f1a98c 100644
--- a/client/src/standalone/player/definitions.ts
+++ b/client/src/standalone/player/definitions.ts
@@ -21,5 +21,5 @@ export type PeerTubeTextTrack = {
21 id: string 21 id: string
22 label: string 22 label: string
23 src: string 23 src: string
24 mode: 'showing' | 'disabled' 24 mode: TextTrackMode
25} 25}
diff --git a/client/src/standalone/player/events.ts b/client/src/standalone/player/events.ts
index 28a13c727..7a8e9dbec 100644
--- a/client/src/standalone/player/events.ts
+++ b/client/src/standalone/player/events.ts
@@ -1,7 +1,7 @@
1import { EventHandler } from './definitions' 1import { EventHandler } from './definitions'
2 2
3interface PlayerEventRegistrar { 3interface PlayerEventRegistrar {
4 registrations: Function[] 4 registrations: EventHandler<any>[]
5} 5}
6 6
7interface PlayerEventRegistrationMap { 7interface PlayerEventRegistrationMap {
@@ -20,28 +20,28 @@ export class EventRegistrar {
20 20
21 public registerTypes (names: string[]) { 21 public registerTypes (names: string[]) {
22 for (const name of names) { 22 for (const name of names) {
23 this.eventRegistrations[ name ] = { registrations: [] } 23 this.eventRegistrations[name] = { registrations: [] }
24 } 24 }
25 } 25 }
26 26
27 public fire<T> (name: string, event: T) { 27 public fire<T> (name: string, event: T) {
28 this.eventRegistrations[ name ].registrations.forEach(x => x(event)) 28 this.eventRegistrations[name].registrations.forEach(x => x(event))
29 } 29 }
30 30
31 public addListener<T> (name: string, handler: EventHandler<T>) { 31 public addListener<T> (name: string, handler: EventHandler<T>) {
32 if (!this.eventRegistrations[ name ]) { 32 if (!this.eventRegistrations[name]) {
33 console.warn(`PeerTube: addEventListener(): The event '${name}' is not supported`) 33 console.warn(`PeerTube: addEventListener(): The event '${name}' is not supported`)
34 return false 34 return false
35 } 35 }
36 36
37 this.eventRegistrations[ name ].registrations.push(handler) 37 this.eventRegistrations[name].registrations.push(handler)
38 return true 38 return true
39 } 39 }
40 40
41 public removeListener<T> (name: string, handler: EventHandler<T>) { 41 public removeListener<T> (name: string, handler: EventHandler<T>) {
42 if (!this.eventRegistrations[ name ]) return false 42 if (!this.eventRegistrations[name]) return false
43 43
44 this.eventRegistrations[ name ].registrations = this.eventRegistrations[ name ].registrations.filter(x => x === handler) 44 this.eventRegistrations[name].registrations = this.eventRegistrations[name].registrations.filter(x => x === handler)
45 45
46 return true 46 return true
47 } 47 }
diff --git a/client/src/standalone/player/player.ts b/client/src/standalone/player/player.ts
index 9776fda12..bbe37a42b 100644
--- a/client/src/standalone/player/player.ts
+++ b/client/src/standalone/player/player.ts
@@ -17,7 +17,7 @@ const PASSTHROUGH_EVENTS = [
17 */ 17 */
18export class PeerTubePlayer { 18export class PeerTubePlayer {
19 19
20 private eventRegistrar: EventRegistrar = new EventRegistrar() 20 private readonly eventRegistrar: EventRegistrar = new EventRegistrar()
21 private channel: Channel.MessagingChannel 21 private channel: Channel.MessagingChannel
22 private readyPromise: Promise<void> 22 private readyPromise: Promise<void>
23 23
@@ -31,8 +31,8 @@ export class PeerTubePlayer {
31 * @param scope 31 * @param scope
32 */ 32 */
33 constructor ( 33 constructor (
34 private embedElement: HTMLIFrameElement, 34 private readonly embedElement: HTMLIFrameElement,
35 private scope?: string 35 private readonly scope?: string
36 ) { 36 ) {
37 this.eventRegistrar.registerTypes(PASSTHROUGH_EVENTS) 37 this.eventRegistrar.registerTypes(PASSTHROUGH_EVENTS)
38 38
@@ -90,6 +90,7 @@ export class PeerTubePlayer {
90 90
91 /** 91 /**
92 * Tell the embed to change the audio volume 92 * Tell the embed to change the audio volume
93 *
93 * @param value A number from 0 to 1 94 * @param value A number from 0 to 1
94 */ 95 */
95 async setVolume (value: number) { 96 async setVolume (value: number) {
@@ -98,14 +99,16 @@ export class PeerTubePlayer {
98 99
99 /** 100 /**
100 * Get the current volume level in the embed. 101 * Get the current volume level in the embed.
102 *
101 * @param value A number from 0 to 1 103 * @param value A number from 0 to 1
102 */ 104 */
103 async getVolume (): Promise<number> { 105 async getVolume (): Promise<number> {
104 return this.sendMessage<void, number>('getVolume') 106 return this.sendMessage<undefined, number>('getVolume')
105 } 107 }
106 108
107 /** 109 /**
108 * Tell the embed to change the current caption 110 * Tell the embed to change the current caption
111 *
109 * @param value Caption id 112 * @param value Caption id
110 */ 113 */
111 async setCaption (value: string) { 114 async setCaption (value: string) {
@@ -116,11 +119,12 @@ export class PeerTubePlayer {
116 * Get video captions 119 * Get video captions
117 */ 120 */
118 async getCaptions (): Promise<PeerTubeTextTrack[]> { 121 async getCaptions (): Promise<PeerTubeTextTrack[]> {
119 return this.sendMessage<void, PeerTubeTextTrack[]>('getCaptions') 122 return this.sendMessage<undefined, PeerTubeTextTrack[]>('getCaptions')
120 } 123 }
121 124
122 /** 125 /**
123 * Tell the embed to seek to a specific position (in seconds) 126 * Tell the embed to seek to a specific position (in seconds)
127 *
124 * @param seconds 128 * @param seconds
125 */ 129 */
126 async seek (seconds: number) { 130 async seek (seconds: number) {
@@ -143,21 +147,21 @@ export class PeerTubePlayer {
143 * resolutions change. 147 * resolutions change.
144 */ 148 */
145 async getResolutions (): Promise<PeerTubeResolution[]> { 149 async getResolutions (): Promise<PeerTubeResolution[]> {
146 return this.sendMessage<void, PeerTubeResolution[]>('getResolutions') 150 return this.sendMessage<undefined, PeerTubeResolution[]>('getResolutions')
147 } 151 }
148 152
149 /** 153 /**
150 * Retrieve a list of available playback rates. 154 * Retrieve a list of available playback rates.
151 */ 155 */
152 async getPlaybackRates (): Promise<number[]> { 156 async getPlaybackRates (): Promise<number[]> {
153 return this.sendMessage<void, number[]>('getPlaybackRates') 157 return this.sendMessage<undefined, number[]>('getPlaybackRates')
154 } 158 }
155 159
156 /** 160 /**
157 * Get the current playback rate. Defaults to 1 (1x playback rate). 161 * Get the current playback rate. Defaults to 1 (1x playback rate).
158 */ 162 */
159 async getPlaybackRate (): Promise<number> { 163 async getPlaybackRate (): Promise<number> {
160 return this.sendMessage<void, number>('getPlaybackRate') 164 return this.sendMessage<undefined, number>('getPlaybackRate')
161 } 165 }
162 166
163 /** 167 /**
@@ -188,7 +192,7 @@ export class PeerTubePlayer {
188 * Get video position currently played (starts from 1) 192 * Get video position currently played (starts from 1)
189 */ 193 */
190 async getCurrentPosition () { 194 async getCurrentPosition () {
191 return this.sendMessage<void, number>('getCurrentPosition') 195 return this.sendMessage<undefined, number>('getCurrentPosition')
192 } 196 }
193 197
194 private constructChannel () { 198 private constructChannel () {
@@ -201,8 +205,8 @@ export class PeerTubePlayer {
201 } 205 }
202 206
203 private prepareToBeReady () { 207 private prepareToBeReady () {
204 let readyResolve: Function 208 let readyResolve: () => void
205 let readyReject: Function 209 let readyReject: () => void
206 210
207 this.readyPromise = new Promise<void>((res, rej) => { 211 this.readyPromise = new Promise<void>((res, rej) => {
208 readyResolve = res 212 readyResolve = res
@@ -219,7 +223,8 @@ export class PeerTubePlayer {
219 private sendMessage<TIn, TOut> (method: string, params?: TIn): Promise<TOut> { 223 private sendMessage<TIn, TOut> (method: string, params?: TIn): Promise<TOut> {
220 return new Promise<TOut>((resolve, reject) => { 224 return new Promise<TOut>((resolve, reject) => {
221 this.channel.call({ 225 this.channel.call({
222 method, params, 226 method,
227 params,
223 success: result => resolve(result), 228 success: result => resolve(result),
224 error: error => reject(error) 229 error: error => reject(error)
225 }) 230 })
@@ -228,4 +233,4 @@ export class PeerTubePlayer {
228} 233}
229 234
230// put it on the window as well as the export 235// put it on the window as well as the export
231(window[ 'PeerTubePlayer' ] as any) = PeerTubePlayer 236(window['PeerTubePlayer'] as any) = PeerTubePlayer
diff --git a/client/src/standalone/videos/embed-api.ts b/client/src/standalone/videos/embed-api.ts
index 75174f2f8..b5c9da431 100644
--- a/client/src/standalone/videos/embed-api.ts
+++ b/client/src/standalone/videos/embed-api.ts
@@ -13,7 +13,8 @@ export class PeerTubeEmbedApi {
13 private isReady = false 13 private isReady = false
14 private resolutions: PeerTubeResolution[] = [] 14 private resolutions: PeerTubeResolution[] = []
15 15
16 constructor (private embed: PeerTubeEmbed) { 16 constructor (private readonly embed: PeerTubeEmbed) {
17
17 } 18 }
18 19
19 initialize () { 20 initialize () {
@@ -45,7 +46,7 @@ export class PeerTubeEmbedApi {
45 channel.bind('getResolutions', (txn, params) => this.resolutions) 46 channel.bind('getResolutions', (txn, params) => this.resolutions)
46 47
47 channel.bind('getCaptions', (txn, params) => this.getCaptions()) 48 channel.bind('getCaptions', (txn, params) => this.getCaptions())
48 channel.bind('setCaption', (txn, id) => this.setCaption(id)), 49 channel.bind('setCaption', (txn, id) => this.setCaption(id))
49 50
50 channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate)) 51 channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate))
51 channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate()) 52 channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate())
@@ -79,14 +80,12 @@ export class PeerTubeEmbedApi {
79 } 80 }
80 81
81 private getCaptions (): PeerTubeTextTrack[] { 82 private getCaptions (): PeerTubeTextTrack[] {
82 return this.embed.player.textTracks().tracks_.map(t => { 83 return this.embed.player.textTracks().tracks_.map(t => ({
83 return { 84 id: t.id,
84 id: t.id, 85 src: t.src,
85 src: t.src, 86 label: t.label,
86 label: t.label, 87 mode: t.mode
87 mode: t.mode as any 88 }))
88 }
89 })
90 } 89 }
91 90
92 private setCaption (id: string) { 91 private setCaption (id: string) {
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts
index c9a4e541c..dad717108 100644
--- a/client/src/standalone/videos/embed.ts
+++ b/client/src/standalone/videos/embed.ts
@@ -64,17 +64,11 @@ export class PeerTubeEmbed {
64 private playlistElements: VideoPlaylistElement[] 64 private playlistElements: VideoPlaylistElement[]
65 private currentPlaylistElement: VideoPlaylistElement 65 private currentPlaylistElement: VideoPlaylistElement
66 66
67 private wrapperElement: HTMLElement 67 private readonly wrapperElement: HTMLElement
68 68
69 private pluginsManager: PluginsManager 69 private pluginsManager: PluginsManager
70 70
71 static async main () { 71 constructor (private readonly videoWrapperId: string) {
72 const videoContainerId = 'video-wrapper'
73 const embed = new PeerTubeEmbed(videoContainerId)
74 await embed.init()
75 }
76
77 constructor (private videoWrapperId: string) {
78 this.wrapperElement = document.getElementById(this.videoWrapperId) 72 this.wrapperElement = document.getElementById(this.videoWrapperId)
79 73
80 try { 74 try {
@@ -84,6 +78,12 @@ export class PeerTubeEmbed {
84 } 78 }
85 } 79 }
86 80
81 static async main () {
82 const videoContainerId = 'video-wrapper'
83 const embed = new PeerTubeEmbed(videoContainerId)
84 await embed.init()
85 }
86
87 getVideoUrl (id: string) { 87 getVideoUrl (id: string) {
88 return window.location.origin + '/api/v1/videos/' + id 88 return window.location.origin + '/api/v1/videos/' + id
89 } 89 }
@@ -316,7 +316,7 @@ export class PeerTubeEmbed {
316 while (total > elements.length && i < 10) { 316 while (total > elements.length && i < 10) {
317 const result = await this.loadPlaylistElements(playlistId, elements.length) 317 const result = await this.loadPlaylistElements(playlistId, elements.length)
318 318
319 const json = await result.json() as ResultList<VideoPlaylistElement> 319 const json = await result.json()
320 total = json.total 320 total = json.total
321 321
322 elements = elements.concat(json.data) 322 elements = elements.concat(json.data)
@@ -469,7 +469,7 @@ export class PeerTubeEmbed {
469 // Issue when we parsed config from HTML, fallback to API 469 // Issue when we parsed config from HTML, fallback to API
470 if (!this.config) { 470 if (!this.config) {
471 this.config = await this.refreshFetch('/api/v1/config') 471 this.config = await this.refreshFetch('/api/v1/config')
472 .then(res => res.json()) 472 .then(res => res.json())
473 } 473 }
474 474
475 const videoInfoPromise = videoResponse.json() 475 const videoInfoPromise = videoResponse.json()
@@ -506,7 +506,7 @@ export class PeerTubeEmbed {
506 this.currentPlaylistElement = videoPlaylistElement 506 this.currentPlaylistElement = videoPlaylistElement
507 507
508 this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid) 508 this.loadVideoAndBuildPlayer(this.currentPlaylistElement.video.uuid)
509 .catch(err => console.error(err)) 509 .catch(err => console.error(err))
510 } 510 }
511 } 511 }
512 : undefined 512 : undefined
@@ -542,7 +542,9 @@ export class PeerTubeEmbed {
542 isLive: videoInfo.isLive, 542 isLive: videoInfo.isLive,
543 543
544 playerElement: this.playerElement, 544 playerElement: this.playerElement,
545 onPlayerElementChange: (element: HTMLVideoElement) => this.playerElement = element, 545 onPlayerElementChange: (element: HTMLVideoElement) => {
546 this.playerElement = element
547 },
546 548
547 videoDuration: videoInfo.duration, 549 videoDuration: videoInfo.duration,
548 enableHotkeys: true, 550 enableHotkeys: true,
@@ -577,10 +579,13 @@ export class PeerTubeEmbed {
577 }) 579 })
578 } 580 }
579 581
580 this.player = await PeertubePlayerManager.initialize(this.mode, options, (player: videojs.Player) => this.player = player) 582 this.player = await PeertubePlayerManager.initialize(this.mode, options, (player: videojs.Player) => {
583 this.player = player
584 })
585
581 this.player.on('customError', (event: any, data: any) => this.handleError(data.err, serverTranslations)) 586 this.player.on('customError', (event: any, data: any) => this.handleError(data.err, serverTranslations))
582 587
583 window[ 'videojsPlayer' ] = this.player 588 window['videojsPlayer'] = this.player
584 589
585 this.buildCSS() 590 this.buildCSS()
586 591
@@ -656,7 +661,7 @@ export class PeerTubeEmbed {
656 this.player.dispose() 661 this.player.dispose()
657 this.playerElement = null 662 this.playerElement = null
658 this.displayError('This video is not available because the remote instance is not responding.', translations) 663 this.displayError('This video is not available because the remote instance is not responding.', translations)
659 return 664
660 } 665 }
661 } 666 }
662 667
@@ -694,9 +699,9 @@ export class PeerTubeEmbed {
694 699
695 private async buildCaptions (serverTranslations: any, captionsResponse: Response): Promise<VideoJSCaption[]> { 700 private async buildCaptions (serverTranslations: any, captionsResponse: Response): Promise<VideoJSCaption[]> {
696 if (captionsResponse.ok) { 701 if (captionsResponse.ok) {
697 const { data } = (await captionsResponse.json()) as ResultList<VideoCaption> 702 const { data } = await captionsResponse.json()
698 703
699 return data.map(c => ({ 704 return data.map((c: VideoCaption) => ({
700 label: peertubeTranslate(c.language.label, serverTranslations), 705 label: peertubeTranslate(c.language.label, serverTranslations),
701 language: c.language.id, 706 language: c.language.id,
702 src: window.location.origin + c.captionPath 707 src: window.location.origin + c.captionPath
@@ -733,7 +738,7 @@ export class PeerTubeEmbed {
733 738
734 private getResourceId () { 739 private getResourceId () {
735 const urlParts = window.location.pathname.split('/') 740 const urlParts = window.location.pathname.split('/')
736 return urlParts[ urlParts.length - 1 ] 741 return urlParts[urlParts.length - 1]
737 } 742 }
738 743
739 private isPlaylistEmbed () { 744 private isPlaylistEmbed () {
@@ -751,7 +756,7 @@ export class PeerTubeEmbed {
751 } 756 }
752 757
753 private buildPeerTubeHelpers (translations?: { [ id: string ]: string }): RegisterClientHelpers { 758 private buildPeerTubeHelpers (translations?: { [ id: string ]: string }): RegisterClientHelpers {
754 function unimplemented (): any { 759 const unimplemented = () => {
755 throw new Error('This helper is not implemented in embed.') 760 throw new Error('This helper is not implemented in embed.')
756 } 761 }
757 762
@@ -780,9 +785,7 @@ export class PeerTubeEmbed {
780 enhancedMarkdownToHTML: unimplemented 785 enhancedMarkdownToHTML: unimplemented
781 }, 786 },
782 787
783 translate: (value: string) => { 788 translate: (value: string) => Promise.resolve(peertubeTranslate(value, translations))
784 return Promise.resolve(peertubeTranslate(value, translations))
785 }
786 } 789 }
787 } 790 }
788} 791}
diff --git a/client/src/standalone/videos/test-embed.ts b/client/src/standalone/videos/test-embed.ts
index 6e035c0c9..066b3e024 100644
--- a/client/src/standalone/videos/test-embed.ts
+++ b/client/src/standalone/videos/test-embed.ts
@@ -4,11 +4,11 @@ import { PeerTubePlayer } from '../player/player'
4 4
5window.addEventListener('load', async () => { 5window.addEventListener('load', async () => {
6 const urlParts = window.location.href.split('/') 6 const urlParts = window.location.href.split('/')
7 const lastPart = urlParts[ urlParts.length - 1 ] 7 const lastPart = urlParts[urlParts.length - 1]
8 8
9 const isPlaylist = window.location.pathname.startsWith('/video-playlists/') 9 const isPlaylist = window.location.pathname.startsWith('/video-playlists/')
10 10
11 const elementId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[ 0 ] 11 const elementId = lastPart.indexOf('?') === -1 ? lastPart : lastPart.split('?')[0]
12 12
13 const iframe = document.createElement('iframe') 13 const iframe = document.createElement('iframe')
14 iframe.src = isPlaylist 14 iframe.src = isPlaylist
@@ -18,14 +18,14 @@ window.addEventListener('load', async () => {
18 const mainElement = document.querySelector('#host') 18 const mainElement = document.querySelector('#host')
19 mainElement.appendChild(iframe) 19 mainElement.appendChild(iframe)
20 20
21 console.log(`Document finished loading.`) 21 console.log('Document finished loading.')
22 const player = new PeerTubePlayer(document.querySelector('iframe')) 22 const player = new PeerTubePlayer(document.querySelector('iframe'))
23 23
24 window[ 'player' ] = player 24 window['player'] = player
25 25
26 console.log(`Awaiting player ready...`) 26 console.log('Awaiting player ready...')
27 await player.ready 27 await player.ready
28 console.log(`Player is ready.`) 28 console.log('Player is ready.')
29 29
30 const monitoredEvents = [ 30 const monitoredEvents = [
31 'pause', 31 'pause',
@@ -39,7 +39,9 @@ window.addEventListener('load', async () => {
39 console.log(`PLAYER: now listening for event '${e}'`) 39 console.log(`PLAYER: now listening for event '${e}'`)
40 40
41 player.getCurrentPosition() 41 player.getCurrentPosition()
42 .then(position => document.getElementById('playlist-position').innerHTML = position + '') 42 .then(position => {
43 document.getElementById('playlist-position').innerHTML = position + ''
44 })
43 }) 45 })
44 46
45 let playbackRates: number[] = [] 47 let playbackRates: number[] = []
@@ -105,7 +107,7 @@ window.addEventListener('load', async () => {
105 107
106 updateCaptions() 108 updateCaptions()
107 109
108 const updateResolutions = ((resolutions: PeerTubeResolution[]) => { 110 const updateResolutions = (resolutions: PeerTubeResolution[]) => {
109 const resolutionListEl = document.querySelector('#resolution-list') 111 const resolutionListEl = document.querySelector('#resolution-list')
110 resolutionListEl.innerHTML = '' 112 resolutionListEl.innerHTML = ''
111 113
@@ -126,7 +128,7 @@ window.addEventListener('load', async () => {
126 resolutionListEl.appendChild(itemEl) 128 resolutionListEl.appendChild(itemEl)
127 } 129 }
128 }) 130 })
129 }) 131 }
130 132
131 player.getResolutions().then( 133 player.getResolutions().then(
132 resolutions => updateResolutions(resolutions)) 134 resolutions => updateResolutions(resolutions))
diff --git a/client/src/types/register-client-option.model.ts b/client/src/types/register-client-option.model.ts
index 59bcbc5ff..3415ef08f 100644
--- a/client/src/types/register-client-option.model.ts
+++ b/client/src/types/register-client-option.model.ts
@@ -30,16 +30,16 @@ export type RegisterClientHelpers = {
30 getServerConfig: () => Promise<ServerConfig> 30 getServerConfig: () => Promise<ServerConfig>
31 31
32 notifier: { 32 notifier: {
33 info: (text: string, title?: string, timeout?: number) => void, 33 info: (text: string, title?: string, timeout?: number) => void
34 error: (text: string, title?: string, timeout?: number) => void, 34 error: (text: string, title?: string, timeout?: number) => void
35 success: (text: string, title?: string, timeout?: number) => void 35 success: (text: string, title?: string, timeout?: number) => void
36 } 36 }
37 37
38 showModal: (input: { 38 showModal: (input: {
39 title: string, 39 title: string
40 content: string, 40 content: string
41 close?: boolean, 41 close?: boolean
42 cancel?: { value: string, action?: () => void }, 42 cancel?: { value: string, action?: () => void }
43 confirm?: { value: string, action?: () => void } 43 confirm?: { value: string, action?: () => void }
44 }) => void 44 }) => void
45 45
diff --git a/client/src/typings.d.ts b/client/src/typings.d.ts
index 24473aede..ad21fdedf 100644
--- a/client/src/typings.d.ts
+++ b/client/src/typings.d.ts
@@ -1,4 +1,5 @@
1/* SystemJS module definition */ 1/* SystemJS module definition */
2// eslint-disable-next-line no-var
2declare var module: NodeModule 3declare var module: NodeModule
3 4
4interface NodeModule { 5interface NodeModule {
diff --git a/client/tsconfig.json b/client/tsconfig.json
index fdf4dc777..56e7b68ee 100644
--- a/client/tsconfig.json
+++ b/client/tsconfig.json
@@ -53,7 +53,8 @@
53 ], 53 ],
54 "exclude": [ 54 "exclude": [
55 "../node_modules", 55 "../node_modules",
56 "../server" 56 "../server",
57 "node_modules"
57 ], 58 ],
58 "angularCompilerOptions": { 59 "angularCompilerOptions": {
59 "strictInjectionParameters": true, 60 "strictInjectionParameters": true,
diff --git a/client/tslint.json b/client/tslint.json
deleted file mode 100644
index d9983182e..000000000
--- a/client/tslint.json
+++ /dev/null
@@ -1,39 +0,0 @@
1{
2 "extends": [ "tslint-angular", "tslint-config-standard" ],
3 "rules": {
4 "deprecation": {
5 "severity": "warning"
6 },
7 "no-inferrable-types": true,
8 "eofline": true,
9 "max-line-length": [true, 140],
10 "no-floating-promises": false, // Memory issues
11 "await-promise": [true, "PromiseLike"],
12 "member-ordering": [true, {
13 "order": [
14 "public-static-field",
15 "private-static-field",
16 "public-instance-field",
17 "private-instance-field",
18 "public-constructor",
19 "private-constructor",
20 "public-instance-method",
21 "protected-instance-method",
22 "private-instance-method"
23 ]}
24 ],
25 "variable-name": [
26 true,
27 "ban-keywords",
28 "check-format",
29 "allow-leading-underscore",
30 "allow-pascal-case",
31 "allow-trailing-underscore"
32 ],
33
34 "no-shadowed-variable": false,
35 "no-bitwise": false,
36 "max-classes-per-file": false,
37 "interface-over-type-literal": false
38 }
39}
diff --git a/client/yarn.lock b/client/yarn.lock
index b2120b31b..75b7a620e 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -131,6 +131,47 @@
131 ora "5.4.1" 131 ora "5.4.1"
132 rxjs "6.6.7" 132 rxjs "6.6.7"
133 133
134"@angular-eslint/builder@12.3.1":
135 version "12.3.1"
136 resolved "https://registry.yarnpkg.com/@angular-eslint/builder/-/builder-12.3.1.tgz#e0a6768a9c7ee23623b1e363a23e59a333b6dabe"
137 integrity sha512-Py7Y9n0evIWGgEIrnMaLvalE1+Nw9HoY+fcYLYd9POfY0cug8j7hbkoPQ6rM7GzNHVcVsqEi/8C4DoF7RXXNRg==
138 dependencies:
139 "@nrwl/devkit" ">= 12.0.0 < 13.0.0"
140
141"@angular-eslint/eslint-plugin-template@12.3.1":
142 version "12.3.1"
143 resolved "https://registry.yarnpkg.com/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-12.3.1.tgz#33260cd5356df5db7e27719443eabcf6c214e32e"
144 integrity sha512-pz+nO64ma/9Sp2aeRnQ+Vktt7Fo1Lay/J+CG//3TIc3lYsoCTj4h42P6yCcxxJ9b4N7SUxMAnchA8eE5mJS4Ug==
145 dependencies:
146 "@typescript-eslint/experimental-utils" "4.28.2"
147 aria-query "^4.2.2"
148 axobject-query "^2.2.0"
149
150"@angular-eslint/eslint-plugin@12.3.1":
151 version "12.3.1"
152 resolved "https://registry.yarnpkg.com/@angular-eslint/eslint-plugin/-/eslint-plugin-12.3.1.tgz#00ac44d5986d86113d65a5373746e1fc22fd8702"
153 integrity sha512-KBm27onYggRcusA/BxuSkDGpVnIs8yG4ARio8ZAhe0H2XIRJTzJZ7oIBBjugDau03AGX3VMG6wAXailjJvsywg==
154 dependencies:
155 "@typescript-eslint/experimental-utils" "4.28.2"
156
157"@angular-eslint/schematics@12.3.1":
158 version "12.3.1"
159 resolved "https://registry.yarnpkg.com/@angular-eslint/schematics/-/schematics-12.3.1.tgz#99060a64fd6dd36ffb4c5e254b85562f4d0150d9"
160 integrity sha512-r1yZaqyO0oJhKDIWio3gH9TWpWEN8bUpiftgkkR6Yyc4hKBbiR5N4RQo5aZ5bnGytdW8QP8zq2k1yYBWjhEX7A==
161 dependencies:
162 "@angular-eslint/eslint-plugin" "12.3.1"
163 "@angular-eslint/eslint-plugin-template" "12.3.1"
164 ignore "5.1.8"
165 strip-json-comments "3.1.1"
166 tmp "0.2.1"
167
168"@angular-eslint/template-parser@12.3.1":
169 version "12.3.1"
170 resolved "https://registry.yarnpkg.com/@angular-eslint/template-parser/-/template-parser-12.3.1.tgz#561fe1bd3fb4a4d75cc55366d27818bca22204c9"
171 integrity sha512-6DkXqTaVEHZdcN3isHQ2CDoTsKLuJ5C1SYEOuFzOU1Zp85SvjxO92v6gPkFPKk0iQNVRmQS2XcKef6weehUUGA==
172 dependencies:
173 eslint-scope "^5.1.0"
174
134"@angular/animations@^12.0.0": 175"@angular/animations@^12.0.0":
135 version "12.2.0" 176 version "12.2.0"
136 resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-12.2.0.tgz#85e4e738bd72011067836b63bb8fc51a44646a7e" 177 resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-12.2.0.tgz#85e4e738bd72011067836b63bb8fc51a44646a7e"
@@ -199,11 +240,6 @@
199 tslib "^2.2.0" 240 tslib "^2.2.0"
200 yargs "^17.0.0" 241 yargs "^17.0.0"
201 242
202"@angular/compiler@9.0.0":
203 version "9.0.0"
204 resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.0.0.tgz#87e0bef4c369b6cadae07e3a4295778fc93799d5"
205 integrity sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ==
206
207"@angular/compiler@^12.0.0": 243"@angular/compiler@^12.0.0":
208 version "12.2.0" 244 version "12.2.0"
209 resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-12.2.0.tgz#d1585f7b7a67b8393eef2aa4cd3ef47c9d7fc3c0" 245 resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-12.2.0.tgz#d1585f7b7a67b8393eef2aa4cd3ef47c9d7fc3c0"
@@ -211,11 +247,6 @@
211 dependencies: 247 dependencies:
212 tslib "^2.2.0" 248 tslib "^2.2.0"
213 249
214"@angular/core@9.0.0":
215 version "9.0.0"
216 resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.0.0.tgz#227dc53e1ac81824f998c6e76000b7efc522641e"
217 integrity sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w==
218
219"@angular/core@^12.0.0": 250"@angular/core@^12.0.0":
220 version "12.2.0" 251 version "12.2.0"
221 resolved "https://registry.yarnpkg.com/@angular/core/-/core-12.2.0.tgz#29869aec3f624f6d4e1b5eedc25475cd5235a2e8" 252 resolved "https://registry.yarnpkg.com/@angular/core/-/core-12.2.0.tgz#29869aec3f624f6d4e1b5eedc25475cd5235a2e8"
@@ -272,6 +303,13 @@
272 resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.10.1.tgz#70e45678f06c72fa2e350e8553ec4a4d72b92e06" 303 resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.10.1.tgz#70e45678f06c72fa2e350e8553ec4a4d72b92e06"
273 integrity sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg== 304 integrity sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==
274 305
306"@babel/code-frame@7.12.11":
307 version "7.12.11"
308 resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
309 integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
310 dependencies:
311 "@babel/highlight" "^7.10.4"
312
275"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.8.3": 313"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.8.3":
276 version "7.14.5" 314 version "7.14.5"
277 resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" 315 resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
@@ -563,7 +601,7 @@
563 "@babel/traverse" "^7.14.8" 601 "@babel/traverse" "^7.14.8"
564 "@babel/types" "^7.14.8" 602 "@babel/types" "^7.14.8"
565 603
566"@babel/highlight@^7.14.5": 604"@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5":
567 version "7.14.5" 605 version "7.14.5"
568 resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" 606 resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
569 integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== 607 integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
@@ -1171,6 +1209,14 @@
1171 "@babel/types" "^7.4.4" 1209 "@babel/types" "^7.4.4"
1172 esutils "^2.0.2" 1210 esutils "^2.0.2"
1173 1211
1212"@babel/runtime-corejs3@^7.10.2":
1213 version "7.15.3"
1214 resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.15.3.tgz#28754263988198f2a928c09733ade2fb4d28089d"
1215 integrity sha512-30A3lP+sRL6ml8uhoJSs+8jwpKzbw8CqBvDc1laeptxPm5FahumJxirigcbD2qTs71Sonvj1cyZB0OKGAmxQ+A==
1216 dependencies:
1217 core-js-pure "^3.16.0"
1218 regenerator-runtime "^0.13.4"
1219
1174"@babel/runtime@7.14.8", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4": 1220"@babel/runtime@7.14.8", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4":
1175 version "7.14.8" 1221 version "7.14.8"
1176 resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446" 1222 resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446"
@@ -1178,6 +1224,13 @@
1178 dependencies: 1224 dependencies:
1179 regenerator-runtime "^0.13.4" 1225 regenerator-runtime "^0.13.4"
1180 1226
1227"@babel/runtime@^7.10.2":
1228 version "7.15.3"
1229 resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b"
1230 integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==
1231 dependencies:
1232 regenerator-runtime "^0.13.4"
1233
1181"@babel/template@7.14.5", "@babel/template@^7.14.5", "@babel/template@^7.8.3": 1234"@babel/template@7.14.5", "@babel/template@^7.14.5", "@babel/template@^7.8.3":
1182 version "7.14.5" 1235 version "7.14.5"
1183 resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" 1236 resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
@@ -1220,6 +1273,44 @@
1220 resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d" 1273 resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d"
1221 integrity sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g== 1274 integrity sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==
1222 1275
1276"@es-joy/jsdoccomment@0.10.7":
1277 version "0.10.7"
1278 resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.10.7.tgz#bdb5dfcaa5cff8b5435f0c9f2777b533075a9c52"
1279 integrity sha512-aNKZEoMESDzOBjKxCWrFuG50mcpMeKVBnBNko4+IZZ5t9zXYs8GT1KB0ZaOq1YUsKumDRc6YII/TQm309MJ0KQ==
1280 dependencies:
1281 comment-parser "1.2.3"
1282 esquery "^1.4.0"
1283 jsdoc-type-pratt-parser "1.1.1"
1284
1285"@eslint/eslintrc@^0.4.3":
1286 version "0.4.3"
1287 resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
1288 integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==
1289 dependencies:
1290 ajv "^6.12.4"
1291 debug "^4.1.1"
1292 espree "^7.3.0"
1293 globals "^13.9.0"
1294 ignore "^4.0.6"
1295 import-fresh "^3.2.1"
1296 js-yaml "^3.13.1"
1297 minimatch "^3.0.4"
1298 strip-json-comments "^3.1.1"
1299
1300"@humanwhocodes/config-array@^0.5.0":
1301 version "0.5.0"
1302 resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
1303 integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==
1304 dependencies:
1305 "@humanwhocodes/object-schema" "^1.2.0"
1306 debug "^4.1.1"
1307 minimatch "^3.0.4"
1308
1309"@humanwhocodes/object-schema@^1.2.0":
1310 version "1.2.0"
1311 resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf"
1312 integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==
1313
1223"@istanbuljs/schema@^0.1.2": 1314"@istanbuljs/schema@^0.1.2":
1224 version "0.1.3" 1315 version "0.1.3"
1225 resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" 1316 resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
@@ -1389,6 +1480,34 @@
1389 node-gyp "^7.1.0" 1480 node-gyp "^7.1.0"
1390 read-package-json-fast "^2.0.1" 1481 read-package-json-fast "^2.0.1"
1391 1482
1483"@nrwl/devkit@>= 12.0.0 < 13.0.0":
1484 version "12.7.1"
1485 resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-12.7.1.tgz#aea0d8db1663fed44b5189452beae87bf432c60f"
1486 integrity sha512-g88SWsXbiZDvL+4PWCBFlhzsg0niEJCxGDJ1EV+dLexAM3iD1aBn3EK2ygaF1sgabBNlJnUgbpU14/N5SexZuA==
1487 dependencies:
1488 "@nrwl/tao" "12.7.1"
1489 ejs "^3.1.5"
1490 ignore "^5.0.4"
1491 rxjs "^6.5.4"
1492 semver "7.3.4"
1493 tslib "^2.0.0"
1494
1495"@nrwl/tao@12.7.1":
1496 version "12.7.1"
1497 resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-12.7.1.tgz#467b5b56f8e503d4a6acbd6eecd4ad51042d8d27"
1498 integrity sha512-cQvrFwA+mEAiY3HwIuTjsO/yxgGEoffdUcsH6Oak3dcypkmTf4mVxqmuyzvJ5smt8cggg8qb7BEWowWs31folw==
1499 dependencies:
1500 chalk "4.1.0"
1501 enquirer "~2.3.6"
1502 fs-extra "^9.1.0"
1503 jsonc-parser "3.0.0"
1504 rxjs "^6.5.4"
1505 rxjs-for-await "0.0.2"
1506 semver "7.3.4"
1507 tmp "~0.2.1"
1508 tslib "^2.0.0"
1509 yargs-parser "20.0.0"
1510
1392"@peertube/p2p-media-loader-core@^1.0.2": 1511"@peertube/p2p-media-loader-core@^1.0.2":
1393 version "1.0.2" 1512 version "1.0.2"
1394 resolved "https://registry.yarnpkg.com/@peertube/p2p-media-loader-core/-/p2p-media-loader-core-1.0.2.tgz#ef36a23df5a5393cc5d180a45dfb70d2c3ecff87" 1513 resolved "https://registry.yarnpkg.com/@peertube/p2p-media-loader-core/-/p2p-media-loader-core-1.0.2.tgz#ef36a23df5a5393cc5d180a45dfb70d2c3ecff87"
@@ -1545,7 +1664,7 @@
1545 resolved "https://registry.yarnpkg.com/@types/jschannel/-/jschannel-1.0.2.tgz#a3649704909df330f6c9cfe72b2bd94f8490ce9f" 1664 resolved "https://registry.yarnpkg.com/@types/jschannel/-/jschannel-1.0.2.tgz#a3649704909df330f6c9cfe72b2bd94f8490ce9f"
1546 integrity sha512-LhEz5aKmiWxHqOmGi31Y+6JGG3OqHkEjESV9U64eQt7mGOnZOVJUs44r4KEe5dmEvt4uGHEqxHtzQhwX2lU3eA== 1665 integrity sha512-LhEz5aKmiWxHqOmGi31Y+6JGG3OqHkEjESV9U64eQt7mGOnZOVJUs44r4KEe5dmEvt4uGHEqxHtzQhwX2lU3eA==
1547 1666
1548"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": 1667"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8":
1549 version "7.0.9" 1668 version "7.0.9"
1550 resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" 1669 resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
1551 integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== 1670 integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==
@@ -1747,6 +1866,75 @@
1747 resolved "https://registry.yarnpkg.com/@types/xmldom/-/xmldom-0.1.31.tgz#519b647cfc66debf82cdf50e49763c8fdee553d6" 1866 resolved "https://registry.yarnpkg.com/@types/xmldom/-/xmldom-0.1.31.tgz#519b647cfc66debf82cdf50e49763c8fdee553d6"
1748 integrity sha512-bVy7s0nvaR5D1mT1a8ZkByHWNOGb6Vn4yi5TWhEdmyKlAG+08SA7Md6+jH+tYmMLueAwNeWvHHpeKrr6S4c4BA== 1867 integrity sha512-bVy7s0nvaR5D1mT1a8ZkByHWNOGb6Vn4yi5TWhEdmyKlAG+08SA7Md6+jH+tYmMLueAwNeWvHHpeKrr6S4c4BA==
1749 1868
1869"@typescript-eslint/eslint-plugin@4.28.2":
1870 version "4.28.2"
1871 resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.2.tgz#7a8320f00141666813d0ae43b49ee8244f7cf92a"
1872 integrity sha512-PGqpLLzHSxq956rzNGasO3GsAPf2lY9lDUBXhS++SKonglUmJypaUtcKzRtUte8CV7nruwnDxtLUKpVxs0wQBw==
1873 dependencies:
1874 "@typescript-eslint/experimental-utils" "4.28.2"
1875 "@typescript-eslint/scope-manager" "4.28.2"
1876 debug "^4.3.1"
1877 functional-red-black-tree "^1.0.1"
1878 regexpp "^3.1.0"
1879 semver "^7.3.5"
1880 tsutils "^3.21.0"
1881
1882"@typescript-eslint/experimental-utils@4.28.2":
1883 version "4.28.2"
1884 resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.2.tgz#4ebdec06a10888e9326e1d51d81ad52a361bd0b0"
1885 integrity sha512-MwHPsL6qo98RC55IoWWP8/opTykjTp4JzfPu1VfO2Z0MshNP0UZ1GEV5rYSSnZSUI8VD7iHvtIPVGW5Nfh7klQ==
1886 dependencies:
1887 "@types/json-schema" "^7.0.7"
1888 "@typescript-eslint/scope-manager" "4.28.2"
1889 "@typescript-eslint/types" "4.28.2"
1890 "@typescript-eslint/typescript-estree" "4.28.2"
1891 eslint-scope "^5.1.1"
1892 eslint-utils "^3.0.0"
1893
1894"@typescript-eslint/parser@4.28.2":
1895 version "4.28.2"
1896 resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.2.tgz#6aff11bf4b91eb67ca7517962eede951e9e2a15d"
1897 integrity sha512-Q0gSCN51eikAgFGY+gnd5p9bhhCUAl0ERMiDKrTzpSoMYRubdB8MJrTTR/BBii8z+iFwz8oihxd0RAdP4l8w8w==
1898 dependencies:
1899 "@typescript-eslint/scope-manager" "4.28.2"
1900 "@typescript-eslint/types" "4.28.2"
1901 "@typescript-eslint/typescript-estree" "4.28.2"
1902 debug "^4.3.1"
1903
1904"@typescript-eslint/scope-manager@4.28.2":
1905 version "4.28.2"
1906 resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz#451dce90303a3ce283750111495d34c9c204e510"
1907 integrity sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==
1908 dependencies:
1909 "@typescript-eslint/types" "4.28.2"
1910 "@typescript-eslint/visitor-keys" "4.28.2"
1911
1912"@typescript-eslint/types@4.28.2":
1913 version "4.28.2"
1914 resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.2.tgz#e6b9e234e0e9a66c4d25bab881661e91478223b5"
1915 integrity sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA==
1916
1917"@typescript-eslint/typescript-estree@4.28.2":
1918 version "4.28.2"
1919 resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz#680129b2a285289a15e7c6108c84739adf3a798c"
1920 integrity sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==
1921 dependencies:
1922 "@typescript-eslint/types" "4.28.2"
1923 "@typescript-eslint/visitor-keys" "4.28.2"
1924 debug "^4.3.1"
1925 globby "^11.0.3"
1926 is-glob "^4.0.1"
1927 semver "^7.3.5"
1928 tsutils "^3.21.0"
1929
1930"@typescript-eslint/visitor-keys@4.28.2":
1931 version "4.28.2"
1932 resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz#bf56a400857bb68b59b311e6d0a5fbef5c3b5130"
1933 integrity sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==
1934 dependencies:
1935 "@typescript-eslint/types" "4.28.2"
1936 eslint-visitor-keys "^2.0.0"
1937
1750"@videojs/http-streaming@2.9.2": 1938"@videojs/http-streaming@2.9.2":
1751 version "2.9.2" 1939 version "2.9.2"
1752 resolved "https://registry.yarnpkg.com/@videojs/http-streaming/-/http-streaming-2.9.2.tgz#47d33bb02bd9c1287200398b1e85d213dee814d0" 1940 resolved "https://registry.yarnpkg.com/@videojs/http-streaming/-/http-streaming-2.9.2.tgz#47d33bb02bd9c1287200398b1e85d213dee814d0"
@@ -1950,11 +2138,21 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
1950 mime-types "~2.1.24" 2138 mime-types "~2.1.24"
1951 negotiator "0.6.2" 2139 negotiator "0.6.2"
1952 2140
2141acorn-jsx@^5.3.1:
2142 version "5.3.2"
2143 resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
2144 integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
2145
1953acorn-walk@^8.0.0: 2146acorn-walk@^8.0.0:
1954 version "8.1.1" 2147 version "8.1.1"
1955 resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.1.1.tgz#3ddab7f84e4a7e2313f6c414c5b7dac85f4e3ebc" 2148 resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.1.1.tgz#3ddab7f84e4a7e2313f6c414c5b7dac85f4e3ebc"
1956 integrity sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w== 2149 integrity sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==
1957 2150
2151acorn@^7.4.0:
2152 version "7.4.1"
2153 resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
2154 integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
2155
1958acorn@^8.0.4, acorn@^8.4.1: 2156acorn@^8.0.4, acorn@^8.4.1:
1959 version "8.4.1" 2157 version "8.4.1"
1960 resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.1.tgz#56c36251fc7cabc7096adc18f05afe814321a28c" 2158 resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.1.tgz#56c36251fc7cabc7096adc18f05afe814321a28c"
@@ -2046,7 +2244,7 @@ ajv@8.6.2, ajv@^8.0.0, ajv@^8.0.1:
2046 require-from-string "^2.0.2" 2244 require-from-string "^2.0.2"
2047 uri-js "^4.2.2" 2245 uri-js "^4.2.2"
2048 2246
2049ajv@^6.1.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: 2247ajv@^6.1.0, ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5:
2050 version "6.12.6" 2248 version "6.12.6"
2051 resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 2249 resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
2052 integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 2250 integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@@ -2078,7 +2276,7 @@ angularx-qrcode@11.0.0:
2078 qrcode "1.4.2" 2276 qrcode "1.4.2"
2079 tslib "^2.0.0" 2277 tslib "^2.0.0"
2080 2278
2081ansi-colors@4.1.1: 2279ansi-colors@4.1.1, ansi-colors@^4.1.1:
2082 version "4.1.1" 2280 version "4.1.1"
2083 resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" 2281 resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
2084 integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== 2282 integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
@@ -2155,11 +2353,6 @@ anymatch@~3.1.2:
2155 normalize-path "^3.0.0" 2353 normalize-path "^3.0.0"
2156 picomatch "^2.0.4" 2354 picomatch "^2.0.4"
2157 2355
2158app-root-path@^3.0.0:
2159 version "3.0.0"
2160 resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad"
2161 integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==
2162
2163aproba@^1.0.3: 2356aproba@^1.0.3:
2164 version "1.2.0" 2357 version "1.2.0"
2165 resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" 2358 resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -2185,13 +2378,13 @@ argparse@^2.0.1:
2185 resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 2378 resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
2186 integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 2379 integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
2187 2380
2188aria-query@^3.0.0: 2381aria-query@^4.2.2:
2189 version "3.0.0" 2382 version "4.2.2"
2190 resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-3.0.0.tgz#65b3fcc1ca1155a8c9ae64d6eee297f15d5133cc" 2383 resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
2191 integrity sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w= 2384 integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==
2192 dependencies: 2385 dependencies:
2193 ast-types-flow "0.0.7" 2386 "@babel/runtime" "^7.10.2"
2194 commander "^2.11.0" 2387 "@babel/runtime-corejs3" "^7.10.2"
2195 2388
2196arr-diff@^4.0.0: 2389arr-diff@^4.0.0:
2197 version "4.0.0" 2390 version "4.0.0"
@@ -2218,6 +2411,17 @@ array-flatten@^2.1.0:
2218 resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" 2411 resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
2219 integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== 2412 integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
2220 2413
2414array-includes@^3.1.3:
2415 version "3.1.3"
2416 resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.3.tgz#c7f619b382ad2afaf5326cddfdc0afc61af7690a"
2417 integrity sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==
2418 dependencies:
2419 call-bind "^1.0.2"
2420 define-properties "^1.1.3"
2421 es-abstract "^1.18.0-next.2"
2422 get-intrinsic "^1.1.1"
2423 is-string "^1.0.5"
2424
2221array-union@^1.0.1: 2425array-union@^1.0.1:
2222 version "1.0.2" 2426 version "1.0.2"
2223 resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" 2427 resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
@@ -2240,6 +2444,15 @@ array-unique@^0.3.2:
2240 resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" 2444 resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
2241 integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= 2445 integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
2242 2446
2447array.prototype.flat@^1.2.4:
2448 version "1.2.4"
2449 resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123"
2450 integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==
2451 dependencies:
2452 call-bind "^1.0.0"
2453 define-properties "^1.1.3"
2454 es-abstract "^1.18.0-next.1"
2455
2243arrify@^1.0.0, arrify@^1.0.1: 2456arrify@^1.0.0, arrify@^1.0.1:
2244 version "1.0.1" 2457 version "1.0.1"
2245 resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" 2458 resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
@@ -2262,11 +2475,6 @@ assign-symbols@^1.0.0:
2262 resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" 2475 resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
2263 integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= 2476 integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
2264 2477
2265ast-types-flow@0.0.7:
2266 version "0.0.7"
2267 resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
2268 integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0=
2269
2270astral-regex@^2.0.0: 2478astral-regex@^2.0.0:
2271 version "2.0.0" 2479 version "2.0.0"
2272 resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" 2480 resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
@@ -2282,6 +2490,11 @@ async-limiter@~1.0.0:
2282 resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" 2490 resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
2283 integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== 2491 integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
2284 2492
2493async@0.9.x:
2494 version "0.9.2"
2495 resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
2496 integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=
2497
2285async@^2.6.2: 2498async@^2.6.2:
2286 version "2.6.3" 2499 version "2.6.3"
2287 resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" 2500 resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
@@ -2294,6 +2507,11 @@ asynckit@^0.4.0:
2294 resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 2507 resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
2295 integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 2508 integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
2296 2509
2510at-least-node@^1.0.0:
2511 version "1.0.0"
2512 resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
2513 integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
2514
2297atob@^2.1.2: 2515atob@^2.1.2:
2298 version "2.1.2" 2516 version "2.1.2"
2299 resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" 2517 resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
@@ -2322,12 +2540,10 @@ aws4@^1.8.0:
2322 resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" 2540 resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
2323 integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== 2541 integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
2324 2542
2325axobject-query@2.0.2: 2543axobject-query@^2.2.0:
2326 version "2.0.2" 2544 version "2.2.0"
2327 resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9" 2545 resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
2328 integrity sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww== 2546 integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
2329 dependencies:
2330 ast-types-flow "0.0.7"
2331 2547
2332babel-loader@8.2.2: 2548babel-loader@8.2.2:
2333 version "8.2.2" 2549 version "8.2.2"
@@ -2721,11 +2937,6 @@ bufferutil@^4.0.3:
2721 dependencies: 2937 dependencies:
2722 node-gyp-build "^4.2.0" 2938 node-gyp-build "^4.2.0"
2723 2939
2724builtin-modules@^1.1.1:
2725 version "1.1.1"
2726 resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
2727 integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
2728
2729builtin-status-codes@^3.0.0: 2940builtin-status-codes@^3.0.0:
2730 version "3.0.0" 2941 version "3.0.0"
2731 resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" 2942 resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
@@ -2857,6 +3068,14 @@ caseless@~0.12.0:
2857 resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 3068 resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
2858 integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= 3069 integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
2859 3070
3071chalk@4.1.0:
3072 version "4.1.0"
3073 resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
3074 integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
3075 dependencies:
3076 ansi-styles "^4.1.0"
3077 supports-color "^7.1.0"
3078
2860chalk@^1.1.1, chalk@^1.1.3: 3079chalk@^1.1.1, chalk@^1.1.3:
2861 version "1.1.3" 3080 version "1.1.3"
2862 resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 3081 resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -2868,7 +3087,7 @@ chalk@^1.1.1, chalk@^1.1.3:
2868 strip-ansi "^3.0.0" 3087 strip-ansi "^3.0.0"
2869 supports-color "^2.0.0" 3088 supports-color "^2.0.0"
2870 3089
2871chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: 3090chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2:
2872 version "2.4.2" 3091 version "2.4.2"
2873 resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 3092 resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
2874 integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 3093 integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@@ -2877,7 +3096,7 @@ chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
2877 escape-string-regexp "^1.0.5" 3096 escape-string-regexp "^1.0.5"
2878 supports-color "^5.3.0" 3097 supports-color "^5.3.0"
2879 3098
2880chalk@^4.1.0, chalk@^4.1.1: 3099chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1:
2881 version "4.1.2" 3100 version "4.1.2"
2882 resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 3101 resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
2883 integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 3102 integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@@ -3108,26 +3327,6 @@ code-point-at@^1.0.0:
3108 resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 3327 resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
3109 integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= 3328 integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
3110 3329
3111codelyzer@^6.0.0:
3112 version "6.0.2"
3113 resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-6.0.2.tgz#25d72eae641e8ff13ffd7d99b27c9c7ad5d7e135"
3114 integrity sha512-v3+E0Ucu2xWJMOJ2fA/q9pDT/hlxHftHGPUay1/1cTgyPV5JTHFdO9hqo837Sx2s9vKBMTt5gO+lhF95PO6J+g==
3115 dependencies:
3116 "@angular/compiler" "9.0.0"
3117 "@angular/core" "9.0.0"
3118 app-root-path "^3.0.0"
3119 aria-query "^3.0.0"
3120 axobject-query "2.0.2"
3121 css-selector-tokenizer "^0.7.1"
3122 cssauron "^1.4.0"
3123 damerau-levenshtein "^1.0.4"
3124 rxjs "^6.5.3"
3125 semver-dsl "^1.0.1"
3126 source-map "^0.5.7"
3127 sprintf-js "^1.1.2"
3128 tslib "^1.10.0"
3129 zone.js "~0.10.3"
3130
3131collection-visit@^1.0.0: 3330collection-visit@^1.0.0:
3132 version "1.0.0" 3331 version "1.0.0"
3133 resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" 3332 resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
@@ -3182,7 +3381,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
3182 dependencies: 3381 dependencies:
3183 delayed-stream "~1.0.0" 3382 delayed-stream "~1.0.0"
3184 3383
3185commander@^2.11.0, commander@^2.12.1, commander@^2.20.0: 3384commander@^2.20.0:
3186 version "2.20.3" 3385 version "2.20.3"
3187 resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 3386 resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
3188 integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 3387 integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@@ -3202,6 +3401,11 @@ commander@^7.0.0, commander@^7.1.0:
3202 resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" 3401 resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
3203 integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== 3402 integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
3204 3403
3404comment-parser@1.2.3:
3405 version "1.2.3"
3406 resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.2.3.tgz#303a7eb99c9b2632efd594e183ccbd32042caf69"
3407 integrity sha512-vnqDwBSXSsdAkGS5NjwMIPelE47q+UkEgWKHvCDNhVIIaQSUFY6sNnEYGzdoPGMdpV+7KR3ZkRd7oyWIjtuvJg==
3408
3205commondir@^1.0.1: 3409commondir@^1.0.1:
3206 version "1.0.1" 3410 version "1.0.1"
3207 resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" 3411 resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -3336,6 +3540,11 @@ core-js-compat@^3.14.0, core-js-compat@^3.15.0:
3336 browserslist "^4.16.6" 3540 browserslist "^4.16.6"
3337 semver "7.0.0" 3541 semver "7.0.0"
3338 3542
3543core-js-pure@^3.16.0:
3544 version "3.16.1"
3545 resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.16.1.tgz#b997df2669c957a5b29f06e95813a171f993592e"
3546 integrity sha512-TyofCdMzx0KMhi84mVRS8rL1XsRk2SPUNz2azmth53iRN0/08Uim9fdhQTaZTG1LqaXHYVci4RDHka6WrXfnvg==
3547
3339core-js@3.16.0, core-js@^3.1.4: 3548core-js@3.16.0, core-js@^3.1.4:
3340 version "3.16.0" 3549 version "3.16.0"
3341 resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.16.0.tgz#1d46fb33720bc1fa7f90d20431f36a5540858986" 3550 resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.16.0.tgz#1d46fb33720bc1fa7f90d20431f36a5540858986"
@@ -3420,7 +3629,7 @@ cross-spawn@^6.0.0:
3420 shebang-command "^1.2.0" 3629 shebang-command "^1.2.0"
3421 which "^1.2.9" 3630 which "^1.2.9"
3422 3631
3423cross-spawn@^7.0.3: 3632cross-spawn@^7.0.2, cross-spawn@^7.0.3:
3424 version "7.0.3" 3633 version "7.0.3"
3425 resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" 3634 resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
3426 integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== 3635 integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -3513,14 +3722,6 @@ css-select@^4.1.3:
3513 domutils "^2.6.0" 3722 domutils "^2.6.0"
3514 nth-check "^2.0.0" 3723 nth-check "^2.0.0"
3515 3724
3516css-selector-tokenizer@^0.7.1:
3517 version "0.7.3"
3518 resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz#735f26186e67c749aaf275783405cf0661fae8f1"
3519 integrity sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==
3520 dependencies:
3521 cssesc "^3.0.0"
3522 fastparse "^1.1.2"
3523
3524css-tree@^1.1.2: 3725css-tree@^1.1.2:
3525 version "1.1.3" 3726 version "1.1.3"
3526 resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" 3727 resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d"
@@ -3553,13 +3754,6 @@ css@^3.0.0:
3553 source-map "^0.6.1" 3754 source-map "^0.6.1"
3554 source-map-resolve "^0.6.0" 3755 source-map-resolve "^0.6.0"
3555 3756
3556cssauron@^1.4.0:
3557 version "1.4.0"
3558 resolved "https://registry.yarnpkg.com/cssauron/-/cssauron-1.4.0.tgz#a6602dff7e04a8306dc0db9a551e92e8b5662ad8"
3559 integrity sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=
3560 dependencies:
3561 through X.X.X
3562
3563cssdb@^4.4.0: 3757cssdb@^4.4.0:
3564 version "4.4.0" 3758 version "4.4.0"
3565 resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" 3759 resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0"
@@ -3642,11 +3836,6 @@ custom-event@~1.0.0:
3642 resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" 3836 resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
3643 integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU= 3837 integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=
3644 3838
3645damerau-levenshtein@^1.0.4:
3646 version "1.0.7"
3647 resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d"
3648 integrity sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==
3649
3650dashdash@^1.12.0: 3839dashdash@^1.12.0:
3651 version "1.14.1" 3840 version "1.14.1"
3652 resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 3841 resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
@@ -3664,21 +3853,21 @@ date-format@^3.0.0:
3664 resolved "https://registry.yarnpkg.com/date-format/-/date-format-3.0.0.tgz#eb8780365c7d2b1511078fb491e6479780f3ad95" 3853 resolved "https://registry.yarnpkg.com/date-format/-/date-format-3.0.0.tgz#eb8780365c7d2b1511078fb491e6479780f3ad95"
3665 integrity sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w== 3854 integrity sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w==
3666 3855
3667debug@2.6.9, debug@^2.2.0, debug@^2.3.3: 3856debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
3668 version "2.6.9" 3857 version "2.6.9"
3669 resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 3858 resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
3670 integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 3859 integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
3671 dependencies: 3860 dependencies:
3672 ms "2.0.0" 3861 ms "2.0.0"
3673 3862
3674debug@4, debug@4.3.2, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@~4.3.1: 3863debug@4, debug@4.3.2, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@~4.3.1:
3675 version "4.3.2" 3864 version "4.3.2"
3676 resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" 3865 resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
3677 integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== 3866 integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
3678 dependencies: 3867 dependencies:
3679 ms "2.1.2" 3868 ms "2.1.2"
3680 3869
3681debug@^3.1.0, debug@^3.1.1, debug@^3.2.6: 3870debug@^3.1.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7:
3682 version "3.2.7" 3871 version "3.2.7"
3683 resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" 3872 resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
3684 integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== 3873 integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
@@ -3729,6 +3918,11 @@ deep-equal@^1.0.1:
3729 object-keys "^1.1.1" 3918 object-keys "^1.1.1"
3730 regexp.prototype.flags "^1.2.0" 3919 regexp.prototype.flags "^1.2.0"
3731 3920
3921deep-is@^0.1.3:
3922 version "0.1.3"
3923 resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
3924 integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
3925
3732deepmerge@^4.2.2: 3926deepmerge@^4.2.2:
3733 version "4.2.2" 3927 version "4.2.2"
3734 resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" 3928 resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
@@ -3849,11 +4043,6 @@ di@^0.0.1:
3849 resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" 4043 resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
3850 integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw= 4044 integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=
3851 4045
3852diff@^4.0.1:
3853 version "4.0.2"
3854 resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
3855 integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
3856
3857dijkstrajs@^1.0.1: 4046dijkstrajs@^1.0.1:
3858 version "1.0.2" 4047 version "1.0.2"
3859 resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.2.tgz#2e48c0d3b825462afe75ab4ad5e829c8ece36257" 4048 resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.2.tgz#2e48c0d3b825462afe75ab4ad5e829c8ece36257"
@@ -3886,13 +4075,19 @@ dns-txt@^2.0.2:
3886 dependencies: 4075 dependencies:
3887 buffer-indexof "^1.0.0" 4076 buffer-indexof "^1.0.0"
3888 4077
3889doctrine@0.7.2: 4078doctrine@^2.1.0:
3890 version "0.7.2" 4079 version "2.1.0"
3891 resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523" 4080 resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
3892 integrity sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM= 4081 integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==
4082 dependencies:
4083 esutils "^2.0.2"
4084
4085doctrine@^3.0.0:
4086 version "3.0.0"
4087 resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
4088 integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
3893 dependencies: 4089 dependencies:
3894 esutils "^1.1.6" 4090 esutils "^2.0.2"
3895 isarray "0.0.1"
3896 4091
3897dom-converter@^0.2.0: 4092dom-converter@^0.2.0:
3898 version "0.2.0" 4093 version "0.2.0"
@@ -4007,6 +4202,13 @@ ee-first@1.1.1:
4007 resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 4202 resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
4008 integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= 4203 integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
4009 4204
4205ejs@^3.1.5:
4206 version "3.1.6"
4207 resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a"
4208 integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==
4209 dependencies:
4210 jake "^10.6.1"
4211
4010electron-to-chromium@^1.3.793: 4212electron-to-chromium@^1.3.793:
4011 version "1.3.798" 4213 version "1.3.798"
4012 resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.798.tgz#12b0bb826ddf35486f2ca41c01be4bd6ad1b9b1e" 4214 resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.798.tgz#12b0bb826ddf35486f2ca41c01be4bd6ad1b9b1e"
@@ -4089,6 +4291,13 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.8.0:
4089 graceful-fs "^4.2.4" 4291 graceful-fs "^4.2.4"
4090 tapable "^2.2.0" 4292 tapable "^2.2.0"
4091 4293
4294enquirer@^2.3.5, enquirer@~2.3.6:
4295 version "2.3.6"
4296 resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
4297 integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
4298 dependencies:
4299 ansi-colors "^4.1.1"
4300
4092ent@~2.2.0: 4301ent@~2.2.0:
4093 version "2.2.0" 4302 version "2.2.0"
4094 resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" 4303 resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
@@ -4143,11 +4352,43 @@ error-ex@^1.2.0, error-ex@^1.3.1:
4143 dependencies: 4352 dependencies:
4144 is-arrayish "^0.2.1" 4353 is-arrayish "^0.2.1"
4145 4354
4355es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2:
4356 version "1.18.5"
4357 resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.5.tgz#9b10de7d4c206a3581fd5b2124233e04db49ae19"
4358 integrity sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==
4359 dependencies:
4360 call-bind "^1.0.2"
4361 es-to-primitive "^1.2.1"
4362 function-bind "^1.1.1"
4363 get-intrinsic "^1.1.1"
4364 has "^1.0.3"
4365 has-symbols "^1.0.2"
4366 internal-slot "^1.0.3"
4367 is-callable "^1.2.3"
4368 is-negative-zero "^2.0.1"
4369 is-regex "^1.1.3"
4370 is-string "^1.0.6"
4371 object-inspect "^1.11.0"
4372 object-keys "^1.1.1"
4373 object.assign "^4.1.2"
4374 string.prototype.trimend "^1.0.4"
4375 string.prototype.trimstart "^1.0.4"
4376 unbox-primitive "^1.0.1"
4377
4146es-module-lexer@^0.7.1: 4378es-module-lexer@^0.7.1:
4147 version "0.7.1" 4379 version "0.7.1"
4148 resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.7.1.tgz#c2c8e0f46f2df06274cdaf0dd3f3b33e0a0b267d" 4380 resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.7.1.tgz#c2c8e0f46f2df06274cdaf0dd3f3b33e0a0b267d"
4149 integrity sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw== 4381 integrity sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw==
4150 4382
4383es-to-primitive@^1.2.1:
4384 version "1.2.1"
4385 resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
4386 integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
4387 dependencies:
4388 is-callable "^1.1.4"
4389 is-date-object "^1.0.1"
4390 is-symbol "^1.0.2"
4391
4151es6-promise@^4.0.3: 4392es6-promise@^4.0.3:
4152 version "4.2.8" 4393 version "4.2.8"
4153 resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" 4394 resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
@@ -4185,7 +4426,64 @@ escape-string-regexp@^4.0.0:
4185 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 4426 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
4186 integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 4427 integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
4187 4428
4188eslint-scope@5.1.1: 4429eslint-import-resolver-node@^0.3.5:
4430 version "0.3.6"
4431 resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd"
4432 integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==
4433 dependencies:
4434 debug "^3.2.7"
4435 resolve "^1.20.0"
4436
4437eslint-module-utils@^2.6.2:
4438 version "2.6.2"
4439 resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz#94e5540dd15fe1522e8ffa3ec8db3b7fa7e7a534"
4440 integrity sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==
4441 dependencies:
4442 debug "^3.2.7"
4443 pkg-dir "^2.0.0"
4444
4445eslint-plugin-import@latest:
4446 version "2.24.0"
4447 resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.24.0.tgz#697ffd263e24da5e84e03b282f5fb62251777177"
4448 integrity sha512-Kc6xqT9hiYi2cgybOc0I2vC9OgAYga5o/rAFinam/yF/t5uBqxQbauNPMC6fgb640T/89P0gFoO27FOilJ/Cqg==
4449 dependencies:
4450 array-includes "^3.1.3"
4451 array.prototype.flat "^1.2.4"
4452 debug "^2.6.9"
4453 doctrine "^2.1.0"
4454 eslint-import-resolver-node "^0.3.5"
4455 eslint-module-utils "^2.6.2"
4456 find-up "^2.0.0"
4457 has "^1.0.3"
4458 is-core-module "^2.4.0"
4459 minimatch "^3.0.4"
4460 object.values "^1.1.3"
4461 pkg-up "^2.0.0"
4462 read-pkg-up "^3.0.0"
4463 resolve "^1.20.0"
4464 tsconfig-paths "^3.9.0"
4465
4466eslint-plugin-jsdoc@latest:
4467 version "36.0.7"
4468 resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-36.0.7.tgz#6e6f9897fc2ff3b3934b09c2748b998bc03d2bf6"
4469 integrity sha512-x73l/WCRQ1qCjLq46Ca7csuGd5o3y3vbJIa3cktg11tdf3UZleBdIXKN9Cf0xjs3tXYPEy2SoNXowT8ydnjNDQ==
4470 dependencies:
4471 "@es-joy/jsdoccomment" "0.10.7"
4472 comment-parser "1.2.3"
4473 debug "^4.3.2"
4474 esquery "^1.4.0"
4475 jsdoc-type-pratt-parser "^1.1.1"
4476 lodash "^4.17.21"
4477 regextras "^0.8.0"
4478 semver "^7.3.5"
4479 spdx-expression-parse "^3.0.1"
4480
4481eslint-plugin-prefer-arrow@latest:
4482 version "1.2.3"
4483 resolved "https://registry.yarnpkg.com/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.2.3.tgz#e7fbb3fa4cd84ff1015b9c51ad86550e55041041"
4484 integrity sha512-J9I5PKCOJretVuiZRGvPQxCbllxGAV/viI20JO3LYblAodofBxyMnZAJ+WGeClHgANnSJberTNoFWWjrWKBuXQ==
4485
4486eslint-scope@5.1.1, eslint-scope@^5.1.0, eslint-scope@^5.1.1:
4189 version "5.1.1" 4487 version "5.1.1"
4190 resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" 4488 resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
4191 integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== 4489 integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
@@ -4193,11 +4491,97 @@ eslint-scope@5.1.1:
4193 esrecurse "^4.3.0" 4491 esrecurse "^4.3.0"
4194 estraverse "^4.1.1" 4492 estraverse "^4.1.1"
4195 4493
4494eslint-utils@^2.1.0:
4495 version "2.1.0"
4496 resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
4497 integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
4498 dependencies:
4499 eslint-visitor-keys "^1.1.0"
4500
4501eslint-utils@^3.0.0:
4502 version "3.0.0"
4503 resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
4504 integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==
4505 dependencies:
4506 eslint-visitor-keys "^2.0.0"
4507
4508eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
4509 version "1.3.0"
4510 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
4511 integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
4512
4513eslint-visitor-keys@^2.0.0:
4514 version "2.1.0"
4515 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
4516 integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
4517
4518eslint@^7.26.0:
4519 version "7.32.0"
4520 resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d"
4521 integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==
4522 dependencies:
4523 "@babel/code-frame" "7.12.11"
4524 "@eslint/eslintrc" "^0.4.3"
4525 "@humanwhocodes/config-array" "^0.5.0"
4526 ajv "^6.10.0"
4527 chalk "^4.0.0"
4528 cross-spawn "^7.0.2"
4529 debug "^4.0.1"
4530 doctrine "^3.0.0"
4531 enquirer "^2.3.5"
4532 escape-string-regexp "^4.0.0"
4533 eslint-scope "^5.1.1"
4534 eslint-utils "^2.1.0"
4535 eslint-visitor-keys "^2.0.0"
4536 espree "^7.3.1"
4537 esquery "^1.4.0"
4538 esutils "^2.0.2"
4539 fast-deep-equal "^3.1.3"
4540 file-entry-cache "^6.0.1"
4541 functional-red-black-tree "^1.0.1"
4542 glob-parent "^5.1.2"
4543 globals "^13.6.0"
4544 ignore "^4.0.6"
4545 import-fresh "^3.0.0"
4546 imurmurhash "^0.1.4"
4547 is-glob "^4.0.0"
4548 js-yaml "^3.13.1"
4549 json-stable-stringify-without-jsonify "^1.0.1"
4550 levn "^0.4.1"
4551 lodash.merge "^4.6.2"
4552 minimatch "^3.0.4"
4553 natural-compare "^1.4.0"
4554 optionator "^0.9.1"
4555 progress "^2.0.0"
4556 regexpp "^3.1.0"
4557 semver "^7.2.1"
4558 strip-ansi "^6.0.0"
4559 strip-json-comments "^3.1.0"
4560 table "^6.0.9"
4561 text-table "^0.2.0"
4562 v8-compile-cache "^2.0.3"
4563
4564espree@^7.3.0, espree@^7.3.1:
4565 version "7.3.1"
4566 resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
4567 integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
4568 dependencies:
4569 acorn "^7.4.0"
4570 acorn-jsx "^5.3.1"
4571 eslint-visitor-keys "^1.3.0"
4572
4196esprima@^4.0.0: 4573esprima@^4.0.0:
4197 version "4.0.1" 4574 version "4.0.1"
4198 resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 4575 resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
4199 integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 4576 integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
4200 4577
4578esquery@^1.4.0:
4579 version "1.4.0"
4580 resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
4581 integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
4582 dependencies:
4583 estraverse "^5.1.0"
4584
4201esrecurse@^4.3.0: 4585esrecurse@^4.3.0:
4202 version "4.3.0" 4586 version "4.3.0"
4203 resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 4587 resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
@@ -4210,16 +4594,11 @@ estraverse@^4.1.1:
4210 resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 4594 resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
4211 integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 4595 integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
4212 4596
4213estraverse@^5.2.0: 4597estraverse@^5.1.0, estraverse@^5.2.0:
4214 version "5.2.0" 4598 version "5.2.0"
4215 resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" 4599 resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
4216 integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== 4600 integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
4217 4601
4218esutils@^1.1.6:
4219 version "1.1.6"
4220 resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.1.6.tgz#c01ccaa9ae4b897c6d0c3e210ae52f3c7a844375"
4221 integrity sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=
4222
4223esutils@^2.0.2: 4602esutils@^2.0.2:
4224 version "2.0.3" 4603 version "2.0.3"
4225 resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 4604 resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
@@ -4407,7 +4786,7 @@ extsprintf@^1.2.0:
4407 resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" 4786 resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
4408 integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= 4787 integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
4409 4788
4410fast-deep-equal@^3.1.1: 4789fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
4411 version "3.1.3" 4790 version "3.1.3"
4412 resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 4791 resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
4413 integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 4792 integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
@@ -4433,16 +4812,16 @@ fast-json-stable-stringify@2.1.0, fast-json-stable-stringify@^2.0.0:
4433 resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 4812 resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
4434 integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 4813 integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
4435 4814
4815fast-levenshtein@^2.0.6:
4816 version "2.0.6"
4817 resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
4818 integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
4819
4436fastest-levenshtein@^1.0.12: 4820fastest-levenshtein@^1.0.12:
4437 version "1.0.12" 4821 version "1.0.12"
4438 resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" 4822 resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2"
4439 integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== 4823 integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==
4440 4824
4441fastparse@^1.1.2:
4442 version "1.1.2"
4443 resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9"
4444 integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
4445
4446fastq@^1.6.0: 4825fastq@^1.6.0:
4447 version "1.11.1" 4826 version "1.11.1"
4448 resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807" 4827 resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.11.1.tgz#5d8175aae17db61947f8b162cfc7f63264d22807"
@@ -4476,6 +4855,13 @@ file-uri-to-path@1.0.0:
4476 resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" 4855 resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
4477 integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== 4856 integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
4478 4857
4858filelist@^1.0.1:
4859 version "1.0.2"
4860 resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b"
4861 integrity sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==
4862 dependencies:
4863 minimatch "^3.0.4"
4864
4479filestream@^5.0.0: 4865filestream@^5.0.0:
4480 version "5.0.0" 4866 version "5.0.0"
4481 resolved "https://registry.yarnpkg.com/filestream/-/filestream-5.0.0.tgz#79015f3bae95ad0f47ef818694846f085087b92e" 4867 resolved "https://registry.yarnpkg.com/filestream/-/filestream-5.0.0.tgz#79015f3bae95ad0f47ef818694846f085087b92e"
@@ -4523,7 +4909,7 @@ find-cache-dir@3.3.1, find-cache-dir@^3.3.1:
4523 make-dir "^3.0.2" 4909 make-dir "^3.0.2"
4524 pkg-dir "^4.1.0" 4910 pkg-dir "^4.1.0"
4525 4911
4526find-up@^2.0.0: 4912find-up@^2.0.0, find-up@^2.1.0:
4527 version "2.1.0" 4913 version "2.1.0"
4528 resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" 4914 resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
4529 integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= 4915 integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
@@ -4640,6 +5026,16 @@ fs-extra@^8.1.0:
4640 jsonfile "^4.0.0" 5026 jsonfile "^4.0.0"
4641 universalify "^0.1.0" 5027 universalify "^0.1.0"
4642 5028
5029fs-extra@^9.1.0:
5030 version "9.1.0"
5031 resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
5032 integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
5033 dependencies:
5034 at-least-node "^1.0.0"
5035 graceful-fs "^4.2.0"
5036 jsonfile "^6.0.1"
5037 universalify "^2.0.0"
5038
4643fs-minipass@^2.0.0, fs-minipass@^2.1.0: 5039fs-minipass@^2.0.0, fs-minipass@^2.1.0:
4644 version "2.1.0" 5040 version "2.1.0"
4645 resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" 5041 resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
@@ -4675,6 +5071,11 @@ function-bind@^1.1.1:
4675 resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 5071 resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
4676 integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 5072 integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
4677 5073
5074functional-red-black-tree@^1.0.1:
5075 version "1.0.1"
5076 resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
5077 integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
5078
4678gauge@~2.7.3: 5079gauge@~2.7.3:
4679 version "2.7.4" 5080 version "2.7.4"
4680 resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" 5081 resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@@ -4709,7 +5110,7 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5:
4709 resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 5110 resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
4710 integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 5111 integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
4711 5112
4712get-intrinsic@^1.0.2: 5113get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
4713 version "1.1.1" 5114 version "1.1.1"
4714 resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" 5115 resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6"
4715 integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== 5116 integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==
@@ -4820,6 +5221,13 @@ globals@^11.1.0:
4820 resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" 5221 resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
4821 integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== 5222 integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
4822 5223
5224globals@^13.6.0, globals@^13.9.0:
5225 version "13.11.0"
5226 resolved "https://registry.yarnpkg.com/globals/-/globals-13.11.0.tgz#40ef678da117fe7bd2e28f1fab24951bd0255be7"
5227 integrity sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==
5228 dependencies:
5229 type-fest "^0.20.2"
5230
4823globby@^11.0.3: 5231globby@^11.0.3:
4824 version "11.0.4" 5232 version "11.0.4"
4825 resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" 5233 resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
@@ -4909,6 +5317,11 @@ has-ansi@^2.0.0:
4909 dependencies: 5317 dependencies:
4910 ansi-regex "^2.0.0" 5318 ansi-regex "^2.0.0"
4911 5319
5320has-bigints@^1.0.1:
5321 version "1.0.1"
5322 resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
5323 integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
5324
4912has-cors@1.1.0: 5325has-cors@1.1.0:
4913 version "1.1.0" 5326 version "1.1.0"
4914 resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" 5327 resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
@@ -5280,11 +5693,16 @@ ignore-walk@^3.0.3:
5280 dependencies: 5693 dependencies:
5281 minimatch "^3.0.4" 5694 minimatch "^3.0.4"
5282 5695
5283ignore@^5.1.4, ignore@^5.1.8: 5696ignore@5.1.8, ignore@^5.0.4, ignore@^5.1.4, ignore@^5.1.8:
5284 version "5.1.8" 5697 version "5.1.8"
5285 resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" 5698 resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
5286 integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== 5699 integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
5287 5700
5701ignore@^4.0.6:
5702 version "4.0.6"
5703 resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
5704 integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
5705
5288image-size@~0.5.0: 5706image-size@~0.5.0:
5289 version "0.5.5" 5707 version "0.5.5"
5290 resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" 5708 resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
@@ -5302,7 +5720,7 @@ immediate@~3.0.5:
5302 resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" 5720 resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
5303 integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= 5721 integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
5304 5722
5305import-fresh@^3.2.1: 5723import-fresh@^3.0.0, import-fresh@^3.2.1:
5306 version "3.3.0" 5724 version "3.3.0"
5307 resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" 5725 resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
5308 integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 5726 integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
@@ -5412,6 +5830,15 @@ internal-ip@^4.3.0:
5412 default-gateway "^4.2.0" 5830 default-gateway "^4.2.0"
5413 ipaddr.js "^1.9.0" 5831 ipaddr.js "^1.9.0"
5414 5832
5833internal-slot@^1.0.3:
5834 version "1.0.3"
5835 resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
5836 integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==
5837 dependencies:
5838 get-intrinsic "^1.1.0"
5839 has "^1.0.3"
5840 side-channel "^1.0.4"
5841
5415interpret@^2.2.0: 5842interpret@^2.2.0:
5416 version "2.2.0" 5843 version "2.2.0"
5417 resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" 5844 resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
@@ -5499,6 +5926,13 @@ is-ascii@^1.0.0:
5499 resolved "https://registry.yarnpkg.com/is-ascii/-/is-ascii-1.0.0.tgz#f02ad0259a0921cd199ff21ce1b09e0f6b4e3929" 5926 resolved "https://registry.yarnpkg.com/is-ascii/-/is-ascii-1.0.0.tgz#f02ad0259a0921cd199ff21ce1b09e0f6b4e3929"
5500 integrity sha1-8CrQJZoJIc0Zn/Ic4bCeD2tOOSk= 5927 integrity sha1-8CrQJZoJIc0Zn/Ic4bCeD2tOOSk=
5501 5928
5929is-bigint@^1.0.1:
5930 version "1.0.4"
5931 resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
5932 integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==
5933 dependencies:
5934 has-bigints "^1.0.1"
5935
5502is-binary-path@^1.0.0: 5936is-binary-path@^1.0.0:
5503 version "1.0.1" 5937 version "1.0.1"
5504 resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" 5938 resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
@@ -5513,6 +5947,14 @@ is-binary-path@~2.1.0:
5513 dependencies: 5947 dependencies:
5514 binary-extensions "^2.0.0" 5948 binary-extensions "^2.0.0"
5515 5949
5950is-boolean-object@^1.1.0:
5951 version "1.1.2"
5952 resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"
5953 integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==
5954 dependencies:
5955 call-bind "^1.0.2"
5956 has-tostringtag "^1.0.0"
5957
5516is-buffer@^1.1.5: 5958is-buffer@^1.1.5:
5517 version "1.1.6" 5959 version "1.1.6"
5518 resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 5960 resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
@@ -5523,6 +5965,11 @@ is-buffer@^2.0.0:
5523 resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" 5965 resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
5524 integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== 5966 integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
5525 5967
5968is-callable@^1.1.4, is-callable@^1.2.3:
5969 version "1.2.4"
5970 resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
5971 integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
5972
5526is-color-stop@^1.1.0: 5973is-color-stop@^1.1.0:
5527 version "1.1.0" 5974 version "1.1.0"
5528 resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" 5975 resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345"
@@ -5535,7 +5982,7 @@ is-color-stop@^1.1.0:
5535 rgb-regex "^1.0.1" 5982 rgb-regex "^1.0.1"
5536 rgba-regex "^1.0.0" 5983 rgba-regex "^1.0.0"
5537 5984
5538is-core-module@^2.2.0: 5985is-core-module@^2.2.0, is-core-module@^2.4.0:
5539 version "2.5.0" 5986 version "2.5.0"
5540 resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491" 5987 resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491"
5541 integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg== 5988 integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==
@@ -5664,6 +6111,18 @@ is-lambda@^1.0.1:
5664 resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" 6111 resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
5665 integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU= 6112 integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=
5666 6113
6114is-negative-zero@^2.0.1:
6115 version "2.0.1"
6116 resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
6117 integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
6118
6119is-number-object@^1.0.4:
6120 version "1.0.6"
6121 resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0"
6122 integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==
6123 dependencies:
6124 has-tostringtag "^1.0.0"
6125
5667is-number@^3.0.0: 6126is-number@^3.0.0:
5668 version "3.0.0" 6127 version "3.0.0"
5669 resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" 6128 resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@@ -5736,7 +6195,7 @@ is-plain-object@^5.0.0:
5736 resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" 6195 resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
5737 integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== 6196 integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
5738 6197
5739is-regex@^1.0.4: 6198is-regex@^1.0.4, is-regex@^1.1.3:
5740 version "1.1.4" 6199 version "1.1.4"
5741 resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" 6200 resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
5742 integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== 6201 integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
@@ -5764,6 +6223,20 @@ is-stream@^2.0.0:
5764 resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" 6223 resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
5765 integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== 6224 integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
5766 6225
6226is-string@^1.0.5, is-string@^1.0.6:
6227 version "1.0.7"
6228 resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
6229 integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
6230 dependencies:
6231 has-tostringtag "^1.0.0"
6232
6233is-symbol@^1.0.2, is-symbol@^1.0.3:
6234 version "1.0.4"
6235 resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
6236 integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
6237 dependencies:
6238 has-symbols "^1.0.2"
6239
5767is-typedarray@^1.0.0, is-typedarray@~1.0.0: 6240is-typedarray@^1.0.0, is-typedarray@~1.0.0:
5768 version "1.0.0" 6241 version "1.0.0"
5769 resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 6242 resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
@@ -5796,11 +6269,6 @@ is-wsl@^2.2.0:
5796 dependencies: 6269 dependencies:
5797 is-docker "^2.0.0" 6270 is-docker "^2.0.0"
5798 6271
5799isarray@0.0.1:
5800 version "0.0.1"
5801 resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
5802 integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
5803
5804isarray@1.0.0, isarray@~1.0.0: 6272isarray@1.0.0, isarray@~1.0.0:
5805 version "1.0.0" 6273 version "1.0.0"
5806 resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 6274 resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -5886,6 +6354,16 @@ istanbul-reports@^3.0.2:
5886 html-escaper "^2.0.0" 6354 html-escaper "^2.0.0"
5887 istanbul-lib-report "^3.0.0" 6355 istanbul-lib-report "^3.0.0"
5888 6356
6357jake@^10.6.1:
6358 version "10.8.2"
6359 resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b"
6360 integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==
6361 dependencies:
6362 async "0.9.x"
6363 chalk "^2.4.2"
6364 filelist "^1.0.1"
6365 minimatch "^3.0.4"
6366
5889jasmine-core@^3.6.0, jasmine-core@~3.8.0: 6367jasmine-core@^3.6.0, jasmine-core@~3.8.0:
5890 version "3.8.0" 6368 version "3.8.0"
5891 resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.8.0.tgz#815399aae5aa5d9beeb1262805f981b99ffc9bf0" 6369 resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.8.0.tgz#815399aae5aa5d9beeb1262805f981b99ffc9bf0"
@@ -5949,6 +6427,11 @@ jschannel@^1.0.2:
5949 resolved "https://registry.yarnpkg.com/jschannel/-/jschannel-1.0.2.tgz#8932010e9c6042a27bc93b918dac2e267976ae14" 6427 resolved "https://registry.yarnpkg.com/jschannel/-/jschannel-1.0.2.tgz#8932010e9c6042a27bc93b918dac2e267976ae14"
5950 integrity sha1-iTIBDpxgQqJ7yTuRjawuJnl2rhQ= 6428 integrity sha1-iTIBDpxgQqJ7yTuRjawuJnl2rhQ=
5951 6429
6430jsdoc-type-pratt-parser@1.1.1, jsdoc-type-pratt-parser@^1.1.1:
6431 version "1.1.1"
6432 resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-1.1.1.tgz#10fe5e409ba38de22a48b555598955a26ff0160f"
6433 integrity sha512-uelRmpghNwPBuZScwgBG/OzodaFk5RbO5xaivBdsAY70icWfShwZ7PCMO0x1zSkOa8T1FzHThmrdoyg/0AwV5g==
6434
5952jsesc@^2.5.1: 6435jsesc@^2.5.1:
5953 version "2.5.2" 6436 version "2.5.2"
5954 resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" 6437 resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
@@ -5959,7 +6442,7 @@ jsesc@~0.5.0:
5959 resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" 6442 resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
5960 integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= 6443 integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
5961 6444
5962json-parse-better-errors@^1.0.2: 6445json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
5963 version "1.0.2" 6446 version "1.0.2"
5964 resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 6447 resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
5965 integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== 6448 integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
@@ -5984,6 +6467,11 @@ json-schema@0.2.3:
5984 resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 6467 resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
5985 integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= 6468 integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
5986 6469
6470json-stable-stringify-without-jsonify@^1.0.1:
6471 version "1.0.1"
6472 resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
6473 integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
6474
5987json-stringify-safe@~5.0.1: 6475json-stringify-safe@~5.0.1:
5988 version "5.0.1" 6476 version "5.0.1"
5989 resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 6477 resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
@@ -6001,7 +6489,7 @@ json5@^1.0.1:
6001 dependencies: 6489 dependencies:
6002 minimist "^1.2.0" 6490 minimist "^1.2.0"
6003 6491
6004json5@^2.1.0, json5@^2.1.2: 6492json5@^2.1.0, json5@^2.1.2, json5@^2.2.0:
6005 version "2.2.0" 6493 version "2.2.0"
6006 resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" 6494 resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
6007 integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== 6495 integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
@@ -6020,6 +6508,15 @@ jsonfile@^4.0.0:
6020 optionalDependencies: 6508 optionalDependencies:
6021 graceful-fs "^4.1.6" 6509 graceful-fs "^4.1.6"
6022 6510
6511jsonfile@^6.0.1:
6512 version "6.1.0"
6513 resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
6514 integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
6515 dependencies:
6516 universalify "^2.0.0"
6517 optionalDependencies:
6518 graceful-fs "^4.1.6"
6519
6023jsonparse@^1.3.1: 6520jsonparse@^1.3.1:
6024 version "1.3.1" 6521 version "1.3.1"
6025 resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" 6522 resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
@@ -6222,6 +6719,14 @@ less@4.1.1:
6222 needle "^2.5.2" 6719 needle "^2.5.2"
6223 source-map "~0.6.0" 6720 source-map "~0.6.0"
6224 6721
6722levn@^0.4.1:
6723 version "0.4.1"
6724 resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
6725 integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
6726 dependencies:
6727 prelude-ls "^1.2.1"
6728 type-check "~0.4.0"
6729
6225license-webpack-plugin@2.3.20: 6730license-webpack-plugin@2.3.20:
6226 version "2.3.20" 6731 version "2.3.20"
6227 resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.3.20.tgz#f51fb674ca31519dbedbe1c7aabc036e5a7f2858" 6732 resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.3.20.tgz#f51fb674ca31519dbedbe1c7aabc036e5a7f2858"
@@ -6285,6 +6790,16 @@ load-json-file@^2.0.0:
6285 pify "^2.0.0" 6790 pify "^2.0.0"
6286 strip-bom "^3.0.0" 6791 strip-bom "^3.0.0"
6287 6792
6793load-json-file@^4.0.0:
6794 version "4.0.0"
6795 resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
6796 integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
6797 dependencies:
6798 graceful-fs "^4.1.2"
6799 parse-json "^4.0.0"
6800 pify "^3.0.0"
6801 strip-bom "^3.0.0"
6802
6288loader-runner@^4.2.0: 6803loader-runner@^4.2.0:
6289 version "4.2.0" 6804 version "4.2.0"
6290 resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" 6805 resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384"
@@ -6351,6 +6866,11 @@ lodash.memoize@^4.1.2:
6351 resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" 6866 resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
6352 integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= 6867 integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
6353 6868
6869lodash.merge@^4.6.2:
6870 version "4.6.2"
6871 resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
6872 integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
6873
6354lodash.truncate@^4.4.2: 6874lodash.truncate@^4.4.2:
6355 version "4.4.2" 6875 version "4.4.2"
6356 resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" 6876 resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
@@ -6876,7 +7396,7 @@ mkdirp-classic@^0.5.2:
6876 resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" 7396 resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
6877 integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== 7397 integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
6878 7398
6879mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5: 7399mkdirp@^0.5.1, mkdirp@^0.5.5:
6880 version "0.5.5" 7400 version "0.5.5"
6881 resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" 7401 resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
6882 integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== 7402 integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
@@ -7010,6 +7530,11 @@ napi-macros@^2.0.0:
7010 resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" 7530 resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b"
7011 integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== 7531 integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==
7012 7532
7533natural-compare@^1.4.0:
7534 version "1.4.0"
7535 resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
7536 integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
7537
7013needle@^2.5.2: 7538needle@^2.5.2:
7014 version "2.8.0" 7539 version "2.8.0"
7015 resolved "https://registry.yarnpkg.com/needle/-/needle-2.8.0.tgz#1c8ef9c1a2c29dcc1e83d73809d7bc681c80a048" 7540 resolved "https://registry.yarnpkg.com/needle/-/needle-2.8.0.tgz#1c8ef9c1a2c29dcc1e83d73809d7bc681c80a048"
@@ -7277,6 +7802,11 @@ object-copy@^0.1.0:
7277 define-property "^0.2.5" 7802 define-property "^0.2.5"
7278 kind-of "^3.0.3" 7803 kind-of "^3.0.3"
7279 7804
7805object-inspect@^1.11.0, object-inspect@^1.9.0:
7806 version "1.11.0"
7807 resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1"
7808 integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==
7809
7280object-is@^1.0.1: 7810object-is@^1.0.1:
7281 version "1.1.5" 7811 version "1.1.5"
7282 resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" 7812 resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
@@ -7297,7 +7827,7 @@ object-visit@^1.0.0:
7297 dependencies: 7827 dependencies:
7298 isobject "^3.0.0" 7828 isobject "^3.0.0"
7299 7829
7300object.assign@^4.1.0: 7830object.assign@^4.1.0, object.assign@^4.1.2:
7301 version "4.1.2" 7831 version "4.1.2"
7302 resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" 7832 resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
7303 integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== 7833 integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
@@ -7314,6 +7844,15 @@ object.pick@^1.3.0:
7314 dependencies: 7844 dependencies:
7315 isobject "^3.0.1" 7845 isobject "^3.0.1"
7316 7846
7847object.values@^1.1.3:
7848 version "1.1.4"
7849 resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30"
7850 integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==
7851 dependencies:
7852 call-bind "^1.0.2"
7853 define-properties "^1.1.3"
7854 es-abstract "^1.18.2"
7855
7317obuf@^1.0.0, obuf@^1.1.2: 7856obuf@^1.0.0, obuf@^1.1.2:
7318 version "1.1.2" 7857 version "1.1.2"
7319 resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" 7858 resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
@@ -7366,6 +7905,18 @@ opn@^5.5.0:
7366 dependencies: 7905 dependencies:
7367 is-wsl "^1.1.0" 7906 is-wsl "^1.1.0"
7368 7907
7908optionator@^0.9.1:
7909 version "0.9.1"
7910 resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
7911 integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
7912 dependencies:
7913 deep-is "^0.1.3"
7914 fast-levenshtein "^2.0.6"
7915 levn "^0.4.1"
7916 prelude-ls "^1.2.1"
7917 type-check "^0.4.0"
7918 word-wrap "^1.2.3"
7919
7369ora@5.4.1, ora@^5.3.0: 7920ora@5.4.1, ora@^5.3.0:
7370 version "5.4.1" 7921 version "5.4.1"
7371 resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" 7922 resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
@@ -7554,6 +8105,14 @@ parse-json@^2.2.0:
7554 dependencies: 8105 dependencies:
7555 error-ex "^1.2.0" 8106 error-ex "^1.2.0"
7556 8107
8108parse-json@^4.0.0:
8109 version "4.0.0"
8110 resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
8111 integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
8112 dependencies:
8113 error-ex "^1.3.1"
8114 json-parse-better-errors "^1.0.1"
8115
7557parse-json@^5.0.0: 8116parse-json@^5.0.0:
7558 version "5.2.0" 8117 version "5.2.0"
7559 resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" 8118 resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
@@ -7704,6 +8263,13 @@ path-type@^2.0.0:
7704 dependencies: 8263 dependencies:
7705 pify "^2.0.0" 8264 pify "^2.0.0"
7706 8265
8266path-type@^3.0.0:
8267 version "3.0.0"
8268 resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
8269 integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
8270 dependencies:
8271 pify "^3.0.0"
8272
7707path-type@^4.0.0: 8273path-type@^4.0.0:
7708 version "4.0.0" 8274 version "4.0.0"
7709 resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" 8275 resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
@@ -7729,6 +8295,11 @@ pify@^2.0.0, pify@^2.3.0:
7729 resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 8295 resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
7730 integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= 8296 integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
7731 8297
8298pify@^3.0.0:
8299 version "3.0.0"
8300 resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
8301 integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
8302
7732pify@^4.0.1: 8303pify@^4.0.1:
7733 version "4.0.1" 8304 version "4.0.1"
7734 resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" 8305 resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
@@ -7764,6 +8335,13 @@ pkcs7@^1.0.4:
7764 dependencies: 8335 dependencies:
7765 "@babel/runtime" "^7.5.5" 8336 "@babel/runtime" "^7.5.5"
7766 8337
8338pkg-dir@^2.0.0:
8339 version "2.0.0"
8340 resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
8341 integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=
8342 dependencies:
8343 find-up "^2.1.0"
8344
7767pkg-dir@^3.0.0: 8345pkg-dir@^3.0.0:
7768 version "3.0.0" 8346 version "3.0.0"
7769 resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" 8347 resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
@@ -7778,6 +8356,13 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0:
7778 dependencies: 8356 dependencies:
7779 find-up "^4.0.0" 8357 find-up "^4.0.0"
7780 8358
8359pkg-up@^2.0.0:
8360 version "2.0.0"
8361 resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f"
8362 integrity sha1-yBmscoBZpGHKscOImivjxJoATX8=
8363 dependencies:
8364 find-up "^2.1.0"
8365
7781pngjs@^3.3.0: 8366pngjs@^3.3.0:
7782 version "3.4.0" 8367 version "3.4.0"
7783 resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" 8368 resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
@@ -8425,6 +9010,11 @@ postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.
8425 source-map "^0.6.1" 9010 source-map "^0.6.1"
8426 supports-color "^6.1.0" 9011 supports-color "^6.1.0"
8427 9012
9013prelude-ls@^1.2.1:
9014 version "1.2.1"
9015 resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
9016 integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
9017
8428pretty-bytes@^5.3.0: 9018pretty-bytes@^5.3.0:
8429 version "5.6.0" 9019 version "5.6.0"
8430 resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" 9020 resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
@@ -8455,6 +9045,11 @@ process@^0.11.10:
8455 resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" 9045 resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
8456 integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= 9046 integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
8457 9047
9048progress@^2.0.0:
9049 version "2.0.3"
9050 resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
9051 integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
9052
8458promise-inflight@^1.0.1: 9053promise-inflight@^1.0.1:
8459 version "1.0.1" 9054 version "1.0.1"
8460 resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" 9055 resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
@@ -8681,6 +9276,14 @@ read-pkg-up@^2.0.0:
8681 find-up "^2.0.0" 9276 find-up "^2.0.0"
8682 read-pkg "^2.0.0" 9277 read-pkg "^2.0.0"
8683 9278
9279read-pkg-up@^3.0.0:
9280 version "3.0.0"
9281 resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07"
9282 integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=
9283 dependencies:
9284 find-up "^2.0.0"
9285 read-pkg "^3.0.0"
9286
8684read-pkg-up@^7.0.1: 9287read-pkg-up@^7.0.1:
8685 version "7.0.1" 9288 version "7.0.1"
8686 resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" 9289 resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
@@ -8699,6 +9302,15 @@ read-pkg@^2.0.0:
8699 normalize-package-data "^2.3.2" 9302 normalize-package-data "^2.3.2"
8700 path-type "^2.0.0" 9303 path-type "^2.0.0"
8701 9304
9305read-pkg@^3.0.0:
9306 version "3.0.0"
9307 resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
9308 integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
9309 dependencies:
9310 load-json-file "^4.0.0"
9311 normalize-package-data "^2.3.2"
9312 path-type "^3.0.0"
9313
8702read-pkg@^5.2.0: 9314read-pkg@^5.2.0:
8703 version "5.2.0" 9315 version "5.2.0"
8704 resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" 9316 resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
@@ -8817,6 +9429,11 @@ regexp.prototype.flags@^1.2.0:
8817 call-bind "^1.0.2" 9429 call-bind "^1.0.2"
8818 define-properties "^1.1.3" 9430 define-properties "^1.1.3"
8819 9431
9432regexpp@^3.1.0:
9433 version "3.2.0"
9434 resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
9435 integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
9436
8820regexpu-core@^4.7.1: 9437regexpu-core@^4.7.1:
8821 version "4.7.1" 9438 version "4.7.1"
8822 resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" 9439 resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6"
@@ -8829,6 +9446,11 @@ regexpu-core@^4.7.1:
8829 unicode-match-property-ecmascript "^1.0.4" 9446 unicode-match-property-ecmascript "^1.0.4"
8830 unicode-match-property-value-ecmascript "^1.2.0" 9447 unicode-match-property-value-ecmascript "^1.2.0"
8831 9448
9449regextras@^0.8.0:
9450 version "0.8.0"
9451 resolved "https://registry.yarnpkg.com/regextras/-/regextras-0.8.0.tgz#ec0f99853d4912839321172f608b544814b02217"
9452 integrity sha512-k519uI04Z3SaY0fLX843MRXnDeG2+vHOFsyhiPZvNLe7r8rD2YNRjq4BQLZZ0oAr2NrtvZlICsXysGNFPGa3CQ==
9453
8832regjsgen@^0.5.1: 9454regjsgen@^0.5.1:
8833 version "0.5.2" 9455 version "0.5.2"
8834 resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" 9456 resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733"
@@ -9106,7 +9728,12 @@ rust-result@^1.0.0:
9106 dependencies: 9728 dependencies:
9107 individual "^2.0.0" 9729 individual "^2.0.0"
9108 9730
9109rxjs@6.6.7, rxjs@^6.5.3: 9731rxjs-for-await@0.0.2:
9732 version "0.0.2"
9733 resolved "https://registry.yarnpkg.com/rxjs-for-await/-/rxjs-for-await-0.0.2.tgz#26598a1d6167147cc192172970e7eed4e620384b"
9734 integrity sha512-IJ8R/ZCFMHOcDIqoABs82jal00VrZx8Xkgfe7TOKoaRPAW5nH/VFlG23bXpeGdrmtqI9UobFPgUKgCuFc7Lncw==
9735
9736rxjs@6.6.7, rxjs@^6.5.4:
9110 version "6.6.7" 9737 version "6.6.7"
9111 resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" 9738 resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
9112 integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== 9739 integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
@@ -9245,13 +9872,6 @@ selfsigned@^1.10.8:
9245 dependencies: 9872 dependencies:
9246 node-forge "^0.10.0" 9873 node-forge "^0.10.0"
9247 9874
9248semver-dsl@^1.0.1:
9249 version "1.0.1"
9250 resolved "https://registry.yarnpkg.com/semver-dsl/-/semver-dsl-1.0.1.tgz#d3678de5555e8a61f629eed025366ae5f27340a0"
9251 integrity sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=
9252 dependencies:
9253 semver "^5.3.0"
9254
9255"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: 9875"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0:
9256 version "5.7.1" 9876 version "5.7.1"
9257 resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 9877 resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
@@ -9262,7 +9882,14 @@ semver@7.0.0:
9262 resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" 9882 resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
9263 integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== 9883 integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
9264 9884
9265semver@7.3.5, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: 9885semver@7.3.4:
9886 version "7.3.4"
9887 resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
9888 integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
9889 dependencies:
9890 lru-cache "^6.0.0"
9891
9892semver@7.3.5, semver@^7.0.0, semver@^7.1.1, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
9266 version "7.3.5" 9893 version "7.3.5"
9267 resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" 9894 resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
9268 integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== 9895 integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
@@ -9392,6 +10019,15 @@ shebang-regex@^3.0.0:
9392 resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 10019 resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
9393 integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 10020 integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
9394 10021
10022side-channel@^1.0.4:
10023 version "1.0.4"
10024 resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
10025 integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
10026 dependencies:
10027 call-bind "^1.0.0"
10028 get-intrinsic "^1.0.2"
10029 object-inspect "^1.9.0"
10030
9395signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: 10031signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
9396 version "3.0.3" 10032 version "3.0.3"
9397 resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" 10033 resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
@@ -9649,7 +10285,7 @@ source-map@0.7.3, source-map@^0.7.3, source-map@~0.7.2:
9649 resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" 10285 resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
9650 integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== 10286 integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
9651 10287
9652source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: 10288source-map@^0.5.0, source-map@^0.5.6:
9653 version "0.5.7" 10289 version "0.5.7"
9654 resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 10290 resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
9655 integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= 10291 integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -9672,7 +10308,7 @@ spdx-exceptions@^2.1.0:
9672 resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" 10308 resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d"
9673 integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== 10309 integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==
9674 10310
9675spdx-expression-parse@^3.0.0: 10311spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1:
9676 version "3.0.1" 10312 version "3.0.1"
9677 resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" 10313 resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
9678 integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== 10314 integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
@@ -9740,11 +10376,6 @@ split@^1.0.1:
9740 dependencies: 10376 dependencies:
9741 through "2" 10377 through "2"
9742 10378
9743sprintf-js@^1.1.2:
9744 version "1.1.2"
9745 resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673"
9746 integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==
9747
9748sprintf-js@~1.0.2: 10379sprintf-js@~1.0.2:
9749 version "1.0.3" 10380 version "1.0.3"
9750 resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 10381 resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
@@ -9878,6 +10509,22 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2:
9878 is-fullwidth-code-point "^3.0.0" 10509 is-fullwidth-code-point "^3.0.0"
9879 strip-ansi "^6.0.0" 10510 strip-ansi "^6.0.0"
9880 10511
10512string.prototype.trimend@^1.0.4:
10513 version "1.0.4"
10514 resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
10515 integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==
10516 dependencies:
10517 call-bind "^1.0.2"
10518 define-properties "^1.1.3"
10519
10520string.prototype.trimstart@^1.0.4:
10521 version "1.0.4"
10522 resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed"
10523 integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==
10524 dependencies:
10525 call-bind "^1.0.2"
10526 define-properties "^1.1.3"
10527
9881string2compact@^1.3.0, string2compact@^1.3.2: 10528string2compact@^1.3.0, string2compact@^1.3.2:
9882 version "1.3.2" 10529 version "1.3.2"
9883 resolved "https://registry.yarnpkg.com/string2compact/-/string2compact-1.3.2.tgz#c9d11a13f368404b8025425cc53f9916de1d0b8b" 10530 resolved "https://registry.yarnpkg.com/string2compact/-/string2compact-1.3.2.tgz#c9d11a13f368404b8025425cc53f9916de1d0b8b"
@@ -9950,6 +10597,11 @@ strip-indent@^3.0.0:
9950 dependencies: 10597 dependencies:
9951 min-indent "^1.0.0" 10598 min-indent "^1.0.0"
9952 10599
10600strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
10601 version "3.1.1"
10602 resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
10603 integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
10604
9953style-loader@3.2.1: 10605style-loader@3.2.1:
9954 version "3.2.1" 10606 version "3.2.1"
9955 resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.2.1.tgz#63cb920ec145c8669e9a50e92961452a1ef5dcde" 10607 resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.2.1.tgz#63cb920ec145c8669e9a50e92961452a1ef5dcde"
@@ -10136,7 +10788,7 @@ symbol-observable@4.0.0:
10136 resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" 10788 resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205"
10137 integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== 10789 integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==
10138 10790
10139table@^6.6.0: 10791table@^6.0.9, table@^6.6.0:
10140 version "6.7.1" 10792 version "6.7.1"
10141 resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" 10793 resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2"
10142 integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== 10794 integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==
@@ -10195,7 +10847,7 @@ terser@^4.6.3:
10195 source-map "~0.6.1" 10847 source-map "~0.6.1"
10196 source-map-support "~0.5.12" 10848 source-map-support "~0.5.12"
10197 10849
10198text-table@0.2.0: 10850text-table@0.2.0, text-table@^0.2.0:
10199 version "0.2.0" 10851 version "0.2.0"
10200 resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 10852 resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
10201 integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 10853 integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
@@ -10205,7 +10857,7 @@ thirty-two@^1.0.2:
10205 resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-1.0.2.tgz#4ca2fffc02a51290d2744b9e3f557693ca6b627a" 10857 resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-1.0.2.tgz#4ca2fffc02a51290d2744b9e3f557693ca6b627a"
10206 integrity sha1-TKL//AKlEpDSdEueP1V2k8prYno= 10858 integrity sha1-TKL//AKlEpDSdEueP1V2k8prYno=
10207 10859
10208through@2, through@X.X.X, through@^2.3.6: 10860through@2, through@^2.3.6:
10209 version "2.3.8" 10861 version "2.3.8"
10210 resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 10862 resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
10211 integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= 10863 integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
@@ -10232,6 +10884,13 @@ tmp@0.0.30:
10232 dependencies: 10884 dependencies:
10233 os-tmpdir "~1.0.1" 10885 os-tmpdir "~1.0.1"
10234 10886
10887tmp@0.2.1, tmp@^0.2.1, tmp@~0.2.1:
10888 version "0.2.1"
10889 resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
10890 integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
10891 dependencies:
10892 rimraf "^3.0.0"
10893
10235tmp@^0.0.33: 10894tmp@^0.0.33:
10236 version "0.0.33" 10895 version "0.0.33"
10237 resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" 10896 resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -10239,13 +10898,6 @@ tmp@^0.0.33:
10239 dependencies: 10898 dependencies:
10240 os-tmpdir "~1.0.2" 10899 os-tmpdir "~1.0.2"
10241 10900
10242tmp@^0.2.1:
10243 version "0.2.1"
10244 resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
10245 integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
10246 dependencies:
10247 rimraf "^3.0.0"
10248
10249to-arraybuffer@^1.0.1: 10901to-arraybuffer@^1.0.1:
10250 version "1.0.1" 10902 version "1.0.1"
10251 resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" 10903 resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
@@ -10352,17 +11004,21 @@ ts-loader@^9.2.2:
10352 micromatch "^4.0.0" 11004 micromatch "^4.0.0"
10353 semver "^7.3.4" 11005 semver "^7.3.4"
10354 11006
10355tslib@1.9.0: 11007tsconfig-paths@^3.9.0:
10356 version "1.9.0" 11008 version "3.10.1"
10357 resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" 11009 resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz#79ae67a68c15289fdf5c51cb74f397522d795ed7"
10358 integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== 11010 integrity sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q==
11011 dependencies:
11012 json5 "^2.2.0"
11013 minimist "^1.2.0"
11014 strip-bom "^3.0.0"
10359 11015
10360tslib@2.3.0, tslib@>=1.7.1, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0: 11016tslib@2.3.0, tslib@>=1.7.1, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0:
10361 version "2.3.0" 11017 version "2.3.0"
10362 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" 11018 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
10363 integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== 11019 integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
10364 11020
10365tslib@^1.10.0, tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0: 11021tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
10366 version "1.14.1" 11022 version "1.14.1"
10367 resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" 11023 resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
10368 integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== 11024 integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
@@ -10372,54 +11028,7 @@ tslib@~2.1.0:
10372 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" 11028 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
10373 integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== 11029 integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
10374 11030
10375tslint-angular@^3.0.2: 11031tsutils@^3.21.0:
10376 version "3.0.3"
10377 resolved "https://registry.yarnpkg.com/tslint-angular/-/tslint-angular-3.0.3.tgz#872d4fe36497d20582dbe4b8ed3338ff0c922c30"
10378 integrity sha512-5xD1gLE89lBExfSbMslDw/ZfOZM0t0CJsoJa4svsgF7tlwVS3IpXjzNcNRN0RZqDBj+cdTlbeel6GpZ3PqpPiw==
10379
10380tslint-config-standard@^9.0.0:
10381 version "9.0.0"
10382 resolved "https://registry.yarnpkg.com/tslint-config-standard/-/tslint-config-standard-9.0.0.tgz#349a94819d93d5f8d803e3c71cb58ef38eff88e0"
10383 integrity sha512-CAw9J743RnPMemQV/XQ4YyNreC+A1NItACfkm+cBedrOkz6CQfwlnbKn8anUXBfoa4Zo4tjAhblRbsMNcSLfSw==
10384 dependencies:
10385 tslint-eslint-rules "^5.3.1"
10386
10387tslint-eslint-rules@^5.3.1:
10388 version "5.4.0"
10389 resolved "https://registry.yarnpkg.com/tslint-eslint-rules/-/tslint-eslint-rules-5.4.0.tgz#e488cc9181bf193fe5cd7bfca213a7695f1737b5"
10390 integrity sha512-WlSXE+J2vY/VPgIcqQuijMQiel+UtmXS+4nvK4ZzlDiqBfXse8FAvkNnTcYhnQyOTW5KFM+uRRGXxYhFpuBc6w==
10391 dependencies:
10392 doctrine "0.7.2"
10393 tslib "1.9.0"
10394 tsutils "^3.0.0"
10395
10396tslint@~6.1.0:
10397 version "6.1.3"
10398 resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904"
10399 integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==
10400 dependencies:
10401 "@babel/code-frame" "^7.0.0"
10402 builtin-modules "^1.1.1"
10403 chalk "^2.3.0"
10404 commander "^2.12.1"
10405 diff "^4.0.1"
10406 glob "^7.1.1"
10407 js-yaml "^3.13.1"
10408 minimatch "^3.0.4"
10409 mkdirp "^0.5.3"
10410 resolve "^1.3.2"
10411 semver "^5.3.0"
10412 tslib "^1.13.0"
10413 tsutils "^2.29.0"
10414
10415tsutils@^2.29.0:
10416 version "2.29.0"
10417 resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99"
10418 integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==
10419 dependencies:
10420 tslib "^1.8.1"
10421
10422tsutils@^3.0.0:
10423 version "3.21.0" 11032 version "3.21.0"
10424 resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" 11033 resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
10425 integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== 11034 integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
@@ -10438,11 +11047,23 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
10438 resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 11047 resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
10439 integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= 11048 integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
10440 11049
11050type-check@^0.4.0, type-check@~0.4.0:
11051 version "0.4.0"
11052 resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
11053 integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
11054 dependencies:
11055 prelude-ls "^1.2.1"
11056
10441type-fest@^0.18.0: 11057type-fest@^0.18.0:
10442 version "0.18.1" 11058 version "0.18.1"
10443 resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" 11059 resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f"
10444 integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== 11060 integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==
10445 11061
11062type-fest@^0.20.2:
11063 version "0.20.2"
11064 resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
11065 integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
11066
10446type-fest@^0.21.3: 11067type-fest@^0.21.3:
10447 version "0.21.3" 11068 version "0.21.3"
10448 resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" 11069 resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
@@ -10500,6 +11121,16 @@ uint64be@^2.0.2:
10500 dependencies: 11121 dependencies:
10501 buffer-alloc "^1.1.0" 11122 buffer-alloc "^1.1.0"
10502 11123
11124unbox-primitive@^1.0.1:
11125 version "1.0.1"
11126 resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
11127 integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==
11128 dependencies:
11129 function-bind "^1.1.1"
11130 has-bigints "^1.0.1"
11131 has-symbols "^1.0.2"
11132 which-boxed-primitive "^1.0.2"
11133
10503unicode-canonical-property-names-ecmascript@^1.0.4: 11134unicode-canonical-property-names-ecmascript@^1.0.4:
10504 version "1.0.4" 11135 version "1.0.4"
10505 resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" 11136 resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
@@ -10593,6 +11224,11 @@ universalify@^0.1.0:
10593 resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" 11224 resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
10594 integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== 11225 integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
10595 11226
11227universalify@^2.0.0:
11228 version "2.0.0"
11229 resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
11230 integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
11231
10596unordered-array-remove@^1.0.2: 11232unordered-array-remove@^1.0.2:
10597 version "1.0.2" 11233 version "1.0.2"
10598 resolved "https://registry.yarnpkg.com/unordered-array-remove/-/unordered-array-remove-1.0.2.tgz#c546e8f88e317a0cf2644c97ecb57dba66d250ef" 11234 resolved "https://registry.yarnpkg.com/unordered-array-remove/-/unordered-array-remove-1.0.2.tgz#c546e8f88e317a0cf2644c97ecb57dba66d250ef"
@@ -10721,7 +11357,7 @@ uuid@^3.3.2, uuid@^3.4.0:
10721 resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" 11357 resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
10722 integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== 11358 integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
10723 11359
10724v8-compile-cache@^2.2.0, v8-compile-cache@^2.3.0: 11360v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0, v8-compile-cache@^2.3.0:
10725 version "2.3.0" 11361 version "2.3.0"
10726 resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" 11362 resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
10727 integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== 11363 integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
@@ -11135,6 +11771,17 @@ whatwg-fetch@^3.0.0:
11135 resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" 11771 resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
11136 integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== 11772 integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
11137 11773
11774which-boxed-primitive@^1.0.2:
11775 version "1.0.2"
11776 resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
11777 integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
11778 dependencies:
11779 is-bigint "^1.0.1"
11780 is-boolean-object "^1.1.0"
11781 is-number-object "^1.0.4"
11782 is-string "^1.0.5"
11783 is-symbol "^1.0.3"
11784
11138which-module@^2.0.0: 11785which-module@^2.0.0:
11139 version "2.0.0" 11786 version "2.0.0"
11140 resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" 11787 resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
@@ -11166,6 +11813,11 @@ wildcard@^2.0.0:
11166 resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" 11813 resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
11167 integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== 11814 integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==
11168 11815
11816word-wrap@^1.2.3:
11817 version "1.2.3"
11818 resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
11819 integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
11820
11169wrap-ansi@^2.0.0: 11821wrap-ansi@^2.0.0:
11170 version "2.1.0" 11822 version "2.1.0"
11171 resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" 11823 resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
@@ -11291,6 +11943,11 @@ yaml@^1.10.0, yaml@^1.10.2:
11291 resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" 11943 resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
11292 integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== 11944 integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
11293 11945
11946yargs-parser@20.0.0:
11947 version "20.0.0"
11948 resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.0.0.tgz#c65a1daaa977ad63cebdd52159147b789a4e19a9"
11949 integrity sha512-8eblPHTL7ZWRkyjIZJjnGf+TijiKJSwA24svzLRVvtgoi/RZiKa9fFQTrlx0OKLnyHSdt/enrdadji6WFfESVA==
11950
11294yargs-parser@^13.1.2: 11951yargs-parser@^13.1.2:
11295 version "13.1.2" 11952 version "13.1.2"
11296 resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" 11953 resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
@@ -11407,11 +12064,6 @@ yocto-queue@^0.1.0:
11407 resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 12064 resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
11408 integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 12065 integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
11409 12066
11410zone.js@~0.10.3:
11411 version "0.10.3"
11412 resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.10.3.tgz#3e5e4da03c607c9dcd92e37dd35687a14a140c16"
11413 integrity sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==
11414
11415zone.js@~0.11.4: 12067zone.js@~0.11.4:
11416 version "0.11.4" 12068 version "0.11.4"
11417 resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.11.4.tgz#0f70dcf6aba80f698af5735cbb257969396e8025" 12069 resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.11.4.tgz#0f70dcf6aba80f698af5735cbb257969396e8025"