diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/files_to_watch.gni b/frameworks/bridge/declarative_frontend/state_mgmt/files_to_watch.gni index 13d444b18a662ff040a2f596d74c7811c78b8b84..fad31a154fbbd730ad241a02109945414254777a 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/files_to_watch.gni +++ b/frameworks/bridge/declarative_frontend/state_mgmt/files_to_watch.gni @@ -90,6 +90,10 @@ state_mgmt_release_files_to_watch = [ "//foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_computed.ts", "//foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_view.ts", "//foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_decorators.ts", + "//foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_env.ts", + "//foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/common.ts", + "//foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/breakpoint.ts", + "//foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/densityupdate.ts", "//foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_json_coder.ts", "//foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_make_observed.ts", "//foundation/arkui/ace_engine/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_recycle_pool.ts", diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/arkts_util.d.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/arkts_util.d.ts index c5a14117448c99b030afeae3af56cb44efcc9b4e..1055e27599b70680e2dbe1fe3d61dd086269f5c9 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/arkts_util.d.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/common/arkts_util.d.ts @@ -18,6 +18,9 @@ */ declare interface ArkTsUtil { getHash(object: object): number; + getUIObserver(): typeof uiObserver; + on(type: 'densityUpdate', callback: (info: IDensityInfo) => void): void; + off(type: 'densityUpdate', callback: (info: IDensityInfo) => void): void; } // Require and local module. diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/breakpoint.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/breakpoint.ts new file mode 100644 index 0000000000000000000000000000000000000000..b65d8d0e333e8b2ffab2d4a032dae9c11788164c --- /dev/null +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/breakpoint.ts @@ -0,0 +1,78 @@ +/** + * Breakpoint Environment Property + * + * This file contains interfaces, enums, and classes representing + * breakpoint environment properties. + * In production, these definitions are expected to be provided by the + * platform (system environment provider) team and imported from their + * respective external repositories. + * + */ + + + +/** + * Enum representing width breakpoints for responsive design. + * Provided by: Platform Environment Provider + */ +enum WidthBreakpoint { + WIDTH_XS, + WIDTH_SM, + WIDTH_MD, + WIDTH_LG, + WIDTH_XL +} + +/** + * Enum representing height breakpoints for responsive design. + * Provided by: Platform Environment Provider + */ +enum HeightBreakpoint { + HEIGHT_XS, + HEIGHT_SM, + HEIGHT_MD, + HEIGHT_LG, + HEIGHT_XL +} + +/** + * Represents both width and height breakpoints. + * Provided by: Platform Environment Provider + */ +interface IBreakPoint { + width: WidthBreakpoint; + height: HeightBreakpoint; +} + + +/** + * ObservedV2 implementation for breakpoint environment value. + * Maintains and updates width/height breakpoints from the system. + * Implements IEnvironmentValue to provide density data + * To be Provided by: Platform Environment Provider + */ +@ObservedV2 +class EnvBreakpoint implements IEnvironmentValue, IBreakPoint { + @Trace width: WidthBreakpoint; + @Trace height: HeightBreakpoint; + + constructor(context: object) { + this.width = WidthBreakpoint.WIDTH_MD; + this.height = HeightBreakpoint.HEIGHT_MD; + //breakpoint callback trigger to be added once its made available from OHOS team + } + + get value(): IBreakPoint { + return { width: this.width, height: this.height }; + } + + update(payload: IBreakPoint) { + this.width = payload.width; + this.height = payload.height; + } + + // This function will be called from statemgmt framework when the component is destroyed + // used to unregister the registered env properties + destroy(): void { + } +} diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/common.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/common.ts new file mode 100644 index 0000000000000000000000000000000000000000..187473a6c9d831a3b70c4150c3ace984603d65dd --- /dev/null +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/common.ts @@ -0,0 +1,64 @@ +/** + * Common interfaces for bridging environment properties between + * the State Management framework and the underlying platform layer. + * + * Purpose: + * -------- + * - Provide a unified abstraction layer so that the framework can interact + * with platform-specific environment details in a consistent, type-safe way. + * - Ensure all the environment properties can be registered, tracked + * and also successfully unregistered when the property is no longer needed + * by the component + * - Act as a common reference point for all environment property definitions, + * reducing duplication and promoting consistency across framework modules. + * + */ + +const uiContext = requireInternal('arkui.uicontext'); + +/** + * Maps environment property keys to their corresponding value types. + * + * This mapping should be maintained in a **common central location**. + * Each environment property provider (platform/system team) is expected to: + * - Add the key for the environment property they provide + * - Map it to its respective type interface + * + * Example: + * "System.Breakpoint" -> IBreakPoint + * "System.DensityInfo" -> IDensityInfo + * + * Provided by: Platform Environment Provider (mocked here for testing) + */ +interface EnvTypeMap { + "System.Breakpoint": IBreakPoint; + "System.DensityInfo": IDensityInfo; +} + + +/** + * Factory map for creating environment property value instances. + * + * Keys match the entries in `EnvTypeMap`, and each factory function: + * - Accepts a `context` object + * - Returns the corresponding `IEnvironmentValue` instance + * + * This enables: + * - On-demand creation of environment value providers + * - Consistent construction logic for all environment properties + * + * To be updated by Platform Environment Provider for each environment property newly introduced(mocked here for testing) + */ +const envFactoryMap: { + [K in keyof EnvTypeMap]: (context: object) => IEnvironmentValue; +} = { + "System.DensityInfo": (context) => new EnvDensityInfo(context), + "System.Breakpoint": (context) => new EnvBreakpoint(context) +}; + + +interface IEnvironmentValue { + readonly value: T; + destroy(): void; + +} diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/densityupdate.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/densityupdate.ts new file mode 100644 index 0000000000000000000000000000000000000000..5bf41a775dd331f8cfa8c2b06e727f154e30d423 --- /dev/null +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/densityupdate.ts @@ -0,0 +1,66 @@ +/** + * Environment Property Definitions for Density update + * + * This file contains interfaces, enums, and classes representing + * environment properties for density information. + * In production, these definitions are expected to be provided by the + * platform (system environment provider) team and imported from their + * respective external repositories. + * + */ + +const uiObserver = requireInternal('arkui.observer'); + +// Interface for DensityInfo +// To be provided by the env provider of densityInfo property +interface IDensityInfo { + density: number; +} + +/** + * ObservedV2 implementation for density information environment value. + * Maintains and updates system density data, handling observer registration and cleanup. + * Implements IEnvironmentValue to provide density data + * To be Provided by: Platform Environment provider team + */ + @ObservedV2 +class EnvDensityInfo implements IEnvironmentValue, IDensityInfo { + @Trace density: number; + context: object; + + private densityCallback = (payload: IDensityInfo) => { + stateMgmtConsole.debug(`densityCallback triggered info: ${JSON.stringify(payload)}`); + this.density = payload.density; + }; + + constructor(context: object) { + this.density = 10; + this.context = context; + if (context) { + (context as typeof uiContext).getUIObserver().on('densityUpdate', this.densityCallback); + stateMgmtConsole.debug(`EnvDensityInfo register success for uiObserver.on`); + } + + // ✅ Test code: simulate density changes every 10 seconds + let testDensity = 10; //this.density; + setInterval(() => { + testDensity += 0.5; // increment density slightly + this.density = testDensity; + this.densityCallback({ density: testDensity }); + }, 10000); + + } + + get value(): IDensityInfo { + return this; + } + + // This function will be called from statemgmt framework when the component is destroyed + // used to unregister the registered env properties + destroy(): void { + if (this.context) { + (this.context as typeof uiContext).getUIObserver().off('densityUpdate', this.densityCallback); + stateMgmtConsole.debug(`EnvDensityInfo unregister success for uiObserver.off`); + } + } +} diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_decorators.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_decorators.ts index b2e6c1651046dcafe53583124e67f3ab4143893a..c5936a5d99d900eaaa017aea1a90f0b23da39fd2 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_decorators.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_decorators.ts @@ -74,6 +74,59 @@ const Local = (target: Object, propertyKey: string): void => { return trackInternal(target, propertyKey); }; +/** + * @Env @ComponentV2/ViewV2 variable decorator + * + * @Env takes a string parameter to identify the property type + * No local init or set supported from application + * Only the framework is allowed to update any value + * + * + */ +const Env = (propertyKey: string) => { + stateMgmtConsole.debug(`@Env ${propertyKey}`); + + return (target: Object, varName: string): void => { + const storeProp = ObserveV2.OB_PREFIX + varName; + const proxyProp = ObserveV2.OB_PREFIX + 'proxy_' + varName; + + Reflect.defineProperty(target, varName, { + get() { + + const cachedProxy = this[proxyProp]; + if (cachedProxy) { + return cachedProxy; + } + const value = this[storeProp]; + if (!value) { + stateMgmtConsole.warn(`@Env ${varName}: Getter called before initialization`); + return undefined; + } + stateMgmtConsole.warn(`@Env ${varName}: Getter called but no proxy cached`); + return value; + }, + set(val) { + if (this[storeProp] === undefined) { + stateMgmtConsole.debug(`@Env ${varName}: Initial set with value ${JSON.stringify(val)}`); + this[storeProp] = val; + this[proxyProp] = new Proxy(this[storeProp], { + get(target, prop) { + return ObserveV2.autoProxyObject(target, prop); + }, + set(target, prop, val) { + stateMgmtConsole.applicationError(`@Env ${varName}.${String(prop)}: Cannot set property, read-only in application.`); + return true; // Prevent setting in application code + } + }); + } else { + stateMgmtConsole.applicationError(`@Env ${varName}: Cannot assign a new value, read-only property.`); + } + }, + enumerable: true + }); + }; +}; + /** * @Param class property decorator * diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_env.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_env.ts new file mode 100644 index 0000000000000000000000000000000000000000..271c6db1fd673b0c9d3ca992e92edce78c532064 --- /dev/null +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_env.ts @@ -0,0 +1,81 @@ + +/** + * Internal System Environment Management (statemgmt framework) + * + * This file is **internal to the statemgmt framework** and is not exposed + * to application code or external repositories. + * + * Purpose: + * - Maintain a central registry of environment property instances + * - Provide a controlled mechanism for creating and registering environment values + * - Use `envFactoryMap` to ensure consistent construction of environment value objects + * + * Notes: + * - Environment definitions and factory map (`EnvTypeMap` and `envFactoryMap`) + * are expected to come from the platform environment provider layer. + * - This registry acts only as an internal store and initializer for EnvV2. + */ + + /** + * Registry type mapping each environment key to its instantiated environment value. + * Used internally to store currently active environment values. + */ +type SystemEnvRegistry = { [K in keyof EnvTypeMap]?: IEnvironmentValue }; + +/** + * EnvV2 + * + * Internal environment manager for statemgmt. + * + * Responsibilities: + * - Keep a singleton registry of all environment values used in the framework + * - Initialize environment values via the `envFactoryMap` factories + * - Allow internal code to register an environment value for a given key + * + * Function registerEnv called from ViewV2's registerEnv function + */ +class EnvV2 { + private static envValues: SystemEnvRegistry = {}; + + + /** + * Registers an environment value for the given key using the provided context. + * Creates and stores the environment instance for later retrieval or cleanup. + */ + public static registerEnv(key: K, context: object): IEnvironmentValue | undefined { + + const factory = envFactoryMap[key]; + if (!factory) { + console.warn(`Unknown environment key: ${key}`); + return undefined; + } + const envInstance = factory(context); + (EnvV2.envValues as Record | undefined>)[key] = envInstance; // Type assertion + return envInstance; + } + + /** + * Unregisters the environment value for the given key. + * Calls its destroy method if available and removes it from storage. + */ + public static unregisterEnv(key: K) { + const env = this.envValues[key] as IEnvironmentValue | undefined; + if (env) { + env.destroy(); + delete EnvV2.envValues[key]; + } + } + + /** + * Unregisters all registered environment values. + * Iterates over stored keys and delegates cleanup to unregisterEnv. + */ + public static unregisterAll(): void { + // Iterate over all keys and call unregisterEnv to reuse its logic + for (const key of Object.keys(EnvV2.envValues) as Array) { + EnvV2.unregisterEnv(key); + } + // Ensure the map is reset (already handled by unregisterEnv, but kept for clarity) + EnvV2.envValues = {}; + } +} \ No newline at end of file diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_view.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_view.ts index faf341ca4645c7b30313ec5974519bbdcf78af4f..fc73c3fbdfcaf04545e74bde81212be1c6e86ddb 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_view.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_view.ts @@ -91,6 +91,27 @@ abstract class ViewV2 extends PUV2ViewBase implements IView { } + /** + * Registers an environment value for the specified environment key. + * + * This method is invoked automatically by the **generated ETS-loader code** + * whenever an `@Env` decorator usage is detected in a `componentV2` class. + * + * Responsibilities: + * - Logs the registration attempt for debugging + * - Retrieves the current UI context for the component + * - Delegates the actual environment value creation and registration + * to the internal `EnvV2.registerEnv` method + * + * @param key - Environment property key (as defined in `EnvTypeMap`) + * @returns The created environment value instance, or `undefined` if no factory is found + */ + public registerEnv(key: K): IEnvironmentValue | undefined { + const ret = EnvV2.registerEnv(key,this.getUIContext()); + return ret; + + } + public debugInfo__(): string { return `@ComponentV2 '${this.constructor.name}'[${this.id__()}]`; } @@ -337,6 +358,9 @@ abstract class ViewV2 extends PUV2ViewBase implements IView { MonitorV2.clearWatchesFromTarget(this); ComputedV2.clearComputedFromTarget(this); + // Clears all environment properties registered by this component, if any + EnvV2.unregisterAll(); + this.updateFuncByElmtId.clear(); if (this.parent_) { this.parent_.removeChild(this); diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json index 3a6b6ce74a605f1a87f83b809d682b23d6e783a2..2ae220e7f9560e3a2a972ca7d7462adacaf2b922 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json +++ b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json @@ -94,6 +94,10 @@ "src/lib/v2/v2_computed.ts", "src/lib/v2/v2_view.ts", "src/lib/v2/v2_decorators.ts", + "src/lib/v2/v2_env.ts", + "src/lib/env_bridge/common.ts", + "src/lib/env_bridge/breakpoint.ts", + "src/lib/env_bridge/densityupdate.ts", "src/lib/v2/v2_json_coder.ts", "src/lib/v2/v2_make_observed.ts", "src/lib/v2/v2_recycle_pool.ts", @@ -123,6 +127,7 @@ ], "compilerOptions": { "module": "none", + "moduleResolution": "node", "target": "ES2016", "outDir": "./distRelease/", "outFile": "./distRelease/stateMgmt.js", diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.test.json b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.test.json index b9fdaa116cfd342b4d22b8ccd152bceed7f0612e..e58cb1caaa0f39316f617fa5adb113cdd05c6cb4 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.test.json +++ b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.test.json @@ -75,6 +75,10 @@ "src/lib/v2/v2_computed.ts", "src/lib/v2/v2_view.ts", "src/lib/v2/v2_decorators.ts", + "src/lib/v2/v2_env.ts", + "src/lib/env_bridge/common.ts", + "src/lib/env_bridge/breakpoint.ts", + "src/lib/env_bridge/densityupdate.ts", "src/lib/v2/v2_json_coder.ts", "src/lib/v2/v2_make_observed.ts", "src/lib/v2/v2_recycle_pool.ts",