Skip to content

Commit

Permalink
Added a dummy electron-updater sample.
Browse files Browse the repository at this point in the history
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
  • Loading branch information
Akos Kitta authored and paul-marechal committed Jun 23, 2020
1 parent c1d58cb commit 3c82aa0
Show file tree
Hide file tree
Showing 15 changed files with 471 additions and 1 deletion.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ cache:
- dev-packages/cli/node_modules
- examples/api-samples/node_modules
- examples/browser/node_modules
- examples/electron-api-samples/node_modules
- examples/electron/node_modules
- node_modules
- packages/callhierarchy/node_modules
Expand Down
3 changes: 3 additions & 0 deletions configs/root-compilation.tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@
},
{
"path": "../packages/electron/compile.tsconfig.json"
},
{
"path": "../examples/electron-api-samples/compile.tsconfig.json"
}
]
}
10 changes: 10 additions & 0 deletions examples/electron-api-samples/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
extends: [
'../../configs/build.eslintrc.json'
],
parserOptions: {
tsconfigRootDir: __dirname,
project: 'compile.tsconfig.json'
}
};
7 changes: 7 additions & 0 deletions examples/electron-api-samples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Theia - Electron API Examples

This extension contains examples of how to customize the electron application.

## License
- [Eclipse Public License 2.0](http://www.eclipse.org/legal/epl-2.0/)
- [一 (Secondary) GNU General Public License, version 2 with the GNU Classpath Exception](https://projects.eclipse.org/license/secondary-gpl-2.0-cp)
19 changes: 19 additions & 0 deletions examples/electron-api-samples/compile.tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"extends": "../../configs/base.tsconfig",
"compilerOptions": {
"composite": true,
"rootDir": "src",
"outDir": "lib"
},
"include": [
"src"
],
"references": [
{
"path": "../../packages/core/compile.tsconfig.json"
},
{
"path": "../../packages/electron/compile.tsconfig.json"
}
]
}
43 changes: 43 additions & 0 deletions examples/electron-api-samples/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"private": true,
"name": "@theia/electron-api-samples",
"version": "1.2.0",
"description": "Theia - Example to demonstrate how to customize the electron application",
"dependencies": {
"@theia/core": "^1.2.0",
"@theia/electron": "^1.2.0"
},
"theiaExtensions": [
{
"electronMain": "lib/electron-main/update/sample-updater-main-module"
},
{
"frontendElectron": "lib/electron-browser/updater/sample-updater-frontend-module"
}
],
"keywords": [
"theia-extension"
],
"license": "EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0",
"repository": {
"type": "git",
"url": "https://github.com/eclipse-theia/theia.git"
},
"bugs": {
"url": "https://github.com/eclipse-theia/theia/issues"
},
"homepage": "https://github.com/eclipse-theia/theia",
"files": [
"lib",
"src"
],
"scripts": {
"lint": "theiaext lint",
"build": "theiaext build",
"watch": "theiaext watch",
"clean": "theiaext clean"
},
"devDependencies": {
"@theia/ext-scripts": "^1.2.0"
}
}
37 changes: 37 additions & 0 deletions examples/electron-api-samples/src/common/updater/sample-updater.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/********************************************************************************
* Copyright (C) 2020 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
import { JsonRpcServer } from '@theia/core/lib/common/messaging/proxy-factory';

export enum UpdateStatus {
InProgress = 'in-progress',
Available = 'available',
NotAvailable = 'not-available'
}

export const SampleUpdaterPath = '/services/sample-updater';
export const SampleUpdater = Symbol('SampleUpdater');
export interface SampleUpdater extends JsonRpcServer<SampleUpdaterClient> {
checkForUpdates(): Promise<{ status: UpdateStatus }>;
onRestartToUpdateRequested(): void;
disconnectClient(client: SampleUpdaterClient): void;

setUpdateAvailable(available: boolean): Promise<void>; // Mock
}

export const SampleUpdaterClient = Symbol('SampleUpdaterClient');
export interface SampleUpdaterClient {
notifyReadyToInstall(): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/********************************************************************************
* Copyright (C) 2020 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { remote, Menu, BrowserWindow } from 'electron';
import { inject, injectable, postConstruct } from 'inversify';
import { isOSX } from '@theia/core/lib/common/os';
import { CommonMenus } from '@theia/core/lib/browser';
import {
Emitter,
Command,
MenuPath,
MessageService,
MenuModelRegistry,
MenuContribution,
CommandRegistry,
CommandContribution
} from '@theia/core/lib/common';
import { ElectronMainMenuFactory } from '@theia/core/lib/electron-browser/menu/electron-main-menu-factory';
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
import { SampleUpdater, UpdateStatus, SampleUpdaterClient } from '../../common/updater/sample-updater';

export namespace SampleUpdaterCommands {

const category = 'Electron Updater Sample';

export const CHECK_FOR_UPDATES: Command = {
id: 'electron-sample:check-for-updates',
label: 'Check for Updates...',
category
};

export const RESTART_TO_UPDATE: Command = {
id: 'electron-sample:restart-to-update',
label: 'Restart to Update',
category
};

// Mock
export const MOCK_UPDATE_AVAILABLE: Command = {
id: 'electron-sample:mock-update-available',
label: 'Mock - Available',
category
};

export const MOCK_UPDATE_NOT_AVAILABLE: Command = {
id: 'electron-sample:mock-update-not-available',
label: 'Mock - Not Available',
category
};

}

export namespace SampleUpdaterMenu {
export const MENU_PATH: MenuPath = [...CommonMenus.FILE_SETTINGS_SUBMENU, '3_settings_submenu_update'];
}

@injectable()
export class SampleUpdaterClientImpl implements SampleUpdaterClient {

protected readonly onReadyToInstallEmitter = new Emitter<void>();
readonly onReadyToInstall = this.onReadyToInstallEmitter.event;

notifyReadyToInstall(): void {
this.onReadyToInstallEmitter.fire();
}

}

// Dynamic menus aren't yet supported by electron: https://github.com/eclipse-theia/theia/issues/446
@injectable()
export class ElectronMenuUpdater {

@inject(ElectronMainMenuFactory)
protected readonly factory: ElectronMainMenuFactory;

public update(): void {
this.setMenu();
}

private setMenu(menu: Menu = this.factory.createMenuBar(), electronWindow: BrowserWindow = remote.getCurrentWindow()): void {
if (isOSX) {
remote.Menu.setApplicationMenu(menu);
} else {
electronWindow.setMenu(menu);
}
}

}

@injectable()
export class SampleUpdaterFrontendContribution implements CommandContribution, MenuContribution {

@inject(MessageService)
protected readonly messageService: MessageService;

@inject(ElectronMenuUpdater)
protected readonly menuUpdater: ElectronMenuUpdater;

@inject(SampleUpdater)
protected readonly updater: SampleUpdater;

@inject(SampleUpdaterClientImpl)
protected readonly updaterClient: SampleUpdaterClientImpl;

protected readyToUpdate = false;

@postConstruct()
protected init(): void {
this.updaterClient.onReadyToInstall(async () => {
this.readyToUpdate = true;
this.menuUpdater.update();
this.handleUpdatesAvailable();
});
}

registerCommands(registry: CommandRegistry): void {
registry.registerCommand(SampleUpdaterCommands.CHECK_FOR_UPDATES, {
execute: async () => {
const { status } = await this.updater.checkForUpdates();
switch (status) {
case UpdateStatus.Available: {
this.handleUpdatesAvailable();
break;
}
case UpdateStatus.NotAvailable: {
const { applicationName } = FrontendApplicationConfigProvider.get();
this.messageService.info(`[Not Available]: You’re all good. You’ve got the latest version of ${applicationName}.`, { timeout: 3000 });
break;
}
case UpdateStatus.InProgress: {
this.messageService.warn('[Downloading]: Work in progress...', { timeout: 3000 });
break;
}
default: throw new Error(`Unexpected status: ${status}`);
}
},
isEnabled: () => !this.readyToUpdate,
isVisible: () => !this.readyToUpdate
});
registry.registerCommand(SampleUpdaterCommands.RESTART_TO_UPDATE, {
execute: () => this.updater.onRestartToUpdateRequested(),
isEnabled: () => this.readyToUpdate,
isVisible: () => this.readyToUpdate
});
registry.registerCommand(SampleUpdaterCommands.MOCK_UPDATE_AVAILABLE, {
execute: () => this.updater.setUpdateAvailable(true)
});
registry.registerCommand(SampleUpdaterCommands.MOCK_UPDATE_NOT_AVAILABLE, {
execute: () => this.updater.setUpdateAvailable(false)
});
}

registerMenus(registry: MenuModelRegistry): void {
registry.registerMenuAction(SampleUpdaterMenu.MENU_PATH, {
commandId: SampleUpdaterCommands.CHECK_FOR_UPDATES.id
});
registry.registerMenuAction(SampleUpdaterMenu.MENU_PATH, {
commandId: SampleUpdaterCommands.RESTART_TO_UPDATE.id
});
}

protected async handleUpdatesAvailable(): Promise<void> {
const answer = await this.messageService.info('[Available]: Found updates, do you want update now?', 'No', 'Yes');
if (answer === 'Yes') {
this.updater.onRestartToUpdateRequested();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/********************************************************************************
* Copyright (C) 2020 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { ContainerModule } from 'inversify';
import { ElectronIpcConnectionProvider } from '@theia/electron/lib/electron-browser/messaging/electron-ipc-connection-provider';
import { CommandContribution, MenuContribution } from '@theia/core/lib/common';
import { SampleUpdater, SampleUpdaterPath, SampleUpdaterClient } from '../../common/updater/sample-updater';
import { SampleUpdaterFrontendContribution, ElectronMenuUpdater, SampleUpdaterClientImpl } from './sample-updater-frontend-contribution';

export default new ContainerModule(bind => {
bind(ElectronMenuUpdater).toSelf().inSingletonScope();
bind(SampleUpdaterClientImpl).toSelf().inSingletonScope();
bind(SampleUpdaterClient).toService(SampleUpdaterClientImpl);
bind(SampleUpdater).toDynamicValue(context => {
const client = context.container.get(SampleUpdaterClientImpl);
return ElectronIpcConnectionProvider.createProxy(context.container, SampleUpdaterPath, client);
}).inSingletonScope();
bind(SampleUpdaterFrontendContribution).toSelf().inSingletonScope();
bind(MenuContribution).toService(SampleUpdaterFrontendContribution);
bind(CommandContribution).toService(SampleUpdaterFrontendContribution);
});
Loading

0 comments on commit 3c82aa0

Please sign in to comment.