diff --git a/app/frontend/src/app/servers/server-list/server-list.component.html b/app/frontend/src/app/servers/server-list/server-list.component.html
index 5212f0d..0ee6a98 100644
--- a/app/frontend/src/app/servers/server-list/server-list.component.html
+++ b/app/frontend/src/app/servers/server-list/server-list.component.html
@@ -3,9 +3,12 @@
diff --git a/app/frontend/src/app/servers/server-list/server-list.component.ts b/app/frontend/src/app/servers/server-list/server-list.component.ts
index 188cca1..bf4a35d 100644
--- a/app/frontend/src/app/servers/server-list/server-list.component.ts
+++ b/app/frontend/src/app/servers/server-list/server-list.component.ts
@@ -1,12 +1,11 @@
-import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
import { trigger, transition, animate, keyframes, style, query } from '@angular/animations';
import { ServersService } from '../servers.service';
import { SubscriptionComponent } from 'src/app/helpers/subscription-component';
import { ElectronService } from 'src/app/messaging/electron.service';
-import { AddOrUpdateConfigCommand } from '../../../../../servers/messages';
-import * as uuid from 'uuid';
import { IServerConfig } from '../../../../../servers/i-server-config';
-import { WebSocketServerConfigMemento } from '../../../../../websocket-servers/i-websocket-server-config';
+import { WorkspaceService } from 'src/app/workspace/workspace.service';
+import { SettingsPageComponent } from 'src/app/settings/settings-page/settings-page.component';
@Component({
selector: 'app-server-list',
@@ -31,7 +30,8 @@ export class ServerListComponent extends SubscriptionComponent implements OnInit
constructor(
private servers: ServersService,
- private electron: ElectronService
+ private electron: ElectronService,
+ private workspace: WorkspaceService
) {
super();
this.recordSubscription(servers.Servers.subscribe(s => {
@@ -46,4 +46,8 @@ export class ServerListComponent extends SubscriptionComponent implements OnInit
private cancelAdd() {
this.adding = false;
}
+ private openSettings() {
+ let t = this.workspace.OpenNewTab(SettingsPageComponent);
+ this.workspace.SetTabTitle(t.id, 'Settings');
+ }
}
diff --git a/app/frontend/src/app/servers/servers.module.ts b/app/frontend/src/app/servers/servers.module.ts
index dc4bf1c..782181e 100644
--- a/app/frontend/src/app/servers/servers.module.ts
+++ b/app/frontend/src/app/servers/servers.module.ts
@@ -8,6 +8,7 @@ import { FormsModule } from '@angular/forms';
import { WorkspaceModule } from '../workspace/workspace.module';
import { ControlsModule } from '../controls/controls.module';
import { WebsocketServersModule } from '../websocket-servers/websocket-servers.module';
+import { SettingsModule } from '../settings/settings.module';
@NgModule({
declarations: [
@@ -23,6 +24,7 @@ import { WebsocketServersModule } from '../websocket-servers/websocket-servers.m
FormsModule,
ControlsModule,
WorkspaceModule,
+ SettingsModule,
WebsocketServersModule
],
providers: [
diff --git a/app/frontend/src/app/servers/servers.service.ts b/app/frontend/src/app/servers/servers.service.ts
index 9dac55f..1a43bf1 100644
--- a/app/frontend/src/app/servers/servers.service.ts
+++ b/app/frontend/src/app/servers/servers.service.ts
@@ -46,6 +46,8 @@ export class ServersService {
if (opened) {
let cfg = this.servers.value.find(_ => _.ID === opened.configID);
this.currentServerType.next(cfg.GetMemento().TypeID);
+ } else {
+ this.currentServerType.next('');
}
});
}
diff --git a/app/frontend/src/app/settings/settings-page/settings-page.component.html b/app/frontend/src/app/settings/settings-page/settings-page.component.html
new file mode 100644
index 0000000..c8f92f5
--- /dev/null
+++ b/app/frontend/src/app/settings/settings-page/settings-page.component.html
@@ -0,0 +1,10 @@
+
+
+
Updates
+
+
+
About
+
Version 0.1.0
+
License MIT
+
+
\ No newline at end of file
diff --git a/app/frontend/src/app/settings/settings-page/settings-page.component.scss b/app/frontend/src/app/settings/settings-page/settings-page.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/app/frontend/src/app/settings/settings-page/settings-page.component.ts b/app/frontend/src/app/settings/settings-page/settings-page.component.ts
new file mode 100644
index 0000000..e7b9cbc
--- /dev/null
+++ b/app/frontend/src/app/settings/settings-page/settings-page.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-settings-page',
+ templateUrl: './settings-page.component.html',
+ styleUrls: ['./settings-page.component.scss']
+})
+export class SettingsPageComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit() {
+ }
+
+}
diff --git a/app/frontend/src/app/settings/settings.module.ts b/app/frontend/src/app/settings/settings.module.ts
new file mode 100644
index 0000000..0a49fe4
--- /dev/null
+++ b/app/frontend/src/app/settings/settings.module.ts
@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { SettingsPageComponent } from './settings-page/settings-page.component';
+import { FormsModule } from '@angular/forms';
+import { WorkspaceModule } from '../workspace/workspace.module';
+
+@NgModule({
+ declarations: [SettingsPageComponent],
+ exports: [SettingsPageComponent],
+ entryComponents: [SettingsPageComponent],
+ imports: [
+ CommonModule,
+ FormsModule,
+ WorkspaceModule
+ ]
+})
+export class SettingsModule { }
diff --git a/app/frontend/src/app/updater/updater.module.ts b/app/frontend/src/app/updater/updater.module.ts
new file mode 100644
index 0000000..3333810
--- /dev/null
+++ b/app/frontend/src/app/updater/updater.module.ts
@@ -0,0 +1,10 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+@NgModule({
+ declarations: [],
+ imports: [
+ CommonModule
+ ]
+})
+export class UpdaterModule { }
diff --git a/app/frontend/src/app/updater/updater.service.ts b/app/frontend/src/app/updater/updater.service.ts
new file mode 100644
index 0000000..0108c57
--- /dev/null
+++ b/app/frontend/src/app/updater/updater.service.ts
@@ -0,0 +1,66 @@
+import { Injectable, EventEmitter } from '@angular/core';
+import { Observable, BehaviorSubject } from 'rxjs';
+import { CalledOnce } from '../helpers/called-once.decorator';
+import { ElectronService } from '../messaging/electron.service';
+import { UpdaterEvent, UpdaterCommand } from '../../../../updater/messages';
+
+@Injectable()
+export class UpdaterService {
+
+ updateVersion: Observable
= new Observable();
+ updaterStatus: Observable = new Observable();
+ updateDownloadProgress: EventEmitter = new EventEmitter();
+
+ private statusSubject: BehaviorSubject = new BehaviorSubject(UpdaterStatus.NoUpdateAvailable);
+ private versionSubject: BehaviorSubject = new BehaviorSubject('');
+ constructor(
+ private electron: ElectronService,
+ ) {
+ this.updaterStatus = this.statusSubject.asObservable();
+ this.updateVersion = this.versionSubject.asObservable();
+ }
+ @CalledOnce
+ init() {
+ this.electron.Receive('UpdaterEvent', (evt: UpdaterEvent) => {
+ if (evt.Event === 'update-available' &&
+ (this.statusSubject.getValue() === UpdaterStatus.NoUpdateAvailable || this.statusSubject.getValue() === UpdaterStatus.CheckingUpdate)) {
+ this.versionSubject.next(evt.Arg.version);
+ this.statusSubject.next(UpdaterStatus.UpdateAvailable);
+ } else if (evt.Event === 'update-not-available') {
+ this.statusSubject.next(UpdaterStatus.NoUpdateAvailable);
+ } else if (evt.Event === 'downloading-update') {
+ if (this.statusSubject.getValue() !== UpdaterStatus.DownloadingUpdate) {
+ this.statusSubject.next(UpdaterStatus.DownloadingUpdate);
+ }
+ this.updateDownloadProgress.emit(Math.floor(evt.Arg.percentage));
+ } else if (evt.Event === 'download-complete') {
+ this.statusSubject.next(UpdaterStatus.InstallingUpdate);
+ let that = this;
+ setTimeout(() => {
+ that.electron.Send(new UpdaterCommand('commence-install-update'));
+ }, 7 * 1000);
+ } else if (evt.Event === 'checking') {
+ if (evt.Arg.inProgress) {
+ this.statusSubject.next(UpdaterStatus.CheckingUpdate);
+ }
+ }
+ });
+ }
+ checkUpdate() {
+ this.electron.Send(new UpdaterCommand('check-for-update'));
+ }
+ installUpdate() {
+ this.statusSubject.next(UpdaterStatus.DownloadingUpdate);
+ this.electron.Send(new UpdaterCommand('commence-download'));
+ }
+
+}
+
+
+export enum UpdaterStatus {
+ NoUpdateAvailable,
+ CheckingUpdate,
+ UpdateAvailable,
+ DownloadingUpdate,
+ InstallingUpdate,
+}
diff --git a/app/main.ts b/app/main.ts
index 7029788..8c7ff68 100644
--- a/app/main.ts
+++ b/app/main.ts
@@ -22,6 +22,7 @@ import { RequestRepository } from "./requests/request-repository";
import { RequestRepositoryMessagingAdapter } from "./requests/request-repository-messaging-adapter";
import { IMessenger } from "./messaging/i-messenger";
import { LoadRequestsCommand } from "./requests/messages";
+import { UpdaterService } from "./updater/updater";
let homeDir = os.homedir();
let appDir = homeDir + "/ReqUI/";
let mainWindow: BrowserWindow;
@@ -140,6 +141,7 @@ function initializeComponents() {
initializePersistence();
initializeServers(messenger, logger, persistence);
initializeRequests(messenger, logger, persistence);
+ initializeUpdater(messenger);
}
function initializeMessaging(log: ILogger) {
@@ -178,3 +180,7 @@ function registerApplicationMessages() {
messenger.Send(new LoadRequestsCommand());
});
}
+
+function initializeUpdater(message: IMessenger) {
+ let updater = new UpdaterService(message);
+}
diff --git a/app/updater/messages.ts b/app/updater/messages.ts
new file mode 100644
index 0000000..4e65618
--- /dev/null
+++ b/app/updater/messages.ts
@@ -0,0 +1,21 @@
+import { IMessage } from "../messaging/i-message";
+
+// tslint:disable:max-classes-per-file
+
+export class UpdaterCommand implements IMessage {
+ public ID = 'UpdaterCommand' ;
+ public Command: string;
+ public constructor(command: string) {
+ this.Command = command;
+ }
+}
+
+export class UpdaterEvent implements IMessage {
+ public ID = 'UpdaterEvent' ;
+ public Event: string;
+ public Arg: any;
+ public constructor(evt: string, arg?: any) {
+ this.Event = evt;
+ this.Arg = arg;
+ }
+}
diff --git a/app/updater/updater.ts b/app/updater/updater.ts
new file mode 100644
index 0000000..00cdeac
--- /dev/null
+++ b/app/updater/updater.ts
@@ -0,0 +1,61 @@
+import { BrowserWindow, app } from "electron";
+import { autoUpdater } from "electron-updater";
+import * as electronLog from "electron-log";
+import { IMessenger } from "../messaging/i-messenger";
+import { UpdaterCommand, UpdaterEvent } from "./messages";
+
+autoUpdater.autoDownload = false;
+autoUpdater.logger = electronLog;
+
+// beta channel for testing
+autoUpdater.channel = 'beta';
+
+export class UpdaterService {
+ private messenger: IMessenger;
+
+ constructor(messenger: IMessenger) {
+ this.messenger = messenger;
+ this.messenger.Receive('UpdaterCommand', (arg: UpdaterCommand) => {
+ if (arg.Command === 'commence-install-update') {
+ setImmediate(() => {
+ app.removeAllListeners("window-all-closed");
+ let browserWindows = BrowserWindow.getAllWindows();
+ browserWindows.forEach((browserWindow) => {
+ browserWindow.close();
+ });
+ autoUpdater.quitAndInstall();
+ });
+ } else if (arg.Command === 'commence-download') {
+ autoUpdater.downloadUpdate();
+ } else if (arg.Command === 'check-for-update') {
+ this.checkUpdate();
+ }
+ });
+ autoUpdater.on('update-available', (info) => {
+ this.messenger.Send(new UpdaterEvent('checking', false));
+ this.messenger.Send(new UpdaterEvent('update-available', { version: info.version }));
+ });
+ autoUpdater.on('update-not-available', () => {
+ this.messenger.Send(new UpdaterEvent('checking', false));
+ this.messenger.Send(new UpdaterEvent('update-not-available'));
+ });
+ autoUpdater.on('download-progress', (progress) => {
+ this.messenger.Send(new UpdaterEvent('downloading-update', { percentage: progress.percent }));
+ });
+ autoUpdater.on('update-downloaded', () => {
+ this.messenger.Send(new UpdaterEvent('download-complete'));
+ });
+ autoUpdater.on('checking-for-update', () => {
+ this.messenger.Send(new UpdaterEvent('checking', true));
+ });
+ setInterval(() => {
+ this.checkUpdate();
+ }, 15 * 60 * 1000);
+ setTimeout(() => {
+ this.checkUpdate();
+ }, 10 * 1000);
+ }
+ public checkUpdate() {
+ autoUpdater.checkForUpdates();
+ }
+}