feat: redesign auto-update component (#910)

This commit is contained in:
Róbert Kiss
2019-02-02 02:11:54 +01:00
committed by László Monda
parent 12d361eb2e
commit 9a0b0f9df1
28 changed files with 178 additions and 105 deletions
@@ -5,7 +5,7 @@ import * as settings from 'electron-settings';
import * as isDev from 'electron-is-dev'; import * as isDev from 'electron-is-dev';
import * as storage from 'electron-settings'; import * as storage from 'electron-settings';
import { IpcEvents, LogService } from 'uhk-common'; import { AutoUpdateSettings, IpcEvents, LogService } from 'uhk-common';
import { MainServiceBase } from './main-service-base'; import { MainServiceBase } from './main-service-base';
export class AppUpdateService extends MainServiceBase { export class AppUpdateService extends MainServiceBase {
@@ -76,14 +76,17 @@ export class AppUpdateService extends MainServiceBase {
} }
}); });
ipcMain.on(IpcEvents.autoUpdater.checkForUpdate, () => { ipcMain.on(IpcEvents.autoUpdater.checkForUpdate, (event: Electron.Event, args: any[]) => {
this.logService.debug('[AppUpdateService] checkForUpdate request from renderer process'); const allowPrerelease: boolean = args[0];
// tslint:disable-next-line:max-line-length
const logMsg = `[AppUpdateService] checkForUpdate request from renderer process. Allow prerelease: ${allowPrerelease}`;
this.logService.debug(logMsg);
this.sendAutoUpdateNotification = true; this.sendAutoUpdateNotification = true;
this.checkForUpdate(); this.checkForUpdate(allowPrerelease);
}); });
} }
private checkForUpdate() { private checkForUpdate(allowPrerelease = false): void {
if (isDev) { if (isDev) {
const msg = '[AppUpdateService] Application update is not working in dev mode.'; const msg = '[AppUpdateService] Application update is not working in dev mode.';
this.logService.info(msg); this.logService.info(msg);
@@ -106,7 +109,7 @@ export class AppUpdateService extends MainServiceBase {
return; return;
} }
autoUpdater.allowPrerelease = this.allowPreRelease(); autoUpdater.allowPrerelease = allowPrerelease;
autoUpdater.checkForUpdates() autoUpdater.checkForUpdates()
.then(() => { .then(() => {
this.logService.debug('[AppUpdateService] checkForUpdate success'); this.logService.debug('[AppUpdateService] checkForUpdate success');
@@ -127,12 +130,6 @@ export class AppUpdateService extends MainServiceBase {
return firstRunVersion !== this.app.getVersion(); return firstRunVersion !== this.app.getVersion();
} }
private allowPreRelease() {
const autoUpdateSettings = this.getAutoUpdateSettings();
return autoUpdateSettings && autoUpdateSettings.usePreReleaseUpdate;
}
private checkForUpdateAtStartup() { private checkForUpdateAtStartup() {
const autoUpdateSettings = this.getAutoUpdateSettings(); const autoUpdateSettings = this.getAutoUpdateSettings();
const checkForUpdate = autoUpdateSettings && autoUpdateSettings.checkForUpdateOnStartUp; const checkForUpdate = autoUpdateSettings && autoUpdateSettings.checkForUpdateOnStartUp;
@@ -142,10 +139,10 @@ export class AppUpdateService extends MainServiceBase {
return checkForUpdate; return checkForUpdate;
} }
private getAutoUpdateSettings() { private getAutoUpdateSettings(): AutoUpdateSettings {
const value = storage.get('auto-update-settings'); const value = storage.get('auto-update-settings');
if (!value) { if (!value) {
return {checkForUpdateOnStartUp: false, usePreReleaseUpdate: false}; return {checkForUpdateOnStartUp: false};
} }
return JSON.parse(<string>value); return JSON.parse(<string>value);
@@ -1,4 +1,4 @@
export interface AutoUpdateSettings { export interface AutoUpdateSettings {
checkForUpdateOnStartUp: boolean; checkForUpdateOnStartUp: boolean;
usePreReleaseUpdate: boolean; usePreReleaseUpdate?: boolean;
} }
+1
View File
@@ -1,3 +1,4 @@
export * from './auto-update-settings';
export * from './command-line-args'; export * from './command-line-args';
export * from './notification'; export * from './notification';
export * from './ipc-response'; export * from './ipc-response';
+8 -3
View File
@@ -1,10 +1,15 @@
<app-update-available *ngIf="showUpdateAvailable$ | async" <app-update-available *ngIf="showUpdateAvailable"
[@updateAvailable]
[updateInfo]="updateInfo$ | async"
(updateApp)="updateApp()" (updateApp)="updateApp()"
(doNotUpdateApp)="doNotUpdateApp()"> (doNotUpdateApp)="doNotUpdateApp()">
</app-update-available> </app-update-available>
<side-menu *ngIf="deviceConfigurationLoaded$ | async"></side-menu> <side-menu *ngIf="deviceConfigurationLoaded$ | async"
<div id="main-content" class="main-content"> [class.update-panel-visible]="showUpdateAvailable"></side-menu>
<div id="main-content"
class="main-content"
[class.update-panel-visible]="showUpdateAvailable">
<router-outlet></router-outlet> <router-outlet></router-outlet>
</div> </div>
<notifier-container></notifier-container> <notifier-container></notifier-container>
+20 -3
View File
@@ -12,9 +12,11 @@ import {
deviceConfigurationLoaded, deviceConfigurationLoaded,
runningInElectron, runningInElectron,
saveToKeyboardState, saveToKeyboardState,
keypressCapturing keypressCapturing,
getUpdateInfo
} from './store'; } from './store';
import { ProgressButtonState } from './store/reducers/progress-button-state'; import { ProgressButtonState } from './store/reducers/progress-button-state';
import { UpdateInfo } from './models/update-info';
@Component({ @Component({
selector: 'main-app', selector: 'main-app',
@@ -32,11 +34,22 @@ import { ProgressButtonState } from './store/reducers/progress-button-state';
style({transform: 'translateY(0)'}), style({transform: 'translateY(0)'}),
animate('400ms ease-in-out', style({transform: 'translateY(100%)'})) animate('400ms ease-in-out', style({transform: 'translateY(100%)'}))
]) ])
]),
trigger('updateAvailable', [
transition(':enter', [
style({transform: 'translateY(-45px)'}),
animate('500ms ease-out', style({transform: 'translateY(0)'}))
]),
transition(':leave', [
style({transform: 'translateY(0)'}),
animate('500ms ease-out', style({transform: 'translateY(-45px)'}))
]) ])
])
] ]
}) })
export class MainAppComponent implements OnDestroy { export class MainAppComponent implements OnDestroy {
showUpdateAvailable$: Observable<boolean>; showUpdateAvailable: boolean;
updateInfo$: Observable<UpdateInfo>;
deviceConfigurationLoaded$: Observable<boolean>; deviceConfigurationLoaded$: Observable<boolean>;
runningInElectron$: Observable<boolean>; runningInElectron$: Observable<boolean>;
saveToKeyboardState: ProgressButtonState; saveToKeyboardState: ProgressButtonState;
@@ -44,9 +57,12 @@ export class MainAppComponent implements OnDestroy {
private keypressCapturing: boolean; private keypressCapturing: boolean;
private saveToKeyboardStateSubscription: Subscription; private saveToKeyboardStateSubscription: Subscription;
private keypressCapturingSubscription: Subscription; private keypressCapturingSubscription: Subscription;
private showUpdateAvailableSubscription: Subscription;
constructor(private store: Store<AppState>) { constructor(private store: Store<AppState>) {
this.showUpdateAvailable$ = store.select(getShowAppUpdateAvailable); this.showUpdateAvailableSubscription = store.select(getShowAppUpdateAvailable)
.subscribe(data => this.showUpdateAvailable = data);
this.updateInfo$ = store.select(getUpdateInfo);
this.deviceConfigurationLoaded$ = store.select(deviceConfigurationLoaded); this.deviceConfigurationLoaded$ = store.select(deviceConfigurationLoaded);
this.runningInElectron$ = store.select(runningInElectron); this.runningInElectron$ = store.select(runningInElectron);
this.saveToKeyboardStateSubscription = store.select(saveToKeyboardState) this.saveToKeyboardStateSubscription = store.select(saveToKeyboardState)
@@ -58,6 +74,7 @@ export class MainAppComponent implements OnDestroy {
ngOnDestroy(): void { ngOnDestroy(): void {
this.saveToKeyboardStateSubscription.unsubscribe(); this.saveToKeyboardStateSubscription.unsubscribe();
this.keypressCapturingSubscription.unsubscribe(); this.keypressCapturingSubscription.unsubscribe();
this.showUpdateAvailableSubscription.unsubscribe();
} }
@HostListener('document:keydown', ['$event']) @HostListener('document:keydown', ['$event'])
@@ -4,10 +4,8 @@
<span class="macro__name pane-title__name">Settings</span> <span class="macro__name pane-title__name">Settings</span>
</h1> </h1>
</div> </div>
<auto-update-settings [version]="version" <auto-update-settings [settings]="autoUpdateSettings$ | async"
[settings]="autoUpdateSettings$ | async"
[checkingForUpdate]="checkingForUpdate$ | async" [checkingForUpdate]="checkingForUpdate$ | async"
(toggleCheckForUpdateOnStartUp)="toogleCheckForUpdateOnStartUp($event)" (toggleCheckForUpdateOnStartUp)="toogleCheckForUpdateOnStartUp($event)"
(toggleUsePreReleaseUpdate)="toogleUsePreReleaseUpdate($event)" (checkForUpdate)="checkForUpdate($event)">
(checkForUpdate)="checkForUpdate()">
</auto-update-settings> </auto-update-settings>
@@ -1,15 +1,13 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { AutoUpdateSettings } from 'uhk-common';
import { AppState, getAutoUpdateSettings, getCheckingForUpdate } from '../../../store'; import { AppState, getAutoUpdateSettings, getCheckingForUpdate } from '../../../store';
import { import {
CheckForUpdateNowAction, CheckForUpdateNowAction,
ToggleCheckForUpdateOnStartupAction, ToggleCheckForUpdateOnStartupAction
TogglePreReleaseFlagAction
} from '../../../store/actions/auto-update-settings'; } from '../../../store/actions/auto-update-settings';
import { AutoUpdateSettings } from '../../../models/auto-update-settings';
import { getVersions } from '../../../util';
@Component({ @Component({
selector: 'settings', selector: 'settings',
@@ -20,7 +18,6 @@ import { getVersions } from '../../../util';
} }
}) })
export class SettingsComponent { export class SettingsComponent {
version: string = getVersions().version;
autoUpdateSettings$: Observable<AutoUpdateSettings>; autoUpdateSettings$: Observable<AutoUpdateSettings>;
checkingForUpdate$: Observable<boolean>; checkingForUpdate$: Observable<boolean>;
@@ -33,11 +30,7 @@ export class SettingsComponent {
this.store.dispatch(new ToggleCheckForUpdateOnStartupAction(value)); this.store.dispatch(new ToggleCheckForUpdateOnStartupAction(value));
} }
toogleUsePreReleaseUpdate(value: boolean) { checkForUpdate(allowPrerelease: boolean): void {
this.store.dispatch(new TogglePreReleaseFlagAction(value)); this.store.dispatch(new CheckForUpdateNowAction(allowPrerelease));
}
checkForUpdate() {
this.store.dispatch(new CheckForUpdateNowAction());
} }
} }
@@ -9,21 +9,7 @@
</label> </label>
</div> </div>
<div class="checkbox"> <button class="btn btn-link" (click)="emitCheckForUpdate($event)">
<label>
<input type="checkbox"
[checked]="settings.usePreReleaseUpdate"
(change)="emitUsePreReleaseUpdate($event.target.checked)"> Allow alpha / pre release
</label>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Version:</label>
<div class="col-sm-10">
<p>{{version}}</p>
</div>
</div>
<button class="btn btn-link" (click)="emitCheckForUpdate()">
Check for update Check for update
<span *ngIf="checkingForUpdate" <span *ngIf="checkingForUpdate"
class="fa fa-spinner fa-spin"></span> class="fa fa-spinner fa-spin"></span>
@@ -9,13 +9,11 @@ import { State } from '../../store/reducers/auto-update-settings';
}) })
export class AutoUpdateSettings { export class AutoUpdateSettings {
@Input() version: string;
@Input() settings: State | undefined; @Input() settings: State | undefined;
@Input() checkingForUpdate: boolean; @Input() checkingForUpdate: boolean;
@Output() toggleCheckForUpdateOnStartUp = new EventEmitter<boolean>(); @Output() toggleCheckForUpdateOnStartUp = new EventEmitter<boolean>();
@Output() toggleUsePreReleaseUpdate = new EventEmitter<boolean>(); @Output() checkForUpdate = new EventEmitter<boolean>();
@Output() checkForUpdate = new EventEmitter();
constructor() { constructor() {
} }
@@ -24,11 +22,7 @@ export class AutoUpdateSettings {
this.toggleCheckForUpdateOnStartUp.emit(value); this.toggleCheckForUpdateOnStartUp.emit(value);
} }
emitUsePreReleaseUpdate(value: boolean) { emitCheckForUpdate($event: MouseEvent) {
this.toggleUsePreReleaseUpdate.emit(value); this.checkForUpdate.emit($event.shiftKey);
}
emitCheckForUpdate() {
this.checkForUpdate.emit();
} }
} }
@@ -136,12 +136,12 @@
(click)="toggleHide($event, 'agent')"></i> (click)="toggleHide($event, 'agent')"></i>
</div> </div>
<ul [@toggler]="animation['agent']"> <ul [@toggler]="animation['agent']">
<!--li class="sidebar__level-2--item"> <li class="sidebar__level-2--item">
<div class="sidebar__level-2" [routerLinkActive]="['active']"> <div class="sidebar__level-2" [routerLinkActive]="['active']">
<a [routerLink]="['/settings']" <a [routerLink]="['/settings']"
[class.disabled]="state.updatingFirmware">Settings</a> [class.disabled]="state.updatingFirmware">Settings</a>
</div> </div>
</li--> </li>
<li class="sidebar__level-2--item"> <li class="sidebar__level-2--item">
<div class="sidebar__level-2" [routerLinkActive]="['active']"> <div class="sidebar__level-2" [routerLinkActive]="['active']">
<a [routerLink]="['/help']" <a [routerLink]="['/help']"
@@ -1,10 +1,15 @@
@import '../../../styles/common';
:host { :host {
background-color: #f5f5f5; background-color: #f5f5f5;
border-right: 1px solid #ccc; border-right: 1px solid #ccc;
position: fixed; position: fixed;
overflow-y: auto; overflow-y: auto;
top: 0;
width: 250px; width: 250px;
height: 100%; height: 100%;
@include updatePanelVisible();
} }
a { a {
@@ -34,6 +39,7 @@ ul {
&__level-0 { &__level-0 {
padding: 0.5rem 1rem 0; padding: 0.5rem 1rem 0;
} }
&__level-1 { &__level-1 {
padding: 0.5rem 1rem 0.5rem 2rem; padding: 0.5rem 1rem 0.5rem 2rem;
} }
@@ -1,5 +1,15 @@
<div class="app-update-available-wrapper"> <div class="app-update-available-wrapper" role="alert">
New version available. Agent {{ updateInfo.version }} has been <span *ngIf="updateInfo.isPrerelease">pre-</span>released.
<button type="button" (click)="updateApp.emit()" class="btn btn-primary">Update</button>
<button type="button" (click)="doNotUpdateApp.emit()" class="btn btn-default">Close</button> <button type="button"
class="btn btn-link underline"
(click)="updateApp.emit()" >Update now!</button>
<button type="button"
class="btn btn-link pull-right"
data-dismiss="alert"
aria-label="Close"
(click)="doNotUpdateApp.emit()">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
@@ -1,5 +1,19 @@
.app-update-available-wrapper { .app-update-available-wrapper {
display: flex; margin: 0;
justify-content: center; padding-top: 5px;
margin: 0.5rem; padding-bottom: 5px;
background-color: #428bca;
color: white;
text-align: center;
border-radius: 0;
border-width: 0;
.btn-link {
color: white;
&.underline {
text-decoration: underline;
}
}
} }
@@ -1,4 +1,6 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angular/core'; import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { UpdateInfo } from '../../models/update-info';
@Component({ @Component({
selector: 'app-update-available', selector: 'app-update-available',
@@ -7,6 +9,8 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Output } from '@angul
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class UpdateAvailableComponent { export class UpdateAvailableComponent {
@Input() updateInfo: UpdateInfo;
@Output() updateApp = new EventEmitter<null>(); @Output() updateApp = new EventEmitter<null>();
@Output() doNotUpdateApp = new EventEmitter<null>(); @Output() doNotUpdateApp = new EventEmitter<null>();
} }
@@ -0,0 +1,4 @@
export interface UpdateInfo {
version: string;
isPrerelease: boolean;
}
@@ -32,8 +32,8 @@ export class AppUpdateRendererService {
this.ipcRenderer.send(IpcEvents.autoUpdater.updateAndRestart); this.ipcRenderer.send(IpcEvents.autoUpdater.updateAndRestart);
} }
checkForUpdate() { checkForUpdate(allowPrerelease: boolean): void {
this.ipcRenderer.send(IpcEvents.autoUpdater.checkForUpdate); this.ipcRenderer.send(IpcEvents.autoUpdater.checkForUpdate, allowPrerelease);
} }
private registerEvents() { private registerEvents() {
@@ -57,7 +57,7 @@ export class AppUpdateRendererService {
this.ipcRenderer.on(IpcEvents.autoUpdater.autoUpdateDownloaded, (event: string, arg: any) => { this.ipcRenderer.on(IpcEvents.autoUpdater.autoUpdateDownloaded, (event: string, arg: any) => {
this.writeUpdateState(IpcEvents.autoUpdater.autoUpdateDownloaded, arg); this.writeUpdateState(IpcEvents.autoUpdater.autoUpdateDownloaded, arg);
this.dispachStoreAction(new UpdateDownloadedAction()); this.dispachStoreAction(new UpdateDownloadedAction(arg));
}); });
this.ipcRenderer.on(IpcEvents.autoUpdater.checkForUpdateNotAvailable, (event: string, arg: any) => { this.ipcRenderer.on(IpcEvents.autoUpdater.checkForUpdateNotAvailable, (event: string, arg: any) => {
@@ -1,7 +1,5 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { UserConfiguration } from 'uhk-common'; import { AutoUpdateSettings, UserConfiguration } from 'uhk-common';
import { AutoUpdateSettings } from '../models/auto-update-settings';
@Injectable() @Injectable()
export class DataStorageRepositoryService { export class DataStorageRepositoryService {
@@ -1,5 +1,6 @@
import { Action } from '@ngrx/store'; import { Action } from '@ngrx/store';
import { type } from 'uhk-common'; import { type } from 'uhk-common';
import { UpdateInfo } from '../../models/update-info';
const PREFIX = '[app-update] '; const PREFIX = '[app-update] ';
@@ -27,6 +28,9 @@ export class DoNotUpdateAppAction implements Action {
export class UpdateDownloadedAction implements Action { export class UpdateDownloadedAction implements Action {
type = ActionTypes.UPDATE_DOWNLOADED; type = ActionTypes.UPDATE_DOWNLOADED;
constructor(public payload: UpdateInfo) {
}
} }
export class UpdatingAction implements Action { export class UpdatingAction implements Action {
@@ -1,7 +1,6 @@
import { Action } from '@ngrx/store'; import { Action } from '@ngrx/store';
import { type } from 'uhk-common'; import { AutoUpdateSettings, type } from 'uhk-common';
import { AutoUpdateSettings } from '../../models/auto-update-settings';
const PREFIX = '[app-update-config] '; const PREFIX = '[app-update-config] ';
@@ -26,6 +25,9 @@ export class ToggleCheckForUpdateOnStartupAction implements Action {
export class CheckForUpdateNowAction implements Action { export class CheckForUpdateNowAction implements Action {
type = ActionTypes.CHECK_FOR_UPDATE_NOW; type = ActionTypes.CHECK_FOR_UPDATE_NOW;
constructor(public payload?: boolean) {
}
} }
export class CheckForUpdateSuccessAction implements Action { export class CheckForUpdateSuccessAction implements Action {
@@ -7,7 +7,7 @@ import { first, map, tap } from 'rxjs/operators';
import { LogService, NotificationType } from 'uhk-common'; import { LogService, NotificationType } from 'uhk-common';
import { ActionTypes, UpdateErrorAction } from '../actions/app-update.action'; import { ActionTypes, UpdateErrorAction } from '../actions/app-update.action';
import { ActionTypes as AutoUpdateActionTypes } from '../actions/auto-update-settings'; import { ActionTypes as AutoUpdateActionTypes, CheckForUpdateNowAction } from '../actions/auto-update-settings';
import { ShowNotificationAction } from '../actions/app'; import { ShowNotificationAction } from '../actions/app';
import { AppUpdateRendererService } from '../../services/app-update-renderer.service'; import { AppUpdateRendererService } from '../../services/app-update-renderer.service';
@@ -23,12 +23,13 @@ export class AppUpdateEffect {
}) })
); );
@Effect({ dispatch: false }) checkForUpdate$: Observable<Action> = this.actions$ @Effect({ dispatch: false }) checkForUpdate$ = this.actions$
.ofType(AutoUpdateActionTypes.CHECK_FOR_UPDATE_NOW) .ofType<CheckForUpdateNowAction>(AutoUpdateActionTypes.CHECK_FOR_UPDATE_NOW)
.pipe( .pipe(
tap(() => { map(action => action.payload),
tap((allowPrerelease: boolean) => {
this.logService.debug('[AppUpdateEffect] call checkForUpdate'); this.logService.debug('[AppUpdateEffect] call checkForUpdate');
this.appUpdateRendererService.checkForUpdate(); this.appUpdateRendererService.checkForUpdate(allowPrerelease);
}) })
); );
@@ -4,7 +4,7 @@ import { Observable } from 'rxjs/Observable';
import { Action, Store } from '@ngrx/store'; import { Action, Store } from '@ngrx/store';
import { map, startWith, switchMap, withLatestFrom } from 'rxjs/operators'; import { map, startWith, switchMap, withLatestFrom } from 'rxjs/operators';
import { NotificationType } from 'uhk-common'; import { AutoUpdateSettings, NotificationType } from 'uhk-common';
import { import {
ActionTypes, ActionTypes,
@@ -16,7 +16,6 @@ import {
import { DataStorageRepositoryService } from '../../services/datastorage-repository.service'; import { DataStorageRepositoryService } from '../../services/datastorage-repository.service';
import { AppState, getAutoUpdateSettings } from '../index'; import { AppState, getAutoUpdateSettings } from '../index';
import { initialState } from '../reducers/auto-update-settings'; import { initialState } from '../reducers/auto-update-settings';
import { AutoUpdateSettings } from '../../models/auto-update-settings';
import { ShowNotificationAction } from '../actions/app'; import { ShowNotificationAction } from '../actions/app';
@Injectable() @Injectable()
+1
View File
@@ -64,6 +64,7 @@ export const firmwareUpgradeAllowed = createSelector(runningOnNotSupportedWindow
export const appUpdateState = (state: AppState) => state.appUpdate; export const appUpdateState = (state: AppState) => state.appUpdate;
export const getShowAppUpdateAvailable = createSelector(appUpdateState, fromAppUpdate.getShowAppUpdateAvailable); export const getShowAppUpdateAvailable = createSelector(appUpdateState, fromAppUpdate.getShowAppUpdateAvailable);
export const getUpdateInfo = createSelector(appUpdateState, fromAppUpdate.getUpdateInfo);
export const appUpdateSettingsState = (state: AppState) => state.autoUpdateSettings; export const appUpdateSettingsState = (state: AppState) => state.autoUpdateSettings;
export const getAutoUpdateSettings = createSelector(appUpdateSettingsState, autoUpdateSettings.getUpdateSettings); export const getAutoUpdateSettings = createSelector(appUpdateSettingsState, autoUpdateSettings.getUpdateSettings);
@@ -1,39 +1,48 @@
import { Actions, ActionTypes } from '../actions/app-update.action'; import { Actions, ActionTypes, UpdateDownloadedAction } from '../actions/app-update.action';
import { UpdateInfo } from '../../models/update-info';
export interface State { export interface State {
updateAvailable: boolean; updateAvailable: boolean;
updateDownloaded: boolean; updateDownloaded: boolean;
doNotUpdateApp: boolean; doNotUpdateApp: boolean;
updateInfo: UpdateInfo;
} }
export const initialState: State = { export const initialState: State = {
updateAvailable: false, updateAvailable: false,
updateDownloaded: false, updateDownloaded: false,
doNotUpdateApp: false doNotUpdateApp: false,
updateInfo: {
isPrerelease: false,
version: ''
}
}; };
export function reducer(state = initialState, action: Actions) { export function reducer(state = initialState, action: Actions) {
switch (action.type) { switch (action.type) {
case ActionTypes.UPDATE_AVAILABLE: { case ActionTypes.UPDATE_AVAILABLE:
const newState = Object.assign({}, state); return {
newState.updateAvailable = true; ...state,
return newState; updateAvailable: true
} };
case ActionTypes.UPDATE_DOWNLOADED: { case ActionTypes.UPDATE_DOWNLOADED:
const newState = Object.assign({}, state); return {
newState.updateDownloaded = true; ...state,
return newState; updateDownloaded: true,
} updateInfo: (action as UpdateDownloadedAction).payload
};
case ActionTypes.DO_NOT_UPDATE_APP:
return {
...state,
doNotUpdateApp: true
};
case ActionTypes.DO_NOT_UPDATE_APP: {
const newState = Object.assign({}, state);
newState.doNotUpdateApp = true;
return newState;
}
default: default:
return state; return state;
} }
} }
export const getShowAppUpdateAvailable = (state: State) => state.updateDownloaded && !state.doNotUpdateApp; export const getShowAppUpdateAvailable = (state: State) => state.updateDownloaded && !state.doNotUpdateApp;
export const getUpdateInfo = (state: State) => state.updateInfo;
@@ -1,7 +1,8 @@
import { Action } from '@ngrx/store'; import { Action } from '@ngrx/store';
import { AutoUpdateSettings } from 'uhk-common';
import { ActionTypes } from '../actions/auto-update-settings'; import { ActionTypes } from '../actions/auto-update-settings';
import { ActionTypes as UpdateActions } from '../actions/app-update.action'; import { ActionTypes as UpdateActions } from '../actions/app-update.action';
import { AutoUpdateSettings } from '../../models/auto-update-settings';
export interface State extends AutoUpdateSettings { export interface State extends AutoUpdateSettings {
checkingForUpdate: boolean; checkingForUpdate: boolean;
@@ -1,8 +1,7 @@
import * as storage from 'electron-settings'; import * as storage from 'electron-settings';
import { UserConfiguration } from 'uhk-common'; import { AutoUpdateSettings, UserConfiguration } from 'uhk-common';
import { DataStorageRepositoryService } from '../../app/services/datastorage-repository.service'; import { DataStorageRepositoryService } from '../../app/services/datastorage-repository.service';
import { AutoUpdateSettings } from '../../app/models/auto-update-settings';
export class ElectronDataStorageRepositoryService implements DataStorageRepositoryService { export class ElectronDataStorageRepositoryService implements DataStorageRepositoryService {
static getValue(key: string): any { static getValue(key: string): any {
+13
View File
@@ -4,6 +4,7 @@ $zindex-navbar-fixed: 1030;
@import '~spacing-bootstrap-3/spacing'; @import '~spacing-bootstrap-3/spacing';
@import './styles/variables'; @import './styles/variables';
@import './styles/common';
@import '~angular-notifier/styles'; @import '~angular-notifier/styles';
@import '~font-awesome/scss/font-awesome'; @import '~font-awesome/scss/font-awesome';
@import './styles/tooltip'; @import './styles/tooltip';
@@ -44,6 +45,9 @@ html, body {
.main-content { .main-content {
height: 100%; height: 100%;
top: 0;
@include updatePanelVisible();
} }
.main-page-content { .main-page-content {
@@ -52,6 +56,15 @@ html, body {
min-height: 100%; min-height: 100%;
} }
app-update-available {
position: fixed;
display: block;
left: 0;
top: 0;
width: 100%;
z-index: 200;
}
.nav-pills > li > a { .nav-pills > li > a {
cursor: pointer; cursor: pointer;
} }
@@ -12,3 +12,6 @@ $tooltip-border-color: $dark-grey;
$tooltip-background-color: #fff; $tooltip-background-color: #fff;
$tooltip-inner-color: #000; $tooltip-inner-color: #000;
$tooltip-arrow-border-width: $tooltip-arrow-width + $tooltip-border-width; $tooltip-arrow-border-width: $tooltip-arrow-width + $tooltip-border-width;
$update-notification-height: 35px;
$main-content-top-margin-on-update: 35px + 10px;
+14
View File
@@ -1,3 +1,5 @@
@import './variables';
%btn-link { %btn-link {
padding: 7px 0; padding: 7px 0;
text-decoration: none; text-decoration: none;
@@ -8,3 +10,15 @@
outline: none; outline: none;
} }
} }
@mixin updatePanelVisible() {
transition-timing-function: ease-out;
transition: 0.5s;
margin-top: 0;
&.update-panel-visible {
transition-timing-function: ease-in;
transition: 0.5s;
margin-top: $main-content-top-margin-on-update;
}
}