Skip to content

Commit

Permalink
settings (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
codephobia committed Apr 4, 2024
1 parent 7b5a214 commit 0f2426f
Show file tree
Hide file tree
Showing 16 changed files with 442 additions and 104 deletions.
30 changes: 28 additions & 2 deletions apps/score-keeper-nativescript/src/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,34 @@
import { Component } from '@angular/core';
import { Component, NgZone } from '@angular/core';
import { SocketService } from './services/socket.service';
import { ScoreKeeperStore } from './services/score-keeper.store';
import { IGame, OverlayState } from '@pool-overlay/models';

@Component({
moduleId: module.id,
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent { }
export class AppComponent {
constructor(
private _store: ScoreKeeperStore,
private ngZone: NgZone,
private _socketService: SocketService,
) {
this._socketService.bind('GAME_EVENT', this.updateGame.bind(this));
this._socketService.bind('OVERLAY_STATE_EVENT', this.updateOverlay.bind(this));
this._socketService.connect();
this._store.getGame();
}

public updateGame({ game }: { game: IGame }) {
this.ngZone.run(() => {
this._store.updateGame(game);
});
}

public updateOverlay(res: OverlayState): void {
this.ngZone.run(() => {
this._store.updateOverlay(res);
});
}
}
17 changes: 16 additions & 1 deletion apps/score-keeper-nativescript/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
import { StoreModule } from '@ngrx/store';
import { EffectsModule } from '@ngrx/effects';

import { CoreModule } from './core/core.module';
import { SharedModule } from './features/shared/shared.module';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { settingsReducer, SettingsStateKey } from './core/settings/settings.reducer';
import { SettingsEffects } from './core/settings/settings.effects';

@NgModule({
imports: [CoreModule, SharedModule, AppRoutingModule],
imports: [
StoreModule.forRoot({
[SettingsStateKey]: settingsReducer,
}),
EffectsModule.forRoot([
SettingsEffects,
]),
CoreModule,
SharedModule,
AppRoutingModule
],
declarations: [AppComponent],
bootstrap: [AppComponent],
schemas: [NO_ERRORS_SCHEMA],
Expand Down
2 changes: 2 additions & 0 deletions apps/score-keeper-nativescript/src/core/settings/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * as SettingsSelectors from './settings.selectors';
export { SettingsActions } from './settings.actions';
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { createActionGroup, emptyProps, props } from '@ngrx/store';
import { AppSettings } from './settings.model';

export const SettingsActions = createActionGroup({
source: 'Settings',
events: {
'Load Settings': emptyProps(),
'Load Settings Success': props<{ settings: AppSettings }>(),

'Save Settings': props<{ settings: AppSettings }>(),
'Save Settings Success': props<{ settings: AppSettings }>(),

'Set Table': props<{ table: number; }>(),
'Set Table Success': props<{ table: number; }>(),

'Set Server': props<{ server: string; }>(),
'Set Server Success': props<{ server: string; }>(),

'Get Max Tables': emptyProps(),
'Get Max Tables Success': props<{ maxTables: number; }>(),
'Get Max Tables Error': props<{ error: string; }>(),
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Injectable } from '@angular/core';
import { Actions, ROOT_EFFECTS_INIT, createEffect, ofType } from '@ngrx/effects';
import { map, switchMap, tap, catchError, of } from 'rxjs';

import { SettingsKeys, SettingsService } from './settings.service';
import { SettingsActions } from './settings.actions';
import { APIService } from '../../services/api.service';

@Injectable()
export class SettingsEffects {
public init$ = createEffect(() => this.actions$.pipe(
ofType(ROOT_EFFECTS_INIT),
map(() => SettingsActions.loadSettings()),
));

public loadSettings$ = createEffect(() => this.actions$.pipe(
ofType(SettingsActions.loadSettings),
map(() => {
const settings = this.settingsService.load();
return SettingsActions.loadSettingsSuccess({ settings });
}),
));

public saveSettings$ = createEffect(() => this.actions$.pipe(
ofType(SettingsActions.saveSettings),
map(({ settings }) => {
return SettingsActions.saveSettingsSuccess({ settings });
}),
));

public saveSettingsSuccess$ = createEffect(() => this.actions$.pipe(
ofType(SettingsActions.saveSettingsSuccess),
tap(({ settings }) => {
this.settingsService.saveAll(settings);
}),
), { dispatch: false });

public setTable$ = createEffect(() => this.actions$.pipe(
ofType(SettingsActions.setTable),
map(({ table }) => SettingsActions.setTableSuccess({ table })),
));

public setTableSuccess$ = createEffect(() => this.actions$.pipe(
ofType(SettingsActions.setTableSuccess),
tap(({ table }) => {
this.settingsService.save({ key: SettingsKeys.TABLE, value: table });
}),
), { dispatch: false });

public setServer$ = createEffect(() => this.actions$.pipe(
ofType(SettingsActions.setServer),
map(({ server }) => SettingsActions.setServerSuccess({ server })),
));

public setServerSuccess$ = createEffect(() => this.actions$.pipe(
ofType(SettingsActions.setServerSuccess),
tap(({ server }) => {
this.settingsService.save({ key: SettingsKeys.SERVER, value: server });
}),
), { dispatch: false });

public getMaxTables$ = createEffect(() => this.actions$.pipe(
ofType(ROOT_EFFECTS_INIT, SettingsActions.getMaxTables),
switchMap(() => this.apiService.getMaxTables().pipe(
map(({ count }) => SettingsActions.getMaxTablesSuccess({ maxTables: count })),
catchError((err) => of(SettingsActions.getMaxTablesError({ error: err.message }))),
)),
));

public getMaxTablesSuccess$ = createEffect(() => this.actions$.pipe(
ofType(SettingsActions.getMaxTablesSuccess),
tap(({ maxTables }) => {
this.settingsService.save({ key: SettingsKeys.MAX_TABLES, value: maxTables });
}),
), { dispatch: false });

public getMaxTablesError$ = createEffect(() => this.actions$.pipe(
ofType(SettingsActions.getMaxTablesError),
tap((err) => console.log(err)),
), { dispatch: false });

constructor(
private actions$: Actions,
private settingsService: SettingsService,
private apiService: APIService,
) { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface AppSettings {
server: string;
table: number;
maxTables: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { createReducer, on } from '@ngrx/store';
import { SettingsActions } from './settings.actions';

export const SettingsStateKey = 'settings';

export interface State {
server: string;
table: number;
maxTables: number;
}

export const initialState: State = {
server: '',
table: 1,
maxTables: 2,
};

export const settingsReducer = createReducer(
initialState,
on(SettingsActions.loadSettingsSuccess, (state, { settings }) => ({
...state,
server: settings.server,
table: settings.table,
maxTables: settings.maxTables,
})),
on(SettingsActions.saveSettings, (state, { settings }) => ({
...state,
server: settings.server,
table: settings.table,
maxTables: settings.maxTables,
})),
on(SettingsActions.setTable, (state, { table }) => ({
...state,
table,
})),
on(SettingsActions.setServer, (state, { server }) => ({
...state,
server,
})),
on(SettingsActions.getMaxTablesSuccess, (state, { maxTables }) => ({
...state,
maxTables,
})),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { SettingsStateKey, State } from './settings.reducer';

export const selectSettingsState = createFeatureSelector<State>(SettingsStateKey);

export const selectServer = createSelector(
selectSettingsState,
(state) => state.server,
);

export const selectTable = createSelector(
selectSettingsState,
(state) => state.table,
);

export const selectMaxTables = createSelector(
selectSettingsState,
(state) => state.maxTables,
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Injectable } from '@angular/core';
import { ApplicationSettings } from '@nativescript/core';
import { AppSettings } from './settings.model';

export const DEFAULT_SERVER = '192.168.0.26';
export const DEFAULT_TABLE = 1;
export const DEFAULT_MAX_TABLES = 2;

export enum SettingsKeys {
SERVER = 'server',
TABLE = 'table',
MAX_TABLES = 'maxTables',
}

@Injectable({ providedIn: 'root' })
export class SettingsService {
public load(): AppSettings {
const server = ApplicationSettings.getString(SettingsKeys.SERVER, DEFAULT_SERVER);
const table = ApplicationSettings.getNumber(SettingsKeys.TABLE, DEFAULT_TABLE);
const maxTables = ApplicationSettings.getNumber(SettingsKeys.MAX_TABLES, DEFAULT_MAX_TABLES);

return {
server,
table,
maxTables,
};
}

public saveAll({ server, table, maxTables }: AppSettings): void {
ApplicationSettings.setString(SettingsKeys.SERVER, server);
ApplicationSettings.setNumber(SettingsKeys.TABLE, table);
ApplicationSettings.setNumber(SettingsKeys.MAX_TABLES, maxTables);
}

public save({ key, value }: { key: SettingsKeys, value: string | number | boolean }): void {
switch (typeof value) {
case 'string':
ApplicationSettings.setString(key, value);
break;
case 'number':
ApplicationSettings.setNumber(key, value);
break;
case 'boolean':
ApplicationSettings.setBoolean(key, value);
break;
default:
throw new Error(`unable to save setting ${key} of type ${typeof value}.`);
}
}

public remove(key: string): void {
return ApplicationSettings.remove(key);
}

public clear(): void {
return ApplicationSettings.clear();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { Component, NgZone } from '@angular/core';
import { IGame, OverlayState } from '@pool-overlay/models';
import { Component } from '@angular/core';
import { PlayerUpdateEvent } from '@pool-overlay/score-keeper';
import { ScoreKeeperStore } from '../../services/score-keeper.store';
import { SocketService } from '../../services/socket.service';

@Component({
moduleId: module.id,
Expand All @@ -15,27 +13,10 @@ export class HomeComponent {

constructor(
private _store: ScoreKeeperStore,
private _socketService: SocketService,
private ngZone: NgZone,
) {
this._socketService.bind('GAME_EVENT', this.updateGame.bind(this));
this._socketService.bind('OVERLAY_STATE_EVENT', this.updateOverlay.bind(this));
this._socketService.connect();
this._store.getGame();
}

public updateGame({ game }: { game: IGame }) {
this.ngZone.run(() => {
this._store.updateGame(game);
});
}

public updateOverlay(res: OverlayState): void {
this.ngZone.run(() => {
this._store.updateOverlay(res);
});
}

public updatePlayer(update: PlayerUpdateEvent) {
this._store.updateScore(update);
}
Expand Down
Loading

0 comments on commit 0f2426f

Please sign in to comment.