import { AppState , ContentRecord , ContentRef , KernelRef , NotebookContentRecord , selectors } from "@nteract/core" ; import { remote } from "electron" ; import path from "path" ; import { Store } from "redux" ; import { combineLatest , EMPTY , Observable , of } from "rxjs" ; import { debounceTime , distinctUntilChanged , map , mergeMap , switchMap } from "rxjs/operators" ; import { KernelStatus } from "@nteract/types" ; const HOME = remote . app . getPath ( "home" ) ; param { string } p return { string } export function tildify ( p ? ) { if ( ! p ) { return "" ; } const s = path . normalize ( p ) + path . sep ; return ( s . indexOf ( HOME ) === 0 ? s . replace ( HOME + path . sep , `~${ path . sep }` ) : s ) . slice ( 0 , - 1 ) ; } interface Attributes { fullpath : string ; modified : boolean ; kernelStatus ? : string | null ; } export function setTitleFromAttributes ( attributes ) { const filename = tildify ( attributes . fullpath ) ; const { kernelStatus } = attributes ; try { const win = remote . getCurrentWindow ( ) ; if ( filename && win . setRepresentedFilename ) { win . setRepresentedFilename ( attributes . fullpath ) ; win . setDocumentEdited ( attributes . modified ) ; } const title = `${ filename } - ${ kernelStatus }` ; win . setTitle ( title ) ; } catch ( e ) { ( ( ) => { console . error ( "Unable to set the filename, see https://github.com/nteract/nteract/issues/1277" ) ; console . error ( e ) ; console . error ( e . stack ) ; } ) ( ) ; } } export function createTitleFeed ( contentRef , state$ ) { const content$ = state$ . pipe ( mergeMap ( ( state ) => { const content = selectors . content ( state , { contentRef } ) ; if ( content ) { return of ( content ) ; } else { return EMPTY ; } } ) ) ; const fullpath$ = content$ . pipe ( map ( content => content . filepath || "Untitled" ) , distinctUntilChanged ( ) ) ; const modified$ = content$ . pipe ( map ( untypedContent => { const content = untypedContent as NotebookContentRecord ; return selectors . notebook . isDirty ( content . model ) ; } ) , distinctUntilChanged ( ) ) ; const kernelRef$ = content$ . pipe ( mergeMap ( content => { if ( content && content . type === "notebook" ) { return of ( content . model . kernelRef ) ; } else { return EMPTY ; } } ) ) ; const kernelStatus$ = combineLatest ( state$ , kernelRef$ , ( state , kernelRef ) => { const kernel = selectors . kernel ( state , { kernelRef } ) ; if ( ! kernel ) { return KernelStatus . NotConnected ; } else { return kernel . status ; } } ) . pipe ( debounceTime ( 200 ) ) ; return combineLatest ( modified$ , fullpath$ , kernelStatus$ , ( modified , fullpath , kernelStatus ) => ( { fullpath , kernelStatus : kernelStatus ? kernelStatus . toString ( ) : null , modified } ) ) . pipe ( distinctUntilChanged ( ) , switchMap ( i => of ( i ) ) ) ; } export function initNativeHandlers ( contentRef , store ) { const state$ = new Observable < AppState > ( observer => { const unsubscribe = store . subscribe ( ( ) => { observer . next ( store . getState ( ) ) ; } ) ; return unsubscribe ; } ) ; return createTitleFeed ( contentRef , state$ ) . subscribe ( setTitleFromAttributes , ( err ) => console . error ( err ) ) ; }