refactor(auto-update): Show notification messages with the angular-notifier (#334)
* refactor(log): Refactor logging service Removed the InjectionToken and changed LogService as default logger. Finally ElectronLogService implements LogService directly. * refactor: Optimize imports * fix(app-update): Add missing rxjs imports * style: Remove extra line * refactor(store): Move app.actions.ts to shared module * feat(notification): Add notification panel Add angular-notifier to the app and created the ShowNotificationAction to manage notifications * style(notification): Fix tslint suggestion * fix(notification): Add missing rxjs imports * refactor(app-update): Refactor app-update notification * fix(auto-update): Add missing rxjs imports
This commit is contained in:
committed by
László Monda
parent
c9a1e9853c
commit
f7212320e6
@@ -3,7 +3,7 @@ import { Store } from '@ngrx/store';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
import { AppState, getShowAppUpdateAvailable } from '../store';
|
||||
import { DoNotUpdateAppAction, UpdateAppAction } from '../store/actions/app-update.action';
|
||||
import { DoNotUpdateAppAction, UpdateAppAction } from '../shared/store/actions/app-update.action';
|
||||
|
||||
@Component({
|
||||
selector: 'app',
|
||||
|
||||
@@ -121,8 +121,8 @@ autoUpdater.on('update-not-available', (ev: any, info: VersionInfo) => {
|
||||
sendIpcToWindow(IpcEvents.autoUpdater.updateNotAvailable, info);
|
||||
});
|
||||
|
||||
autoUpdater.on('error', (ev: any, err: Error) => {
|
||||
sendIpcToWindow(IpcEvents.autoUpdater.autoUpdateError, err);
|
||||
autoUpdater.on('error', (ev: any, err: string) => {
|
||||
sendIpcToWindow(IpcEvents.autoUpdater.autoUpdateError, err.substr(0, 100));
|
||||
});
|
||||
|
||||
autoUpdater.on('download-progress', (progressObj: ProgressInfo) => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ipcRenderer } from 'electron';
|
||||
|
||||
import { IpcEvents } from '../shared/util';
|
||||
import { AppState } from '../store';
|
||||
import { UpdateDownloadedAction } from '../store/actions/app-update.action';
|
||||
import { UpdateDownloadedAction, UpdateErrorAction } from '../shared/store/actions/app-update.action';
|
||||
import { CheckForUpdateFailedAction, CheckForUpdateSuccessAction } from '../shared/store/actions/auto-update-settings';
|
||||
|
||||
/**
|
||||
@@ -47,7 +47,7 @@ export class AppUpdateRendererService {
|
||||
|
||||
ipcRenderer.on(IpcEvents.autoUpdater.autoUpdateError, (event: string, arg: any) => {
|
||||
this.writeUpdateState(IpcEvents.autoUpdater.autoUpdateError, arg);
|
||||
this.dispachStoreAction(new CheckForUpdateFailedAction(arg));
|
||||
this.dispachStoreAction(new UpdateErrorAction(arg));
|
||||
});
|
||||
|
||||
ipcRenderer.on(IpcEvents.autoUpdater.autoUpdateDownloadProgress, (event: string, arg: any) => {
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Action } from '@ngrx/store';
|
||||
import { Actions, Effect } from '@ngrx/effects';
|
||||
import { Actions, Effect, toPayload } from '@ngrx/effects';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import 'rxjs/add/operator/do';
|
||||
import 'rxjs/add/operator/map';
|
||||
import 'rxjs/add/operator/first';
|
||||
|
||||
import { ActionTypes } from '../actions/app-update.action';
|
||||
import { ActionTypes } from '../../shared/store/actions/app-update.action';
|
||||
import { ActionTypes as AutoUpdateActionTypes } from '../../shared/store/actions/auto-update-settings';
|
||||
import { AppUpdateRendererService } from '../../services/app-update-renderer.service';
|
||||
import { NotificationType } from '../../shared/models/notification';
|
||||
import { ShowNotificationAction } from '../../shared/store/actions/app.action';
|
||||
|
||||
@Injectable()
|
||||
export class AppUpdateEffect {
|
||||
@@ -25,6 +29,16 @@ export class AppUpdateEffect {
|
||||
this.appUpdateRendererService.checkForUpdate();
|
||||
});
|
||||
|
||||
@Effect() handleError$: Observable<Action> = this.actions$
|
||||
.ofType(ActionTypes.UPDATE_ERROR)
|
||||
.map(toPayload)
|
||||
.map((message: string) => {
|
||||
return new ShowNotificationAction({
|
||||
type: NotificationType.Error,
|
||||
message
|
||||
});
|
||||
});
|
||||
|
||||
constructor(private actions$: Actions,
|
||||
private appUpdateRendererService: AppUpdateRendererService) {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Actions, ActionTypes } from '../actions/app-update.action';
|
||||
import { Actions, ActionTypes } from '../../shared/store/actions/app-update.action';
|
||||
|
||||
export interface State {
|
||||
updateAvailable: boolean;
|
||||
@@ -19,11 +19,13 @@ export function reducer(state = initialState, action: Actions) {
|
||||
newState.updateAvailable = true;
|
||||
return newState;
|
||||
}
|
||||
|
||||
case ActionTypes.UPDATE_DOWNLOADED: {
|
||||
const newState = Object.assign({}, state);
|
||||
newState.updateDownloaded = true;
|
||||
return newState;
|
||||
}
|
||||
|
||||
case ActionTypes.DO_NOT_UPDATE_APP: {
|
||||
const newState = Object.assign({}, state);
|
||||
newState.doNotUpdateApp = true;
|
||||
|
||||
@@ -12,7 +12,6 @@ export class AutoUpdateSettings {
|
||||
@Input() version: string;
|
||||
@Input() settings: State;
|
||||
@Input() checkingForUpdate: boolean;
|
||||
@Input() message: string;
|
||||
|
||||
@Output() toggleCheckForUpdateOnStartUp = new EventEmitter<boolean>();
|
||||
@Output() toggleUsePreReleaseUpdate = new EventEmitter<boolean>();
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
[version]="version"
|
||||
[settings]="autoUpdateSettings$ | async"
|
||||
[checkingForUpdate]="checkingForUpdate$ | async"
|
||||
[message]="autoUpdateMessage$ | async"
|
||||
(toggleCheckForUpdateOnStartUp)="toogleCheckForUpdateOnStartUp($event)"
|
||||
(toggleUsePreReleaseUpdate)="toogleUsePreReleaseUpdate($event)"
|
||||
(checkForUpdate)="checkForUpdate()">
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Store } from '@ngrx/store';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { runInElectron } from '../../util/index';
|
||||
import { AppState, getAutoUpdateMessage, getAutoUpdateSettings, getCheckingForUpdate } from '../../store';
|
||||
import { AppState, getAutoUpdateSettings, getCheckingForUpdate } from '../../store';
|
||||
import {
|
||||
CheckForUpdateNowAction,
|
||||
ToggleCheckForUpdateOnStartupAction,
|
||||
@@ -25,12 +25,10 @@ export class SettingsComponent {
|
||||
version = '1.0.0';
|
||||
autoUpdateSettings$: Observable<AutoUpdateSettings>;
|
||||
checkingForUpdate$: Observable<boolean>;
|
||||
autoUpdateMessage$: Observable<string>;
|
||||
|
||||
constructor(private store: Store<AppState>) {
|
||||
this.autoUpdateSettings$ = store.select(getAutoUpdateSettings);
|
||||
this.checkingForUpdate$ = store.select(getCheckingForUpdate);
|
||||
this.autoUpdateMessage$ = store.select(getAutoUpdateMessage);
|
||||
}
|
||||
|
||||
toogleCheckForUpdateOnStartUp(value: boolean) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { type } from '../../shared/util/';
|
||||
import { type } from '../../util';
|
||||
|
||||
const PREFIX = '[app-update] ';
|
||||
|
||||
@@ -9,7 +9,8 @@ export const ActionTypes = {
|
||||
UPDATE_APP: type(PREFIX + 'update app'),
|
||||
DO_NOT_UPDATE_APP: type(PREFIX + 'do not update app'),
|
||||
UPDATE_DOWNLOADED: type(PREFIX + 'update downloaded'),
|
||||
UPDATING: type(PREFIX + 'updating')
|
||||
UPDATING: type(PREFIX + 'updating'),
|
||||
UPDATE_ERROR: type(PREFIX + 'error')
|
||||
};
|
||||
|
||||
export class UpdateAvailableAction implements Action {
|
||||
@@ -32,9 +33,16 @@ export class UpdatingAction implements Action {
|
||||
type = ActionTypes.UPDATING;
|
||||
}
|
||||
|
||||
export class UpdateErrorAction implements Action {
|
||||
type = ActionTypes.UPDATE_ERROR;
|
||||
|
||||
constructor(public payload: any) {}
|
||||
}
|
||||
|
||||
export type Actions
|
||||
= UpdateAvailableAction
|
||||
| UpdateAppAction
|
||||
| DoNotUpdateAppAction
|
||||
| UpdateDownloadedAction
|
||||
| UpdatingAction;
|
||||
| UpdatingAction
|
||||
| UpdateErrorAction;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { Actions, Effect } from '@ngrx/effects';
|
||||
import { Actions, Effect, toPayload } from '@ngrx/effects';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Action, Store } from '@ngrx/store';
|
||||
|
||||
@@ -18,6 +18,8 @@ import { DATA_STORAGE_REPOSITORY, DataStorageRepositoryService } from '../../ser
|
||||
import { AppState, getAutoUpdateSettings } from '../index';
|
||||
import { initialState } from '../reducers/auto-update-settings';
|
||||
import { AutoUpdateSettings } from '../../models/auto-update-settings';
|
||||
import { NotificationType } from '../../models/notification';
|
||||
import { ShowNotificationAction } from '../actions/app.action';
|
||||
|
||||
@Injectable()
|
||||
export class AutoUpdateSettingsEffects {
|
||||
@@ -40,6 +42,16 @@ export class AutoUpdateSettingsEffects {
|
||||
return new SaveAutoUpdateSettingsSuccessAction();
|
||||
});
|
||||
|
||||
@Effect() sendNotification$: Observable<Action> = this.actions$
|
||||
.ofType(ActionTypes.CHECK_FOR_UPDATE_FAILED, ActionTypes.CHECK_FOR_UPDATE_SUCCESS)
|
||||
.map(toPayload)
|
||||
.map((message: string) => {
|
||||
return new ShowNotificationAction({
|
||||
type: NotificationType.Info,
|
||||
message
|
||||
});
|
||||
});
|
||||
|
||||
constructor(private actions$: Actions,
|
||||
@Inject(DATA_STORAGE_REPOSITORY) private dataStorageRepository: DataStorageRepositoryService,
|
||||
private store: Store<AppState>) {
|
||||
|
||||
@@ -17,4 +17,3 @@ export const appUpdateState = (state: AppState) => state.autoUpdateSettings;
|
||||
|
||||
export const getAutoUpdateSettings = createSelector(appUpdateState, autoUpdate.getUpdateSettings);
|
||||
export const getCheckingForUpdate = createSelector(appUpdateState, autoUpdate.checkingForUpdate);
|
||||
export const getAutoUpdateMessage = createSelector(appUpdateState, autoUpdate.getMessage);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { ActionTypes } from '../actions/auto-update-settings';
|
||||
import { ActionTypes as UpdateActions } from '../actions/app-update.action';
|
||||
import { AutoUpdateSettings } from '../../models/auto-update-settings';
|
||||
|
||||
export interface State extends AutoUpdateSettings {
|
||||
checkingForUpdate: boolean;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export const initialState: State = {
|
||||
@@ -28,12 +28,13 @@ export function reducer(state = initialState, action: Action): State {
|
||||
}
|
||||
|
||||
case ActionTypes.CHECK_FOR_UPDATE_NOW: {
|
||||
return Object.assign({}, state, { checkingForUpdate: true, message: null });
|
||||
return Object.assign({}, state, { checkingForUpdate: true});
|
||||
}
|
||||
|
||||
case UpdateActions.UPDATE_ERROR:
|
||||
case ActionTypes.CHECK_FOR_UPDATE_SUCCESS:
|
||||
case ActionTypes.CHECK_FOR_UPDATE_FAILED: {
|
||||
return Object.assign({}, state, { checkingForUpdate: false, message: action.payload });
|
||||
return Object.assign({}, state, { checkingForUpdate: false });
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -47,4 +48,3 @@ export const getUpdateSettings = (state: State) => ({
|
||||
});
|
||||
|
||||
export const checkingForUpdate = (state: State) => state.checkingForUpdate;
|
||||
export const getMessage = (state: State) => state.message;
|
||||
|
||||
Reference in New Issue
Block a user