fix(ios): properly serialize arrays of Codable objects in widget config#377
fix(ios): properly serialize arrays of Codable objects in widget config#377galacticgibbon wants to merge 2 commits into
Conversation
|
To view this pull requests documentation preview, visit the following URL: docs.page/abausg/home_widget~377 Documentation is deployed and generated using docs.page. |
WalkthroughAdds special-case encoding for arrays of Codable elements in the iOS widget plugin, encoding each element to JSON dictionaries with a string fallback. Separately, Android background work now supports an expedited flag propagated through intent, HomeWidgetBackgroundReceiver, HomeWidgetIntent, and HomeWidgetBackgroundWorker. Changes
Sequence Diagram(s)sequenceDiagram
participant Plugin as iOS HomeWidgetPlugin
participant Param as Parameter Value (Array)
participant Element as Element (Any)
participant Encoder as JSONEncoder
participant Dict as Dictionary
participant Fallback as String Conversion
participant Output as Widget Config Value
Plugin->>Param: receive array parameter
Param->>Element: iterate elements
Element->>Encoder: try encode (if Codable)
alt encode succeeds for all elements
Encoder->>Dict: decode JSON -> Dictionary
Dict->>Output: store array of dictionaries
else any encode fails
Element->>Fallback: convert each element to string
Fallback->>Output: store array of strings
end
sequenceDiagram
participant Intent as HomeWidgetIntent.getBroadcast
participant Receiver as HomeWidgetBackgroundReceiver
participant Worker as HomeWidgetBackgroundWorker
participant WorkManager as Android WorkManager
Intent->>Receiver: send PendingIntent (includes EXTRA_IS_EXPEDITED)
Receiver->>Worker: call enqueueWork(context, intent, expedited)
Worker->>Worker: build OneTimeWorkRequestBuilder
alt expedited == true
Worker->>Worker: set OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST (expedited)
end
Worker->>WorkManager: enqueue UniqueWork with APPEND policy
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Points to review:
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
[pre_merge_check_pass] The pull request description comprehensively follows the provided template with all required sections present. It includes a clear Description section explaining the bug and solution, a Problem subsection detailing the root cause, a Solution subsection with implementation details, and an Example showing the before/after behavior. The Checklist, Breaking Change, and Related Issues sections are all included as required. While the checkboxes for tests and documentation updates are unchecked, the description itself is detailed and complete rather than vague or incomplete. [pre_merge_check_pass] The iOS changes in HomeWidgetPlugin.swift directly address the primary objective from linked issue #376, which requires handling arrays of Codable objects (specifically AppEntity types like EntryTypeEntity) to prevent crashes when accessing widget configuration via getInstalledWidgets(). The fix implements the expected behavior by attempting to encode each array element as Codable, converting to JSON dictionaries, and falling back to string conversion if encoding fails, which matches the stated requirements to return standard-codec-compatible representations accessible in Flutter. | ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/home_widget/android/src/main/kotlin/es/antonborri/home_widget/HomeWidgetBackgroundReceiver.kt(1 hunks)packages/home_widget/android/src/main/kotlin/es/antonborri/home_widget/HomeWidgetBackgroundWorker.kt(2 hunks)packages/home_widget/android/src/main/kotlin/es/antonborri/home_widget/HomeWidgetIntent.kt(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: iOS Integration Tests
- GitHub Check: iOS Integration Tests
🔇 Additional comments (3)
packages/home_widget/android/src/main/kotlin/es/antonborri/home_widget/HomeWidgetBackgroundReceiver.kt (1)
13-14: LGTM! Expedited flag propagation is correct.The extraction of the expedited flag from the intent and its propagation to
enqueueWorkis implemented correctly. The use ofgetBooleanExtrawith afalsedefault ensures safe handling when the extra is not present.packages/home_widget/android/src/main/kotlin/es/antonborri/home_widget/HomeWidgetBackgroundWorker.kt (2)
12-12: Import is correct for expedited work support.The
OutOfQuotaPolicyimport is necessary for configuring expedited work requests.
115-125: Expedited work implementation is correct and verified.The refactor to a builder pattern with conditional expedited policy application is clean and correct. The choice of
OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUESTprovides appropriate graceful degradation when the expedited work quota is exhausted.Verification confirms that the project's WorkManager dependency (
androidx.work:work-runtime-ktx:2.+in the main library and2.8.1in the example app) meets the 2.7.0+ requirement for expedited work support.
| const val EXTRA_IS_EXPEDITED = "es.antonborri.home_widget.extra.IS_EXPEDITED" | ||
|
|
||
| fun getBroadcast(context: Context, uri: Uri? = null): PendingIntent { | ||
| fun getBroadcast(context: Context, uri: Uri? = null, expedited: Boolean = false): PendingIntent { | ||
| val intent = Intent(context, HomeWidgetBackgroundReceiver::class.java) | ||
| intent.data = uri | ||
| intent.action = HOME_WIDGET_BACKGROUND_ACTION | ||
| intent.putExtra(EXTRA_IS_EXPEDITED, expedited) |
There was a problem hiding this comment.
🧩 Analysis chain
Expedited flag integration is well-implemented.
The constant definition, parameter addition with a sensible default (false), and intent storage are all correct and maintain backward compatibility.
Verify that the Flutter/Dart API has been updated to expose this expedited parameter to plugin users. The Android native side is ready, but users need a way to set this flag from Dart.
🏁 Script executed:
#!/bin/bash
# Search for Flutter/Dart API that exposes the expedited parameter
rg -n --type dart -C3 'expedited'Length of output: 0
🏁 Script executed:
#!/bin/bash
# Find Dart/Flutter files in the plugin structure
fd -e dart -type f | head -20Length of output: 170
🏁 Script executed:
#!/bin/bash
# Look for files that might define the Flutter API
rg -n 'getBroadcast' --type dart -C2Length of output: 0
🏁 Script executed:
#!/bin/bash
# Search for any reference to expedited with case-insensitive matching
rg -ni 'expedited' --type dart --type kotlin --type javaLength of output: 1404
🏁 Script executed:
#!/bin/bash
# Check the lib directory structure for plugin API files
find . -path '*/lib/*.dart' -o -path '*/lib/*/*.dart' 2>/dev/null | grep -E '(home_widget|plugin)' | head -20Length of output: 257
🏁 Script executed:
#!/bin/bash
# Search for broadcast-related methods in Dart files
rg -n 'broadcast|update|enqueue' packages/home_widget/lib/ -C2Length of output: 1361
🏁 Script executed:
#!/bin/bash
# Inspect the main Dart plugin API file
cat packages/home_widget/lib/src/home_widget.dartLength of output: 10005
🏁 Script executed:
#!/bin/bash
# Check for TODO or FIXME comments related to expedited or broadcast
rg -n 'TODO|FIXME|todo' packages/home_widget/lib/ | grep -i 'expedited\|broadcast'Length of output: 0
Add the expedited parameter to the Dart API.
The Android implementation is complete and ready to use the expedited flag, but the Flutter/Dart API has no way to expose this feature to users. The updateWidget() method and related broadcast trigger methods need the expedited parameter added to allow developers to enable expedited work requests from Dart.
Verify that changes are made to packages/home_widget/lib/src/home_widget.dart to add expedited: bool = false parameter to methods that trigger background work on Android (likely updateWidget()), and that this parameter is passed through the MethodChannel to the native Android layer.
🤖 Prompt for AI Agents
In packages/home_widget/lib/src/home_widget.dart (methods that trigger Android
background work, e.g., updateWidget) add an optional parameter expedited: bool =
false to the public API and to any internal helper methods that build the
platform call; include expedited in the arguments map passed to
MethodChannel.invokeMethod (key name "expedited" or match the Android
EXTRA_IS_EXPEDITED naming convention) so the boolean is forwarded to the native
side, and ensure the default remains false so existing callers are unaffected.
|
Hi. Thanks for this. Can you please remove the changes in the Android implementation? They don't seem to be related to the fix you are describing in the title/description. |
Description
Fixes a serialization bug in
HomeWidgetPlugin.swiftwhere arrays ofCodableobjects (e.g.,[EntryTypeEntity]) were not being properly encoded when extracting widget configuration viagetInstalledWidgets().Problem
When a widget configuration contains an array parameter (like
entryTypes: [EntryTypeEntity]), the existing code would match the genericcase let arrayValue as [Any]:case before reaching theCodablecase. This caused raw Swift objects to be passed through the Flutter method channel, resulting in a"Unsupported value for standard codec"crash.Solution
Reordered the type checking in
getInstalledWidgets()to handle arrays ofCodableobjects before the generic array case. The fix:CodableThis allows arrays of
AppEntitytypes (which conform toCodable) to be properly serialized and accessible in Flutter.Example
Before: Crash when accessing
widget.configuration['entryTypes']After: Returns properly serialized array:
[ {id: "task", displayString: "Task"}, {id: "event", displayString: "Event"}, {id: "note", displayString: "Note"} ]Checklist
exampleor documentation.Breaking Change?
Related Issues
Fixes #376