diff --git a/src/lib/core/MRPBlockLoader.ts b/src/lib/core/MRPBlockLoader.ts index 0fb5315..d52ed6e 100644 --- a/src/lib/core/MRPBlockLoader.ts +++ b/src/lib/core/MRPBlockLoader.ts @@ -34,14 +34,13 @@ export class BlockLoader extends MRPData { constructor($state: MRPState, config: MRPConfig | undefined){ super($state.signal, 'blockLoader') this.$ = $state - if(!config) return this._config = config } async init(){ this.begin() - if(this._config?.componentVisible && Object.keys(this._config?.componentVisible)?.length){ - this._config = { ...config.componentVisible, ...this.defaultComponents } + if(this.config?.componentVisible && Object.keys(this.config?.componentVisible)?.length){ + this.config = { ...config.componentVisible, ...this.defaultComponents } } else { console.log('loading default components') @@ -117,6 +116,10 @@ export class BlockLoader extends MRPData { console.error(`BlockLoader: ${error}`) } + get config(): MRPConfig | undefined { + return this.config + } + get components(): Record { return this._components } diff --git a/src/lib/core/kinds/app-config.ts b/src/lib/core/kinds/app-config.ts index 8345f5b..e97708c 100644 --- a/src/lib/core/kinds/app-config.ts +++ b/src/lib/core/kinds/app-config.ts @@ -3,9 +3,6 @@ import type { NDKTag, NostrEvent } from '@nostr-dev-kit/ndk'; import jsonpack from 'jsonpack'; -type ComponentVisible = { - [key: string]: boolean -} type Colors = { background?: string, @@ -28,6 +25,68 @@ type Json = { type Theme = string +type ConfigTheme = { + native: Theme, + custom: boolean, + customUrl: string, + customType: 'url' +} + + +type ConfigBlock = { + enabled: boolean, + order: number, + options?: any +} + +type ConfigBlocks = { + [key: string]: ConfigBlock +} + +type Config = { + general: { + login: { + enabled: boolean, + join: { + enabled: boolean + } + }, + theme: ConfigTheme + }, + blocks: ConfigBlocks +} + +const defaults = { + general: { + login: { + enabled: true, + join: { + enabled: true + } + }, + theme: { + native: 'classic', + custom: false, + customType: 'url', + customUrl: '', + } + }, + blocks: { + 'operator-profile': { + enabled: true, + order: 0 + }, + 'relay-feed': { + enabled: true, + order: 1 + }, + 'map': { + enabled: true, + order: 2 + } + } +} + export class AppConfig extends NDKEvent { private _config: any = {} @@ -36,7 +95,7 @@ export class AppConfig extends NDKEvent { this.kind ?? NDKKind.AppSpecificData console.log('AppConfig', this.content) if(!this?.content || this.content.length === 0) return - this._config = this.parseConfig() + this._config = { ...defaults, ...this.parseConfig() } } static from( ndk: NDK, rawEvent: NostrEvent ){ @@ -53,20 +112,119 @@ export class AppConfig extends NDKEvent { json = jsonpack.unpack(this.content) } catch(e){ - throw new Error(`Error parsing content: ${e}`) + console.error(`Error parsing content: ${e}`) } } return json } - get(key?: string): any | undefined { - return key? this._config?.[key]: this._config + set config(config: Config) { + this._config = this.deepProxy(config, () => { + this.content = jsonpack.pack(config); + }); + } + + get config(): Config { + return this._config; + } + + get theme(): ConfigTheme { + return this.config.general?.theme + } + + get blocks(): ConfigBlocks { + return this.config.blocks + } + + get general(): any { + return this.config.general } - set(key: string, payload: Json){ - const json = this.parseConfig() - json[key] = payload - this.content = jsonpack.pack(json) + private deepProxy(obj: Config, callback: () => void): Config { + const handler: ProxyHandler = { + set: (target, property, value) => { + target[property] = (value && typeof value === 'object') ? this.deepProxy(value, callback) : value; + callback(); // Call the callback whenever a property is set + return true; + }, + get: (target, property) => { + const item = target[property]; + return (item && typeof item === 'object') ? this.deepProxy(item, callback) : item; + } + }; + return new Proxy(obj, handler); } + private updateConfig(path: string[], value: any) { + let current = this._config; + for (let i = 0; i < path.length - 1; i++) { + current = current[path[i]]; + } + current[path[path.length - 1]] = value; + this.config = this._config; + } + + setLoginEnabled(enabled: boolean) { + this.updateConfig(['general', 'login', 'enabled'], enabled); + } + + setJoinEnabled(enabled: boolean) { + this.updateConfig(['general', 'login', 'join', 'enabled'], enabled); + } + + setTheme(theme: ConfigTheme) { + this.updateConfig(['general', 'theme'], theme); + } + + setBlocks(blocks: ConfigBlocks) { + this.updateConfig(['blocks'], blocks); + } + + setBlocksOrder(order: string[]) { + const newConfig = { ...this.config } + order.forEach((key, index) => { + newConfig.blocks[key].order = index + }) + this.config = newConfig + } + + setBlock(key: string, block: ConfigBlock) { + this.updateConfig(['blocks', key], block); + } + + setBlockEnabled(key: string, enabled: boolean) { + this.updateConfig(['blocks', key, 'enabled'], enabled); + } + + setBlockOrder(key: string, order: number) { + this.updateConfig(['blocks', key, 'order'], order); + } + + setBlockOptions(key: string, options: any) { + this.updateConfig(['blocks', key, 'options'], options); + } + + isThemeCustom(): boolean { + return this.config.general?.theme?.custom + } + + isLoginEnabled(): boolean { + return this.config.general?.login?.enabled + } + + isJoinEnabled(): boolean { + return this.config.general?.login?.join?.enabled + } + + isBlockEnabled(key: string): boolean { + return this.getBlock(key)?.enabled + } + + getBlock(key: string): ConfigBlock { + return this.blocks?.[key] + } + + getBlocksOrder(): string[] { + return Object.keys(this.blocks).sort((a, b) => this.getBlock(a).order - this.getBlock(b).order) + } } \ No newline at end of file