| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- import { type AnimationLevel } from '../../utils/animationLevel'
- import { type TrackColorPreset, type TrackDisplayMode, type TrackStyleProfile, type TrackTailLengthPreset } from '../presentation/trackStyleConfig'
- import { type GpsMarkerColorPreset, type GpsMarkerSizePreset, type GpsMarkerStyleId } from '../presentation/gpsMarkerStyleConfig'
- export type SideButtonPlacement = 'left' | 'right'
- export type CenterScaleRulerAnchorMode = 'screen-center' | 'compass-center'
- export type UserNorthReferenceMode = 'magnetic' | 'true'
- export type CompassTuningProfile = 'smooth' | 'balanced' | 'responsive'
- export type SettingLockKey =
- | 'lockAnimationLevel'
- | 'lockTrackMode'
- | 'lockTrackTailLength'
- | 'lockTrackColor'
- | 'lockTrackStyle'
- | 'lockGpsMarkerVisible'
- | 'lockGpsMarkerStyle'
- | 'lockGpsMarkerSize'
- | 'lockGpsMarkerColor'
- | 'lockSideButtonPlacement'
- | 'lockAutoRotate'
- | 'lockCompassTuning'
- | 'lockScaleRulerVisible'
- | 'lockScaleRulerAnchor'
- | 'lockNorthReference'
- | 'lockHeartRateDevice'
- export type StoredUserSettings = {
- animationLevel?: AnimationLevel
- trackDisplayMode?: TrackDisplayMode
- trackTailLength?: TrackTailLengthPreset
- trackColorPreset?: TrackColorPreset
- trackStyleProfile?: TrackStyleProfile
- gpsMarkerVisible?: boolean
- gpsMarkerStyle?: GpsMarkerStyleId
- gpsMarkerSize?: GpsMarkerSizePreset
- gpsMarkerColorPreset?: GpsMarkerColorPreset
- autoRotateEnabled?: boolean
- compassTuningProfile?: CompassTuningProfile
- northReferenceMode?: UserNorthReferenceMode
- sideButtonPlacement?: SideButtonPlacement
- showCenterScaleRuler?: boolean
- centerScaleRulerAnchorMode?: CenterScaleRulerAnchorMode
- }
- export interface SystemSettingsConfig {
- values: Partial<StoredUserSettings>
- locks: Partial<Record<SettingLockKey, boolean>>
- }
- export type ResolvedSystemSettingsState = {
- values: Required<StoredUserSettings>
- locks: Record<SettingLockKey, boolean>
- }
- export const USER_SETTINGS_STORAGE_KEY = 'cmr_user_settings_v1'
- export const DEFAULT_STORED_USER_SETTINGS: Required<StoredUserSettings> = {
- animationLevel: 'standard',
- trackDisplayMode: 'full',
- trackTailLength: 'medium',
- trackColorPreset: 'mint',
- trackStyleProfile: 'neon',
- gpsMarkerVisible: true,
- gpsMarkerStyle: 'beacon',
- gpsMarkerSize: 'medium',
- gpsMarkerColorPreset: 'cyan',
- autoRotateEnabled: true,
- compassTuningProfile: 'balanced',
- northReferenceMode: 'magnetic',
- sideButtonPlacement: 'left',
- showCenterScaleRuler: false,
- centerScaleRulerAnchorMode: 'screen-center',
- }
- export const DEFAULT_SETTING_LOCKS: Record<SettingLockKey, boolean> = {
- lockAnimationLevel: false,
- lockTrackMode: false,
- lockTrackTailLength: false,
- lockTrackColor: false,
- lockTrackStyle: false,
- lockGpsMarkerVisible: false,
- lockGpsMarkerStyle: false,
- lockGpsMarkerSize: false,
- lockGpsMarkerColor: false,
- lockSideButtonPlacement: false,
- lockAutoRotate: false,
- lockCompassTuning: false,
- lockScaleRulerVisible: false,
- lockScaleRulerAnchor: false,
- lockNorthReference: false,
- lockHeartRateDevice: false,
- }
- export const SETTING_LOCK_VALUE_MAP: Record<SettingLockKey, keyof StoredUserSettings | null> = {
- lockAnimationLevel: 'animationLevel',
- lockTrackMode: 'trackDisplayMode',
- lockTrackTailLength: 'trackTailLength',
- lockTrackColor: 'trackColorPreset',
- lockTrackStyle: 'trackStyleProfile',
- lockGpsMarkerVisible: 'gpsMarkerVisible',
- lockGpsMarkerStyle: 'gpsMarkerStyle',
- lockGpsMarkerSize: 'gpsMarkerSize',
- lockGpsMarkerColor: 'gpsMarkerColorPreset',
- lockSideButtonPlacement: 'sideButtonPlacement',
- lockAutoRotate: 'autoRotateEnabled',
- lockCompassTuning: 'compassTuningProfile',
- lockScaleRulerVisible: 'showCenterScaleRuler',
- lockScaleRulerAnchor: 'centerScaleRulerAnchorMode',
- lockNorthReference: 'northReferenceMode',
- lockHeartRateDevice: null,
- }
- function normalizeStoredUserSettings(raw: unknown): StoredUserSettings {
- if (!raw || typeof raw !== 'object') {
- return {}
- }
- const normalized = raw as Record<string, unknown>
- const settings: StoredUserSettings = {}
- if (normalized.animationLevel === 'standard' || normalized.animationLevel === 'lite') {
- settings.animationLevel = normalized.animationLevel
- }
- if (normalized.trackDisplayMode === 'none' || normalized.trackDisplayMode === 'full' || normalized.trackDisplayMode === 'tail') {
- settings.trackDisplayMode = normalized.trackDisplayMode
- }
- if (normalized.trackTailLength === 'short' || normalized.trackTailLength === 'medium' || normalized.trackTailLength === 'long') {
- settings.trackTailLength = normalized.trackTailLength
- }
- if (normalized.trackStyleProfile === 'classic' || normalized.trackStyleProfile === 'neon') {
- settings.trackStyleProfile = normalized.trackStyleProfile
- }
- if (typeof normalized.gpsMarkerVisible === 'boolean') {
- settings.gpsMarkerVisible = normalized.gpsMarkerVisible
- }
- if (
- normalized.gpsMarkerStyle === 'dot'
- || normalized.gpsMarkerStyle === 'beacon'
- || normalized.gpsMarkerStyle === 'disc'
- || normalized.gpsMarkerStyle === 'badge'
- ) {
- settings.gpsMarkerStyle = normalized.gpsMarkerStyle
- }
- if (normalized.gpsMarkerSize === 'small' || normalized.gpsMarkerSize === 'medium' || normalized.gpsMarkerSize === 'large') {
- settings.gpsMarkerSize = normalized.gpsMarkerSize
- }
- if (
- normalized.gpsMarkerColorPreset === 'mint'
- || normalized.gpsMarkerColorPreset === 'cyan'
- || normalized.gpsMarkerColorPreset === 'sky'
- || normalized.gpsMarkerColorPreset === 'blue'
- || normalized.gpsMarkerColorPreset === 'violet'
- || normalized.gpsMarkerColorPreset === 'pink'
- || normalized.gpsMarkerColorPreset === 'orange'
- || normalized.gpsMarkerColorPreset === 'yellow'
- ) {
- settings.gpsMarkerColorPreset = normalized.gpsMarkerColorPreset
- }
- if (
- normalized.trackColorPreset === 'mint'
- || normalized.trackColorPreset === 'cyan'
- || normalized.trackColorPreset === 'sky'
- || normalized.trackColorPreset === 'blue'
- || normalized.trackColorPreset === 'violet'
- || normalized.trackColorPreset === 'pink'
- || normalized.trackColorPreset === 'orange'
- || normalized.trackColorPreset === 'yellow'
- ) {
- settings.trackColorPreset = normalized.trackColorPreset
- }
- if (normalized.northReferenceMode === 'magnetic' || normalized.northReferenceMode === 'true') {
- settings.northReferenceMode = normalized.northReferenceMode
- }
- if (typeof normalized.autoRotateEnabled === 'boolean') {
- settings.autoRotateEnabled = normalized.autoRotateEnabled
- }
- if (normalized.compassTuningProfile === 'smooth' || normalized.compassTuningProfile === 'balanced' || normalized.compassTuningProfile === 'responsive') {
- settings.compassTuningProfile = normalized.compassTuningProfile
- }
- if (normalized.sideButtonPlacement === 'left' || normalized.sideButtonPlacement === 'right') {
- settings.sideButtonPlacement = normalized.sideButtonPlacement
- }
- if (typeof normalized.showCenterScaleRuler === 'boolean') {
- settings.showCenterScaleRuler = normalized.showCenterScaleRuler
- }
- if (normalized.centerScaleRulerAnchorMode === 'screen-center' || normalized.centerScaleRulerAnchorMode === 'compass-center') {
- settings.centerScaleRulerAnchorMode = normalized.centerScaleRulerAnchorMode
- }
- return settings
- }
- export function loadStoredUserSettings(storageKey = USER_SETTINGS_STORAGE_KEY): StoredUserSettings {
- try {
- return normalizeStoredUserSettings(wx.getStorageSync(storageKey))
- } catch {
- return {}
- }
- }
- export function persistStoredUserSettings(
- settings: StoredUserSettings,
- storageKey = USER_SETTINGS_STORAGE_KEY,
- ): void {
- try {
- wx.setStorageSync(storageKey, settings)
- } catch {}
- }
- export function mergeStoredUserSettings(
- current: StoredUserSettings,
- patch: Partial<StoredUserSettings>,
- ): StoredUserSettings {
- return {
- ...current,
- ...patch,
- }
- }
- export function buildInitialSystemSettingsState(
- stored: StoredUserSettings,
- config?: Partial<SystemSettingsConfig>,
- ): ResolvedSystemSettingsState {
- const values = {
- ...DEFAULT_STORED_USER_SETTINGS,
- ...(config && config.values ? config.values : {}),
- }
- const locks = {
- ...DEFAULT_SETTING_LOCKS,
- ...(config && config.locks ? config.locks : {}),
- }
- const resolvedValues: Required<StoredUserSettings> = {
- ...values,
- }
- for (const [lockKey, isLocked] of Object.entries(locks) as Array<[SettingLockKey, boolean]>) {
- const valueKey = SETTING_LOCK_VALUE_MAP[lockKey]
- if (!valueKey) {
- continue
- }
- if (!isLocked && stored[valueKey] !== undefined) {
- ;(resolvedValues as Record<string, unknown>)[valueKey] = stored[valueKey]
- }
- }
- for (const [key, value] of Object.entries(stored) as Array<[keyof StoredUserSettings, StoredUserSettings[keyof StoredUserSettings]]>) {
- const matchingLockKey = (Object.keys(SETTING_LOCK_VALUE_MAP) as SettingLockKey[])
- .find((lockKey) => SETTING_LOCK_VALUE_MAP[lockKey] === key)
- if (matchingLockKey && locks[matchingLockKey]) {
- continue
- }
- if (value !== undefined) {
- ;(resolvedValues as Record<string, unknown>)[key] = value
- }
- }
- return {
- values: resolvedValues,
- locks,
- }
- }
- export function buildRuntimeSettingLocks(
- locks: Partial<Record<SettingLockKey, boolean>> | undefined,
- runtimeActive: boolean,
- ): Partial<Record<SettingLockKey, boolean>> {
- const sourceLocks = locks || {}
- if (runtimeActive) {
- return { ...sourceLocks }
- }
- const unlocked: Partial<Record<SettingLockKey, boolean>> = {}
- for (const key of Object.keys(sourceLocks) as SettingLockKey[]) {
- unlocked[key] = false
- }
- return unlocked
- }
- export function resolveSystemSettingsState(
- config?: Partial<SystemSettingsConfig>,
- storageKey = USER_SETTINGS_STORAGE_KEY,
- runtimeActive = false,
- ): ResolvedSystemSettingsState {
- return buildInitialSystemSettingsState(
- loadStoredUserSettings(storageKey),
- {
- values: config && config.values ? config.values : {},
- locks: buildRuntimeSettingLocks(config && config.locks ? config.locks : {}, runtimeActive),
- },
- )
- }
|