Reorganize client shared modules
[oweals/peertube.git] / client / src / app / shared / shared-forms / reactive-file.component.ts
1 import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core'
2 import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
3 import { Notifier } from '@app/core'
4 import { GlobalIconName } from '@app/shared/shared-icons'
5 import { I18n } from '@ngx-translate/i18n-polyfill'
6
7 @Component({
8   selector: 'my-reactive-file',
9   styleUrls: [ './reactive-file.component.scss' ],
10   templateUrl: './reactive-file.component.html',
11   providers: [
12     {
13       provide: NG_VALUE_ACCESSOR,
14       useExisting: forwardRef(() => ReactiveFileComponent),
15       multi: true
16     }
17   ]
18 })
19 export class ReactiveFileComponent implements OnInit, ControlValueAccessor {
20   @Input() inputLabel: string
21   @Input() inputName: string
22   @Input() extensions: string[] = []
23   @Input() maxFileSize: number
24   @Input() displayFilename = false
25   @Input() icon: GlobalIconName
26
27   @Output() fileChanged = new EventEmitter<Blob>()
28
29   allowedExtensionsMessage = ''
30   fileInputValue: any
31
32   private file: File
33
34   constructor (
35     private notifier: Notifier,
36     private i18n: I18n
37   ) {}
38
39   get filename () {
40     if (!this.file) return ''
41
42     return this.file.name
43   }
44
45   ngOnInit () {
46     this.allowedExtensionsMessage = this.extensions.join(', ')
47   }
48
49   fileChange (event: any) {
50     if (event.target.files && event.target.files.length) {
51       const [ file ] = event.target.files
52
53       if (file.size > this.maxFileSize) {
54         this.notifier.error(this.i18n('This file is too large.'))
55         return
56       }
57
58       const extension = '.' + file.name.split('.').pop()
59       if (this.extensions.includes(extension) === false) {
60         const message = this.i18n(
61           'PeerTube cannot handle this kind of file. Accepted extensions are {{extensions}}.',
62           { extensions: this.allowedExtensionsMessage }
63         )
64         this.notifier.error(message)
65
66         return
67       }
68
69       this.file = file
70
71       this.propagateChange(this.file)
72       this.fileChanged.emit(this.file)
73     }
74   }
75
76   propagateChange = (_: any) => { /* empty */ }
77
78   writeValue (file: any) {
79     this.file = file
80
81     if (!this.file) this.fileInputValue = null
82   }
83
84   registerOnChange (fn: (_: any) => void) {
85     this.propagateChange = fn
86   }
87
88   registerOnTouched () {
89     // Unused
90   }
91 }