66
77import { CodeEditor } from '@acrodata/code-editor'
88import { HttpClient , HttpErrorResponse } from '@angular/common/http'
9- import { Component , inject , input , linkedSignal , OnDestroy , OnInit , signal , ViewEncapsulation } from '@angular/core'
9+ import { Component , HostListener , inject , input , linkedSignal , OnDestroy , OnInit , signal , ViewChild , ViewEncapsulation } from '@angular/core'
1010import { FormsModule } from '@angular/forms'
1111import { LanguageDescription } from '@codemirror/language'
1212import { languages } from '@codemirror/language-data'
13- import { openSearchPanel } from '@codemirror/search'
13+ import { closeSearchPanel , openSearchPanel } from '@codemirror/search'
1414import { FaIconComponent } from '@fortawesome/angular-fontawesome'
1515import { faFloppyDisk , faLock , faLockOpen , faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons'
1616import { L10N_LOCALE , L10nLocale , L10nTranslatePipe } from 'angular-l10n'
17+ import { ButtonCheckboxDirective } from 'ngx-bootstrap/buttons'
1718import { TooltipModule } from 'ngx-bootstrap/tooltip'
1819import { themeDark } from '../../../../layout/layout.interfaces'
1920import { LayoutService } from '../../../../layout/layout.service'
@@ -23,38 +24,72 @@ import { FilesUploadService } from '../../services/files-upload.service'
2324@Component ( {
2425 selector : 'app-files-viewer-text' ,
2526 encapsulation : ViewEncapsulation . None ,
26- imports : [ CodeEditor , TooltipModule , FormsModule , FaIconComponent , L10nTranslatePipe ] ,
27+ imports : [ CodeEditor , TooltipModule , FormsModule , FaIconComponent , L10nTranslatePipe , ButtonCheckboxDirective ] ,
2728 styles : [
2829 `
2930 .code-editor {
3031 height: calc(100% - 40px);
31- font-size: 0.75rem ;
32+ font-size: 0.8rem ;
3233 }
3334 `
3435 ] ,
3536 templateUrl : 'files-viewer-text.component.html'
3637} )
3738export class FilesViewerTextComponent implements OnInit , OnDestroy {
39+ @ViewChild ( 'editor' ) editor : CodeEditor
3840 currentHeight = input < number > ( )
3941 file = input < FileModel > ( )
4042 mode = input < 'view' | 'edit' > ( 'view' )
4143 isReadonly = linkedSignal ( ( ) => this . mode ( ) === 'view' )
4244 isReadable = signal ( false )
4345 isModified = signal ( false )
44- protected readonly openSearchPanel = openSearchPanel
4546 protected content : string
4647 protected currentLanguage = undefined
4748 protected readonly languages : LanguageDescription [ ] = languages
4849 protected currentTheme : any = 'light'
4950 protected readonly icons = { faFloppyDisk, faLock, faLockOpen, faMagnifyingGlass }
5051 protected readonly locale = inject < L10nLocale > ( L10N_LOCALE )
52+ protected isSearchPanelOpen = false
5153 private isContentReady = false
5254 private readonly layout = inject ( LayoutService )
5355 private readonly http = inject ( HttpClient )
5456 private readonly filesUpload = inject ( FilesUploadService )
5557 private subscription = this . layout . switchTheme . subscribe ( ( layout : string ) => ( this . currentTheme = layout === themeDark ? 'dark' : 'light' ) )
5658 private readonly maxSize = 5242880 // 5MB
5759
60+ @HostListener ( 'document:keydown' , [ '$event' ] )
61+ onKeyDown ( event : KeyboardEvent ) {
62+ // ESC
63+ if ( event . key === 'Escape' || event . key === 'Esc' ) {
64+ event . stopPropagation ( )
65+ event . preventDefault ( )
66+ if ( this . isSearchPanelOpen ) {
67+ this . toggleSearch ( )
68+ } else if ( ! this . isModified ( ) ) {
69+ if ( this . isModified ( ) ) {
70+ // show dialog alert
71+ } else {
72+ this . layout . closeDialog ( )
73+ }
74+ }
75+ return
76+ }
77+ // Ctrl/Cmd+S | Ctrl/Cmd+F
78+ if ( event . ctrlKey || event . metaKey ) {
79+ switch ( event . key . toLowerCase ( ) ) {
80+ case 's' :
81+ event . preventDefault ( )
82+ this . save ( )
83+ return
84+ case 'f' :
85+ event . preventDefault ( )
86+ event . stopPropagation ( )
87+ this . toggleSearch ( )
88+ return
89+ }
90+ }
91+ }
92+
5893 ngOnInit ( ) {
5994 const language : LanguageDescription = LanguageDescription . matchFilename ( languages , this . file ( ) . name )
6095 if ( language ?. name || this . file ( ) . size <= this . maxSize ) {
@@ -78,6 +113,15 @@ export class FilesViewerTextComponent implements OnInit, OnDestroy {
78113 } )
79114 }
80115
116+ toggleSearch ( ) {
117+ this . isSearchPanelOpen = ! this . isSearchPanelOpen
118+ if ( this . isSearchPanelOpen ) {
119+ openSearchPanel ( this . editor . view )
120+ } else {
121+ closeSearchPanel ( this . editor . view )
122+ }
123+ }
124+
81125 contentChange ( ) {
82126 // Ignore first call
83127 if ( this . isContentReady ) {
0 commit comments