From 28f332b0a7a22c55e3f2d95f83cab71d4637663d Mon Sep 17 00:00:00 2001 From: Nikolai Sukhanov Date: Tue, 26 Mar 2024 22:27:41 +0400 Subject: [PATCH] refactor: split single notification effects service + increase notification contrast for the dark theme --- .../lib/servo/servo-binding-edit.component.ts | 8 +- .../app-updated-notification.component.html | 2 +- .../error-notification.component.html | 18 ++ .../error-notification.component.scss | 10 + .../error-notification.component.ts | 37 ++++ .../src/lib/error-notification/index.ts | 1 + modules/shared/components/src/lib/index.ts | 2 + .../src/lib/info-notification/index.ts | 1 + .../info-notification.component.html | 14 ++ .../info-notification.component.scss | 10 + .../info-notification.component.ts | 35 ++++ .../store/src/lib/actions/common.actions.ts | 2 - modules/store/src/lib/actions/index.ts | 1 + .../lib/actions/show-notification.actions.ts | 11 + .../src/lib/effects/app-update.effects.ts | 10 +- .../store/src/lib/effects/common.effects.ts | 10 +- .../compose-tasks.effect.ts | 0 .../consume-queue.effect.ts | 0 .../execute-task.effect.ts | 0 .../i-task-factory.ts | 0 .../i-task-filter.ts | 0 .../i-task-input-extractor.ts | 0 .../i-task-runner.ts | 0 .../index.ts | 10 +- ...otify-on-control-scheme-imported.effect.ts | 17 ++ ...-on-control-scheme-start-failure.effect.ts | 23 ++ ...eate-pre-run-motor-position-query-tasks.ts | 0 .../create-pre-run-servo-calibration-tasks.ts | 0 ...-pre-run-set-acceleration-profile-tasks.ts | 0 ...-pre-run-set-deceleration-profile-tasks.ts | 0 .../create-widget-read-tasks.ts | 0 .../i-widgets-read-tasks-factory.ts | 0 .../scheme-pre-run/index.ts | 0 .../scheme-pre-run/pre-run-scheme.effect.ts | 2 +- .../stop-scheme-on-hub-disconnect.effect.ts | 0 .../stop-scheme.effect.ts | 0 .../controllers/capture-input/index.ts | 15 +- .../src/lib/effects/controllers/index.ts | 20 +- .../controllers/listen-connect/index.ts | 22 +- .../notify-on-gamepad-connected.effect.ts | 26 +++ .../notify-on-gamepad-discovered.effect.ts | 26 +++ .../notify-on-keyboard-connected.effect.ts | 24 +++ .../notify-on-keyboard-discovered.effect.ts | 24 +++ .../controllers/listen-disconnect/index.ts | 11 +- .../notify-on-gamepad-disconnected.effect.ts | 32 +++ modules/store/src/lib/effects/hub/index.ts | 8 + .../notify-on-hub-connect-failed.effect.ts | 16 ++ .../hub/notify-on-hub-connected.effect.ts | 17 ++ .../hub/notify-on-hub-disconnected.effect.ts | 17 ++ .../notify-on-hub-name-set-error.effect.ts | 16 ++ modules/store/src/lib/effects/index.ts | 4 +- .../src/lib/effects/notifications.effects.ts | 198 ------------------ .../src/lib/effects/notifications/index.ts | 11 + .../show-app-updated-notification.effect.ts | 16 ++ .../show-error-notification.effect.ts | 20 ++ .../show-generic-error-notification.effect.ts | 18 ++ .../show-info-notification.effect.ts | 20 ++ .../src/lib/notification-facade.service.ts | 61 ++++++ modules/store/src/lib/provide-store.ts | 14 +- package-lock.json | 4 +- package.json | 2 +- src/assets/i18n/en.json | 9 +- src/assets/i18n/ru.json | 9 +- src/changelog.ts | 6 + src/styles/theming.scss | 2 +- 65 files changed, 641 insertions(+), 251 deletions(-) create mode 100644 modules/shared/components/src/lib/error-notification/error-notification.component.html create mode 100644 modules/shared/components/src/lib/error-notification/error-notification.component.scss create mode 100644 modules/shared/components/src/lib/error-notification/error-notification.component.ts create mode 100644 modules/shared/components/src/lib/error-notification/index.ts create mode 100644 modules/shared/components/src/lib/info-notification/index.ts create mode 100644 modules/shared/components/src/lib/info-notification/info-notification.component.html create mode 100644 modules/shared/components/src/lib/info-notification/info-notification.component.scss create mode 100644 modules/shared/components/src/lib/info-notification/info-notification.component.ts create mode 100644 modules/store/src/lib/actions/show-notification.actions.ts rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/compose-tasks.effect.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/consume-queue.effect.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/execute-task.effect.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/i-task-factory.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/i-task-filter.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/i-task-input-extractor.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/i-task-runner.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/index.ts (64%) create mode 100644 modules/store/src/lib/effects/control-scheme/notify-on-control-scheme-imported.effect.ts create mode 100644 modules/store/src/lib/effects/control-scheme/notify-on-control-scheme-start-failure.effect.ts rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/scheme-pre-run/create-pre-run-motor-position-query-tasks.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/scheme-pre-run/create-pre-run-servo-calibration-tasks.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/scheme-pre-run/create-pre-run-set-acceleration-profile-tasks.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/scheme-pre-run/create-pre-run-set-deceleration-profile-tasks.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/scheme-pre-run/create-widget-read-tasks.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/scheme-pre-run/i-widgets-read-tasks-factory.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/scheme-pre-run/index.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/scheme-pre-run/pre-run-scheme.effect.ts (99%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/stop-scheme-on-hub-disconnect.effect.ts (100%) rename modules/store/src/lib/effects/{tasks-processing => control-scheme}/stop-scheme.effect.ts (100%) create mode 100644 modules/store/src/lib/effects/controllers/listen-connect/notify-on-gamepad-connected.effect.ts create mode 100644 modules/store/src/lib/effects/controllers/listen-connect/notify-on-gamepad-discovered.effect.ts create mode 100644 modules/store/src/lib/effects/controllers/listen-connect/notify-on-keyboard-connected.effect.ts create mode 100644 modules/store/src/lib/effects/controllers/listen-connect/notify-on-keyboard-discovered.effect.ts create mode 100644 modules/store/src/lib/effects/controllers/listen-disconnect/notify-on-gamepad-disconnected.effect.ts create mode 100644 modules/store/src/lib/effects/hub/notify-on-hub-connect-failed.effect.ts create mode 100644 modules/store/src/lib/effects/hub/notify-on-hub-connected.effect.ts create mode 100644 modules/store/src/lib/effects/hub/notify-on-hub-disconnected.effect.ts create mode 100644 modules/store/src/lib/effects/hub/notify-on-hub-name-set-error.effect.ts delete mode 100644 modules/store/src/lib/effects/notifications.effects.ts create mode 100644 modules/store/src/lib/effects/notifications/index.ts create mode 100644 modules/store/src/lib/effects/notifications/show-app-updated-notification.effect.ts create mode 100644 modules/store/src/lib/effects/notifications/show-error-notification.effect.ts create mode 100644 modules/store/src/lib/effects/notifications/show-generic-error-notification.effect.ts create mode 100644 modules/store/src/lib/effects/notifications/show-info-notification.effect.ts create mode 100644 modules/store/src/lib/notification-facade.service.ts diff --git a/modules/bindings/src/lib/servo/servo-binding-edit.component.ts b/modules/bindings/src/lib/servo/servo-binding-edit.component.ts index 3c82761c..3ff39447 100644 --- a/modules/bindings/src/lib/servo/servo-binding-edit.component.ts +++ b/modules/bindings/src/lib/servo/servo-binding-edit.component.ts @@ -15,11 +15,12 @@ import { ControlSchemeBindingType, ValidationErrorsL10nMap, ValidationMessagesDi import { HideOnSmallScreenDirective, ToggleControlComponent } from '@app/shared-components'; import { ATTACHED_IO_PROPS_SELECTORS, - CONTROL_SCHEME_ACTIONS, CalibrationResult, CalibrationResultType, HubMotorPositionFacadeService, InputPipeType, + OutOfRangeCalibrationError, + SHOW_NOTIFICATION_ACTIONS, ServoBindingInputAction } from '@app/store'; import { BindingControlSelectHubComponent, BindingControlSelectIoComponent, MotorPositionAdjustmentComponent } from '@app/shared-control-schemes'; @@ -224,7 +225,10 @@ export class ServoBindingEditComponent implements IBindingsDetailsEditComponent< this._form.updateValueAndValidity(); } if (result.type === CalibrationResultType.error) { - this.store.dispatch(CONTROL_SCHEME_ACTIONS.servoCalibrationError({ error: result.error })); + const errorL10nKey = result.error instanceof OutOfRangeCalibrationError + ? 'controlScheme.servoBinding.calibrationOutOfRangeError' + : 'controlScheme.servoBinding.calibrationError'; + this.store.dispatch(SHOW_NOTIFICATION_ACTIONS.error({ l10nKey: errorL10nKey })); } }); } diff --git a/modules/shared/components/src/lib/app-updated-notification/app-updated-notification.component.html b/modules/shared/components/src/lib/app-updated-notification/app-updated-notification.component.html index 560a2ec2..219eb832 100644 --- a/modules/shared/components/src/lib/app-updated-notification/app-updated-notification.component.html +++ b/modules/shared/components/src/lib/app-updated-notification/app-updated-notification.component.html @@ -12,6 +12,6 @@ matSnackBarAction (click)="onDismiss()" > - {{ 'appUpdatedNotification.dismissButton' | transloco }} + {{ 'common.dismissNotification' | transloco }} diff --git a/modules/shared/components/src/lib/error-notification/error-notification.component.html b/modules/shared/components/src/lib/error-notification/error-notification.component.html new file mode 100644 index 00000000..ca204cda --- /dev/null +++ b/modules/shared/components/src/lib/error-notification/error-notification.component.html @@ -0,0 +1,18 @@ + + + + {{ error$ | async }} + + + + + + diff --git a/modules/shared/components/src/lib/error-notification/error-notification.component.scss b/modules/shared/components/src/lib/error-notification/error-notification.component.scss new file mode 100644 index 00000000..ca246664 --- /dev/null +++ b/modules/shared/components/src/lib/error-notification/error-notification.component.scss @@ -0,0 +1,10 @@ +:host { + display: flex; + align-items: center; +} + +.message { + display: flex; + align-items: center; + gap: 10px; +} diff --git a/modules/shared/components/src/lib/error-notification/error-notification.component.ts b/modules/shared/components/src/lib/error-notification/error-notification.component.ts new file mode 100644 index 00000000..11b953c1 --- /dev/null +++ b/modules/shared/components/src/lib/error-notification/error-notification.component.ts @@ -0,0 +1,37 @@ +import { ChangeDetectionStrategy, Component, Inject, inject } from '@angular/core'; +import { MatButton } from '@angular/material/button'; +import { MAT_SNACK_BAR_DATA, MatSnackBarAction, MatSnackBarActions, MatSnackBarLabel, MatSnackBarRef } from '@angular/material/snack-bar'; +import { TranslocoPipe } from '@ngneat/transloco'; +import { Observable } from 'rxjs'; +import { AsyncPipe } from '@angular/common'; +import { MatIcon } from '@angular/material/icon'; + +@Component({ + standalone: true, + selector: 'lib-error-notification', + templateUrl: './error-notification.component.html', + styleUrls: [ './error-notification.component.scss' ], + imports: [ + MatButton, + MatSnackBarAction, + MatSnackBarActions, + MatSnackBarLabel, + TranslocoPipe, + AsyncPipe, + MatIcon + ], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ErrorNotificationComponent { + public readonly snackBarRef = inject(MatSnackBarRef); + + constructor( + @Inject(MAT_SNACK_BAR_DATA) public readonly error$: Observable + ) { + } + + + public onDismiss(): void { + this.snackBarRef.dismiss(); + } +} diff --git a/modules/shared/components/src/lib/error-notification/index.ts b/modules/shared/components/src/lib/error-notification/index.ts new file mode 100644 index 00000000..c2b7f21e --- /dev/null +++ b/modules/shared/components/src/lib/error-notification/index.ts @@ -0,0 +1 @@ +export * from './error-notification.component'; diff --git a/modules/shared/components/src/lib/index.ts b/modules/shared/components/src/lib/index.ts index 20fdb063..ab1b1dea 100644 --- a/modules/shared/components/src/lib/index.ts +++ b/modules/shared/components/src/lib/index.ts @@ -23,3 +23,5 @@ export * from './motor-position-adjustment-controls'; export * from './battery-indicator'; export * from './tilt-gauge'; export * from './app-updated-notification'; +export * from './info-notification'; +export * from './error-notification'; diff --git a/modules/shared/components/src/lib/info-notification/index.ts b/modules/shared/components/src/lib/info-notification/index.ts new file mode 100644 index 00000000..39d7d4ca --- /dev/null +++ b/modules/shared/components/src/lib/info-notification/index.ts @@ -0,0 +1 @@ +export * from './info-notification.component'; diff --git a/modules/shared/components/src/lib/info-notification/info-notification.component.html b/modules/shared/components/src/lib/info-notification/info-notification.component.html new file mode 100644 index 00000000..110738d1 --- /dev/null +++ b/modules/shared/components/src/lib/info-notification/info-notification.component.html @@ -0,0 +1,14 @@ + + + {{ caption$ | async }} + + + + + + diff --git a/modules/shared/components/src/lib/info-notification/info-notification.component.scss b/modules/shared/components/src/lib/info-notification/info-notification.component.scss new file mode 100644 index 00000000..a61d6751 --- /dev/null +++ b/modules/shared/components/src/lib/info-notification/info-notification.component.scss @@ -0,0 +1,10 @@ +:host { + display: flex; + align-items: center; +} + +.message { + display: flex; + align-items: baseline; + gap: 10px; +} diff --git a/modules/shared/components/src/lib/info-notification/info-notification.component.ts b/modules/shared/components/src/lib/info-notification/info-notification.component.ts new file mode 100644 index 00000000..f6aed274 --- /dev/null +++ b/modules/shared/components/src/lib/info-notification/info-notification.component.ts @@ -0,0 +1,35 @@ +import { ChangeDetectionStrategy, Component, Inject, inject } from '@angular/core'; +import { MatButton } from '@angular/material/button'; +import { MAT_SNACK_BAR_DATA, MatSnackBarAction, MatSnackBarActions, MatSnackBarLabel, MatSnackBarRef } from '@angular/material/snack-bar'; +import { TranslocoPipe } from '@ngneat/transloco'; +import { Observable } from 'rxjs'; +import { AsyncPipe } from '@angular/common'; + +@Component({ + standalone: true, + selector: 'lib-info-notification', + templateUrl: './info-notification.component.html', + styleUrls: [ './info-notification.component.scss' ], + imports: [ + MatButton, + MatSnackBarAction, + MatSnackBarActions, + MatSnackBarLabel, + TranslocoPipe, + AsyncPipe + ], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InfoNotificationComponent { + public readonly snackBarRef = inject(MatSnackBarRef); + + constructor( + @Inject(MAT_SNACK_BAR_DATA) public readonly caption$: Observable + ) { + } + + + public onDismiss(): void { + this.snackBarRef.dismiss(); + } +} diff --git a/modules/store/src/lib/actions/common.actions.ts b/modules/store/src/lib/actions/common.actions.ts index 4e996cc0..a1004378 100644 --- a/modules/store/src/lib/actions/common.actions.ts +++ b/modules/store/src/lib/actions/common.actions.ts @@ -4,8 +4,6 @@ export const COMMON_ACTIONS = createActionGroup({ source: 'Common', events: { copyToClipboard: props<{ content: string }>(), - copyToClipboardSuccess: emptyProps(), - copyToClipboardFailure: emptyProps(), appReady: emptyProps(), } }); diff --git a/modules/store/src/lib/actions/index.ts b/modules/store/src/lib/actions/index.ts index c2e7bbce..5b3a6fa2 100644 --- a/modules/store/src/lib/actions/index.ts +++ b/modules/store/src/lib/actions/index.ts @@ -14,3 +14,4 @@ export * from './control-scheme-widgets-data.actions'; export * from './settings.actions'; export * from './common.actions'; export * from './app-update.actions'; +export * from './show-notification.actions'; diff --git a/modules/store/src/lib/actions/show-notification.actions.ts b/modules/store/src/lib/actions/show-notification.actions.ts new file mode 100644 index 00000000..7c56a00a --- /dev/null +++ b/modules/store/src/lib/actions/show-notification.actions.ts @@ -0,0 +1,11 @@ +import { createActionGroup, emptyProps, props } from '@ngrx/store'; + +export const SHOW_NOTIFICATION_ACTIONS = createActionGroup({ + source: 'Show Notification', + events: { + error: props<{ l10nKey: string; l10nPayload?: object }>(), + genericError: props<{ error: Error }>(), + info: props<{ l10nKey: string; l10nPayload?: object }>(), + appUpdated: emptyProps() + } +}); diff --git a/modules/store/src/lib/effects/app-update.effects.ts b/modules/store/src/lib/effects/app-update.effects.ts index 62a50f52..a9280846 100644 --- a/modules/store/src/lib/effects/app-update.effects.ts +++ b/modules/store/src/lib/effects/app-update.effects.ts @@ -6,7 +6,7 @@ import { filter, map, switchMap } from 'rxjs'; // eslint-disable-next-line @nx/enforce-module-boundaries import packageJson from '../../../../../package.json'; import { IState } from '../i-state'; -import { APP_UPDATE_ACTIONS, COMMON_ACTIONS } from '../actions'; +import { APP_UPDATE_ACTIONS, COMMON_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../actions'; export const APP_UPDATE_EFFECTS: {[k in string]: FunctionalEffect} = { detectAppUpdate: createEffect(( @@ -24,5 +24,13 @@ export const APP_UPDATE_EFFECTS: {[k in string]: FunctionalEffect} = { filter(({ prev, current }) => prev !== current), map(({prev, current}) => APP_UPDATE_ACTIONS.appUpdated({prev, current})) ); + }, { functional: true }), + notifyOnAppUpdate: createEffect(( + actions$: Actions = inject(Actions) + ) => { + return actions$.pipe( + ofType(APP_UPDATE_ACTIONS.appUpdated), + map(() => SHOW_NOTIFICATION_ACTIONS.appUpdated()) + ); }, { functional: true }) }; diff --git a/modules/store/src/lib/effects/common.effects.ts b/modules/store/src/lib/effects/common.effects.ts index 762dff85..1ecdd520 100644 --- a/modules/store/src/lib/effects/common.effects.ts +++ b/modules/store/src/lib/effects/common.effects.ts @@ -4,7 +4,7 @@ import { filter, pairwise, switchMap } from 'rxjs'; import { Store } from '@ngrx/store'; import { NAVIGATOR, WakeLockService } from '@app/shared-misc'; -import { COMMON_ACTIONS } from '../actions'; +import { COMMON_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../actions'; import { HUB_RUNTIME_DATA_SELECTORS } from '../selectors'; const COPY_TO_CLIPBOARD_EFFECT = createEffect(( @@ -16,9 +16,13 @@ const COPY_TO_CLIPBOARD_EFFECT = createEffect(( switchMap(async (action) => { try { await navigator.clipboard.writeText(action.content); - return COMMON_ACTIONS.copyToClipboardSuccess(); + return SHOW_NOTIFICATION_ACTIONS.info({ + l10nKey: 'common.copyToClipboardSuccessNotification' + }); } catch (e) { - return COMMON_ACTIONS.copyToClipboardFailure(); + return SHOW_NOTIFICATION_ACTIONS.error({ + l10nKey: 'common.copyToClipboardErrorNotification' + }); } }) ); diff --git a/modules/store/src/lib/effects/tasks-processing/compose-tasks.effect.ts b/modules/store/src/lib/effects/control-scheme/compose-tasks.effect.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/compose-tasks.effect.ts rename to modules/store/src/lib/effects/control-scheme/compose-tasks.effect.ts diff --git a/modules/store/src/lib/effects/tasks-processing/consume-queue.effect.ts b/modules/store/src/lib/effects/control-scheme/consume-queue.effect.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/consume-queue.effect.ts rename to modules/store/src/lib/effects/control-scheme/consume-queue.effect.ts diff --git a/modules/store/src/lib/effects/tasks-processing/execute-task.effect.ts b/modules/store/src/lib/effects/control-scheme/execute-task.effect.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/execute-task.effect.ts rename to modules/store/src/lib/effects/control-scheme/execute-task.effect.ts diff --git a/modules/store/src/lib/effects/tasks-processing/i-task-factory.ts b/modules/store/src/lib/effects/control-scheme/i-task-factory.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/i-task-factory.ts rename to modules/store/src/lib/effects/control-scheme/i-task-factory.ts diff --git a/modules/store/src/lib/effects/tasks-processing/i-task-filter.ts b/modules/store/src/lib/effects/control-scheme/i-task-filter.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/i-task-filter.ts rename to modules/store/src/lib/effects/control-scheme/i-task-filter.ts diff --git a/modules/store/src/lib/effects/tasks-processing/i-task-input-extractor.ts b/modules/store/src/lib/effects/control-scheme/i-task-input-extractor.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/i-task-input-extractor.ts rename to modules/store/src/lib/effects/control-scheme/i-task-input-extractor.ts diff --git a/modules/store/src/lib/effects/tasks-processing/i-task-runner.ts b/modules/store/src/lib/effects/control-scheme/i-task-runner.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/i-task-runner.ts rename to modules/store/src/lib/effects/control-scheme/i-task-runner.ts diff --git a/modules/store/src/lib/effects/tasks-processing/index.ts b/modules/store/src/lib/effects/control-scheme/index.ts similarity index 64% rename from modules/store/src/lib/effects/tasks-processing/index.ts rename to modules/store/src/lib/effects/control-scheme/index.ts index 65a1894f..9d79259a 100644 --- a/modules/store/src/lib/effects/tasks-processing/index.ts +++ b/modules/store/src/lib/effects/control-scheme/index.ts @@ -6,6 +6,8 @@ import { STOP_SCHEME_ON_HUB_DISCONNECT_EFFECT } from './stop-scheme-on-hub-disco import { STOP_SCHEME_EFFECT } from './stop-scheme.effect'; import { CONSUME_QUEUE_EFFECT } from './consume-queue.effect'; import { EXECUTE_TASK_EFFECT } from './execute-task.effect'; +import { NOTIFY_ON_CONTROL_SCHEME_IMPORTED_EFFECT } from './notify-on-control-scheme-imported.effect'; +import { NOTIFY_ON_CONTROL_SCHEME_START_FAILURE_EFFECT } from './notify-on-control-scheme-start-failure.effect'; export * from './i-task-filter'; export * from './i-task-runner'; @@ -13,11 +15,13 @@ export * from './i-task-factory'; export * from './i-task-input-extractor'; export { IWidgetsReadTasksFactory, WIDGET_READ_TASKS_FACTORY } from './scheme-pre-run'; -export const TASK_PROCESSING_EFFECTS: Record = { +export const CONTROL_SCHEME_EFFECTS: {[name in string]: FunctionalEffect} = { preRunScheme: PRE_RUN_SCHEME_EFFECT, composeTasks: COMPOSE_TASKS_EFFECT, stopSchemeOnHubDisconnect: STOP_SCHEME_ON_HUB_DISCONNECT_EFFECT, stopScheme: STOP_SCHEME_EFFECT, consumeQueue: CONSUME_QUEUE_EFFECT, - executeTask: EXECUTE_TASK_EFFECT -}; + executeTask: EXECUTE_TASK_EFFECT, + notifyOnControlSchemeImported: NOTIFY_ON_CONTROL_SCHEME_IMPORTED_EFFECT, + notifyOnControlSchemeStartFailure: NOTIFY_ON_CONTROL_SCHEME_START_FAILURE_EFFECT, +} as const; diff --git a/modules/store/src/lib/effects/control-scheme/notify-on-control-scheme-imported.effect.ts b/modules/store/src/lib/effects/control-scheme/notify-on-control-scheme-imported.effect.ts new file mode 100644 index 00000000..26a17a6d --- /dev/null +++ b/modules/store/src/lib/effects/control-scheme/notify-on-control-scheme-imported.effect.ts @@ -0,0 +1,17 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { map } from 'rxjs'; + +import { CONTROL_SCHEME_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../actions'; + +export const NOTIFY_ON_CONTROL_SCHEME_IMPORTED_EFFECT = createEffect(( + actions: Actions = inject(Actions) +) => { + return actions.pipe( + ofType(CONTROL_SCHEME_ACTIONS.importControlScheme), + map((action) => SHOW_NOTIFICATION_ACTIONS.info({ + l10nKey: 'controlScheme.importSuccessNotification', + l10nPayload: action.scheme + })) + ); +}, { functional: true }); diff --git a/modules/store/src/lib/effects/control-scheme/notify-on-control-scheme-start-failure.effect.ts b/modules/store/src/lib/effects/control-scheme/notify-on-control-scheme-start-failure.effect.ts new file mode 100644 index 00000000..ef1474b3 --- /dev/null +++ b/modules/store/src/lib/effects/control-scheme/notify-on-control-scheme-start-failure.effect.ts @@ -0,0 +1,23 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { map } from 'rxjs'; + +import { CONTROL_SCHEME_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../actions'; +import { OutOfRangeCalibrationError } from '../../hub-facades'; + +export const NOTIFY_ON_CONTROL_SCHEME_START_FAILURE_EFFECT = createEffect(( + actions: Actions = inject(Actions), +) => { + return actions.pipe( + ofType(CONTROL_SCHEME_ACTIONS.schemeStartFailed), + map((action) => { + const l10nKey = action.reason instanceof OutOfRangeCalibrationError + ? 'controlScheme.runFailedCalibrationOutOfRange' + : 'controlScheme.runFailed'; + return SHOW_NOTIFICATION_ACTIONS.error({ + l10nKey, + l10nPayload: action + }); + }) + ); +}, { functional: true }); diff --git a/modules/store/src/lib/effects/tasks-processing/scheme-pre-run/create-pre-run-motor-position-query-tasks.ts b/modules/store/src/lib/effects/control-scheme/scheme-pre-run/create-pre-run-motor-position-query-tasks.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/scheme-pre-run/create-pre-run-motor-position-query-tasks.ts rename to modules/store/src/lib/effects/control-scheme/scheme-pre-run/create-pre-run-motor-position-query-tasks.ts diff --git a/modules/store/src/lib/effects/tasks-processing/scheme-pre-run/create-pre-run-servo-calibration-tasks.ts b/modules/store/src/lib/effects/control-scheme/scheme-pre-run/create-pre-run-servo-calibration-tasks.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/scheme-pre-run/create-pre-run-servo-calibration-tasks.ts rename to modules/store/src/lib/effects/control-scheme/scheme-pre-run/create-pre-run-servo-calibration-tasks.ts diff --git a/modules/store/src/lib/effects/tasks-processing/scheme-pre-run/create-pre-run-set-acceleration-profile-tasks.ts b/modules/store/src/lib/effects/control-scheme/scheme-pre-run/create-pre-run-set-acceleration-profile-tasks.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/scheme-pre-run/create-pre-run-set-acceleration-profile-tasks.ts rename to modules/store/src/lib/effects/control-scheme/scheme-pre-run/create-pre-run-set-acceleration-profile-tasks.ts diff --git a/modules/store/src/lib/effects/tasks-processing/scheme-pre-run/create-pre-run-set-deceleration-profile-tasks.ts b/modules/store/src/lib/effects/control-scheme/scheme-pre-run/create-pre-run-set-deceleration-profile-tasks.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/scheme-pre-run/create-pre-run-set-deceleration-profile-tasks.ts rename to modules/store/src/lib/effects/control-scheme/scheme-pre-run/create-pre-run-set-deceleration-profile-tasks.ts diff --git a/modules/store/src/lib/effects/tasks-processing/scheme-pre-run/create-widget-read-tasks.ts b/modules/store/src/lib/effects/control-scheme/scheme-pre-run/create-widget-read-tasks.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/scheme-pre-run/create-widget-read-tasks.ts rename to modules/store/src/lib/effects/control-scheme/scheme-pre-run/create-widget-read-tasks.ts diff --git a/modules/store/src/lib/effects/tasks-processing/scheme-pre-run/i-widgets-read-tasks-factory.ts b/modules/store/src/lib/effects/control-scheme/scheme-pre-run/i-widgets-read-tasks-factory.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/scheme-pre-run/i-widgets-read-tasks-factory.ts rename to modules/store/src/lib/effects/control-scheme/scheme-pre-run/i-widgets-read-tasks-factory.ts diff --git a/modules/store/src/lib/effects/tasks-processing/scheme-pre-run/index.ts b/modules/store/src/lib/effects/control-scheme/scheme-pre-run/index.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/scheme-pre-run/index.ts rename to modules/store/src/lib/effects/control-scheme/scheme-pre-run/index.ts diff --git a/modules/store/src/lib/effects/tasks-processing/scheme-pre-run/pre-run-scheme.effect.ts b/modules/store/src/lib/effects/control-scheme/scheme-pre-run/pre-run-scheme.effect.ts similarity index 99% rename from modules/store/src/lib/effects/tasks-processing/scheme-pre-run/pre-run-scheme.effect.ts rename to modules/store/src/lib/effects/control-scheme/scheme-pre-run/pre-run-scheme.effect.ts index bb02ba87..a64df96b 100644 --- a/modules/store/src/lib/effects/tasks-processing/scheme-pre-run/pre-run-scheme.effect.ts +++ b/modules/store/src/lib/effects/control-scheme/scheme-pre-run/pre-run-scheme.effect.ts @@ -65,7 +65,7 @@ export const PRE_RUN_SCHEME_EFFECT = createEffect(( ...createPreRunMotorPositionQueryTasks(scheme, hubStorage, store), ...createPreRunSetAccelerationProfileTasks(scheme, hubStorage), ...createPreRunSetDecelerationProfileTasks(scheme, hubStorage), - ...createWidgetReadTasks(scheme, store, widgetReadTaskFactory), + ...createWidgetReadTasks(scheme, store, widgetReadTaskFactory) ]), timeout(appConfig.schemeStartStopTimeoutMs), map(() => CONTROL_SCHEME_ACTIONS.schemeStarted({ name: scheme.name })), diff --git a/modules/store/src/lib/effects/tasks-processing/stop-scheme-on-hub-disconnect.effect.ts b/modules/store/src/lib/effects/control-scheme/stop-scheme-on-hub-disconnect.effect.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/stop-scheme-on-hub-disconnect.effect.ts rename to modules/store/src/lib/effects/control-scheme/stop-scheme-on-hub-disconnect.effect.ts diff --git a/modules/store/src/lib/effects/tasks-processing/stop-scheme.effect.ts b/modules/store/src/lib/effects/control-scheme/stop-scheme.effect.ts similarity index 100% rename from modules/store/src/lib/effects/tasks-processing/stop-scheme.effect.ts rename to modules/store/src/lib/effects/control-scheme/stop-scheme.effect.ts diff --git a/modules/store/src/lib/effects/controllers/capture-input/index.ts b/modules/store/src/lib/effects/controllers/capture-input/index.ts index e4058a71..998959e3 100644 --- a/modules/store/src/lib/effects/controllers/capture-input/index.ts +++ b/modules/store/src/lib/effects/controllers/capture-input/index.ts @@ -1,4 +1,11 @@ -export * from './capture-gamepad-input.effect'; -export * from './capture-keyboard-input.effect'; -export * from './capture-hub-green-button-input.effect'; -export * from './capture-hub-button-groups-input.effect'; +import { CAPTURE_GAMEPAD_INPUT } from './capture-gamepad-input.effect'; +import { CAPTURE_KEYBOARD_INPUT } from './capture-keyboard-input.effect'; +import { CAPTURE_HUB_GREEN_BUTTON_INPUT } from './capture-hub-green-button-input.effect'; +import { CAPTURE_HUB_BUTTON_GROUPS_INPUT } from './capture-hub-button-groups-input.effect'; + +export const CONTROLLER_CAPTURE_INPUT_EFFECTS = { + gamepadInput: CAPTURE_GAMEPAD_INPUT, + keyboardInput: CAPTURE_KEYBOARD_INPUT, + hubGreenButtonInput: CAPTURE_HUB_GREEN_BUTTON_INPUT, + hubButtonGroupsInput: CAPTURE_HUB_BUTTON_GROUPS_INPUT, +} as const; diff --git a/modules/store/src/lib/effects/controllers/index.ts b/modules/store/src/lib/effects/controllers/index.ts index c58d1ae9..bbd95e4d 100644 --- a/modules/store/src/lib/effects/controllers/index.ts +++ b/modules/store/src/lib/effects/controllers/index.ts @@ -1,17 +1,11 @@ import { FunctionalEffect } from '@ngrx/effects'; -import { CAPTURE_GAMEPAD_INPUT, CAPTURE_HUB_BUTTON_GROUPS_INPUT, CAPTURE_HUB_GREEN_BUTTON_INPUT, CAPTURE_KEYBOARD_INPUT } from './capture-input'; -import { LISTEN_GAMEPAD_CONNECT, LISTEN_HUB_CONNECT, LISTEN_KEYBOARD_CONNECT } from './listen-connect'; -import { LISTEN_GAMEPAD_DISCONNECT, LISTEN_HUB_DISCONNECT } from './listen-disconnect'; +import { CONTROLLER_LISTEN_CONNECT_EFFECTS } from './listen-connect'; +import { CONTROLLER_LISTEN_DISCONNECT_EFFECTS } from './listen-disconnect'; +import { CONTROLLER_CAPTURE_INPUT_EFFECTS } from './capture-input'; export const CONTROLLER_EFFECTS: { [name: string]: FunctionalEffect } = { - gamepadInput: CAPTURE_GAMEPAD_INPUT, - gamepadConnect: LISTEN_GAMEPAD_CONNECT, - gamepadDisconnect: LISTEN_GAMEPAD_DISCONNECT, - keyboardConnect: LISTEN_KEYBOARD_CONNECT, - keyboardInput: CAPTURE_KEYBOARD_INPUT, - hubConnect: LISTEN_HUB_CONNECT, - hubDisconnect: LISTEN_HUB_DISCONNECT, - hubGreenButtonInput: CAPTURE_HUB_GREEN_BUTTON_INPUT, - hubButtonGroupsInput: CAPTURE_HUB_BUTTON_GROUPS_INPUT -}; + ...CONTROLLER_CAPTURE_INPUT_EFFECTS, + ...CONTROLLER_LISTEN_CONNECT_EFFECTS, + ...CONTROLLER_LISTEN_DISCONNECT_EFFECTS +} as const; diff --git a/modules/store/src/lib/effects/controllers/listen-connect/index.ts b/modules/store/src/lib/effects/controllers/listen-connect/index.ts index 5df6f58f..413ca247 100644 --- a/modules/store/src/lib/effects/controllers/listen-connect/index.ts +++ b/modules/store/src/lib/effects/controllers/listen-connect/index.ts @@ -1,3 +1,19 @@ -export * from './listen-gamepad-connect.effect'; -export * from './listen-keyboard-connect.effect'; -export * from './listen-hub-connect.effect'; +import { FunctionalEffect } from '@ngrx/effects'; + +import { LISTEN_HUB_CONNECT } from './listen-hub-connect.effect'; +import { LISTEN_KEYBOARD_CONNECT } from './listen-keyboard-connect.effect'; +import { LISTEN_GAMEPAD_CONNECT } from './listen-gamepad-connect.effect'; +import { NOTIFY_ON_HUB_KEYBOARD_DISCOVERED_EFFECT } from './notify-on-keyboard-discovered.effect'; +import { NOTIFY_ON_HUB_KEYBOARD_CONNECTED_EFFECT } from './notify-on-keyboard-connected.effect'; +import { NOTIFY_ON_GAMEPAD_CONNECTED_EFFECT } from './notify-on-gamepad-connected.effect'; +import { NOTIFY_ON_GAMEPAD_DISCOVERED_EFFECT } from './notify-on-gamepad-discovered.effect'; + +export const CONTROLLER_LISTEN_CONNECT_EFFECTS: {[name: string]: FunctionalEffect} = { + gamepadConnect: LISTEN_GAMEPAD_CONNECT, + keyboardConnect: LISTEN_KEYBOARD_CONNECT, + hubConnect: LISTEN_HUB_CONNECT, + notifyOnHubKeyboardDiscovered: NOTIFY_ON_HUB_KEYBOARD_DISCOVERED_EFFECT, + notifyOnHubKeyboardConnected: NOTIFY_ON_HUB_KEYBOARD_CONNECTED_EFFECT, + notifyOnGamepadDiscovered: NOTIFY_ON_GAMEPAD_DISCOVERED_EFFECT, + notifyOnGamepadConnected: NOTIFY_ON_GAMEPAD_CONNECTED_EFFECT, +} as const; diff --git a/modules/store/src/lib/effects/controllers/listen-connect/notify-on-gamepad-connected.effect.ts b/modules/store/src/lib/effects/controllers/listen-connect/notify-on-gamepad-connected.effect.ts new file mode 100644 index 00000000..5e98a1e0 --- /dev/null +++ b/modules/store/src/lib/effects/controllers/listen-connect/notify-on-gamepad-connected.effect.ts @@ -0,0 +1,26 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { map, mergeMap, take } from 'rxjs'; +import { GamepadProfileFactoryService } from '@app/controller-profiles'; + +import { CONTROLLERS_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../../actions'; + +export const NOTIFY_ON_GAMEPAD_CONNECTED_EFFECT = createEffect(( + actions: Actions = inject(Actions), + gamepadProfileFactoryService: GamepadProfileFactoryService = inject(GamepadProfileFactoryService), +) => { + return actions.pipe( + ofType(CONTROLLERS_ACTIONS.gamepadConnected), + mergeMap((action) => + gamepadProfileFactoryService.getByProfileUid(action.profileUid).name$.pipe( + take(1), + map((name) => SHOW_NOTIFICATION_ACTIONS.info({ + l10nKey: 'controller.controllerConnectedNotification', + l10nPayload: { name } + })) + ) + ), + ); +}, { functional: true }); + + diff --git a/modules/store/src/lib/effects/controllers/listen-connect/notify-on-gamepad-discovered.effect.ts b/modules/store/src/lib/effects/controllers/listen-connect/notify-on-gamepad-discovered.effect.ts new file mode 100644 index 00000000..96d18953 --- /dev/null +++ b/modules/store/src/lib/effects/controllers/listen-connect/notify-on-gamepad-discovered.effect.ts @@ -0,0 +1,26 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { map, mergeMap, take } from 'rxjs'; +import { GamepadProfileFactoryService } from '@app/controller-profiles'; + +import { CONTROLLERS_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../../actions'; + +export const NOTIFY_ON_GAMEPAD_DISCOVERED_EFFECT = createEffect(( + actions: Actions = inject(Actions), + gamepadProfileFactoryService: GamepadProfileFactoryService = inject(GamepadProfileFactoryService), +) => { + return actions.pipe( + ofType(CONTROLLERS_ACTIONS.gamepadDiscovered), + mergeMap((action) => + gamepadProfileFactoryService.getByProfileUid(action.profileUid).name$.pipe( + take(1), + map((name) => SHOW_NOTIFICATION_ACTIONS.info({ + l10nKey: 'controller.controllerDiscoveredNotification', + l10nPayload: { name } + })) + ) + ), + ); +}, { functional: true }); + + diff --git a/modules/store/src/lib/effects/controllers/listen-connect/notify-on-keyboard-connected.effect.ts b/modules/store/src/lib/effects/controllers/listen-connect/notify-on-keyboard-connected.effect.ts new file mode 100644 index 00000000..9975eaed --- /dev/null +++ b/modules/store/src/lib/effects/controllers/listen-connect/notify-on-keyboard-connected.effect.ts @@ -0,0 +1,24 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { map, mergeMap, take } from 'rxjs'; +import { KeyboardProfileFactoryService } from '@app/controller-profiles'; + +import { CONTROLLERS_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../../actions'; + +export const NOTIFY_ON_HUB_KEYBOARD_CONNECTED_EFFECT = createEffect(( + actions: Actions = inject(Actions), + keyboardProfileFactoryService: KeyboardProfileFactoryService = inject(KeyboardProfileFactoryService), +) => { + return actions.pipe( + ofType(CONTROLLERS_ACTIONS.keyboardConnected), + mergeMap(() => keyboardProfileFactoryService.getKeyboardProfile().name$.pipe( + take(1), + map((name) => SHOW_NOTIFICATION_ACTIONS.info({ + l10nKey: 'controller.controllerConnectedNotification', + l10nPayload: { name } + })) + )), + ); +}, { functional: true }); + + diff --git a/modules/store/src/lib/effects/controllers/listen-connect/notify-on-keyboard-discovered.effect.ts b/modules/store/src/lib/effects/controllers/listen-connect/notify-on-keyboard-discovered.effect.ts new file mode 100644 index 00000000..d7b5399d --- /dev/null +++ b/modules/store/src/lib/effects/controllers/listen-connect/notify-on-keyboard-discovered.effect.ts @@ -0,0 +1,24 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { map, mergeMap, take } from 'rxjs'; +import { KeyboardProfileFactoryService } from '@app/controller-profiles'; + +import { CONTROLLERS_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../../actions'; + +export const NOTIFY_ON_HUB_KEYBOARD_DISCOVERED_EFFECT = createEffect(( + actions: Actions = inject(Actions), + keyboardProfileFactoryService: KeyboardProfileFactoryService = inject(KeyboardProfileFactoryService), +) => { + return actions.pipe( + ofType(CONTROLLERS_ACTIONS.keyboardDiscovered), + mergeMap(() => keyboardProfileFactoryService.getKeyboardProfile().name$.pipe( + take(1), + map((name) => SHOW_NOTIFICATION_ACTIONS.info({ + l10nKey: 'controller.controllerDiscoveredNotification', + l10nPayload: { name } + })) + )), + ); +}, { functional: true }); + + diff --git a/modules/store/src/lib/effects/controllers/listen-disconnect/index.ts b/modules/store/src/lib/effects/controllers/listen-disconnect/index.ts index d2416f20..09ff533f 100644 --- a/modules/store/src/lib/effects/controllers/listen-disconnect/index.ts +++ b/modules/store/src/lib/effects/controllers/listen-disconnect/index.ts @@ -1,2 +1,9 @@ -export * from './listen-gamepad-disconnect.effect'; -export * from './listen-hub-disconnect.effect'; +import { LISTEN_GAMEPAD_DISCONNECT } from './listen-gamepad-disconnect.effect'; +import { LISTEN_HUB_DISCONNECT } from './listen-hub-disconnect.effect'; +import { NOTIFY_ON_GAMEPAD_DISCONNECTED_EFFECT } from './notify-on-gamepad-disconnected.effect'; + +export const CONTROLLER_LISTEN_DISCONNECT_EFFECTS = { + gamepadDisconnect: LISTEN_GAMEPAD_DISCONNECT, + hubDisconnect: LISTEN_HUB_DISCONNECT, + notifyOnGamepadDisconnected: NOTIFY_ON_GAMEPAD_DISCONNECTED_EFFECT, +} as const; diff --git a/modules/store/src/lib/effects/controllers/listen-disconnect/notify-on-gamepad-disconnected.effect.ts b/modules/store/src/lib/effects/controllers/listen-disconnect/notify-on-gamepad-disconnected.effect.ts new file mode 100644 index 00000000..5e579d30 --- /dev/null +++ b/modules/store/src/lib/effects/controllers/listen-disconnect/notify-on-gamepad-disconnected.effect.ts @@ -0,0 +1,32 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { filter, map, mergeMap, switchMap, take } from 'rxjs'; +import { Store } from '@ngrx/store'; +import { GamepadProfileFactoryService } from '@app/controller-profiles'; + +import { CONTROLLERS_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../../actions'; +import { ControllerModel } from '../../../models'; +import { CONTROLLER_SELECTORS } from '../../../selectors'; + +export const NOTIFY_ON_GAMEPAD_DISCONNECTED_EFFECT = createEffect(( + actions: Actions = inject(Actions), + store: Store = inject(Store), + gamepadProfileFactoryService: GamepadProfileFactoryService = inject(GamepadProfileFactoryService), +) => { + return actions.pipe( + ofType(CONTROLLERS_ACTIONS.gamepadDisconnected), + mergeMap((action) => + store.select(CONTROLLER_SELECTORS.selectById(action.id)).pipe( + filter((controller): controller is ControllerModel => !!controller), + switchMap((controller) => gamepadProfileFactoryService.getByProfileUid(controller.profileUid).name$), + take(1), + map((name) => SHOW_NOTIFICATION_ACTIONS.info({ + l10nKey: 'controller.controllerDisconnectedNotification', + l10nPayload: { name } + })) + ) + ), + ); +}, { functional: true }); + + diff --git a/modules/store/src/lib/effects/hub/index.ts b/modules/store/src/lib/effects/hub/index.ts index 8dc982da..a84d5cc9 100644 --- a/modules/store/src/lib/effects/hub/index.ts +++ b/modules/store/src/lib/effects/hub/index.ts @@ -13,6 +13,10 @@ import { REQUEST_PORT_ABSOLUTE_POSITION_EFFECT } from './request-port-absolute-p import { SET_MOTOR_POSITION_EFFECT } from './set-motor-position.effect'; import { REQUEST_HUB_FIRMWARE_VERSION_ON_CONNECT } from './request-hub-firmware-version-on-connect'; import { REQUEST_HUB_HARDWARE_VERSION_ON_CONNECT } from './request-hub-hardware-version-on-connect'; +import { NOTIFY_ON_HUB_CONNECT_FAILED_EFFECT } from './notify-on-hub-connect-failed.effect'; +import { NOTIFY_ON_HUB_CONNECTED_EFFECT } from './notify-on-hub-connected.effect'; +import { NOTIFY_ON_HUB_DISCONNECTED_EFFECT } from './notify-on-hub-disconnected.effect'; +import { NOTIFY_ON_HUB_SET_NAME_ERROR_EFFECT } from './notify-on-hub-name-set-error.effect'; export const HUB_EFFECTS: { [k in string]: FunctionalEffect } = { discoverHub: DISCOVER_HUB_EFFECT, @@ -28,4 +32,8 @@ export const HUB_EFFECTS: { [k in string]: FunctionalEffect } = { requestPortPosition: REQUEST_PORT_POSITION_EFFECT, requestPortAbsolutePosition: REQUEST_PORT_ABSOLUTE_POSITION_EFFECT, setMotorPosition: SET_MOTOR_POSITION_EFFECT, + notifyOnHubConnectFailed: NOTIFY_ON_HUB_CONNECT_FAILED_EFFECT, + notifyOnHubConnected: NOTIFY_ON_HUB_CONNECTED_EFFECT, + notifyOnHubDisconnected: NOTIFY_ON_HUB_DISCONNECTED_EFFECT, + notifyOnHubSetNameError: NOTIFY_ON_HUB_SET_NAME_ERROR_EFFECT } as const; diff --git a/modules/store/src/lib/effects/hub/notify-on-hub-connect-failed.effect.ts b/modules/store/src/lib/effects/hub/notify-on-hub-connect-failed.effect.ts new file mode 100644 index 00000000..d4057408 --- /dev/null +++ b/modules/store/src/lib/effects/hub/notify-on-hub-connect-failed.effect.ts @@ -0,0 +1,16 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { map } from 'rxjs'; + +import { HUBS_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../actions'; + +export const NOTIFY_ON_HUB_CONNECT_FAILED_EFFECT = createEffect(( + actions: Actions = inject(Actions) +) => { + return actions.pipe( + ofType(HUBS_ACTIONS.deviceConnectFailed), + map(() => SHOW_NOTIFICATION_ACTIONS.error({ + l10nKey: 'hub.connectFailed' + })) + ); +}, { functional: true }); diff --git a/modules/store/src/lib/effects/hub/notify-on-hub-connected.effect.ts b/modules/store/src/lib/effects/hub/notify-on-hub-connected.effect.ts new file mode 100644 index 00000000..c4d4444d --- /dev/null +++ b/modules/store/src/lib/effects/hub/notify-on-hub-connected.effect.ts @@ -0,0 +1,17 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { map } from 'rxjs'; + +import { HUBS_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../actions'; + +export const NOTIFY_ON_HUB_CONNECTED_EFFECT = createEffect(( + actions: Actions = inject(Actions) +) => { + return actions.pipe( + ofType(HUBS_ACTIONS.connected), + map((action) => SHOW_NOTIFICATION_ACTIONS.info({ + l10nKey: 'hub.connected', + l10nPayload: action + })) + ); +}, { functional: true }); diff --git a/modules/store/src/lib/effects/hub/notify-on-hub-disconnected.effect.ts b/modules/store/src/lib/effects/hub/notify-on-hub-disconnected.effect.ts new file mode 100644 index 00000000..d91cbac9 --- /dev/null +++ b/modules/store/src/lib/effects/hub/notify-on-hub-disconnected.effect.ts @@ -0,0 +1,17 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { map } from 'rxjs'; + +import { HUBS_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../actions'; + +export const NOTIFY_ON_HUB_DISCONNECTED_EFFECT = createEffect(( + actions: Actions = inject(Actions) +) => { + return actions.pipe( + ofType(HUBS_ACTIONS.disconnected), + map((action) => SHOW_NOTIFICATION_ACTIONS.info({ + l10nKey: 'hub.disconnected', + l10nPayload: action + })) + ); +}, { functional: true }); diff --git a/modules/store/src/lib/effects/hub/notify-on-hub-name-set-error.effect.ts b/modules/store/src/lib/effects/hub/notify-on-hub-name-set-error.effect.ts new file mode 100644 index 00000000..5785a40d --- /dev/null +++ b/modules/store/src/lib/effects/hub/notify-on-hub-name-set-error.effect.ts @@ -0,0 +1,16 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { map } from 'rxjs'; + +import { HUBS_ACTIONS, SHOW_NOTIFICATION_ACTIONS } from '../../actions'; + +export const NOTIFY_ON_HUB_SET_NAME_ERROR_EFFECT = createEffect(( + actions: Actions = inject(Actions) +) => { + return actions.pipe( + ofType(HUBS_ACTIONS.hubNameSetError), + map(() => SHOW_NOTIFICATION_ACTIONS.error({ + l10nKey: 'hub.hubNameSetError' + })) + ); +}, { functional: true }); diff --git a/modules/store/src/lib/effects/index.ts b/modules/store/src/lib/effects/index.ts index 507503fc..23ebe35c 100644 --- a/modules/store/src/lib/effects/index.ts +++ b/modules/store/src/lib/effects/index.ts @@ -1,11 +1,11 @@ export * from './controllers'; export * from './attached-ios.effects'; -export * from './tasks-processing'; +export * from './control-scheme'; export * from './hub-attached-ios-state.effects'; export * from './attached-io-modes.effects'; export * from './hub-port-mode-info-effects'; -export * from './notifications.effects'; export * from './hub'; export * from './settings'; export * from './common.effects'; export * from './app-update.effects'; +export * from './notifications'; diff --git a/modules/store/src/lib/effects/notifications.effects.ts b/modules/store/src/lib/effects/notifications.effects.ts deleted file mode 100644 index 516a22d3..00000000 --- a/modules/store/src/lib/effects/notifications.effects.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { Injectable } from '@angular/core'; -import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects'; -import { Observable, OperatorFunction, filter, switchMap, tap } from 'rxjs'; -import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar'; -import { TranslocoService } from '@ngneat/transloco'; -import { Action, Store } from '@ngrx/store'; -import { GamepadProfileFactoryService, KeyboardProfileFactoryService } from '@app/controller-profiles'; -import { ScreenSizeObserverService } from '@app/shared-misc'; -import { AppUpdatedNotificationComponent } from '@app/shared-components'; - -import { APP_UPDATE_ACTIONS, COMMON_ACTIONS, CONTROLLERS_ACTIONS, CONTROL_SCHEME_ACTIONS, HUBS_ACTIONS } from '../actions'; -import { CONTROLLER_SELECTORS } from '../selectors'; -import { ControllerModel } from '../models'; -import { ControllerProfilesFacadeService } from '../controller-profiles-facade.service'; -import { OutOfRangeCalibrationError } from '../hub-facades'; - -@Injectable() -export class NotificationsEffects { - public readonly deviceConnectFailedNotification$ = createEffect(() => { - return this.actions$.pipe( - ofType(HUBS_ACTIONS.deviceConnectFailed), - tap((action) => { - console.error(action.error); - }), - this.showMessage((action) => this.translocoService.selectTranslate('hub.connectFailed', action)) - ); - }, { dispatch: false }); - - public readonly deviceConnectedNotification$ = createEffect(() => { - return this.actions$.pipe( - ofType(HUBS_ACTIONS.connected), - this.showMessage((action) => this.translocoService.selectTranslate('hub.connected', action)) - ); - }, { dispatch: false }); - - public readonly deviceDisconnectedNotification$ = createEffect(() => { - return this.actions$.pipe( - ofType(HUBS_ACTIONS.disconnected), - this.showMessage((action) => this.translocoService.selectTranslate('hub.disconnected', action)) - ); - }, { dispatch: false }); - - public readonly servoCalibrationErrorNotification$ = createEffect(() => { - return this.actions$.pipe( - ofType(CONTROL_SCHEME_ACTIONS.servoCalibrationError), - this.showMessage((action) => { - return action.error instanceof OutOfRangeCalibrationError - ? this.translocoService.selectTranslate('controlScheme.servoBinding.calibrationOutOfRangeError') - : this.translocoService.selectTranslate('controlScheme.servoBinding.calibrationError'); - }, { duration: Number.MAX_SAFE_INTEGER }) - ); - }, { dispatch: false }); - - public readonly controllerDiscovered$ = createEffect(() => { - return this.actions$.pipe( - ofType(CONTROLLERS_ACTIONS.gamepadDiscovered, CONTROLLERS_ACTIONS.keyboardDiscovered), - this.showMessage((action) => { - switch (action.type) { - case CONTROLLERS_ACTIONS.gamepadDiscovered.type: - return this.gamepadProfileFactoryService.getByProfileUid(action.profileUid).name$.pipe( - switchMap((name) => this.translocoService.selectTranslate('controller.controllerDiscoveredNotification', { name })) - ); - case CONTROLLERS_ACTIONS.keyboardDiscovered.type: - return this.keyboardProfileFactoryService.getByProfileUid(action.profileUid).name$.pipe( - switchMap((name) => this.translocoService.selectTranslate('controller.controllerDiscoveredNotification', { name })) - ); - } - }) - ); - }, { dispatch: false }); - - public readonly controllerConnected$ = createEffect(() => { - return this.actions$.pipe( - ofType(CONTROLLERS_ACTIONS.gamepadConnected, CONTROLLERS_ACTIONS.keyboardConnected), - this.showMessage((action) => { - switch (action.type) { - case CONTROLLERS_ACTIONS.gamepadConnected.type: - return this.gamepadProfileFactoryService.getByProfileUid(action.profileUid).name$.pipe( - switchMap((name) => this.translocoService.selectTranslate('controller.controllerConnectedNotification', { name })) - ); - case CONTROLLERS_ACTIONS.keyboardConnected.type: - return this.keyboardProfileFactoryService.getByProfileUid(action.profileUid).name$.pipe( - switchMap((name) => this.translocoService.selectTranslate('controller.controllerConnectedNotification', { name })) - ); - } - }) - ); - }, { dispatch: false }); - - public readonly controllerDisconnected$ = createEffect(() => { - return this.actions$.pipe( - ofType(CONTROLLERS_ACTIONS.gamepadDisconnected), - this.showMessage((action) => this.store.select(CONTROLLER_SELECTORS.selectById(action.id)).pipe( - filter((controller): controller is ControllerModel => !!controller), - switchMap((controller) => this.controllerProfilesFacade.getByControllerModel(controller).name$), - switchMap((name) => this.translocoService.selectTranslate('controller.controllerDisconnectedNotification', { name })) - )) - ); - }, { dispatch: false }); - - public readonly stringCopiedToClipboard$ = createEffect(() => { - return this.actions$.pipe( - ofType(COMMON_ACTIONS.copyToClipboardSuccess), - this.showMessage(() => this.translocoService.selectTranslate('common.copyToClipboardSuccessNotification')), - ); - }, { dispatch: false }); - - public readonly stringCopyToClipboardFailed$ = createEffect(() => { - return this.actions$.pipe( - ofType(COMMON_ACTIONS.copyToClipboardFailure), - this.showMessage(() => this.translocoService.selectTranslate('common.copyToClipboardErrorNotification')), - ); - }, { dispatch: false }); - - public readonly controlSchemeImported$ = createEffect(() => { - return this.actions$.pipe( - ofType(CONTROL_SCHEME_ACTIONS.importControlScheme), - this.showMessage((action) => this.translocoService.selectTranslate('controlScheme.importSuccessNotification', action.scheme)), - ); - }, { dispatch: false }); - - public readonly hubNameSetError$ = createEffect(() => { - return this.actions$.pipe( - ofType(HUBS_ACTIONS.hubNameSetError), - this.showMessage(() => this.translocoService.selectTranslate('hub.hubNameSetError')), - ); - }, { dispatch: false }); - - public readonly startSchemeFailed$ = createEffect(() => { - return this.actions$.pipe( - ofType(CONTROL_SCHEME_ACTIONS.schemeStartFailed), - this.showMessage((action) => { - return action.reason instanceof OutOfRangeCalibrationError - ? this.translocoService.selectTranslate('controlScheme.runFailedCalibrationOutOfRange') - : this.translocoService.selectTranslate('controlScheme.runFailed'); - }, { duration: Number.MAX_SAFE_INTEGER } - ), - ); - }, { dispatch: false }); - - public readonly displayAppUpdatedNotification$ = createEffect(() => { - return this.actions$.pipe( - ofType(APP_UPDATE_ACTIONS.appUpdated), - this.showAppUpdatedNotification(), - ); - }, { dispatch: false }); - - constructor( - private readonly actions$: Actions, - private readonly snackBar: MatSnackBar, - private readonly translocoService: TranslocoService, - private readonly store: Store, - private readonly screenSizeObserverService: ScreenSizeObserverService, - private readonly controllerProfilesFacade: ControllerProfilesFacadeService, - private readonly keyboardProfileFactoryService: KeyboardProfileFactoryService, - private readonly gamepadProfileFactoryService: GamepadProfileFactoryService, - ) { - } - - private showMessage( - fn: (action: T) => Observable, - config: MatSnackBarConfig = {} - ): OperatorFunction { - return (source: Observable) => source.pipe( - concatLatestFrom((action) => [ - fn(action), - this.screenSizeObserverService.isSmallScreen$ - ]), - tap(([ , message, isSmallScreen ]) => { - this.snackBar.open( - message, - 'OK', - { - horizontalPosition: 'end', - verticalPosition: isSmallScreen ? 'top' : 'bottom', - duration: 5000, - ...config - } - ); - }), - ); - } - - private showAppUpdatedNotification(): OperatorFunction { - return (source: Observable) => source.pipe( - tap(() => { - this.snackBar.openFromComponent( - AppUpdatedNotificationComponent, - { - horizontalPosition: 'center', - verticalPosition: 'bottom', - duration: Number.MAX_SAFE_INTEGER - } - ); - }), - ); - } -} diff --git a/modules/store/src/lib/effects/notifications/index.ts b/modules/store/src/lib/effects/notifications/index.ts new file mode 100644 index 00000000..890f829c --- /dev/null +++ b/modules/store/src/lib/effects/notifications/index.ts @@ -0,0 +1,11 @@ +import { SHOW_ERROR_NOTIFICATION_EFFECT } from './show-error-notification.effect'; +import { SHOW_GENERIC_ERROR_NOTIFICATION_EFFECT } from './show-generic-error-notification.effect'; +import { SHOW_INFO_NOTIFICATION_EFFECT } from './show-info-notification.effect'; +import { SHOW_APP_UPDATED_NOTIFICATION_EFFECT } from './show-app-updated-notification.effect'; + +export const NOTIFICATION_EFFECTS = { + showErrorNotification: SHOW_ERROR_NOTIFICATION_EFFECT, + showGenericErrorNotification: SHOW_GENERIC_ERROR_NOTIFICATION_EFFECT, + showInfoNotification: SHOW_INFO_NOTIFICATION_EFFECT, + showAppUpdatedNotification: SHOW_APP_UPDATED_NOTIFICATION_EFFECT, +} as const; diff --git a/modules/store/src/lib/effects/notifications/show-app-updated-notification.effect.ts b/modules/store/src/lib/effects/notifications/show-app-updated-notification.effect.ts new file mode 100644 index 00000000..066d4d5c --- /dev/null +++ b/modules/store/src/lib/effects/notifications/show-app-updated-notification.effect.ts @@ -0,0 +1,16 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { tap } from 'rxjs'; + +import { SHOW_NOTIFICATION_ACTIONS } from '../../actions'; +import { NotificationFacadeService } from '../../notification-facade.service'; + +export const SHOW_APP_UPDATED_NOTIFICATION_EFFECT = createEffect(( + actions: Actions = inject(Actions), + notificationsFacadeService: NotificationFacadeService = inject(NotificationFacadeService), +) => { + return actions.pipe( + ofType(SHOW_NOTIFICATION_ACTIONS.appUpdated), + tap(() => notificationsFacadeService.showAppUpdatedNotification()) + ); +}, { functional: true, dispatch: false }); diff --git a/modules/store/src/lib/effects/notifications/show-error-notification.effect.ts b/modules/store/src/lib/effects/notifications/show-error-notification.effect.ts new file mode 100644 index 00000000..0a47a7bf --- /dev/null +++ b/modules/store/src/lib/effects/notifications/show-error-notification.effect.ts @@ -0,0 +1,20 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { tap } from 'rxjs'; +import { TranslocoService } from '@ngneat/transloco'; + +import { SHOW_NOTIFICATION_ACTIONS } from '../../actions'; +import { NotificationFacadeService } from '../../notification-facade.service'; + +export const SHOW_ERROR_NOTIFICATION_EFFECT = createEffect(( + actions: Actions = inject(Actions), + notificationsFacadeService: NotificationFacadeService = inject(NotificationFacadeService), + translocoService: TranslocoService = inject(TranslocoService), +) => { + return actions.pipe( + ofType(SHOW_NOTIFICATION_ACTIONS.error), + tap((action) => notificationsFacadeService.showErrorNotification( + translocoService.selectTranslate(action.l10nKey, action.l10nPayload), + )) + ); +}, { functional: true, dispatch: false }); diff --git a/modules/store/src/lib/effects/notifications/show-generic-error-notification.effect.ts b/modules/store/src/lib/effects/notifications/show-generic-error-notification.effect.ts new file mode 100644 index 00000000..bea326c3 --- /dev/null +++ b/modules/store/src/lib/effects/notifications/show-generic-error-notification.effect.ts @@ -0,0 +1,18 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { of, tap } from 'rxjs'; + +import { SHOW_NOTIFICATION_ACTIONS } from '../../actions'; +import { NotificationFacadeService } from '../../notification-facade.service'; + +export const SHOW_GENERIC_ERROR_NOTIFICATION_EFFECT = createEffect(( + actions: Actions = inject(Actions), + notificationsFacadeService: NotificationFacadeService = inject(NotificationFacadeService), +) => { + return actions.pipe( + ofType(SHOW_NOTIFICATION_ACTIONS.genericError), + tap((action) => notificationsFacadeService.showErrorNotification( + of(action.error.message), + )) + ); +}, { functional: true, dispatch: false }); diff --git a/modules/store/src/lib/effects/notifications/show-info-notification.effect.ts b/modules/store/src/lib/effects/notifications/show-info-notification.effect.ts new file mode 100644 index 00000000..bd430d7c --- /dev/null +++ b/modules/store/src/lib/effects/notifications/show-info-notification.effect.ts @@ -0,0 +1,20 @@ +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { inject } from '@angular/core'; +import { tap } from 'rxjs'; +import { TranslocoService } from '@ngneat/transloco'; + +import { SHOW_NOTIFICATION_ACTIONS } from '../../actions'; +import { NotificationFacadeService } from '../../notification-facade.service'; + +export const SHOW_INFO_NOTIFICATION_EFFECT = createEffect(( + actions: Actions = inject(Actions), + notificationsFacadeService: NotificationFacadeService = inject(NotificationFacadeService), + translocoService: TranslocoService = inject(TranslocoService), +) => { + return actions.pipe( + ofType(SHOW_NOTIFICATION_ACTIONS.info), + tap((action) => notificationsFacadeService.showInfoNotification( + translocoService.selectTranslate(action.l10nKey, action.l10nPayload), + )) + ); +}, { functional: true, dispatch: false }); diff --git a/modules/store/src/lib/notification-facade.service.ts b/modules/store/src/lib/notification-facade.service.ts new file mode 100644 index 00000000..92849578 --- /dev/null +++ b/modules/store/src/lib/notification-facade.service.ts @@ -0,0 +1,61 @@ +import { Injectable } from '@angular/core'; +import { Observable, take } from 'rxjs'; +import { MatSnackBar } from '@angular/material/snack-bar'; +import { ScreenSizeObserverService } from '@app/shared-misc'; +import { AppUpdatedNotificationComponent, ErrorNotificationComponent, InfoNotificationComponent } from '@app/shared-components'; + +@Injectable() +export class NotificationFacadeService { + constructor( + private readonly screenSizeObserverService: ScreenSizeObserverService, + private readonly snackBar: MatSnackBar, + ) { + } + + public showInfoNotification( + message$: Observable + ): void { + this.screenSizeObserverService.isSmallScreen$.pipe( + take(1) + ).subscribe((isSmallScreen) => { + this.snackBar.openFromComponent( + InfoNotificationComponent, + { + horizontalPosition: 'end', + verticalPosition: isSmallScreen ? 'top' : 'bottom', + duration: 5000, + data: message$ + } + ); + }); + } + + public showErrorNotification( + message$: Observable + ): void { + this.screenSizeObserverService.isSmallScreen$.pipe( + take(1) + ).subscribe((isSmallScreen) => { + this.snackBar.openFromComponent( + ErrorNotificationComponent, + { + horizontalPosition: 'end', + verticalPosition: isSmallScreen ? 'top' : 'bottom', + duration: 10000, + data: message$ + } + ); + }); + } + + public showAppUpdatedNotification(): void { + this.snackBar.openFromComponent( + AppUpdatedNotificationComponent, + { + horizontalPosition: 'center', + verticalPosition: 'bottom', + duration: Number.MAX_SAFE_INTEGER + } + ); + } +} diff --git a/modules/store/src/lib/provide-store.ts b/modules/store/src/lib/provide-store.ts index 9afecd99..ba94aa10 100644 --- a/modules/store/src/lib/provide-store.ts +++ b/modules/store/src/lib/provide-store.ts @@ -36,12 +36,12 @@ import { AttachedIoModesEffects, COMMON_EFFECTS, CONTROLLER_EFFECTS, + CONTROL_SCHEME_EFFECTS, HUB_EFFECTS, HubAttachedIosStateEffects, HubPortModeInfoEffects, - NotificationsEffects, - SETTINGS_EFFECTS, - TASK_PROCESSING_EFFECTS + NOTIFICATION_EFFECTS, + SETTINGS_EFFECTS } from './effects'; import { bluetoothAvailabilityCheckFactory } from './bluetooth-availability-check-factory'; import { HubStorageService } from './hub-storage.service'; @@ -53,6 +53,7 @@ import { AppStoreVersion } from './app-store-version'; // eslint-disable-next-line @nx/enforce-module-boundaries import packageJson from '../../../../package.json'; import { CopyToClipboardHandlerService } from './copy-to-clipboard-handler.service'; +import { NotificationFacadeService } from './notification-facade.service'; const REDUCERS: ActionReducerMap = { bluetoothAvailability: BLUETOOTH_AVAILABILITY_FEATURE.reducer, @@ -95,14 +96,14 @@ export function provideApplicationStore(): EnvironmentProviders { AttachedIOsEffects, HubPortModeInfoEffects, AttachedIoModesEffects, - NotificationsEffects, HubAttachedIosStateEffects, CONTROLLER_EFFECTS, SETTINGS_EFFECTS, HUB_EFFECTS, - TASK_PROCESSING_EFFECTS, + CONTROL_SCHEME_EFFECTS, COMMON_EFFECTS, - APP_UPDATE_EFFECTS + APP_UPDATE_EFFECTS, + NOTIFICATION_EFFECTS ), { provide: APP_INITIALIZER, @@ -119,6 +120,7 @@ export function provideApplicationStore(): EnvironmentProviders { HubMotorPositionFacadeService, HubServoCalibrationFacadeService, ControllerProfilesFacadeService, + NotificationFacadeService, { provide: COPY_TO_CLIPBOARD_HANDLER, useClass: CopyToClipboardHandlerService }, provideRouterStore({ navigationActionTiming: NavigationActionTiming.PostActivation diff --git a/package-lock.json b/package-lock.json index fd757bc4..23c9aebe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "moc-commander", - "version": "1.2.7", + "version": "1.2.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "moc-commander", - "version": "1.2.7", + "version": "1.2.8", "dependencies": { "@angular/animations": "^17.2.0", "@angular/cdk": "^17.2.0", diff --git a/package.json b/package.json index 375ca33e..5bc1f4cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "moc-commander", - "version": "1.2.7", + "version": "1.2.8", "scripts": { "start": "nx serve", "serve:prod": "nx serve -c production", diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 01adf8f9..021afb46 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -10,12 +10,12 @@ "common": { "copyToClipboard": "Copy to clipboard", "copyToClipboardSuccessNotification": "Copied to clipboard", - "copyToClipboardErrorNotification": "Failed to copy to clipboard" + "copyToClipboardErrorNotification": "Failed to copy to clipboard", + "dismissNotification": "Dismiss" }, "appUpdatedNotification": { "prefixMessage": "App has been updated, for details see", - "linkText": "About page", - "dismissButton": "Dismiss" + "linkText": "About page" }, "adjustMotorPosition": { "title": "Motor position adjustment", @@ -823,6 +823,9 @@ "runningControlSchemePerformanceImprovements": "Performance improvements for running control schemes", "fixPwaBackgroundColor": "Fixed background color of the PWA app", "fixHighFrequencyTaskStalling": "Fixed task stalling when processing high-frequency inputs" + }, + "1-2-8": { + "minorNotificationImprovements": "Minor improvements to notifications" } } } diff --git a/src/assets/i18n/ru.json b/src/assets/i18n/ru.json index 553aacf6..fc39a877 100644 --- a/src/assets/i18n/ru.json +++ b/src/assets/i18n/ru.json @@ -10,12 +10,12 @@ "common": { "copyToClipboard": "Копировать в буфер обмена", "copyToClipboardSuccessNotification": "Скопировано в буфер обмена", - "copyToClipboardErrorNotification": "Не удалось скопировать в буфер обмена" + "copyToClipboardErrorNotification": "Не удалось скопировать в буфер обмена", + "dismissNotification": "Закрыть" }, "appUpdatedNotification": { "prefixMessage": "Приложение было обновлено, см. ", - "linkText": "'О программе'", - "dismissButton": "Закрыть" + "linkText": "'О программе'" }, "adjustMotorPosition": { "title": "Подстройка положения мотора", @@ -823,6 +823,9 @@ "runningControlSchemePerformanceImprovements": "Улучшение производительности при работе схем управления", "fixPwaBackgroundColor": "Исправлена ошибка цвета фона при установке приложения как PWA", "fixHighFrequencyTaskStalling": "Исправлено зависание задач при обработке интенсивого ввода" + }, + "1-2-8": { + "minorNotificationImprovements": "Небольшие улучшения уведомлений" } } } diff --git a/src/changelog.ts b/src/changelog.ts index b5531fff..90c32d5f 100644 --- a/src/changelog.ts +++ b/src/changelog.ts @@ -1,6 +1,12 @@ import { IChangelog } from '@app/shared-components'; export const CHANGELOG: IChangelog = [ + { + version: '1.2.8', + changeL10nKeys: [ + 'changelog.1-2-8.minorNotificationImprovements' + ] + }, { version: '1.2.7', changeL10nKeys: [ diff --git a/src/styles/theming.scss b/src/styles/theming.scss index 30cfff3f..63e21cdb 100644 --- a/src/styles/theming.scss +++ b/src/styles/theming.scss @@ -126,7 +126,7 @@ $elevated-dark-color: mat.get-color-from-palette($dark-palette, 800); } .mat-mdc-snack-bar-container { - --mdc-snackbar-container-color: #{mat.get-color-from-palette($dark-palette, 500)}; + --mdc-snackbar-container-color: #{mat.get-color-from-palette($dark-palette, 700)}; --mdc-snackbar-supporting-text-color: #{$light-primary-text}; --mat-snack-bar-button-color: #{rgba($light-primary-text, 0.87)}; }