2021-01-12 01:33:10 +02:00
import ViewController , { EmitMessageEvent } from './ViewController' ;
2020-11-05 18:58:23 +02:00
import shim from '../../shim' ;
2021-02-07 12:09:28 +02:00
import { ButtonSpec , DialogResult , ViewHandle } from './api/types' ;
2020-11-05 18:58:23 +02:00
const { toSystemSlashes } = require ( '../../path-utils' ) ;
2020-10-09 19:35:46 +02:00
export enum ContainerType {
Panel = 'panel' ,
Dialog = 'dialog' ,
}
export interface Options {
2020-11-12 21:29:22 +02:00
containerType : ContainerType ;
2020-10-09 19:35:46 +02:00
}
interface CloseResponse {
resolve : Function ;
reject : Function ;
}
2021-01-02 15:32:15 +02:00
// TODO: Copied from:
// packages/app-desktop/gui/ResizableLayout/utils/findItemByKey.ts
function findItemByKey ( layout : any , key : string ) : any {
if ( ! layout ) throw new Error ( 'Layout cannot be null' ) ;
function recurseFind ( item : any ) : any {
if ( item . key === key ) return item ;
if ( item . children ) {
for ( const child of item . children ) {
const found = recurseFind ( child ) ;
if ( found ) return found ;
}
}
return null ;
}
return recurseFind ( layout ) ;
}
2020-10-09 19:35:46 +02:00
export default class WebviewController extends ViewController {
2020-11-12 21:13:28 +02:00
private baseDir_ : string ;
private messageListener_ : Function = null ;
private closeResponse_ : CloseResponse = null ;
2020-10-09 19:35:46 +02:00
2021-02-07 12:09:28 +02:00
public constructor ( handle : ViewHandle , pluginId : string , store : any , baseDir : string , containerType : ContainerType ) {
super ( handle , pluginId , store ) ;
2020-10-09 19:35:46 +02:00
this . baseDir_ = toSystemSlashes ( baseDir , 'linux' ) ;
this . store . dispatch ( {
type : 'PLUGIN_VIEW_ADD' ,
pluginId : pluginId ,
view : {
id : this.handle ,
type : this . type ,
2020-11-13 19:09:28 +02:00
containerType : containerType ,
2020-10-09 19:35:46 +02:00
html : '' ,
scripts : [ ] ,
opened : false ,
buttons : null ,
} ,
} ) ;
}
2020-11-12 21:13:28 +02:00
public get type ( ) : string {
2020-10-09 19:35:46 +02:00
return 'webview' ;
}
2020-11-12 21:13:28 +02:00
private setStoreProp ( name : string , value : any ) {
2020-10-09 19:35:46 +02:00
this . store . dispatch ( {
type : 'PLUGIN_VIEW_PROP_SET' ,
pluginId : this.pluginId ,
id : this.handle ,
name : name ,
value : value ,
} ) ;
}
2020-11-12 21:13:28 +02:00
public get html ( ) : string {
2020-10-09 19:35:46 +02:00
return this . storeView . html ;
}
2020-11-12 21:13:28 +02:00
public set html ( html : string ) {
2020-10-09 19:35:46 +02:00
this . setStoreProp ( 'html' , html ) ;
}
2020-11-12 21:13:28 +02:00
public get containerType ( ) : ContainerType {
2020-10-09 19:35:46 +02:00
return this . storeView . containerType ;
}
2020-11-12 21:13:28 +02:00
public async addScript ( path : string ) {
2020-10-09 19:35:46 +02:00
const fullPath = toSystemSlashes ( shim . fsDriver ( ) . resolve ( ` ${ this . baseDir_ } / ${ path } ` ) , 'linux' ) ;
if ( fullPath . indexOf ( this . baseDir_ ) !== 0 ) throw new Error ( ` Script appears to be outside of plugin base directory: ${ fullPath } (Base dir: ${ this . baseDir_ } ) ` ) ;
this . store . dispatch ( {
type : 'PLUGIN_VIEW_PROP_PUSH' ,
pluginId : this.pluginId ,
id : this.handle ,
name : 'scripts' ,
value : fullPath ,
} ) ;
}
2021-01-12 01:33:10 +02:00
public async emitMessage ( event : EmitMessageEvent ) : Promise < any > {
2020-10-09 19:35:46 +02:00
if ( ! this . messageListener_ ) return ;
2021-01-12 01:33:10 +02:00
return this . messageListener_ ( event . message ) ;
2020-10-09 19:35:46 +02:00
}
2020-11-12 21:13:28 +02:00
public onMessage ( callback : any ) {
2020-10-09 19:35:46 +02:00
this . messageListener_ = callback ;
}
2021-01-02 15:32:15 +02:00
// ---------------------------------------------
// Specific to panels
// ---------------------------------------------
public async show ( show : boolean = true ) : Promise < void > {
this . store . dispatch ( {
type : 'MAIN_LAYOUT_SET_ITEM_PROP' ,
itemKey : this.handle ,
propName : 'visible' ,
propValue : show ,
} ) ;
}
public async hide ( ) : Promise < void > {
return this . show ( false ) ;
}
public get visible ( ) : boolean {
const mainLayout = this . store . getState ( ) . mainLayout ;
const item = findItemByKey ( mainLayout , this . handle ) ;
return item ? item.visible : false ;
}
2020-10-09 19:35:46 +02:00
// ---------------------------------------------
// Specific to dialogs
// ---------------------------------------------
2020-11-13 20:48:42 +02:00
public async open ( ) : Promise < DialogResult > {
2021-02-07 12:09:28 +02:00
this . store . dispatch ( {
type : 'VISIBLE_DIALOGS_ADD' ,
name : this.handle ,
} ) ;
2020-10-09 19:35:46 +02:00
this . setStoreProp ( 'opened' , true ) ;
2020-11-12 21:13:28 +02:00
return new Promise ( ( resolve : Function , reject : Function ) = > {
2020-10-09 19:35:46 +02:00
this . closeResponse_ = { resolve , reject } ;
} ) ;
}
2020-11-25 16:40:25 +02:00
public close() {
2021-02-07 12:09:28 +02:00
this . store . dispatch ( {
type : 'VISIBLE_DIALOGS_REMOVE' ,
name : this.handle ,
} ) ;
2020-10-09 19:35:46 +02:00
this . setStoreProp ( 'opened' , false ) ;
}
2020-11-13 20:48:42 +02:00
public closeWithResponse ( result : DialogResult ) {
2020-10-09 19:35:46 +02:00
this . close ( ) ;
this . closeResponse_ . resolve ( result ) ;
}
2020-11-12 21:13:28 +02:00
public get buttons ( ) : ButtonSpec [ ] {
2020-10-09 19:35:46 +02:00
return this . storeView . buttons ;
}
2020-11-12 21:13:28 +02:00
public set buttons ( buttons : ButtonSpec [ ] ) {
2020-10-09 19:35:46 +02:00
this . setStoreProp ( 'buttons' , buttons ) ;
}
}