Skip to content

feat: Support passing appGroupId directly with functions#416

Merged
ABausG merged 2 commits into
mainfrom
feat/non-global-app-group
May 10, 2026
Merged

feat: Support passing appGroupId directly with functions#416
ABausG merged 2 commits into
mainfrom
feat/non-global-app-group

Conversation

@ABausG
Copy link
Copy Markdown
Owner

@ABausG ABausG commented May 3, 2026

Description

Support providing an appGroupId directly in invocations of saveWidgetData, updateWidget etc to not rely on storing it globally for the whole plugin statically

Checklist

  • I have updated/added tests for ALL new/updated/fixed functionality.
  • I have updated/added relevant documentation and added code (documentation) comments where necessary.
  • I have updated/added relevant examples in example or documentation.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Related Issues

@docs-page
Copy link
Copy Markdown

docs-page Bot commented May 3, 2026

To view this pull requests documentation preview, visit the following URL:

docs.page/abausg/home_widget~416

Documentation is deployed and generated using docs.page.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 618fbca1-609f-4c51-90cc-35e507ec8256

📥 Commits

Reviewing files that changed from the base of the PR and between 41493df and e0a1eb3.

📒 Files selected for processing (1)
  • packages/home_widget/test/home_widget_test.dart
✅ Files skipped from review due to trivial changes (1)
  • packages/home_widget/test/home_widget_test.dart

Walkthrough

Adds optional per-call appGroupId to HomeWidget APIs and threads it through method-channel calls; iOS plugin resolves the effective group ID from call arguments (falling back to global), and tests/integration verify per-call behavior without global setup.

Changes

Per-Call App Group ID Support

Layer / File(s) Summary
API Signatures
packages/home_widget/lib/src/home_widget.dart
saveWidgetData, getWidgetData, saveFile, saveImage, and renderFlutterWidget gain optional appGroupId named parameters.
Core Implementation (Dart)
packages/home_widget/lib/src/home_widget.dart
Dart methods include appGroupId in method-channel payloads for saveWidgetData/getWidgetData; iOS path resolution uses appGroupId ?? HomeWidget.groupId and asserts presence when required.
Native Resolution (iOS)
packages/home_widget/ios/home_widget/Sources/home_widget/HomeWidgetPlugin.swift
Added resolvedAppGroupId(from:) helper to extract appGroupId from FlutterMethodCall args, falling back to static HomeWidgetPlugin.groupId. saveWidgetData/getWidgetData now initialize UserDefaults with the resolved suite name.
Method Channel Wiring
packages/home_widget/lib/src/home_widget.dart, packages/home_widget/ios/.../HomeWidgetPlugin.swift
Dart forwards optional appGroupId in channel calls; iOS handlers read it and use the resolved group when accessing UserDefaults or performing file operations.
Integration Tests / Examples
packages/home_widget/example/integration_test/ios_test.dart
Introduced integrationAppGroupId constant and added a Per-call app group without global setup test group that clears global HomeWidget.groupId, uses per-call appGroupId to seed and read widget data/files, and verifies delete/clear behavior.
Unit Tests
packages/home_widget/test/home_widget_test.dart
Added tests asserting appGroupId is included in method-channel args for getWidgetData, saveWidgetData, delete flow, that per-call IDs don't mutate global HomeWidget.groupId, and that saveFile sends appGroupId in saved-path metadata.

Sequence Diagram(s)

sequenceDiagram
    participant Flutter as Flutter (HomeWidget)
    participant Channel as MethodChannel
    participant Plugin as iOS HomeWidgetPlugin
    participant UD as UserDefaults / FileSystem

    Flutter->>Channel: saveWidgetData(id, data, appGroupId?)
    Channel->>Plugin: invokeMethod("saveWidgetData", {id, data, appGroupId?})
    Plugin->>Plugin: resolvedId = resolvedAppGroupId(from: call) // arg or global
    Plugin->>UD: UserDefaults(suiteName: resolvedId).set(...)/write file
    UD-->>Plugin: ack
    Plugin-->>Channel: result(success)
    Channel-->>Flutter: result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description explains what the PR does and its motivation. However, the checklist items are unchecked, indicating tests, documentation, and examples may not have been fully addressed. Check the relevant boxes in the checklist after confirming that tests, documentation/comments, and examples have been added or updated as needed.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding support for passing appGroupId directly in function calls.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/non-global-app-group

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (ac84f31) to head (e0a1eb3).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #416   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            3         3           
  Lines          167       175    +8     
=========================================
+ Hits           167       175    +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/home_widget/test/home_widget_test.dart (1)

181-198: ⚡ Quick win

Test path /widget/file.bin doesn't exercise the managed-file deletion branch with appGroupId.

_isHomeWidgetManagedFilePath('/widget/file.bin') returns false (no /home_widget/ segment), so this test validates appGroupId forwarding through both channel calls but not the actual file-deletion sub-path. The iOS integration test (saveFile and clear with appGroupId override) covers that end-to-end; consider adding an analogue here using a path like /app/home_widget/file.bin to close the unit-test gap on the deletion branch.

✏️ Suggested addition to cover the managed-path + appGroupId deletion branch
  test('delete flow forwards appGroupId to get and save', () async {
    getWidgetDataReturn = '/widget/file.bin';
    // ...existing assertions...
  });
+
+  test('managed path deletion forwards appGroupId', () async {
+    getWidgetDataReturn = '/app/home_widget/file.bin';
+    const id = 'fileKey';
+    const appGroupId = 'group.test.per.call';
+    final file = MockFile();
+    when(() => file.exists()).thenAnswer((_) async => true);
+    when(() => file.delete()).thenAnswer((_) async => file);
+
+    await IOOverrides.runZoned(
+      () async {
+        expect(
+          await HomeWidget.saveWidgetData(id, null, appGroupId: appGroupId),
+          true,
+        );
+      },
+      createFile: (path) {
+        when(() => file.path).thenReturn(path);
+        return file;
+      },
+    );
+    expect(invocations[0].arguments['appGroupId'], appGroupId);
+    expect(invocations[1].arguments['appGroupId'], appGroupId);
+    verify(() => file.delete()).called(1);
+  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/home_widget/test/home_widget_test.dart` around lines 181 - 198, The
test uses getWidgetDataReturn = '/widget/file.bin' which does not trigger the
managed-file deletion branch because _isHomeWidgetManagedFilePath returns false;
update the test (the one named "delete flow forwards appGroupId to get and
save") to use a managed path such as '/app/home_widget/file.bin' for
getWidgetDataReturn so that HomeWidget.saveWidgetData exercises the deletion
sub-path, and keep asserting that both platform channel invocations
(getWidgetData and saveWidgetData) include the appGroupId as before.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/home_widget/test/home_widget_test.dart`:
- Around line 181-198: The test uses getWidgetDataReturn = '/widget/file.bin'
which does not trigger the managed-file deletion branch because
_isHomeWidgetManagedFilePath returns false; update the test (the one named
"delete flow forwards appGroupId to get and save") to use a managed path such as
'/app/home_widget/file.bin' for getWidgetDataReturn so that
HomeWidget.saveWidgetData exercises the deletion sub-path, and keep asserting
that both platform channel invocations (getWidgetData and saveWidgetData)
include the appGroupId as before.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a48fb1e9-0d17-451d-ba1b-1f3d01b33e19

📥 Commits

Reviewing files that changed from the base of the PR and between ac84f31 and 41493df.

📒 Files selected for processing (4)
  • packages/home_widget/example/integration_test/ios_test.dart
  • packages/home_widget/ios/home_widget/Sources/home_widget/HomeWidgetPlugin.swift
  • packages/home_widget/lib/src/home_widget.dart
  • packages/home_widget/test/home_widget_test.dart

Co-authored-by: Cursor <cursoragent@cursor.com>
@ABausG ABausG merged commit 55e6f43 into main May 10, 2026
18 checks passed
@ABausG ABausG deleted the feat/non-global-app-group branch May 10, 2026 11:19
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