treetrail-frontend/src/app/config.service.ts

157 lines
4 KiB
TypeScript
Raw Normal View History

2024-10-19 11:53:15 +02:00
import { Injectable, Component } from "@angular/core"
import { Observable, BehaviorSubject, Subject, ReplaySubject, combineLatest } from 'rxjs'
import { map, take } from 'rxjs/operators'
import { LngLat, LngLatLike } from "maplibre-gl"
import { DataService } from "./data.service"
import { DefaultService } from "./openapi/services.gen"
import { Bootstrap, Map } from "./openapi/types.gen"
export type MapPos = {
center: LngLatLike,
zoom: number,
bearing: number,
pitch: number,
}
export const dbName = 'treetrail' // See also dbConfig in app.module
export const settingsDbName = 'settings'
export class Config {
constructor(
public user: string = undefined,
public skipIntro: boolean = false,
public vibrate: boolean = true,
public showZones: { [zone: string]: boolean } = {},
public alertDistance = 250,
public map?: Map,
public bootstrap?: Bootstrap,
public mapPos?: MapPos,
public background: string = undefined,
// public server: {} = {},
// public client: {} = {},
// public app: {} = {},
) { }
}
@Injectable()
export class ConfigService {
constructor(
public dataService: DataService,
private api: DefaultService,
) {
}
public conf: BehaviorSubject<Config> // = new BehaviorSubject<Config>(new Config())
userPrefsKeyList = ['userName', 'skipIntro', 'vibrate', 'showZones', 'background']
bootstrap(): Observable<Bootstrap> {
return this.api.getBootstrapBootstrapGet().pipe(map(
resp => {
this.conf = new BehaviorSubject<Config>(new Config(
'',
false,
true,
{},
250,
resp.map,
resp,
undefined,
))
// this.conf.value.bootstrap = resp
// this.conf.value.map = resp.map
// this.conf.next(this.conf.value)
return resp
}
))
}
getMapCenter(): Observable<LngLatLike> {
return this.conf.pipe(map(
conf => <LngLatLike>{
lng: conf.map.lng,
lat: conf.map.lat
}
))
}
loadUserSettings(data: unknown[]) {
// TODO: assert the whole idea and use of storing the config in a BahaviourSubject
data.forEach(kv => {
if (kv['value']) {
this.conf.value[kv['key']] = kv['value']
}
})
// Update the list of types of zones from actual data
this.dataService.all.subscribe(
all => {
let zoneTypes = new Set((Object.values(all.zones).map(
zone => zone.type
)))
zoneTypes.forEach(
zoneType => {
if (this.conf.value.showZones[zoneType] === undefined) {
this.conf.value.showZones[zoneType] = false
}
}
)
this.conf.next(this.conf.value)
}
)
// if (!this.conf.value.skipIntro) {
// this.router.navigate(['intro'], {relativeTo: this.route});
// }
}
storeUserData(): void {
this.userPrefsKeyList.forEach(
key => this.dataService.dbService.update(
settingsDbName, {
key: key,
value: this.conf.value[key]
}).subscribe()
)
}
setUserPrefValue(pref: string, key: string, value: any) {
let conf = this.conf.value
conf[pref][key] = value
this.conf.next(conf)
this.storeUserData()
}
setUserPref(pref: string, value: any) {
let conf = this.conf.value
// userName is special, read (and thus stored) in bootstrap
if (pref == 'userName') {
conf.bootstrap.user = value
this.conf.next(this.conf.value)
}
else {
conf[pref] = value
}
this.conf.next(conf)
this.storeUserData()
}
setMapPos(mapPos: MapPos): Observable<unknown> {
this.updateConf({mapPos: mapPos})
return this.dataService.dbService.update(settingsDbName, {
key: 'mapPos',
value: {
center: mapPos.center,
zoom: mapPos.zoom,
pitch: mapPos.pitch,
bearing: mapPos.bearing,
}
})
}
updateConf(newConf: Object) {
this.conf.pipe(take(1)).subscribe(
conf => this.conf.next({ ...conf, ...newConf })
)
}
}