rdesktop
filip mertens 1 year ago
parent 971e4d0265
commit 87f65eeba7
  1. 8
      apps/1test/src/electron/fsPlugin.ts
  2. 12
      apps/1test/src/global.d.ts
  3. 5
      apps/1test/src/index.html
  4. 19
      apps/1test/src/preload.ts
  5. 9
      apps/1test/src/remix/fsPlugin.ts
  6. 9
      apps/1test/src/remix/gitPlugin.ts
  7. 41
      apps/1test/src/remix/lib/electronPlugin.ts
  8. 10
      apps/1test/src/renderer.ts

@ -1,6 +1,6 @@
import { PluginClient } from "@remixproject/plugin"; import { PluginClient } from "@remixproject/plugin";
import { createClient } from "./lib/electronPluginClient" import { createClient } from "./lib/electronPluginClient"
import { Engine, PluginManager, Plugin } from '@remixproject/engine'; import { Plugin } from '@remixproject/engine';
import fs from 'fs/promises' import fs from 'fs/promises'
import { Stats } from "fs"; import { Stats } from "fs";
@ -17,7 +17,6 @@ export class FSPlugin extends Plugin {
} }
onActivation(): void { onActivation(): void {
console.log('fsPlugin onActivation')
this.client = new FSPluginClient() this.client = new FSPluginClient()
} }
@ -66,5 +65,10 @@ class FSPluginClient extends PluginClient {
return fs.stat(path) return fs.stat(path)
} }
async exists(path: string): Promise<boolean> {
return fs.access(path).then(() => true).catch(() => false)
}
} }

@ -1,13 +1,15 @@
export interface IElectronAPI { export interface IElectronAPI {
activatePlugin: (name: string) => Promise<boolean> activatePlugin: (name: string) => Promise<boolean>
receiveFromFS: (cb: any) => void plugins: {
sendToFS: (message: Partial<Message>) => void name: string
receiveFromGit: (cb: any) => void activate: () => Promise<boolean>
sendToGit: (message: Partial<Message>) => void on: (cb: any) => void
send: (message: Partial<Message>) => void
}[]
} }
declare global { declare global {
interface Window { interface Window {
api: IElectronAPI electronAPI: IElectronAPI
} }
} }

@ -1,12 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8" />
<title>Hello World!</title>
</head> </head>
<body> <body>
<h1>💖 Hello World!</h1>
<p>Welcome to your Electron application.</p>
</body> </body>
</html> </html>

@ -4,12 +4,21 @@ import { contextBridge, ipcRenderer } from 'electron'
console.log('preload.ts') console.log('preload.ts')
contextBridge.exposeInMainWorld('api', { /* preload script needs statically defined API for each plugin */
const exposedPLugins = ['fs', 'git']
contextBridge.exposeInMainWorld('electronAPI', {
activatePlugin: (name: string) => { activatePlugin: (name: string) => {
return ipcRenderer.invoke('engine:activatePlugin', name) return ipcRenderer.invoke('engine:activatePlugin', name)
}, },
receiveFromFS: (cb:any) => ipcRenderer.on('fs:send', cb),
sendToFS: (message: Partial<Message>) => ipcRenderer.send('fs:on', message), plugins: exposedPLugins.map(name => {
receiveFromGit: (cb:any) => ipcRenderer.on('git:send', cb), return {
sendToGit: (message: Partial<Message>) => ipcRenderer.send('git:on', message) name,
activate: () => ipcRenderer.invoke('engine:activatePlugin', name),
on: (cb:any) => ipcRenderer.on(`${name}:send`, cb),
send: (message: Partial<Message>) => ipcRenderer.send(`${name}:on`, message)
}
})
}) })

@ -1,17 +1,12 @@
import { Engine, PluginManager, Plugin, PluginConnector } from '@remixproject/engine'; import { ElectronPlugin } from './lib/electronPlugin';
import { Message, Profile } from '@remixproject/plugin-utils';
import { ElectronPluginConnector } from './lib/electronPluginConnector';
export class fsPlugin extends ElectronPluginConnector { export class fsPlugin extends ElectronPlugin {
constructor(){ constructor(){
super({ super({
displayName: 'fs', displayName: 'fs',
name: 'fs', name: 'fs',
description: 'fs', description: 'fs',
}, {
sendAPI: window.api.sendToFS,
receiveAPI: window.api.receiveFromFS
}) })
this.methods = ['readdir', 'readFile', 'writeFile', 'mkdir', 'rmdir', 'unlink', 'rename', 'stat', 'exists'] this.methods = ['readdir', 'readFile', 'writeFile', 'mkdir', 'rmdir', 'unlink', 'rename', 'stat', 'exists']
} }

@ -1,16 +1,11 @@
import { Engine, PluginManager, Plugin, PluginConnector } from '@remixproject/engine'; import { ElectronPlugin } from './lib/electronPlugin';
import { Message, Profile } from '@remixproject/plugin-utils';
import { ElectronPluginConnector } from './lib/electronPluginConnector';
export class gitPlugin extends ElectronPluginConnector { export class gitPlugin extends ElectronPlugin {
constructor(){ constructor(){
super({ super({
displayName: 'git', displayName: 'git',
name: 'git', name: 'git',
description: 'git', description: 'git',
},{
sendAPI: window.api.sendToGit,
receiveAPI: window.api.receiveFromGit
}) })
this.methods = ['log', 'status', 'add', 'commit', 'push', 'pull', 'clone', 'checkout', 'branch', 'merge', 'reset', 'revert', 'diff', 'stash', 'apply', 'cherryPick', 'rebase', 'tag', 'fetch', 'remote', 'config', 'show', 'init', 'help', 'version'] this.methods = ['log', 'status', 'add', 'commit', 'push', 'pull', 'clone', 'checkout', 'branch', 'merge', 'reset', 'revert', 'diff', 'stash', 'apply', 'cherryPick', 'rebase', 'tag', 'fetch', 'remote', 'config', 'show', 'init', 'help', 'version']
} }

@ -1,26 +1,30 @@
import type { ExternalProfile, Profile, Message, PluginOptions } from '@remixproject/plugin-utils' import type { Profile, Message } from '@remixproject/plugin-utils'
import { Plugin } from '@remixproject/engine'; import { Plugin } from '@remixproject/engine';
export abstract class ElectronPlugin extends Plugin {
export interface ElectronPluginConnectorOptions extends PluginOptions {
sendAPI?: (message: Partial<Message>) => void
receiveAPI?: (cb: (event:any, message: Partial<Message>) => void) => void
}
export abstract class ElectronPluginConnector extends Plugin {
protected loaded: boolean protected loaded: boolean
protected id = 0 protected id = 0
protected pendingRequest: Record<number, (result: any, error: Error | string) => void> = {} protected pendingRequest: Record<number, (result: any, error: Error | string) => void> = {}
protected options: ElectronPluginConnectorOptions protected api: {
send: (message: Partial<Message>) => void
on: (cb: (event: any, message: any) => void) => void
}
profile: Profile profile: Profile
constructor(profile: Profile, options: ElectronPluginConnectorOptions = {}) { constructor(profile: Profile) {
super(profile) super(profile)
this.loaded = false this.loaded = false
if(!options.sendAPI || !options.receiveAPI) throw new Error('ElectronPluginConnector requires sendAPI and receiveAPI')
this.options = options
options.receiveAPI((event: any, message: any) => { if(!window.electronAPI) throw new Error('ElectronPluginConnector requires window.api')
if(!window.electronAPI.plugins) throw new Error('ElectronPluginConnector requires window.api.plugins')
window.electronAPI.plugins.find((plugin: any) => {
if(plugin.name === profile.name){
this.api = plugin
return true
}
})
this.api.on((event: any, message: any) => {
this.getMessage(message) this.getMessage(message)
}) })
} }
@ -31,14 +35,14 @@ export abstract class ElectronPluginConnector extends Plugin {
*/ */
protected send(message: Partial<Message>): void { protected send(message: Partial<Message>): void {
if(this.loaded) if(this.loaded)
this.options.sendAPI(message) this.api.send(message)
} }
/** /**
* Open connection with the plugin * Open connection with the plugin
* @param name The name of the plugin should connect to * @param name The name of the plugin should connect to
*/ */
protected async connect(name: string) { protected async connect(name: string) {
if(await window.api.activatePlugin(name) && !this.loaded){ if(await window.electronAPI.activatePlugin(name) && !this.loaded){
this.handshake() this.handshake()
} }
} }
@ -58,11 +62,6 @@ export abstract class ElectronPluginConnector extends Plugin {
return super.deactivate() return super.deactivate()
} }
/** Set options for an external plugin */
setOptions(options: Partial<ElectronPluginConnectorOptions> = {}) {
super.setOptions(options)
}
/** Call a method from this plugin */ /** Call a method from this plugin */
protected callPluginMethod(key: string, payload: any[] = []): Promise<any> { protected callPluginMethod(key: string, payload: any[] = []): Promise<any> {
const action = 'request' const action = 'request'

@ -9,6 +9,16 @@ class MyAppManager extends PluginManager {
this.on('fs', 'loaded', async () => { this.on('fs', 'loaded', async () => {
const files = await this.call('fs', 'readdir', './src') const files = await this.call('fs', 'readdir', './src')
console.log('files', files) console.log('files', files)
let exists = await this.call('fs', 'exists', './src')
console.log('exists', exists)
exists = await this.call('fs', 'exists', './notexists')
console.log('exists', exists)
// stat test
const stat = await this.call('fs', 'stat', './src')
console.log('stat', stat)
// read file test
const content = await this.call('fs', 'readFile', './src/index.html')
console.log('content', content)
}) })
this.on('git', 'loaded', async () => { this.on('git', 'loaded', async () => {

Loading…
Cancel
Save