import { FocusKeyManager } from '@angular/cdk/a11y' ; import { AfterViewInit , Component , HostListener , OnDestroy , OnInit , QueryList , ViewChildren } from '@angular/core' ; import { select , Store } from '@ngrx/store' ; import { shell } from 'electron' ; import { Observable , Subscription } from 'rxjs' ; import { tap } from 'rxjs/operators' ; import { VcsFileChangeStatusTypes } from '../../../../core/vcs' ; import { NoteStateWithRoot } from '../../note.state' ; import { NoteCollectionService } from '../note-collection.service' ; import { NoteCollectionViewModes } from '../note-collection.state' ; import { NoteItem } from '../note-item.model' ; import { NoteItemComponent , NoteItemContextMenuEvent , NoteItemSelectionChange } from '../note-item/note-item.component' ; @ Component ( { selector : 'gd-note-list' , templateUrl : './note-list.component.html' , styleUrls : [ './note-list.component.scss' ] , } ) export class NoteListComponent implements OnInit , OnDestroy , AfterViewInit { private _isEmpty = false ; get isEmpty ( ) : boolean { return this . _isEmpty ; } private _initialLoaded = false ; get initialLoaded ( ) : boolean { return this . _initialLoaded ; } private _viewMode : NoteCollectionViewModes ; get viewMode ( ) : NoteCollectionViewModes { return this . _viewMode ; } /** Filtered and sorted notes stream from collection. */ readonly notes : Observable < NoteItem [ ] > = this . collection . getFilteredAndSortedNoteList ( ) . pipe ( tap ( ( notes ) => { if ( ! this . _initialLoaded ) { this . _initialLoaded = true ; } this . _isEmpty = notes . length === 0 ; } ) ) ; /** Focus key manager for note items. */ _focusKeyManager : FocusKeyManager < NoteItemComponent > ; /** Query list for note items. */ @ ViewChildren ( NoteItemComponent ) private noteItemChildren : QueryList < NoteItemComponent > ; private _selectedNote : NoteItem | null = null ; private selectedNoteSubscription = Subscription . EMPTY ; private viewModeSubscription = Subscription . EMPTY ; constructor ( private store , private collection ) { } ngOnInit ( ) { this . selectedNoteSubscription = this . collection . getSelectedNote ( ) . subscribe ( selectedNote => this . _selectedNote = selectedNote ) ; this . viewModeSubscription = this . store . pipe ( select ( state => state . note . collection . viewMode ) ) . subscribe ( viewMode => this . _viewMode = viewMode ) ; } ngOnDestroy ( ) { this . selectedNoteSubscription . unsubscribe ( ) ; this . viewModeSubscription . unsubscribe ( ) ; } ngAfterViewInit ( ) { this . _focusKeyManager = new FocusKeyManager ( this . noteItemChildren ) . withVerticalOrientation ( true ) ; } selectNote ( event ) { const index = this . getIndexOfNote ( event . source . note ) ; if ( index !== - 1 ) { if ( event . isUserInput ) { this . _focusKeyManager . setActiveItem ( index ) ; } else { this . _focusKeyManager . updateActiveItem ( index ) ; } } this . collection . toggleNoteSelection ( event . source . note ) ; } isSelectedItem ( note ) { if ( this . _selectedNote ) { return this . _selectedNote . id === note . id ; } else { return false ; } } isActiveItem ( note ) { if ( ! this . _focusKeyManager . activeItem ) { return false ; } return this . _focusKeyManager . activeItem . note === note ; } getVcsFileStatus ( note ) { return this . collection . getNoteVcsFileChangeStatus ( note ) ; } handleContextMenuCommand ( event ) { switch ( event . command ) { case 'revealInFinder' : shell . showItemInFolder ( event . source . note . contentFilePath ) ; break ; case 'deleteNote' : this . collection . deleteNote ( event . source . note ) ; break ; } } @ HostListener ( 'keydown' , [ '$event' ] ) private handleKeyDown ( event ) { this . _focusKeyManager . onKeydown ( event ) ; } private getIndexOfNote ( note ) { const arrayItems = this . noteItemChildren . toArray ( ) ; if ( ! arrayItems ) { return - 1 ; } return this . noteItemChildren . toArray ( ) . findIndex ( noteElem => noteElem . note . id === note . id ) ; } }