From 7468d9d235c97f544cadd3e19ebec422a20b4216 Mon Sep 17 00:00:00 2001 From: Vidhya Pria Date: Fri, 8 Aug 2025 16:30:34 +0300 Subject: [PATCH 1/5] PoC for mocked environment V2 of densityUpdate Signed-off-by: Vidhya Pria Change-Id: I5e8caec86dba4d11b555b1165f0230dc97f4d1c6 --- .../state_mgmt/files_to_watch.gni | 2 + .../state_mgmt/src/lib/common/arkts_util.d.ts | 1 + .../state_mgmt/src/lib/v2/v2_decorators.ts | 6 + .../state_mgmt/src/lib/v2/v2_env.ts | 61 +++++ .../src/lib/v2/v2_mockenv_platform.ts | 219 ++++++++++++++++++ .../state_mgmt/src/lib/v2/v2_view.ts | 22 ++ .../state_mgmt/tsconfig.base.json | 3 + .../state_mgmt/tsconfig.test.json | 2 + 8 files changed, 316 insertions(+) create mode 100644 frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_env.ts create mode 100644 frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts 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 13d444b18a6..c552be22c7b 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,8 @@ 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/v2/v2_mockenv_platform.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 c5a14117448..40a7da0db2b 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,7 @@ */ declare interface ArkTsUtil { getHash(object: object): number; + on(type: 'densityUpdate', callback: (info: IDensityInfo) => void): void; } // Require and local module. 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 b2e6c165104..a428be5b120 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,12 @@ const Local = (target: Object, propertyKey: string): void => { return trackInternal(target, propertyKey); }; +const Env = (envKey?: string) => { + return (proto: Object, varName: string): void => { + stateMgmtConsole.error(`VPAK @Env proto: ${JSON.stringify(proto)} - aliasName: ${envKey}`); + }; +}; // @Env + /** * @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 00000000000..46afdb6c9e0 --- /dev/null +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_env.ts @@ -0,0 +1,61 @@ + +/** + * 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. + */ + + +// import { uiObserver } from "@ohos:arkui/observer" // -> Not working +// const uiObserver = globalThis.requireNapi('arkui.observer'); // -> Not working +// const uiObserver = globalThis.require('@ohos/arkui.observer'); // -> Not working + + + /** + * 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 = {}; + + 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); + (this.envValues as Record | undefined>)[key] = envInstance; // Type assertion + return envInstance; + } +} \ No newline at end of file diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts new file mode 100644 index 00000000000..6a8ac1402f7 --- /dev/null +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts @@ -0,0 +1,219 @@ +/** + * Mock Environment Property Definitions for Testing + * + * This file contains mocked interfaces, enums, and classes representing + * environment properties such as density information and breakpoints. + * In production, these definitions are expected to be provided by the + * platform (system environment provider) team and imported from their + * respective external repositories. + * + * Current purpose: + * - Enable local testing of environment property handling in `statemgmt` + * - Simulate system callbacks and property updates until real implementations are integrated + */ + + +/** + * Represents density information for the system's UI. + * Provided by: Platform Environment Provider + */ +interface IDensityInfo { + densityInfo: number; +} + +/** + * 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; +} + + +/** + * 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 SystemEnvDensityInfo(context).value, + "System.Breakpoint": (context) => new SystemEnvBreakpoint(context).value +}; + + +// common interface with value to be extended by Environment provider class +interface IEnvironmentValue { + readonly value: T; +} + + +/** + * ObservedV2 mock implementation for density info environment value. + * Maintains and updates density data from the system. + * Provided by: Platform Environment Provider (mocked here for testing) + + */ +class EnvDensityInfo implements IEnvironmentValue { + density: number; + + constructor(density: number) { + stateMgmtConsole.error(`VPAK EnvDensityInfo constructor`) + this.density = density; + } + + /** Returns the density info in the expected structure */ + get value(): IDensityInfo { + return { + densityInfo: this.density + }; + } + + /** Updates the density value from a new payload */ + update(payload: IDensityInfo) { + this.density = payload.densityInfo; + } +} + +/** + * ObservedV2 mock implementation for breakpoint environment value. + * Maintains and updates width/height breakpoints from the system. + * Provided by: Platform Environment Provider (mocked here for testing) + */ +class EnvBreakpoint implements IEnvironmentValue { + width: WidthBreakpoint; + height: HeightBreakpoint; + + constructor(breakpoint: IBreakPoint) { + this.width = breakpoint.width; + this.height = breakpoint.height; + } + + /** Returns the breakpoint in the expected structure */ + get value(): IBreakPoint { + return { + width: this.width, + height: this.height + }; + } + + /** Updates the breakpoint values from a new payload */ + update(payload: IBreakPoint) { + this.width = payload.width; + this.height = payload.height; + } +} + + +/** + * System-level environment property provider for breakpoints. + * Expected to register with the platform and receive updates. + * Provided by: Platform Environment Provider (mocked here for testing) + */ +class SystemEnvBreakpoint { + private value_: EnvBreakpoint; + + private breakpointCallback = (info: IBreakPoint) => { + this.value_.update(info); + }; + + constructor(context: object) { + this.value_ = new EnvBreakpoint({ width: WidthBreakpoint.WIDTH_MD, height: HeightBreakpoint.HEIGHT_MD }); + // TODO: Register with platform for breakpoint callbacks + } + + /** Returns the current breakpoint environment value */ + get value(): IEnvironmentValue { + return this.value_; + } +} + +/** + * System-level environment property provider for density information. + * Registers with the platform's UI observer to receive density updates. + * Provided by: Platform Environment Provider (mocked here for testing) + */ +class SystemEnvDensityInfo { + private value_: EnvDensityInfo; + // private uiObserver = require('ohos:arkui.observer'); + + private densityCallback = (info: IDensityInfo) => { + stateMgmtConsole.error(`VPAK densityCallback triggered info: ${JSON.stringify(info)}`) + this.value_.update(info); + }; + + constructor(context: object) { + this.value_ = new EnvDensityInfo(10); + try { + const uiObserver = requireInternal('arkui/observer'); + if (uiObserver && typeof uiObserver.on === 'function') { + // uiObserver.on('densityUpdate', context, this.densityCallback); + uiObserver.on('densityUpdate', this.densityCallback); + stateMgmtConsole.error(`VPAK SystemEnvDensityInfo call success for uiObserver.on`); + } else { + stateMgmtConsole.error(`VPAK SystemEnvDensityInfo: uiObserver is unavailable or invalid`); + } + } catch (error) { + stateMgmtConsole.error(`VPAK SystemEnvDensityInfo: Failed to register uiObserver: ${error}`); + } + } + + /** Returns the current density environment value */ + get value(): IEnvironmentValue { + return this.value_; + } +} 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 faf341ca464..51f5628a4bb 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,28 @@ 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 { + stateMgmtConsole.error(`VPAK registerEnv key: ${key}`) + const ret = EnvV2.registerEnv(key,this.getUIContext()); + return ret; + + } + public debugInfo__(): string { return `@ComponentV2 '${this.constructor.name}'[${this.id__()}]`; } diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json index 3a6b6ce74a6..f2a56e0dd9e 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json +++ b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json @@ -94,6 +94,8 @@ "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/v2/v2_mockenv_platform.ts", "src/lib/v2/v2_json_coder.ts", "src/lib/v2/v2_make_observed.ts", "src/lib/v2/v2_recycle_pool.ts", @@ -123,6 +125,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 b9fdaa116cf..27a56eb248a 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.test.json +++ b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.test.json @@ -75,6 +75,8 @@ "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/v2/v2_mockenv_platform.ts", "src/lib/v2/v2_json_coder.ts", "src/lib/v2/v2_make_observed.ts", "src/lib/v2/v2_recycle_pool.ts", -- Gitee From e200ad79d8f73c8c1e8b571f6d6127f889963552 Mon Sep 17 00:00:00 2001 From: Vidhya Pria Date: Mon, 11 Aug 2025 18:31:00 +0300 Subject: [PATCH 2/5] uiobserver call from framework to platform registration and unregistration working version Signed-off-by: Vidhya Pria Change-Id: Id55c5dae4d751776e63d63e647ca4b4e365b1526 --- .../state_mgmt/src/lib/common/arkts_util.d.ts | 1 + .../state_mgmt/src/lib/v2/v2_env.ts | 42 +++- .../src/lib/v2/v2_mockenv_platform.ts | 206 +++++++----------- .../state_mgmt/src/lib/v2/v2_view.ts | 3 + 4 files changed, 116 insertions(+), 136 deletions(-) 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 40a7da0db2b..0ac032a57fc 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 @@ -19,6 +19,7 @@ declare interface ArkTsUtil { getHash(object: object): number; 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/v2/v2_env.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_env.ts index 46afdb6c9e0..e24859fd274 100644 --- 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 @@ -16,21 +16,11 @@ * - This registry acts only as an internal store and initializer for EnvV2. */ - -// import { uiObserver } from "@ohos:arkui/observer" // -> Not working -// const uiObserver = globalThis.requireNapi('arkui.observer'); // -> Not working -// const uiObserver = globalThis.require('@ohos/arkui.observer'); // -> Not working - - /** * 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; -}; - - +type SystemEnvRegistry = { [K in keyof EnvTypeMap]?: IEnvironmentValue }; /** * EnvV2 @@ -47,6 +37,11 @@ type SystemEnvRegistry = { 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]; @@ -58,4 +53,29 @@ class EnvV2 { (this.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 this.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(this.envValues) as Array) { + this.unregisterEnv(key); + } + // Ensure the map is reset (already handled by unregisterEnv, but kept for clarity) + this.envValues = {}; + } } \ No newline at end of file diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts index 6a8ac1402f7..1bf789099d5 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts @@ -13,47 +13,8 @@ */ -/** - * Represents density information for the system's UI. - * Provided by: Platform Environment Provider - */ -interface IDensityInfo { - densityInfo: number; -} - -/** - * 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; -} +const uiObserver = requireInternal('arkui.observer'); /** * Maps environment property keys to their corresponding value types. @@ -91,129 +52,124 @@ interface EnvTypeMap { const envFactoryMap: { [K in keyof EnvTypeMap]: (context: object) => IEnvironmentValue; } = { - "System.DensityInfo": (context) => new SystemEnvDensityInfo(context).value, - "System.Breakpoint": (context) => new SystemEnvBreakpoint(context).value + "System.DensityInfo": (context) => new EnvDensityInfo(context), + "System.Breakpoint": (context) => new EnvBreakpoint(context) }; -// common interface with value to be extended by Environment provider class interface IEnvironmentValue { readonly value: T; + destroy(): void; + } +// Interface for DensityInfo +// To be provided by the env provider of densityInfo property +interface IDensityInfo { + densityInfo: number; +} /** - * ObservedV2 mock implementation for density info environment value. - * Maintains and updates density data from the system. - * Provided by: Platform Environment Provider (mocked here for testing) + * 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 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 { - density: number; + @Trace density: number; + private densityCallback = (info: IDensityInfo) => { + stateMgmtConsole.error(`VPAK densityCallback triggered info: ${JSON.stringify(info)}`); + this.update(info); + }; - constructor(density: number) { - stateMgmtConsole.error(`VPAK EnvDensityInfo constructor`) - this.density = density; + constructor(context: object) { + this.density = 10; + if (uiObserver && typeof uiObserver.on === 'function') { + uiObserver.on('densityUpdate', this.densityCallback); + stateMgmtConsole.error(`VPAK EnvDensityInfo register success for uiObserver.on`); + } } - /** Returns the density info in the expected structure */ get value(): IDensityInfo { - return { - densityInfo: this.density - }; + return { densityInfo: this.density }; } - /** Updates the density value from a new payload */ update(payload: IDensityInfo) { this.density = payload.densityInfo; } + + // This function will be called from statemgmt framework when the component is destroyed + // used to unregister the registered env properties + destroy(): void { + if (uiObserver && typeof uiObserver.off === 'function') { + uiObserver.off('densityUpdate', this.densityCallback); + stateMgmtConsole.error(`VPAK EnvDensityInfo unregister success for uiObserver.off`); + } + } } /** * ObservedV2 mock implementation for breakpoint environment value. * Maintains and updates width/height breakpoints from the system. - * Provided by: Platform Environment Provider (mocked here for testing) + * Implements IEnvironmentValue to provide density data + * To be Provided by: Platform Environment Provider */ +@ObservedV2 class EnvBreakpoint implements IEnvironmentValue { - width: WidthBreakpoint; - height: HeightBreakpoint; + @Trace width: WidthBreakpoint; + @Trace height: HeightBreakpoint; - constructor(breakpoint: IBreakPoint) { - this.width = breakpoint.width; - this.height = breakpoint.height; + constructor(context: object) { + this.width = WidthBreakpoint.WIDTH_MD; + this.height = HeightBreakpoint.HEIGHT_MD; } - /** Returns the breakpoint in the expected structure */ get value(): IBreakPoint { - return { - width: this.width, - height: this.height - }; + return { width: this.width, height: this.height }; } - /** Updates the breakpoint values from a new payload */ update(payload: IBreakPoint) { this.width = payload.width; this.height = payload.height; } -} - - -/** - * System-level environment property provider for breakpoints. - * Expected to register with the platform and receive updates. - * Provided by: Platform Environment Provider (mocked here for testing) - */ -class SystemEnvBreakpoint { - private value_: EnvBreakpoint; - - private breakpointCallback = (info: IBreakPoint) => { - this.value_.update(info); - }; - - constructor(context: object) { - this.value_ = new EnvBreakpoint({ width: WidthBreakpoint.WIDTH_MD, height: HeightBreakpoint.HEIGHT_MD }); - // TODO: Register with platform for breakpoint callbacks - } - - /** Returns the current breakpoint environment value */ - get value(): IEnvironmentValue { - return this.value_; - } -} - -/** - * System-level environment property provider for density information. - * Registers with the platform's UI observer to receive density updates. - * Provided by: Platform Environment Provider (mocked here for testing) - */ -class SystemEnvDensityInfo { - private value_: EnvDensityInfo; - // private uiObserver = require('ohos:arkui.observer'); - - private densityCallback = (info: IDensityInfo) => { - stateMgmtConsole.error(`VPAK densityCallback triggered info: ${JSON.stringify(info)}`) - this.value_.update(info); - }; - - constructor(context: object) { - this.value_ = new EnvDensityInfo(10); - try { - const uiObserver = requireInternal('arkui/observer'); - if (uiObserver && typeof uiObserver.on === 'function') { - // uiObserver.on('densityUpdate', context, this.densityCallback); - uiObserver.on('densityUpdate', this.densityCallback); - stateMgmtConsole.error(`VPAK SystemEnvDensityInfo call success for uiObserver.on`); - } else { - stateMgmtConsole.error(`VPAK SystemEnvDensityInfo: uiObserver is unavailable or invalid`); - } - } catch (error) { - stateMgmtConsole.error(`VPAK SystemEnvDensityInfo: Failed to register uiObserver: ${error}`); - } - } - /** Returns the current density environment value */ - get value(): IEnvironmentValue { - return this.value_; + // 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/v2/v2_view.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_view.ts index 51f5628a4bb..410486d34d3 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 @@ -359,6 +359,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); -- Gitee From 8100bc243b81dee1077821dedcfd81fd0af98fee Mon Sep 17 00:00:00 2001 From: Vidhya Pria Date: Mon, 18 Aug 2025 16:50:55 +0300 Subject: [PATCH 3/5] Sync the platform update value back to the application Signed-off-by: Vidhya Pria Change-Id: I06a0748da86247428501a33fa400ba129b7076f4 --- .../state_mgmt/src/lib/common/arkts_util.d.ts | 1 + .../state_mgmt/src/lib/v2/v2_env.ts | 10 +++--- .../src/lib/v2/v2_mockenv_platform.ts | 32 +++++++++++++------ 3 files changed, 29 insertions(+), 14 deletions(-) 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 0ac032a57fc..1055e27599b 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,7 @@ */ 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; } 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 index e24859fd274..271c6db1fd6 100644 --- 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 @@ -50,7 +50,7 @@ class EnvV2 { return undefined; } const envInstance = factory(context); - (this.envValues as Record | undefined>)[key] = envInstance; // Type assertion + (EnvV2.envValues as Record | undefined>)[key] = envInstance; // Type assertion return envInstance; } @@ -62,7 +62,7 @@ class EnvV2 { const env = this.envValues[key] as IEnvironmentValue | undefined; if (env) { env.destroy(); - delete this.envValues[key]; + delete EnvV2.envValues[key]; } } @@ -72,10 +72,10 @@ class EnvV2 { */ public static unregisterAll(): void { // Iterate over all keys and call unregisterEnv to reuse its logic - for (const key of Object.keys(this.envValues) as Array) { - this.unregisterEnv(key); + 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) - this.envValues = {}; + EnvV2.envValues = {}; } } \ No newline at end of file diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts index 1bf789099d5..2da52bb7d93 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts @@ -15,6 +15,7 @@ const uiObserver = requireInternal('arkui.observer'); +const uiContext = requireInternal('arkui.uicontext'); /** * Maps environment property keys to their corresponding value types. @@ -66,7 +67,7 @@ interface IEnvironmentValue { // Interface for DensityInfo // To be provided by the env provider of densityInfo property interface IDensityInfo { - densityInfo: number; + density: number; } /** @@ -109,9 +110,11 @@ interface IBreakPoint { * Implements IEnvironmentValue to provide density data * To be Provided by: Platform Environment provider team */ -@ObservedV2 -class EnvDensityInfo implements IEnvironmentValue { + @ObservedV2 +class EnvDensityInfo implements IEnvironmentValue, IDensityInfo { @Trace density: number; + context: object; + private densityCallback = (info: IDensityInfo) => { stateMgmtConsole.error(`VPAK densityCallback triggered info: ${JSON.stringify(info)}`); this.update(info); @@ -119,25 +122,36 @@ class EnvDensityInfo implements IEnvironmentValue { constructor(context: object) { this.density = 10; - if (uiObserver && typeof uiObserver.on === 'function') { - uiObserver.on('densityUpdate', this.densityCallback); + this.context = context; + if (context) { + (context as typeof uiContext).getUIObserver().on('densityUpdate', this.densityCallback); stateMgmtConsole.error(`VPAK 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 { densityInfo: this.density }; + // return { density: this.density }; + return this; } update(payload: IDensityInfo) { - this.density = payload.densityInfo; + this.density = payload.density; } // This function will be called from statemgmt framework when the component is destroyed // used to unregister the registered env properties destroy(): void { - if (uiObserver && typeof uiObserver.off === 'function') { - uiObserver.off('densityUpdate', this.densityCallback); + if (this.context) { + (this.context as typeof uiContext).getUIObserver().off('densityUpdate', this.densityCallback); stateMgmtConsole.error(`VPAK EnvDensityInfo unregister success for uiObserver.off`); } } -- Gitee From d8a2d39bfbd175ca654015992b1f1be2bcdab4f7 Mon Sep 17 00:00:00 2001 From: Vidhya Pria Date: Tue, 19 Aug 2025 16:20:46 +0300 Subject: [PATCH 4/5] Support app updates from env property changes and restrict direct app assignment Signed-off-by: Vidhya Pria Change-Id: I367eaebb7b3bbb8439db38692ee86aaa6a357779 --- .../state_mgmt/files_to_watch.gni | 4 +- .../src/lib/env_bridge/breakpoint.ts | 78 ++++++++++ .../state_mgmt/src/lib/env_bridge/common.ts | 64 ++++++++ .../densityupdate.ts} | 141 ++---------------- .../state_mgmt/src/lib/v2/v2_decorators.ts | 55 ++++++- .../state_mgmt/src/lib/v2/v2_view.ts | 1 - .../state_mgmt/tsconfig.base.json | 4 +- .../state_mgmt/tsconfig.test.json | 4 +- 8 files changed, 211 insertions(+), 140 deletions(-) create mode 100644 frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/breakpoint.ts create mode 100644 frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/common.ts rename frameworks/bridge/declarative_frontend/state_mgmt/src/lib/{v2/v2_mockenv_platform.ts => env_bridge/densityupdate.ts} (31%) 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 c552be22c7b..fad31a154fb 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/files_to_watch.gni +++ b/frameworks/bridge/declarative_frontend/state_mgmt/files_to_watch.gni @@ -91,7 +91,9 @@ state_mgmt_release_files_to_watch = [ "//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/v2/v2_mockenv_platform.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/env_bridge/breakpoint.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/breakpoint.ts new file mode 100644 index 00000000000..b65d8d0e333 --- /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 00000000000..187473a6c9d --- /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/v2/v2_mockenv_platform.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/densityupdate.ts similarity index 31% rename from frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts rename to frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/densityupdate.ts index 2da52bb7d93..5bf41a775dd 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_mockenv_platform.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/env_bridge/densityupdate.ts @@ -1,68 +1,15 @@ /** - * Mock Environment Property Definitions for Testing + * Environment Property Definitions for Density update * - * This file contains mocked interfaces, enums, and classes representing - * environment properties such as density information and breakpoints. + * 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. * - * Current purpose: - * - Enable local testing of environment property handling in `statemgmt` - * - Simulate system callbacks and property updates until real implementations are integrated */ - - - + const uiObserver = requireInternal('arkui.observer'); -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; - -} // Interface for DensityInfo // To be provided by the env provider of densityInfo property @@ -70,40 +17,6 @@ interface IDensityInfo { density: number; } -/** - * 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 density information environment value. * Maintains and updates system density data, handling observer registration and cleanup. @@ -115,9 +28,9 @@ class EnvDensityInfo implements IEnvironmentValue, IDensityInfo { @Trace density: number; context: object; - private densityCallback = (info: IDensityInfo) => { - stateMgmtConsole.error(`VPAK densityCallback triggered info: ${JSON.stringify(info)}`); - this.update(info); + private densityCallback = (payload: IDensityInfo) => { + stateMgmtConsole.debug(`densityCallback triggered info: ${JSON.stringify(payload)}`); + this.density = payload.density; }; constructor(context: object) { @@ -125,7 +38,7 @@ class EnvDensityInfo implements IEnvironmentValue, IDensityInfo { this.context = context; if (context) { (context as typeof uiContext).getUIObserver().on('densityUpdate', this.densityCallback); - stateMgmtConsole.error(`VPAK EnvDensityInfo register success for uiObserver.on`); + stateMgmtConsole.debug(`EnvDensityInfo register success for uiObserver.on`); } // ✅ Test code: simulate density changes every 10 seconds @@ -139,51 +52,15 @@ class EnvDensityInfo implements IEnvironmentValue, IDensityInfo { } get value(): IDensityInfo { - // return { density: this.density }; return this; } - update(payload: IDensityInfo) { - this.density = payload.density; - } - // 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.error(`VPAK EnvDensityInfo unregister success for uiObserver.off`); + stateMgmtConsole.debug(`EnvDensityInfo unregister success for uiObserver.off`); } } } - -/** - * ObservedV2 mock 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 { - @Trace width: WidthBreakpoint; - @Trace height: HeightBreakpoint; - - constructor(context: object) { - this.width = WidthBreakpoint.WIDTH_MD; - this.height = HeightBreakpoint.HEIGHT_MD; - } - - 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/v2/v2_decorators.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/v2/v2_decorators.ts index a428be5b120..c5936a5d99d 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,11 +74,58 @@ const Local = (target: Object, propertyKey: string): void => { return trackInternal(target, propertyKey); }; -const Env = (envKey?: string) => { - return (proto: Object, varName: string): void => { - stateMgmtConsole.error(`VPAK @Env proto: ${JSON.stringify(proto)} - aliasName: ${envKey}`); +/** + * @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 + }); }; -}; // @Env +}; /** * @Param class property decorator 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 410486d34d3..fc73c3fbdfc 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 @@ -107,7 +107,6 @@ abstract class ViewV2 extends PUV2ViewBase implements IView { * @returns The created environment value instance, or `undefined` if no factory is found */ public registerEnv(key: K): IEnvironmentValue | undefined { - stateMgmtConsole.error(`VPAK registerEnv key: ${key}`) const ret = EnvV2.registerEnv(key,this.getUIContext()); return ret; diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json index f2a56e0dd9e..2ae220e7f95 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json +++ b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.base.json @@ -95,7 +95,9 @@ "src/lib/v2/v2_view.ts", "src/lib/v2/v2_decorators.ts", "src/lib/v2/v2_env.ts", - "src/lib/v2/v2_mockenv_platform.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", diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.test.json b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.test.json index 27a56eb248a..e58cb1caaa0 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.test.json +++ b/frameworks/bridge/declarative_frontend/state_mgmt/tsconfig.test.json @@ -76,7 +76,9 @@ "src/lib/v2/v2_view.ts", "src/lib/v2/v2_decorators.ts", "src/lib/v2/v2_env.ts", - "src/lib/v2/v2_mockenv_platform.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", -- Gitee From 3c9aa5c8c59e2e0b35a1d47b0bd8cff546470772 Mon Sep 17 00:00:00 2001 From: Vidhya Pria Date: Fri, 22 Aug 2025 13:43:34 +0300 Subject: [PATCH 5/5] Custom Env properties implemented Signed-off-by: Vidhya Pria Change-Id: I2e77eee5cf6ec86d1e638078fc4136ac7b726940 --- .../src/lib/env_bridge/densityupdate.ts | 8 ----- .../state_mgmt/src/lib/puv2_common/iview.ts | 1 + .../src/lib/puv2_common/puv2_view_base.ts | 31 +++++++++++++++++++ .../state_mgmt/src/lib/v2/v2_decorators.ts | 25 +++++++++------ .../state_mgmt/src/lib/v2/v2_view.ts | 17 +++++++++- 5 files changed, 64 insertions(+), 18 deletions(-) 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 index 5bf41a775dd..69a2e25215c 100644 --- 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 @@ -40,14 +40,6 @@ class EnvDensityInfo implements IEnvironmentValue, IDensityInfo { (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); } diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/iview.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/iview.ts index 69dfe6a5e7b..c588505f134 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/iview.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/iview.ts @@ -29,6 +29,7 @@ interface IView { getCardId(): number; // implemented in NativeViewPartialUpdate getParent(): IView | undefined; + getCustomEnvInternal__(key:string): any; setParent(p: IView) : void; setParentBuilderNode__(node: ViewBuildNodeBase): void; addChild(c: IView): boolean; diff --git a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_base.ts b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_base.ts index e9be8d1e0b8..fa360ae4b46 100644 --- a/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_base.ts +++ b/frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_base.ts @@ -231,6 +231,37 @@ abstract class PUV2ViewBase extends ViewBuildNodeBase { this.id_ = elmtId; } + /** + * Retrieves the value of a custom environment property by key. + * + * Lookup order: + * 1. Checks if the current component has the property. + * 2. If not found, recursively checks parent components. + * 3. If no matching property is found in the hierarchy, an error is thrown. + * + * @param {string} key - The name of the custom environment property to retrieve. + * @returns {any} The value of the custom environment property. + * @throws {Error} If the property is not found in the component or its ancestors. + */ + getCustomEnvInternal__(key: string): any { + stateMgmtConsole.debug(`${this.debugInfo__()} getCustomEnvInternal__ key: ${key}, `); + // 1. Check if current component has the key + if (this[key] !== undefined) { + return this[key]; + } + + // 2. If not, ask the parent recursively + if (this.parent_) { + return this.parent_.getCustomEnvInternal__(key); + } + + // 3. If no parent, throw exception + throw new Error(`custom env property returns: undefined`); + + return undefined; + } + + /* Adds the elmtId to elmtIdsDelayedUpdate for delayed update once the view gets active */ 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 c5936a5d99d..40fb0341085 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 @@ -109,15 +109,22 @@ const Env = (propertyKey: string) => { 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 - } - }); + + if (val && typeof val === 'object') { + + 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 { + // Primitives don’t need a Proxy — just return the raw value + this[proxyProp] = this[storeProp]; + } } else { stateMgmtConsole.applicationError(`@Env ${varName}: Cannot assign a new value, read-only property.`); } 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 fc73c3fbdfc..ada8c7a7c75 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 @@ -68,6 +68,21 @@ abstract class ViewV2 extends PUV2ViewBase implements IView { stateMgmtConsole.debug(`ViewV2 constructor: Creating @Component '${this.constructor.name}' from parent '${parent?.constructor.name}'`); } + /** + * Sets the value of a custom environment property on the current component + * + * This updates the property locally on the component and does not propagate + * changes to parent or child components. + * + * @param {string} key - The name of the custom environment property to set. + * @param {any} value - The value to assign to the custom environment property. + * @returns {void} + */ + public setCustomEnvInternal__(key: string, value: any): void { + stateMgmtConsole.debug(`setCustomEnv: key: ${key}, value: ${value}`); + this[key] = value; + } + /** * The `freezeState` parameter determines whether this @ComponentV2 is allowed to freeze, when inactive * Its called with value of the `freezeWhenInactive` parameter from the @ComponentV2 decorator, @@ -106,7 +121,7 @@ abstract class ViewV2 extends PUV2ViewBase implements IView { * @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 { + public registerEnvInternal__(key: K): IEnvironmentValue | undefined { const ret = EnvV2.registerEnv(key,this.getUIContext()); return ret; -- Gitee