voltra 1.2.0 → 1.3.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -7
- package/android/build.gradle +33 -0
- package/android/src/main/java/voltra/VoltraModule.kt +44 -0
- package/android/src/main/java/voltra/VoltraRN.kt +41 -32
- package/android/src/main/java/voltra/generated/ShortNames.kt +7 -0
- package/android/src/main/java/voltra/glance/renderers/ChartBitmapRenderer.kt +827 -0
- package/android/src/main/java/voltra/glance/renderers/ChartRenderers.kt +155 -0
- package/android/src/main/java/voltra/glance/renderers/RenderCommon.kt +5 -2
- package/android/src/main/java/voltra/glance/renderers/TextAndImageRenderers.kt +51 -6
- package/android/src/main/java/voltra/glance/renderers/TextBitmapRenderer.kt +134 -0
- package/android/src/main/java/voltra/models/parameters/AndroidChartParameters.kt +30 -0
- package/android/src/main/java/voltra/payload/ComponentTypeID.kt +2 -0
- package/android/src/main/java/voltra/styling/StyleConverter.kt +6 -0
- package/android/src/main/java/voltra/styling/StyleModifiers.kt +23 -0
- package/android/src/main/java/voltra/styling/StyleStructures.kt +1 -0
- package/android/src/main/java/voltra/widget/VoltraCryptoManager.kt +99 -0
- package/android/src/main/java/voltra/widget/VoltraWidgetCredentialStore.kt +174 -0
- package/android/src/main/java/voltra/widget/VoltraWidgetManager.kt +32 -5
- package/android/src/main/java/voltra/widget/VoltraWidgetUpdateScheduler.kt +233 -0
- package/android/src/main/java/voltra/widget/VoltraWidgetUpdateWorker.kt +189 -0
- package/build/VoltraModule.d.ts +15 -1
- package/build/VoltraModule.d.ts.map +1 -1
- package/build/VoltraModule.js.map +1 -1
- package/build/android/client.d.ts +1 -0
- package/build/android/client.d.ts.map +1 -1
- package/build/android/client.js +2 -0
- package/build/android/client.js.map +1 -1
- package/build/android/jsx/AreaMark.d.ts +14 -0
- package/build/android/jsx/AreaMark.d.ts.map +1 -0
- package/build/android/jsx/AreaMark.js +6 -0
- package/build/android/jsx/AreaMark.js.map +1 -0
- package/build/android/jsx/BarMark.d.ts +16 -0
- package/build/android/jsx/BarMark.d.ts.map +1 -0
- package/build/android/jsx/BarMark.js +7 -0
- package/build/android/jsx/BarMark.js.map +1 -0
- package/build/android/jsx/Chart.d.ts +16 -0
- package/build/android/jsx/Chart.d.ts.map +1 -0
- package/build/android/jsx/Chart.js +110 -0
- package/build/android/jsx/Chart.js.map +1 -0
- package/build/android/jsx/LineMark.d.ts +15 -0
- package/build/android/jsx/LineMark.d.ts.map +1 -0
- package/build/android/jsx/LineMark.js +6 -0
- package/build/android/jsx/LineMark.js.map +1 -0
- package/build/android/jsx/PointMark.d.ts +14 -0
- package/build/android/jsx/PointMark.d.ts.map +1 -0
- package/build/android/jsx/PointMark.js +6 -0
- package/build/android/jsx/PointMark.js.map +1 -0
- package/build/android/jsx/RuleMark.d.ts +13 -0
- package/build/android/jsx/RuleMark.d.ts.map +1 -0
- package/build/android/jsx/RuleMark.js +6 -0
- package/build/android/jsx/RuleMark.js.map +1 -0
- package/build/android/jsx/SectorMark.d.ts +15 -0
- package/build/android/jsx/SectorMark.d.ts.map +1 -0
- package/build/android/jsx/SectorMark.js +6 -0
- package/build/android/jsx/SectorMark.js.map +1 -0
- package/build/android/jsx/chart-types.d.ts +2 -0
- package/build/android/jsx/chart-types.d.ts.map +1 -0
- package/build/android/jsx/chart-types.js +2 -0
- package/build/android/jsx/chart-types.js.map +1 -0
- package/build/android/jsx/primitives.d.ts +8 -0
- package/build/android/jsx/primitives.d.ts.map +1 -1
- package/build/android/jsx/primitives.js +8 -0
- package/build/android/jsx/primitives.js.map +1 -1
- package/build/android/jsx/props/Text.d.ts +6 -0
- package/build/android/jsx/props/Text.d.ts.map +1 -1
- package/build/android/jsx/props/Text.js.map +1 -1
- package/build/android/payload/component-ids.d.ts.map +1 -1
- package/build/android/payload/component-ids.js +2 -1
- package/build/android/payload/component-ids.js.map +1 -1
- package/build/android/styles/types.d.ts +2 -0
- package/build/android/styles/types.d.ts.map +1 -1
- package/build/android/styles/types.js.map +1 -1
- package/build/android/widgets/server-credentials.d.ts +18 -0
- package/build/android/widgets/server-credentials.d.ts.map +1 -0
- package/build/android/widgets/server-credentials.js +24 -0
- package/build/android/widgets/server-credentials.js.map +1 -0
- package/build/client.d.ts +1 -0
- package/build/client.d.ts.map +1 -1
- package/build/client.js +2 -0
- package/build/client.js.map +1 -1
- package/build/jsx/AreaMark.d.ts +13 -0
- package/build/jsx/AreaMark.d.ts.map +1 -0
- package/build/jsx/AreaMark.js +6 -0
- package/build/jsx/AreaMark.js.map +1 -0
- package/build/jsx/BarMark.d.ts +15 -0
- package/build/jsx/BarMark.d.ts.map +1 -0
- package/build/jsx/BarMark.js +6 -0
- package/build/jsx/BarMark.js.map +1 -0
- package/build/jsx/Chart.d.ts +20 -0
- package/build/jsx/Chart.d.ts.map +1 -0
- package/build/jsx/Chart.js +124 -0
- package/build/jsx/Chart.js.map +1 -0
- package/build/jsx/LineMark.d.ts +15 -0
- package/build/jsx/LineMark.d.ts.map +1 -0
- package/build/jsx/LineMark.js +6 -0
- package/build/jsx/LineMark.js.map +1 -0
- package/build/jsx/PointMark.d.ts +14 -0
- package/build/jsx/PointMark.d.ts.map +1 -0
- package/build/jsx/PointMark.js +6 -0
- package/build/jsx/PointMark.js.map +1 -0
- package/build/jsx/RuleMark.d.ts +13 -0
- package/build/jsx/RuleMark.d.ts.map +1 -0
- package/build/jsx/RuleMark.js +6 -0
- package/build/jsx/RuleMark.js.map +1 -0
- package/build/jsx/SectorMark.d.ts +15 -0
- package/build/jsx/SectorMark.d.ts.map +1 -0
- package/build/jsx/SectorMark.js +6 -0
- package/build/jsx/SectorMark.js.map +1 -0
- package/build/jsx/chart-types.d.ts +10 -0
- package/build/jsx/chart-types.d.ts.map +1 -0
- package/build/jsx/chart-types.js +2 -0
- package/build/jsx/chart-types.js.map +1 -0
- package/build/jsx/primitives.d.ts +8 -0
- package/build/jsx/primitives.d.ts.map +1 -1
- package/build/jsx/primitives.js +8 -0
- package/build/jsx/primitives.js.map +1 -1
- package/build/jsx/props/AndroidChart.d.ts +16 -0
- package/build/jsx/props/AndroidChart.d.ts.map +1 -0
- package/build/jsx/props/AndroidChart.js +5 -0
- package/build/jsx/props/AndroidChart.js.map +1 -0
- package/build/jsx/props/Chart.d.ts +18 -0
- package/build/jsx/props/Chart.d.ts.map +1 -0
- package/build/jsx/props/Chart.js +5 -0
- package/build/jsx/props/Chart.js.map +1 -0
- package/build/live-activity/api.d.ts +10 -0
- package/build/live-activity/api.d.ts.map +1 -1
- package/build/live-activity/api.js +1 -0
- package/build/live-activity/api.js.map +1 -1
- package/build/package.json +1 -0
- package/build/payload/component-ids.d.ts.map +1 -1
- package/build/payload/component-ids.js +2 -1
- package/build/payload/component-ids.js.map +1 -1
- package/build/payload/short-names.d.ts.map +1 -1
- package/build/payload/short-names.js +14 -1
- package/build/payload/short-names.js.map +1 -1
- package/build/renderer/dispatcher.d.ts +22 -15
- package/build/renderer/dispatcher.d.ts.map +1 -1
- package/build/renderer/dispatcher.js +27 -0
- package/build/renderer/dispatcher.js.map +1 -1
- package/build/server.d.ts +1 -0
- package/build/server.d.ts.map +1 -1
- package/build/server.js +2 -0
- package/build/server.js.map +1 -1
- package/build/types.d.ts +16 -0
- package/build/types.d.ts.map +1 -1
- package/build/types.js.map +1 -1
- package/build/widget-server.d.ts +103 -0
- package/build/widget-server.d.ts.map +1 -0
- package/build/widget-server.js +170 -0
- package/build/widget-server.js.map +1 -0
- package/build/widgets/server-credentials.d.ts +49 -0
- package/build/widgets/server-credentials.d.ts.map +1 -0
- package/build/widgets/server-credentials.js +55 -0
- package/build/widgets/server-credentials.js.map +1 -0
- package/ios/app/VoltraImagePreload.swift +166 -0
- package/ios/app/VoltraLiveActivityManager.swift +228 -0
- package/ios/app/VoltraLiveActivityService.swift +24 -79
- package/ios/app/VoltraModule.swift +16 -1
- package/ios/app/VoltraModuleImpl.swift +81 -275
- package/ios/app/VoltraOptions.swift +4 -53
- package/ios/app/VoltraRN.swift +2 -1
- package/ios/app/VoltraWidgetService.swift +154 -0
- package/ios/shared/ComponentTypeID.swift +4 -0
- package/ios/shared/ShortNames.swift +7 -0
- package/ios/shared/VoltraConfig.swift +8 -2
- package/ios/shared/VoltraConstants.swift +44 -0
- package/ios/shared/VoltraEvent.swift +1 -1
- package/ios/shared/VoltraEventBus.swift +2 -1
- package/ios/shared/VoltraInteractionIntent.swift +2 -2
- package/ios/shared/VoltraKeychainHelper.swift +178 -0
- package/ios/shared/VoltraLogger.swift +30 -0
- package/ios/shared/VoltraNode.swift +7 -0
- package/ios/shared/VoltraPersistentEventQueue.swift +7 -6
- package/ios/shared/VoltraWidgetDefaults.swift +114 -0
- package/ios/shared/VoltraWidgetServerFetcher.swift +157 -0
- package/ios/target/VoltraHomeWidget.swift +68 -33
- package/ios/ui/Generated/Parameters/ChartParameters.swift +33 -0
- package/ios/ui/Layout/VoltraFlexStackLayout.swift +23 -6
- package/ios/ui/Protocols/VoltraView.swift +3 -1
- package/ios/ui/Style/BackgroundValue.swift +27 -0
- package/ios/ui/Style/DecorationStyle.swift +107 -3
- package/ios/ui/Style/JSColorParser.swift +230 -33
- package/ios/ui/Style/JSGradientParser.swift +674 -0
- package/ios/ui/Style/JSStyleParser.swift +16 -4
- package/ios/ui/Style/LayoutStyle.swift +7 -7
- package/ios/ui/Style/StyleConverter.swift +1 -1
- package/ios/ui/Views/VoltraChart.swift +810 -0
- package/ios/ui/Views/VoltraGauge.swift +0 -1
- package/ios/ui/Views/VoltraGroupBox.swift +0 -1
- package/ios/ui/Views/VoltraLinearGradient.swift +2 -2
- package/ios/ui/Views/VoltraTimer.swift +10 -11
- package/package.json +14 -6
- package/plugin/build/android/files/fonts.d.ts +18 -0
- package/plugin/build/android/files/fonts.js +97 -0
- package/plugin/build/android/files/index.d.ts +1 -0
- package/plugin/build/android/files/index.js +10 -1
- package/plugin/build/android/files/kotlin.js +52 -2
- package/plugin/build/android/index.js +2 -2
- package/plugin/build/index.d.ts +1 -1
- package/plugin/build/index.js +8 -0
- package/plugin/build/ios/entitlements.d.ts +5 -3
- package/plugin/build/ios/entitlements.js +26 -6
- package/plugin/build/ios/index.d.ts +3 -0
- package/plugin/build/ios/index.js +4 -0
- package/plugin/build/ios/infoPlist.d.ts +6 -0
- package/plugin/build/ios/infoPlist.js +22 -0
- package/plugin/build/ios-widget/files/entitlements.d.ts +2 -1
- package/plugin/build/ios-widget/files/entitlements.js +11 -3
- package/plugin/build/ios-widget/files/index.d.ts +1 -0
- package/plugin/build/ios-widget/files/index.js +3 -2
- package/plugin/build/ios-widget/index.d.ts +1 -0
- package/plugin/build/ios-widget/index.js +3 -3
- package/plugin/build/ios-widget/widgetPlist.d.ts +5 -0
- package/plugin/build/ios-widget/widgetPlist.js +24 -1
- package/plugin/build/ios-widget/xcode/buildPhases.js +0 -1
- package/plugin/build/ios-widget/xcode/groups.js +0 -1
- package/plugin/build/types.d.ts +57 -0
- package/skills/voltra/SKILL.md +75 -0
- package/skills/voltra/references/android-widgets.md +35 -0
- package/skills/voltra/references/app-config.md +29 -0
- package/skills/voltra/references/charts.md +66 -0
- package/skills/voltra/references/component-mapping.md +31 -0
- package/skills/voltra/references/images.md +50 -0
- package/skills/voltra/references/ios-live-activities.md +27 -0
- package/skills/voltra/references/ios-server-updates.md +27 -0
- package/skills/voltra/references/ios-widgets.md +32 -0
- package/skills/voltra/references/plugin-schema.md +68 -0
- package/skills/voltra/references/push-flow.md +27 -0
- package/skills/voltra/references/runtime-api-checklist.md +23 -0
- package/skills/voltra/references/server-driven-widgets.md +45 -0
- package/skills/voltra/references/setup.md +23 -0
- package/skills/voltra/references/source-of-truth.md +32 -0
- package/skills/voltra/references/variant-shapes.md +43 -0
- package/skills/voltra/references/widget-families.md +29 -0
- package/turbo.json +25 -0
package/README.md
CHANGED
|
@@ -24,14 +24,18 @@ Voltra turns React Native JSX into SwiftUI and Jetpack Compose Glance so you can
|
|
|
24
24
|
|
|
25
25
|
The documentation is available at [use-voltra.dev](https://use-voltra.dev). You can also use the following links to jump to specific topics:
|
|
26
26
|
|
|
27
|
-
- [
|
|
28
|
-
- [
|
|
29
|
-
- [
|
|
30
|
-
- [
|
|
27
|
+
- [Getting Started](https://use-voltra.dev/getting-started/introduction)
|
|
28
|
+
- [Installation](https://use-voltra.dev/getting-started/installation)
|
|
29
|
+
- [iOS Setup](https://use-voltra.dev/ios/setup)
|
|
30
|
+
- [Android Setup](https://use-voltra.dev/android/setup)
|
|
31
|
+
- [iOS Development](https://use-voltra.dev/ios/development/developing-live-activities)
|
|
32
|
+
- [Android Development](https://use-voltra.dev/android/development/developing-widgets)
|
|
33
|
+
- [iOS API Reference](https://use-voltra.dev/ios/api/configuration)
|
|
34
|
+
- [Android API Reference](https://use-voltra.dev/android/api/plugin-configuration)
|
|
31
35
|
|
|
32
36
|
## Getting started
|
|
33
37
|
|
|
34
|
-
> [!NOTE]
|
|
38
|
+
> [!NOTE]
|
|
35
39
|
> The library isn't supported in Expo Go. To set it up correctly, you need to use [Expo Dev Client](https://docs.expo.dev/versions/latest/sdk/dev-client/).
|
|
36
40
|
|
|
37
41
|
Install the package:
|
|
@@ -52,7 +56,7 @@ Add the config plugin to your `app.json`:
|
|
|
52
56
|
|
|
53
57
|
Then run `npx expo prebuild --clean` to generate the native extension targets.
|
|
54
58
|
|
|
55
|
-
See the [documentation](https://use-voltra.dev/getting-started/
|
|
59
|
+
See the [documentation](https://use-voltra.dev/getting-started/installation) for detailed setup instructions.
|
|
56
60
|
|
|
57
61
|
## Quick example
|
|
58
62
|
|
|
@@ -90,7 +94,7 @@ Voltra is a cross-platform library that supports:
|
|
|
90
94
|
|
|
91
95
|
## Authors
|
|
92
96
|
|
|
93
|
-
`voltra` is an open source collaboration between [Saúl Sharma](https://github.com/
|
|
97
|
+
`voltra` is an open source collaboration between [Saúl Sharma](https://github.com/saulsharma) and [Szymon Chmal](https://github.com/szymonchmal) at [Callstack][callstack-readme-with-love].
|
|
94
98
|
|
|
95
99
|
If you think it's cool, please star it 🌟. This project will always remain free to use.
|
|
96
100
|
|
package/android/build.gradle
CHANGED
|
@@ -51,11 +51,20 @@ if (useManagedAndroidSdkVersions) {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
// Read version from package.json for BuildConfig
|
|
55
|
+
def packageJsonFile = new File(project.projectDir.parentFile, "package.json")
|
|
56
|
+
def packageJson = new groovy.json.JsonSlurper().parseText(packageJsonFile.text)
|
|
57
|
+
def voltraVersion = packageJson.version
|
|
58
|
+
|
|
54
59
|
android {
|
|
55
60
|
namespace "voltra"
|
|
56
61
|
defaultConfig {
|
|
57
62
|
versionCode 1
|
|
58
63
|
versionName "0.1.0"
|
|
64
|
+
buildConfigField "String", "VOLTRA_VERSION", "\"${voltraVersion}\""
|
|
65
|
+
}
|
|
66
|
+
buildFeatures {
|
|
67
|
+
buildConfig true
|
|
59
68
|
}
|
|
60
69
|
lintOptions {
|
|
61
70
|
abortOnError false
|
|
@@ -63,6 +72,17 @@ android {
|
|
|
63
72
|
buildFeatures {
|
|
64
73
|
compose true
|
|
65
74
|
}
|
|
75
|
+
testOptions {
|
|
76
|
+
unitTests.all {
|
|
77
|
+
testLogging {
|
|
78
|
+
events "passed", "failed", "skipped"
|
|
79
|
+
exceptionFormat "full"
|
|
80
|
+
showCauses true
|
|
81
|
+
showExceptions true
|
|
82
|
+
showStackTraces true
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
66
86
|
}
|
|
67
87
|
|
|
68
88
|
dependencies {
|
|
@@ -73,6 +93,15 @@ dependencies {
|
|
|
73
93
|
// Compose runtime (required for Glance)
|
|
74
94
|
api "androidx.compose.runtime:runtime:1.6.8"
|
|
75
95
|
|
|
96
|
+
// WorkManager (for periodic server-driven widget updates)
|
|
97
|
+
api "androidx.work:work-runtime-ktx:2.9.1"
|
|
98
|
+
|
|
99
|
+
// DataStore (credential storage for widget server updates)
|
|
100
|
+
api "androidx.datastore:datastore-preferences:1.1.4"
|
|
101
|
+
|
|
102
|
+
// Google Tink (encryption for credential storage)
|
|
103
|
+
implementation "com.google.crypto.tink:tink-android:1.19.0"
|
|
104
|
+
|
|
76
105
|
// JSON parsing
|
|
77
106
|
implementation "com.google.code.gson:gson:2.10.1"
|
|
78
107
|
|
|
@@ -81,4 +110,8 @@ dependencies {
|
|
|
81
110
|
|
|
82
111
|
// Kotlinx Serialization
|
|
83
112
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3"
|
|
113
|
+
|
|
114
|
+
// Unit tests
|
|
115
|
+
testImplementation "junit:junit:4.13.2"
|
|
116
|
+
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1"
|
|
84
117
|
}
|
|
@@ -328,6 +328,50 @@ class VoltraModule : Module() {
|
|
|
328
328
|
imageManager.clearPreloadedImages(keys)
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
+
// Widget Server Credentials APIs
|
|
332
|
+
|
|
333
|
+
AsyncFunction("setWidgetServerCredentials") { credentials: Map<String, Any?> ->
|
|
334
|
+
Log.d(TAG, "setWidgetServerCredentials called")
|
|
335
|
+
|
|
336
|
+
val context = appContext.reactContext!!
|
|
337
|
+
val token =
|
|
338
|
+
credentials["token"] as? String
|
|
339
|
+
?: throw IllegalArgumentException("token is required in credentials")
|
|
340
|
+
|
|
341
|
+
@Suppress("UNCHECKED_CAST")
|
|
342
|
+
val headers = credentials["headers"] as? Map<String, String>
|
|
343
|
+
|
|
344
|
+
runBlocking {
|
|
345
|
+
voltra.widget.VoltraWidgetCredentialStore.saveToken(context, token)
|
|
346
|
+
if (headers != null && headers.isNotEmpty()) {
|
|
347
|
+
voltra.widget.VoltraWidgetCredentialStore.saveHeaders(context, headers)
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
Log.d(TAG, "Widget server credentials saved")
|
|
352
|
+
|
|
353
|
+
val widgetManager = voltra.widget.VoltraWidgetManager(context)
|
|
354
|
+
runBlocking {
|
|
355
|
+
widgetManager.reloadAllWidgets()
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
AsyncFunction("clearWidgetServerCredentials") {
|
|
360
|
+
Log.d(TAG, "clearWidgetServerCredentials called")
|
|
361
|
+
|
|
362
|
+
val context = appContext.reactContext!!
|
|
363
|
+
runBlocking {
|
|
364
|
+
voltra.widget.VoltraWidgetCredentialStore.clearAll(context)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
Log.d(TAG, "Widget server credentials cleared")
|
|
368
|
+
|
|
369
|
+
val widgetManager = voltra.widget.VoltraWidgetManager(context)
|
|
370
|
+
runBlocking {
|
|
371
|
+
widgetManager.reloadAllWidgets()
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
331
375
|
AsyncFunction("reloadLiveActivities") { activityNames: List<String>? ->
|
|
332
376
|
// On Android, we don't have "Live Activities" in the same sense as iOS,
|
|
333
377
|
// but we might want to refresh widgets or notifications.
|
|
@@ -60,6 +60,10 @@ class VoltraRN(
|
|
|
60
60
|
val widthDp = frameLayout.width.toFloat() / density
|
|
61
61
|
val heightDp = frameLayout.height.toFloat() / density
|
|
62
62
|
|
|
63
|
+
// Don't render until we have real dimensions from layout.
|
|
64
|
+
// onLayout() will call updateView() once dimensions are available.
|
|
65
|
+
if (widthDp <= 1f || heightDp <= 1f) return
|
|
66
|
+
|
|
63
67
|
// Avoid redundant updates if nothing significant changed and we already have a view
|
|
64
68
|
if (frameLayout.childCount > 0 &&
|
|
65
69
|
payloadStr == lastRenderedPayload &&
|
|
@@ -94,14 +98,7 @@ class VoltraRN(
|
|
|
94
98
|
return@launch
|
|
95
99
|
}
|
|
96
100
|
|
|
97
|
-
|
|
98
|
-
// Glance needs a non-zero size. If we don't have one yet, use a fallback.
|
|
99
|
-
val composeSize =
|
|
100
|
-
if (widthDp > 1f && heightDp > 1f) {
|
|
101
|
-
DpSize(widthDp.dp, heightDp.dp)
|
|
102
|
-
} else {
|
|
103
|
-
DpSize(300.dp, 200.dp)
|
|
104
|
-
}
|
|
101
|
+
val composeSize = DpSize(widthDp.dp, heightDp.dp)
|
|
105
102
|
|
|
106
103
|
val glanceRemoteViews = GlanceRemoteViews()
|
|
107
104
|
val factory = GlanceFactory(id, voltraPayload.e, voltraPayload.s)
|
|
@@ -117,19 +114,27 @@ class VoltraRN(
|
|
|
117
114
|
|
|
118
115
|
val remoteViews = result.remoteViews
|
|
119
116
|
|
|
117
|
+
// Check if the frameLayout dimensions have changed since we started composing.
|
|
118
|
+
// If so, skip this render — a new updateView() will be triggered by onLayout.
|
|
119
|
+
val currentWidthDp = frameLayout.width.toFloat() / density
|
|
120
|
+
val currentHeightDp = frameLayout.height.toFloat() / density
|
|
121
|
+
if (abs(currentWidthDp - widthDp) >= 1.0f || abs(currentHeightDp - heightDp) >= 1.0f) {
|
|
122
|
+
return@launch
|
|
123
|
+
}
|
|
124
|
+
|
|
120
125
|
withContext(Dispatchers.Main) {
|
|
121
126
|
try {
|
|
122
|
-
// Try to reapply to the existing view first to avoid flickering/replacing
|
|
127
|
+
// Try to reapply to the existing view first to avoid flickering/replacing.
|
|
128
|
+
// IMPORTANT: Only use reapply for dimension-only changes (same payload).
|
|
129
|
+
// When the payload changes, always do a fresh apply to prevent stale
|
|
130
|
+
// style bleed (e.g. padding from a previous widget persisting because
|
|
131
|
+
// the new widget's RemoteViews doesn't explicitly reset it to zero).
|
|
123
132
|
var applied = false
|
|
124
|
-
if (frameLayout.childCount > 0) {
|
|
133
|
+
if (frameLayout.childCount > 0 && payloadStr == lastRenderedPayload) {
|
|
125
134
|
try {
|
|
126
135
|
val existingView = frameLayout.getChildAt(0)
|
|
127
136
|
remoteViews.reapply(context, existingView)
|
|
128
137
|
applied = true
|
|
129
|
-
// Update tracking state
|
|
130
|
-
lastRenderedPayload = payloadStr
|
|
131
|
-
lastRenderedWidthDp = widthDp
|
|
132
|
-
lastRenderedHeightDp = heightDp
|
|
133
138
|
} catch (e: Exception) {
|
|
134
139
|
}
|
|
135
140
|
}
|
|
@@ -145,25 +150,29 @@ class VoltraRN(
|
|
|
145
150
|
if (childCount > 1) {
|
|
146
151
|
frameLayout.removeViews(0, childCount - 1)
|
|
147
152
|
}
|
|
148
|
-
|
|
149
|
-
// CRITICAL FIX: Manually trigger layout for the new content.
|
|
150
|
-
// Since we are adding this async, the parent won't do it for us automatically.
|
|
151
|
-
frameLayout.measure(
|
|
152
|
-
View.MeasureSpec.makeMeasureSpec(frameLayout.width, View.MeasureSpec.EXACTLY),
|
|
153
|
-
View.MeasureSpec.makeMeasureSpec(frameLayout.height, View.MeasureSpec.EXACTLY),
|
|
154
|
-
)
|
|
155
|
-
frameLayout.layout(
|
|
156
|
-
frameLayout.left,
|
|
157
|
-
frameLayout.top,
|
|
158
|
-
frameLayout.right,
|
|
159
|
-
frameLayout.bottom,
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
// Update tracking state
|
|
163
|
-
lastRenderedPayload = payloadStr
|
|
164
|
-
lastRenderedWidthDp = widthDp
|
|
165
|
-
lastRenderedHeightDp = heightDp
|
|
166
153
|
}
|
|
154
|
+
|
|
155
|
+
// Always re-measure and re-layout after applying RemoteViews.
|
|
156
|
+
// This is critical because:
|
|
157
|
+
// 1) After fresh inflate: the view was added asynchronously so the parent
|
|
158
|
+
// won't trigger layout automatically.
|
|
159
|
+
// 2) After reapply: text content or styles may have changed, requiring
|
|
160
|
+
// re-measurement to avoid stale layout constraints (e.g. truncated text).
|
|
161
|
+
frameLayout.measure(
|
|
162
|
+
View.MeasureSpec.makeMeasureSpec(frameLayout.width, View.MeasureSpec.EXACTLY),
|
|
163
|
+
View.MeasureSpec.makeMeasureSpec(frameLayout.height, View.MeasureSpec.EXACTLY),
|
|
164
|
+
)
|
|
165
|
+
frameLayout.layout(
|
|
166
|
+
frameLayout.left,
|
|
167
|
+
frameLayout.top,
|
|
168
|
+
frameLayout.right,
|
|
169
|
+
frameLayout.bottom,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
// Update tracking state
|
|
173
|
+
lastRenderedPayload = payloadStr
|
|
174
|
+
lastRenderedWidthDp = widthDp
|
|
175
|
+
lastRenderedHeightDp = heightDp
|
|
167
176
|
} catch (e: Exception) {
|
|
168
177
|
}
|
|
169
178
|
}
|
|
@@ -67,6 +67,7 @@ object ShortNames {
|
|
|
67
67
|
"fvar" to "fontVariant",
|
|
68
68
|
"fw" to "fontWeight",
|
|
69
69
|
"fgs" to "foregroundStyle",
|
|
70
|
+
"fss" to "foregroundStyleScale",
|
|
70
71
|
"f" to "frame",
|
|
71
72
|
"g" to "gap",
|
|
72
73
|
"gs" to "gaugeStyle",
|
|
@@ -83,6 +84,7 @@ object ShortNames {
|
|
|
83
84
|
"ly" to "layout",
|
|
84
85
|
"lp" to "layoutPriority",
|
|
85
86
|
"l" to "left",
|
|
87
|
+
"lgv" to "legendVisibility",
|
|
86
88
|
"ls" to "letterSpacing",
|
|
87
89
|
"lh" to "lineHeight",
|
|
88
90
|
"ll" to "lineLimit",
|
|
@@ -95,6 +97,7 @@ object ShortNames {
|
|
|
95
97
|
"mr" to "marginRight",
|
|
96
98
|
"mt" to "marginTop",
|
|
97
99
|
"mv" to "marginVertical",
|
|
100
|
+
"mrk" to "marks",
|
|
98
101
|
"me" to "maskElement",
|
|
99
102
|
"maxh" to "maxHeight",
|
|
100
103
|
"max" to "maximumValue",
|
|
@@ -163,6 +166,10 @@ object ShortNames {
|
|
|
163
166
|
"valig" to "verticalAlignment",
|
|
164
167
|
"wt" to "weight",
|
|
165
168
|
"w" to "width",
|
|
169
|
+
"xgs" to "xAxisGridStyle",
|
|
170
|
+
"xav" to "xAxisVisibility",
|
|
171
|
+
"ygs" to "yAxisGridStyle",
|
|
172
|
+
"yav" to "yAxisVisibility",
|
|
166
173
|
"zi" to "zIndex",
|
|
167
174
|
)
|
|
168
175
|
|