(core) dust off electron build a little bit

Summary:
The changes in this diff are sufficient to make this sequence work again:

```
./build electron-dev
bin/electron app/electron/runPrebuild.js
```

This brings up the local server within an electron window.

This is an unambitious diff, aimed at checking how rusty electron support had become. It does not revive Grist as a packaged electron app. The first substantial work needed would be to make the app aware of the local file system again, and think through how local files should be visualized and accessed now. In the past, there was a simple list of grist docs in a directory.

Test Plan: manual

Reviewers: georgegevoian

Reviewed By: georgegevoian

Differential Revision: https://phab.getgrist.com/D3534
This commit is contained in:
Paul Fitzpatrick 2022-07-25 16:11:11 -04:00
parent 5f51dd7a00
commit 4c678f12cb
5 changed files with 37 additions and 19 deletions

View File

@ -40,7 +40,7 @@ import { getOriginUrl } from 'app/common/urlUtils';
import { GristAPI, RPC_GRISTAPI_INTERFACE } from 'app/plugin/GristAPI'; import { GristAPI, RPC_GRISTAPI_INTERFACE } from 'app/plugin/GristAPI';
import { RenderOptions, RenderTarget } from 'app/plugin/RenderOptions'; import { RenderOptions, RenderTarget } from 'app/plugin/RenderOptions';
import { checkers } from 'app/plugin/TypeCheckers'; import { checkers } from 'app/plugin/TypeCheckers';
import { IpcMessageEvent, WebviewTag } from 'electron'; import { IpcMessageEvent } from 'electron';
import { IMsgCustom, IMsgRpcCall, Rpc } from 'grain-rpc'; import { IMsgCustom, IMsgRpcCall, Rpc } from 'grain-rpc';
import { Disposable } from './dispose'; import { Disposable } from './dispose';
const G = getBrowserGlobals('document', 'window'); const G = getBrowserGlobals('document', 'window');
@ -305,7 +305,7 @@ class IframeProcess extends ViewProcess {
class WebviewProcess extends ViewProcess { class WebviewProcess extends ViewProcess {
public create(safeBrowser: SafeBrowser, rpc: Rpc, src: string) { public create(safeBrowser: SafeBrowser, rpc: Rpc, src: string) {
super.create(safeBrowser, rpc, src); super.create(safeBrowser, rpc, src);
const webview: WebviewTag = this.element = this.autoDispose(dom('webview.safe_browser_process.clipboard_focus', { const webview = this.element = this.autoDispose(dom('webview.safe_browser_process.clipboard_focus', {
src, src,
allowpopups: '', allowpopups: '',
// Requests with this partition get an extra header (see main.js) to get access to plugin content. // Requests with this partition get an extra header (see main.js) to get access to plugin content.

View File

@ -43,7 +43,7 @@ export class DocStorageManager implements IDocStorageManager {
// If we have a way to communicate with clients, watch the docsRoot for changes. // If we have a way to communicate with clients, watch the docsRoot for changes.
this._watcher = null; this._watcher = null;
this._shell = gristServer?.create.Shell?.() || { this._shell = gristServer?.create.Shell?.() || {
moveItemToTrash() { throw new Error('Unable to move document to trash'); }, trashItem() { throw new Error('Unable to move document to trash'); },
showItemInFolder() { throw new Error('Unable to show item in folder'); } showItemInFolder() { throw new Error('Unable to show item in folder'); }
}; };
if (_comm) { if (_comm) {
@ -118,16 +118,15 @@ export class DocStorageManager implements IDocStorageManager {
* @param {String} docName: docName of the document to delete. * @param {String} docName: docName of the document to delete.
* @returns {Promise} Resolved on success. * @returns {Promise} Resolved on success.
*/ */
public deleteDoc(docName: string, deletePermanently?: boolean): Promise<void> { public async deleteDoc(docName: string, deletePermanently?: boolean): Promise<void> {
const docPath = this.getPath(docName); const docPath = this.getPath(docName);
// Keep this check, to protect against wiping out the whole disk or the user's home. // Keep this check, to protect against wiping out the whole disk or the user's home.
if (path.extname(docPath) !== '.grist') { if (path.extname(docPath) !== '.grist') {
return Promise.reject(new Error("Refusing to delete path which does not end in .grist")); return Promise.reject(new Error("Refusing to delete path which does not end in .grist"));
} else if (deletePermanently) { } else if (deletePermanently) {
return fse.remove(docPath); await fse.remove(docPath);
} else { } else {
this._shell.moveItemToTrash(docPath); // this is a synchronous action await this._shell.trashItem(docPath);
return Promise.resolve();
} }
} }

View File

@ -190,6 +190,29 @@ export class FlexServer implements GristServer {
this._pluginUrl = options.pluginUrl || process.env.APP_UNTRUSTED_URL; this._pluginUrl = options.pluginUrl || process.env.APP_UNTRUSTED_URL;
this.info.push(['pluginUrl', this._pluginUrl]); this.info.push(['pluginUrl', this._pluginUrl]);
// The electron build is not supported at this time, but this stub
// implementation of electronServerMethods is present to allow kicking
// its tires.
let userConfig: any = {
recentItems: [],
};
this.electronServerMethods = {
async importDoc() { throw new Error('not implemented'); },
onDocOpen(cb) {
// currently only a stub.
cb('');
},
async getUserConfig() {
return userConfig;
},
async updateUserConfig(obj: any) {
userConfig = obj;
},
onBackupMade() {
log.info('backup skipped');
}
};
this.app.use((req, res, next) => { this.app.use((req, res, next) => {
(req as RequestWithGrist).gristServer = this; (req as RequestWithGrist).gristServer = this;
next(); next();
@ -1790,7 +1813,7 @@ function noCaching(req: express.Request, res: express.Response, next: express.Ne
// Methods that Electron app relies on. // Methods that Electron app relies on.
export interface ElectronServerMethods { export interface ElectronServerMethods {
importDoc(filepath: string): Promise<DocCreationInfo>; importDoc(filepath: string): Promise<DocCreationInfo>;
onDocOpen(cb: () => void): void; onDocOpen(cb: (filePath: string) => void): void;
getUserConfig(): Promise<any>; getUserConfig(): Promise<any>;
updateUserConfig(obj: any): Promise<void>; updateUserConfig(obj: any): Promise<void>;
onBackupMade(cb: () => void): void; onBackupMade(cb: () => void): void;

View File

@ -1,4 +1,4 @@
export interface IShell { export interface IShell {
moveItemToTrash(docPath: string): void; trashItem(docPath: string): Promise<void>;
showItemInFolder(docPath: string): void; showItemInFolder(docPath: string): void;
} }

View File

@ -88,7 +88,7 @@ export async function main(port: number, serverTypes: ServerType[],
await server.addAssetsForPlugins(); await server.addAssetsForPlugins();
} }
if (includeHome && !includeApp) { if (includeHome) {
server.addEarlyWebhooks(); server.addEarlyWebhooks();
} }
@ -103,21 +103,17 @@ export async function main(port: number, serverTypes: ServerType[],
await server.start(); await server.start();
if (includeHome) { if (includeHome) {
if (!includeApp) {
server.addUsage(); server.addUsage();
}
if (!includeDocs) { if (!includeDocs) {
server.addDocApiForwarder(); server.addDocApiForwarder();
} }
server.addJsonSupport(); server.addJsonSupport();
await server.addLandingPages(); await server.addLandingPages();
// todo: add support for home api to standalone app // todo: add support for home api to standalone app
if (!includeApp) {
server.addHomeApi(); server.addHomeApi();
server.addBillingApi(); server.addBillingApi();
server.addNotifier(); server.addNotifier();
await server.addHousekeeper(); await server.addHousekeeper();
}
await server.addLoginRoutes(); await server.addLoginRoutes();
server.addAccountPage(); server.addAccountPage();
server.addBillingPages(); server.addBillingPages();