aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/shared
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app/shared')
-rw-r--r--client/src/app/shared/shared-actor-image/actor-avatar.component.ts5
-rw-r--r--client/src/app/shared/shared-custom-markup/dynamic-element.service.ts5
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/video-miniature-markup.component.ts3
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/videos-list-markup.component.ts3
-rw-r--r--client/src/app/shared/shared-forms/form-validator.service.ts11
-rw-r--r--client/src/app/shared/shared-icons/global-icon.component.ts2
-rw-r--r--client/src/app/shared/shared-instance/instance.service.ts3
-rw-r--r--client/src/app/shared/shared-main/misc/help.component.ts2
-rw-r--r--client/src/app/shared/shared-main/video/video-edit.model.ts6
-rw-r--r--client/src/app/shared/shared-share-modal/video-share.component.ts3
-rw-r--r--client/src/app/shared/shared-video-miniature/video-download.component.ts27
-rw-r--r--client/src/app/shared/shared-video-miniature/video-filters.model.ts2
-rw-r--r--client/src/app/shared/shared-video-miniature/videos-selection.component.ts3
13 files changed, 44 insertions, 31 deletions
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 f1c1aa03f..ab2e02ad7 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
@@ -1,6 +1,7 @@
1import { Component, Input, OnChanges, OnInit } from '@angular/core' 1import { Component, Input, OnChanges, OnInit } from '@angular/core'
2import { VideoChannel } from '../shared-main' 2import { VideoChannel } from '../shared-main'
3import { Account } from '../shared-main/account/account.model' 3import { Account } from '../shared-main/account/account.model'
4import { objectKeysTyped } from '@shared/core-utils'
4 5
5type ActorInput = { 6type ActorInput = {
6 name: string 7 name: string
@@ -154,8 +155,8 @@ export class ActorAvatarComponent implements OnInit, OnChanges {
154 'wxyz': 'dark-blue' 155 'wxyz': 'dark-blue'
155 } 156 }
156 157
157 const theme = Object.keys(themes) 158 const theme = objectKeysTyped(themes)
158 .find(chars => chars.includes(initialLowercase)) 159 .find(chars => chars.includes(initialLowercase))
159 160
160 return themes[theme] || 'blue' 161 return themes[theme] || 'blue'
161 } 162 }
diff --git a/client/src/app/shared/shared-custom-markup/dynamic-element.service.ts b/client/src/app/shared/shared-custom-markup/dynamic-element.service.ts
index 208dba721..a12907055 100644
--- a/client/src/app/shared/shared-custom-markup/dynamic-element.service.ts
+++ b/client/src/app/shared/shared-custom-markup/dynamic-element.service.ts
@@ -10,6 +10,7 @@ import {
10 SimpleChanges, 10 SimpleChanges,
11 Type 11 Type
12} from '@angular/core' 12} from '@angular/core'
13import { objectKeysTyped } from '@shared/core-utils'
13 14
14@Injectable() 15@Injectable()
15export class DynamicElementService { 16export class DynamicElementService {
@@ -41,12 +42,12 @@ export class DynamicElementService {
41 setModel <T> (componentRef: ComponentRef<T>, attributes: Partial<T>) { 42 setModel <T> (componentRef: ComponentRef<T>, attributes: Partial<T>) {
42 const changes: SimpleChanges = {} 43 const changes: SimpleChanges = {}
43 44
44 for (const key of Object.keys(attributes)) { 45 for (const key of objectKeysTyped(attributes)) {
45 const previousValue = componentRef.instance[key] 46 const previousValue = componentRef.instance[key]
46 const newValue = attributes[key] 47 const newValue = attributes[key]
47 48
48 componentRef.instance[key] = newValue 49 componentRef.instance[key] = newValue
49 changes[key] = new SimpleChange(previousValue, newValue, previousValue === undefined) 50 changes[key as string] = new SimpleChange(previousValue, newValue, previousValue === undefined)
50 } 51 }
51 52
52 const component = componentRef.instance 53 const component = componentRef.instance
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 21774b7aa..bd93929c9 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
@@ -2,6 +2,7 @@ import { finalize } from 'rxjs/operators'
2import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core' 2import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
3import { AuthService, Notifier } from '@app/core' 3import { AuthService, Notifier } from '@app/core'
4import { FindInBulkService } from '@app/shared/shared-search' 4import { FindInBulkService } from '@app/shared/shared-search'
5import { objectKeysTyped } from '@shared/core-utils'
5import { Video } from '../../shared-main' 6import { Video } from '../../shared-main'
6import { MiniatureDisplayOptions } from '../../shared-video-miniature' 7import { MiniatureDisplayOptions } from '../../shared-video-miniature'
7import { CustomMarkupComponent } from './shared' 8import { CustomMarkupComponent } from './shared'
@@ -47,7 +48,7 @@ export class VideoMiniatureMarkupComponent implements CustomMarkupComponent, OnI
47 48
48 ngOnInit () { 49 ngOnInit () {
49 if (this.onlyDisplayTitle) { 50 if (this.onlyDisplayTitle) {
50 for (const key of Object.keys(this.displayOptions)) { 51 for (const key of objectKeysTyped(this.displayOptions)) {
51 this.displayOptions[key] = false 52 this.displayOptions[key] = false
52 } 53 }
53 } 54 }
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/videos-list-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/videos-list-markup.component.ts
index 7c2e7db6a..81363be87 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/videos-list-markup.component.ts
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/videos-list-markup.component.ts
@@ -1,6 +1,7 @@
1import { finalize } from 'rxjs/operators' 1import { finalize } from 'rxjs/operators'
2import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core' 2import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
3import { AuthService, Notifier } from '@app/core' 3import { AuthService, Notifier } from '@app/core'
4import { objectKeysTyped } from '@shared/core-utils'
4import { VideoSortField } from '@shared/models' 5import { VideoSortField } from '@shared/models'
5import { Video, VideoService } from '../../shared-main' 6import { Video, VideoService } from '../../shared-main'
6import { MiniatureDisplayOptions } from '../../shared-video-miniature' 7import { MiniatureDisplayOptions } from '../../shared-video-miniature'
@@ -66,7 +67,7 @@ export class VideosListMarkupComponent implements CustomMarkupComponent, OnInit
66 67
67 ngOnInit () { 68 ngOnInit () {
68 if (this.onlyDisplayTitle) { 69 if (this.onlyDisplayTitle) {
69 for (const key of Object.keys(this.displayOptions)) { 70 for (const key of objectKeysTyped(this.displayOptions)) {
70 this.displayOptions[key] = false 71 this.displayOptions[key] = false
71 } 72 }
72 } 73 }
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 897008242..14ee044b5 100644
--- a/client/src/app/shared/shared-forms/form-validator.service.ts
+++ b/client/src/app/shared/shared-forms/form-validator.service.ts
@@ -1,5 +1,6 @@
1import { Injectable } from '@angular/core' 1import { Injectable } from '@angular/core'
2import { AsyncValidatorFn, FormArray, FormBuilder, FormControl, FormGroup, ValidatorFn } from '@angular/forms' 2import { AsyncValidatorFn, FormArray, FormBuilder, FormControl, FormGroup, ValidatorFn } from '@angular/forms'
3import { objectKeysTyped } from '@shared/core-utils'
3import { BuildFormArgument, BuildFormDefaultValues } from '../form-validators/form-validator.model' 4import { BuildFormArgument, BuildFormDefaultValues } from '../form-validators/form-validator.model'
4import { FormReactiveErrors, FormReactiveValidationMessages } from './form-reactive.service' 5import { FormReactiveErrors, FormReactiveValidationMessages } from './form-reactive.service'
5 6
@@ -47,13 +48,14 @@ export class FormValidatorService {
47 obj: BuildFormArgument, 48 obj: BuildFormArgument,
48 defaultValues: BuildFormDefaultValues = {} 49 defaultValues: BuildFormDefaultValues = {}
49 ) { 50 ) {
50 for (const name of Object.keys(obj)) { 51 for (const name of objectKeysTyped(obj)) {
51 formErrors[name] = '' 52 formErrors[name] = ''
52 53
53 const field = obj[name] 54 const field = obj[name]
54 if (this.isRecursiveField(field)) { 55 if (this.isRecursiveField(field)) {
55 this.updateFormGroup( 56 this.updateFormGroup(
56 form[name], 57 // FIXME: typings
58 (form as any)[name],
57 formErrors[name] as FormReactiveErrors, 59 formErrors[name] as FormReactiveErrors,
58 validationMessages[name] as FormReactiveValidationMessages, 60 validationMessages[name] as FormReactiveValidationMessages,
59 obj[name] as BuildFormArgument, 61 obj[name] as BuildFormArgument,
@@ -67,7 +69,7 @@ export class FormValidatorService {
67 const defaultValue = defaultValues[name] || '' 69 const defaultValue = defaultValues[name] || ''
68 70
69 form.addControl( 71 form.addControl(
70 name, 72 name + '',
71 new FormControl(defaultValue, field?.VALIDATORS as ValidatorFn[], field?.ASYNC_VALIDATORS as AsyncValidatorFn[]) 73 new FormControl(defaultValue, field?.VALIDATORS as ValidatorFn[], field?.ASYNC_VALIDATORS as AsyncValidatorFn[])
72 ) 74 )
73 } 75 }
@@ -75,7 +77,8 @@ export class FormValidatorService {
75 77
76 updateTreeValidity (group: FormGroup | FormArray): void { 78 updateTreeValidity (group: FormGroup | FormArray): void {
77 for (const key of Object.keys(group.controls)) { 79 for (const key of Object.keys(group.controls)) {
78 const abstractControl = group.controls[key] as FormControl 80 // FIXME: typings
81 const abstractControl = (group.controls as any)[key] as FormControl
79 82
80 if (abstractControl instanceof FormGroup || abstractControl instanceof FormArray) { 83 if (abstractControl instanceof FormGroup || abstractControl instanceof FormArray) {
81 this.updateTreeValidity(abstractControl) 84 this.updateTreeValidity(abstractControl)
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 96179cbe6..eea460831 100644
--- a/client/src/app/shared/shared-icons/global-icon.component.ts
+++ b/client/src/app/shared/shared-icons/global-icon.component.ts
@@ -112,7 +112,7 @@ export class GlobalIconComponent implements OnInit {
112 } 112 }
113 } 113 }
114 114
115 private getSVGContent (options: { name: string }) { 115 private getSVGContent (options: { name: GlobalIconName }) {
116 return icons[options.name] 116 return icons[options.name]
117 } 117 }
118} 118}
diff --git a/client/src/app/shared/shared-instance/instance.service.ts b/client/src/app/shared/shared-instance/instance.service.ts
index 2defffbbe..3088f0899 100644
--- a/client/src/app/shared/shared-instance/instance.service.ts
+++ b/client/src/app/shared/shared-instance/instance.service.ts
@@ -3,6 +3,7 @@ import { catchError, map } from 'rxjs/operators'
3import { HttpClient } from '@angular/common/http' 3import { HttpClient } from '@angular/common/http'
4import { Injectable } from '@angular/core' 4import { Injectable } from '@angular/core'
5import { MarkdownService, RestExtractor, ServerService } from '@app/core' 5import { MarkdownService, RestExtractor, ServerService } from '@app/core'
6import { objectKeysTyped } from '@shared/core-utils'
6import { peertubeTranslate } from '@shared/core-utils/i18n' 7import { peertubeTranslate } from '@shared/core-utils/i18n'
7import { About } from '@shared/models' 8import { About } from '@shared/models'
8import { environment } from '../../../environments/environment' 9import { environment } from '../../../environments/environment'
@@ -55,7 +56,7 @@ export class InstanceService {
55 hardwareInformation: '' 56 hardwareInformation: ''
56 } 57 }
57 58
58 for (const key of Object.keys(html)) { 59 for (const key of objectKeysTyped(html)) {
59 html[key] = await this.markdownService.enhancedMarkdownToHTML({ markdown: about.instance[key] }) 60 html[key] = await this.markdownService.enhancedMarkdownToHTML({ markdown: about.instance[key] })
60 } 61 }
61 62
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 37e2abd97..80fe0e160 100644
--- a/client/src/app/shared/shared-main/misc/help.component.ts
+++ b/client/src/app/shared/shared-main/misc/help.component.ts
@@ -77,7 +77,7 @@ export class HelpComponent implements OnInit, OnChanges, AfterContentInit {
77 } 77 }
78 78
79 private createMarkdownList (rules: string[]) { 79 private createMarkdownList (rules: string[]) {
80 const rulesToText = { 80 const rulesToText: { [id: string]: string } = {
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`,
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 91d57cb6b..47eee80d8 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
@@ -1,6 +1,7 @@
1import { getAbsoluteAPIUrl } from '@app/helpers' 1import { getAbsoluteAPIUrl } from '@app/helpers'
2import { VideoPrivacy, VideoScheduleUpdate, VideoUpdate } from '@shared/models' 2import { VideoPrivacy, VideoScheduleUpdate, VideoUpdate } from '@shared/models'
3import { VideoDetails } from './video-details.model' 3import { VideoDetails } from './video-details.model'
4import { objectKeysTyped } from '@shared/core-utils'
4 5
5export class VideoEdit implements VideoUpdate { 6export class VideoEdit implements VideoUpdate {
6 static readonly SPECIAL_SCHEDULED_PRIVACY = -1 7 static readonly SPECIAL_SCHEDULED_PRIVACY = -1
@@ -65,8 +66,9 @@ export class VideoEdit implements VideoUpdate {
65 } 66 }
66 67
67 patch (values: { [ id: string ]: any }) { 68 patch (values: { [ id: string ]: any }) {
68 Object.keys(values).forEach((key) => { 69 objectKeysTyped(values).forEach(key => {
69 this[key] = values[key] 70 // FIXME: typings
71 (this as any)[key] = values[key]
70 }) 72 })
71 73
72 // If schedule publication, the video is private and will be changed to public privacy 74 // If schedule publication, the video is private and will be changed to public privacy
diff --git a/client/src/app/shared/shared-share-modal/video-share.component.ts b/client/src/app/shared/shared-share-modal/video-share.component.ts
index 1b69aa2d0..32f900f15 100644
--- a/client/src/app/shared/shared-share-modal/video-share.component.ts
+++ b/client/src/app/shared/shared-share-modal/video-share.component.ts
@@ -106,7 +106,8 @@ export class VideoShareComponent {
106 includeVideoInPlaylist: false 106 includeVideoInPlaylist: false
107 }, { 107 }, {
108 set: (target, prop, value) => { 108 set: (target, prop, value) => {
109 target[prop] = value 109 // FIXME: typings
110 (target as any)[prop] = value
110 111
111 if (prop === 'embedP2P') { 112 if (prop === 'embedP2P') {
112 // Auto enabled warning title if P2P is enabled 113 // Auto enabled warning title if P2P is enabled
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 4135542dc..cac82d8d0 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
@@ -1,4 +1,4 @@
1import { mapValues, pick } from 'lodash-es' 1import { mapValues } from 'lodash-es'
2import { firstValueFrom } from 'rxjs' 2import { firstValueFrom } from 'rxjs'
3import { tap } from 'rxjs/operators' 3import { tap } from 'rxjs/operators'
4import { Component, ElementRef, Inject, LOCALE_ID, ViewChild } from '@angular/core' 4import { Component, ElementRef, Inject, LOCALE_ID, ViewChild } from '@angular/core'
@@ -6,11 +6,12 @@ import { HooksService } from '@app/core'
6import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' 6import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'
7import { logger } from '@root-helpers/logger' 7import { logger } from '@root-helpers/logger'
8import { videoRequiresAuth } from '@root-helpers/video' 8import { videoRequiresAuth } from '@root-helpers/video'
9import { objectKeysTyped, pick } from '@shared/core-utils'
9import { VideoCaption, VideoFile, VideoPrivacy } from '@shared/models' 10import { VideoCaption, VideoFile, VideoPrivacy } from '@shared/models'
10import { BytesPipe, NumberFormatterPipe, VideoDetails, VideoFileTokenService, VideoService } from '../shared-main' 11import { BytesPipe, NumberFormatterPipe, VideoDetails, VideoFileTokenService, VideoService } from '../shared-main'
11 12
12type DownloadType = 'video' | 'subtitles' 13type DownloadType = 'video' | 'subtitles'
13type FileMetadata = { [key: string]: { label: string, value: string } } 14type FileMetadata = { [key: string]: { label: string, value: string | number } }
14 15
15@Component({ 16@Component({
16 selector: 'my-video-download', 17 selector: 'my-video-download',
@@ -218,10 +219,10 @@ export class VideoDownloadComponent {
218 const keyToTranslateFunction = { 219 const keyToTranslateFunction = {
219 encoder: (value: string) => ({ label: $localize`Encoder`, value }), 220 encoder: (value: string) => ({ label: $localize`Encoder`, value }),
220 format_long_name: (value: string) => ({ label: $localize`Format name`, value }), 221 format_long_name: (value: string) => ({ label: $localize`Format name`, value }),
221 size: (value: number) => ({ label: $localize`Size`, value: this.bytesPipe.transform(value, 2) }), 222 size: (value: number | string) => ({ label: $localize`Size`, value: this.bytesPipe.transform(+value, 2) }),
222 bit_rate: (value: number) => ({ 223 bit_rate: (value: number | string) => ({
223 label: $localize`Bitrate`, 224 label: $localize`Bitrate`,
224 value: `${this.numbersPipe.transform(value)}bps` 225 value: `${this.numbersPipe.transform(+value)}bps`
225 }) 226 })
226 } 227 }
227 228
@@ -230,8 +231,8 @@ export class VideoDownloadComponent {
230 delete sanitizedFormat.tags 231 delete sanitizedFormat.tags
231 232
232 return mapValues( 233 return mapValues(
233 pick(sanitizedFormat, Object.keys(keyToTranslateFunction)), 234 pick(sanitizedFormat, objectKeysTyped(keyToTranslateFunction)),
234 (val, key) => keyToTranslateFunction[key](val) 235 (val: string, key: keyof typeof keyToTranslateFunction) => keyToTranslateFunction[key](val)
235 ) 236 )
236 } 237 }
237 238
@@ -242,29 +243,29 @@ export class VideoDownloadComponent {
242 let keyToTranslateFunction = { 243 let keyToTranslateFunction = {
243 codec_long_name: (value: string) => ({ label: $localize`Codec`, value }), 244 codec_long_name: (value: string) => ({ label: $localize`Codec`, value }),
244 profile: (value: string) => ({ label: $localize`Profile`, value }), 245 profile: (value: string) => ({ label: $localize`Profile`, value }),
245 bit_rate: (value: number) => ({ 246 bit_rate: (value: number | string) => ({
246 label: $localize`Bitrate`, 247 label: $localize`Bitrate`,
247 value: `${this.numbersPipe.transform(value)}bps` 248 value: `${this.numbersPipe.transform(+value)}bps`
248 }) 249 })
249 } 250 }
250 251
251 if (type === 'video') { 252 if (type === 'video') {
252 keyToTranslateFunction = Object.assign(keyToTranslateFunction, { 253 keyToTranslateFunction = Object.assign(keyToTranslateFunction, {
253 width: (value: number) => ({ label: $localize`Resolution`, value: `${value}x${stream.height}` }), 254 width: (value: string | number) => ({ label: $localize`Resolution`, value: `${value}x${stream.height}` }),
254 display_aspect_ratio: (value: string) => ({ label: $localize`Aspect ratio`, value }), 255 display_aspect_ratio: (value: string) => ({ label: $localize`Aspect ratio`, value }),
255 avg_frame_rate: (value: string) => ({ label: $localize`Average frame rate`, value }), 256 avg_frame_rate: (value: string) => ({ label: $localize`Average frame rate`, value }),
256 pix_fmt: (value: string) => ({ label: $localize`Pixel format`, value }) 257 pix_fmt: (value: string) => ({ label: $localize`Pixel format`, value })
257 }) 258 })
258 } else { 259 } else {
259 keyToTranslateFunction = Object.assign(keyToTranslateFunction, { 260 keyToTranslateFunction = Object.assign(keyToTranslateFunction, {
260 sample_rate: (value: number) => ({ label: $localize`Sample rate`, value }), 261 sample_rate: (value: string | number) => ({ label: $localize`Sample rate`, value }),
261 channel_layout: (value: number) => ({ label: $localize`Channel Layout`, value }) 262 channel_layout: (value: string | number) => ({ label: $localize`Channel Layout`, value })
262 }) 263 })
263 } 264 }
264 265
265 return mapValues( 266 return mapValues(
266 pick(stream, Object.keys(keyToTranslateFunction)), 267 pick(stream, Object.keys(keyToTranslateFunction)),
267 (val, key) => keyToTranslateFunction[key](val) 268 (val: string, key: keyof typeof keyToTranslateFunction) => keyToTranslateFunction[key](val)
268 ) 269 )
269 } 270 }
270 271
diff --git a/client/src/app/shared/shared-video-miniature/video-filters.model.ts b/client/src/app/shared/shared-video-miniature/video-filters.model.ts
index 6b4b72c75..4db73b25a 100644
--- a/client/src/app/shared/shared-video-miniature/video-filters.model.ts
+++ b/client/src/app/shared/shared-video-miniature/video-filters.model.ts
@@ -84,7 +84,7 @@ export class VideoFilters {
84 if (specificKey && specificKey !== key) continue 84 if (specificKey && specificKey !== key) continue
85 85
86 // FIXME: typings 86 // FIXME: typings
87 this[key as any] = value 87 (this as any)[key] = value
88 } 88 }
89 89
90 this.buildActiveFilters() 90 this.buildActiveFilters()
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 460a0080e..86fe502e2 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
@@ -2,6 +2,7 @@ import { Observable, Subject } from 'rxjs'
2import { AfterContentInit, Component, ContentChildren, EventEmitter, Input, Output, QueryList, TemplateRef } from '@angular/core' 2import { AfterContentInit, Component, ContentChildren, EventEmitter, Input, Output, QueryList, TemplateRef } from '@angular/core'
3import { ComponentPagination, Notifier, User } from '@app/core' 3import { ComponentPagination, Notifier, User } from '@app/core'
4import { logger } from '@root-helpers/logger' 4import { logger } from '@root-helpers/logger'
5import { objectKeysTyped } from '@shared/core-utils'
5import { ResultList, VideosExistInPlaylists, VideoSortField } from '@shared/models' 6import { ResultList, VideosExistInPlaylists, VideoSortField } from '@shared/models'
6import { PeerTubeTemplateDirective, Video } from '../shared-main' 7import { PeerTubeTemplateDirective, Video } from '../shared-main'
7import { MiniatureDisplayOptions } from './video-miniature.component' 8import { MiniatureDisplayOptions } from './video-miniature.component'
@@ -93,7 +94,7 @@ export class VideosSelectionComponent implements AfterContentInit {
93 } 94 }
94 95
95 isInSelectionMode () { 96 isInSelectionMode () {
96 return Object.keys(this._selection).some(k => this._selection[k] === true) 97 return objectKeysTyped(this._selection).some(k => this._selection[k] === true)
97 } 98 }
98 99
99 videoById (index: number, video: Video) { 100 videoById (index: number, video: Video) {