Skip to content

Conversation

@CMingTseng
Copy link

upgrade gradle & agp & kotlin & compose bom & kotlin comipler Ext version

…ervices

This commit introduces a major architectural refactor of the JavaScript integration, moving from a monolithic, hardcoded approach to a dynamic, modular, and scalable system for handling GATT services.

The previous implementation tightly coupled Kotlin classes (`HrmGattValue`, `BatteryGattValue`) with specific JS files and relied on fragile data access patterns (reading global variables directly). The new architecture addresses these limitations and establishes a robust foundation for future expansion.

### Key Architectural Changes:

1.  **Dynamic & Modular JS with `gatt-core.js`:**
    *   A central `gatt-core.js` now provides a registration pattern (`registerGatt`).
    *   Individual service files (`hrm.js`, `battery.js`) are now self-contained modules that register themselves upon loading.
    *   This decouples the Android host from knowing which services exist, enabling true dynamic loading.

2.  **Centralized Clock and Scheduler:**
    *   A new `clock.js` provides a shared sense of time for all JS modules.
    *   `MainActivity` now acts as a scheduler, driving the JS world by periodically calling `Clock.tick()` and the universal `next(uuid)` function for all registered modules. This aligns with QuickJS's passive execution model and removes the need for `setInterval` from within JS.

3.  **On-Demand Script Loading:**
    *   The app now only loads core scripts (`clock.js`, `gatt-core.js`) on startup.
    *   Service-specific scripts (`hrm.js`, `battery.js`) are loaded dynamically when the user interacts with new UI buttons, demonstrating the system's extensibility.

4.  **Robust Data Fetching ("Two-Step Method"):**
    *   A critical issue was discovered where `jsContext.evaluate()` returns `null` if the target JS function's definition contains a `console.log`, regardless of whether it's executed.
    *   This was solved by implementing a robust "two-step" data fetching pattern:
        1.  **Execute:** Use `evaluate()` to run the JS function and assign its result to a temporary global variable (e.g., `__temp_result = getValue(...)`).
        2.  **Read:** Use `globalObject.getProperty("__temp_result")` to safely read the value, bypassing the `evaluate()` return value issue.

5.  **Integration of Legacy Abstractions:**
    *   The legacy `HrmGattValue` and `BatteryGattValue` classes were refactored.
    *   They no longer handle script loading and instead are initialized with a `JSContext`.
    *   Their internal logic was updated to use the new "two-step" data fetching method, proving the new JS backend can support various Kotlin-side consumer patterns.

### UI and Code Cleanup:

*   The `MainScreen` UI was updated to include buttons for on-demand script loading.
*   It now displays data fetched via two methods (direct access and through the legacy classes) for side-by-side comparison, validating the refactor.
*   Redundant engine classes (`KJsEngine`, `JsEngine.java`) were removed, simplifying the architecture to a single `QuickJsEngine`.

This new architecture is significantly more maintainable, scalable, and decoupled. Adding a new GATT service is now as simple as adding a new JS file to the assets without needing to modify any Kotlin code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant