Skip to content

Conversation

@robertherber
Copy link
Member

@robertherber robertherber commented Apr 10, 2025

Summary by CodeRabbit

  • New Features

    • Enhanced device activity controls with broader configurable actions including app blocking, whitelist management, badge count setting, and improved notification management.
  • Refactor

    • Streamlined the action execution process by introducing a generic action handler for a more consistent and reliable device activity experience.
  • Chores

    • Updated the package version to 0.4.27.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 10, 2025

Walkthrough

This pull request introduces a new function, executeGenericAction, to streamline the action processing flow within the React Native Device Activity package. Existing functions in the device monitor and shield action extensions have been refactored to utilize this generic function instead of maintaining their own specific logic. Additionally, type definitions have been updated to support an array of actions, and the package version has been incremented from 0.4.24 to 0.4.27.

Changes

File(s) Change Summary
packages/react-native-device-activity/ios/Shared.swift, .../targets/ActivityMonitorExtension/DeviceActivityMonitorExtension.swift, .../targets/ShieldAction/ShieldActionExtension.swift Introduces the executeGenericAction function and refactors action handling. Updates include the removal of the old executeAction method, renaming handleAction to handleShieldAction with an added placeholders parameter, and iterating through multiple actions.
packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts Updates the ShieldAction type by deprecating and making the type field optional, and adds an actions array. Introduces new action types: setBadgeCount, removeAllPendingNotificationRequests, removePendingNotificationRequests, addCurrentToWhitelist, and removeAllDeliveredNotifications.
packages/react-native-device-activity/package.json Bumps version from 0.4.24 to 0.4.27.

Sequence Diagram(s)

sequenceDiagram
    participant MonitorExt as DeviceActivityMonitorExtension
    participant Shared as Shared.swift
    MonitorExt->>Shared: executeGenericAction(action, placeholders, triggeredBy)
    Note right of Shared: Processes sleepBefore, evaluates action types, then sleepAfter
    Shared-->>MonitorExt: Action processed
Loading
sequenceDiagram
    participant Shield as ShieldActionExtension
    participant Shared as Shared.swift
    Shield->>Shared: executeGenericAction(action, placeholders, triggeredBy)
    Note right of Shared: Iterates through actions from configForSelectedAction
    Shared-->>Shield: Action executed
Loading

Poem

I am a rabbit, hopping through the code,
With new actions leaping down a shiny road.
executeGenericAction now leads the way,
In a refactored dance of code all day.
Carrot-filled logs and updates so bright—
Hop on, dear coder, into the light!


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between 6dd0ed5 and 71535f8.

📒 Files selected for processing (1)
  • packages/react-native-device-activity/package.json (1 hunks)
🔇 Additional comments (1)
packages/react-native-device-activity/package.json (1)

3-3: Version Bump Updated Correctly
The package version has been updated to "0.4.27" reflecting the new functionalities such as the generic action processor and the multiple notification/shield actions. Please ensure that the changelog and release notes are updated accordingly to document these changes.


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Apr 10, 2025

Open in StackBlitz

npm i https://pkg.pr.new/kingstinct/react-native-device-activity@53

commit: 6dd0ed5

Copy link
Contributor

@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.

Actionable comments posted: 10

🔭 Outside diff range comments (2)
packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (2)

121-125: 🛠️ Refactor suggestion

Use placeholders in sendNotification

The sendNotification call uses an empty placeholders dictionary instead of the newly passed placeholders parameter, which seems inconsistent with the rest of the changes.

  if type == "sendNotification" {
    if let payload = configForSelectedAction["payload"] as? [String: Any] {
-     sendNotification(contents: payload, placeholders: [:])
+     sendNotification(contents: payload, placeholders: placeholders)
    }
  }

25-145: 🧹 Nitpick (assertive)

Consider refactoring specific action types to use executeGenericAction

The function still contains logic for handling specific action types directly instead of leveraging the new generic action execution mechanism. This creates duplication and makes maintenance harder.

Consider refactoring each action type block to use executeGenericAction for consistency. For example:

  if type == "disableBlockAllMode" {
-   disableBlockAllMode(triggeredBy: "shieldAction")
+   executeGenericAction(
+     action: ["type": "disableBlockAllMode"],
+     placeholders: placeholders,
+     eventKey: "shieldAction"
+   )
  }

This would create a more consistent pattern throughout the codebase where all action execution goes through the same code path.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c119e34 and ec957ed.

📒 Files selected for processing (5)
  • packages/react-native-device-activity/ios/Shared.swift (1 hunks)
  • packages/react-native-device-activity/package.json (1 hunks)
  • packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (2 hunks)
  • packages/react-native-device-activity/targets/ActivityMonitorExtension/DeviceActivityMonitorExtension.swift (2 hunks)
  • packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
packages/react-native-device-activity/targets/ActivityMonitorExtension/DeviceActivityMonitorExtension.swift (1)
packages/react-native-device-activity/ios/Shared.swift (1)
  • executeGenericAction (100-218)
packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (1)
packages/react-native-device-activity/ios/Shared.swift (1)
  • executeGenericAction (100-218)
packages/react-native-device-activity/ios/Shared.swift (1)
packages/react-native-device-activity/src/index.ts (9)
  • updateShield (569-584)
  • blockSelection (424-436)
  • unblockSelection (450-462)
  • addSelectionToWhitelistAndUpdateBlock (135-147)
  • removeSelectionFromWhitelistAndUpdateBlock (149-161)
  • clearWhitelist (105-107)
  • resetBlocks (446-448)
  • disableBlockAllMode (442-444)
  • enableBlockAllMode (438-440)
🔇 Additional comments (11)
packages/react-native-device-activity/package.json (1)

3-3: Version bump confirms alignment with new features.
No concerns here; incrementing from 0.4.24 to 0.4.25 is appropriate for the additional functionality introduced elsewhere.

packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (2)

182-182: Expanding ShieldAction to support multiple actions is a good improvement.
This addition promotes flexibility by allowing multiple Action items. Ensure any top-level parsing handles both deprecated and new properties gracefully.


272-283:

Details

❓ Verification inconclusive

Excellent extension of action types.
The new "setBadgeCount", "removeAllPendingNotificationRequests", and "removePendingNotificationRequests" actions broaden functionality. Given that setBadgeCount requires iOS 16, verify that any fallback behavior is clear for earlier iOS versions.


🏁 Script executed:

#!/bin/bash
# Description: Check usage of "setBadgeCount" for iOS <16 fallback.
rg --json "setBadgeCount"

Length of output: 1938


Action Required: Validate Fallback Handling for iOS Versions <16

Excellent extension of the action types with the introduction of "setBadgeCount", "removeAllPendingNotificationRequests", and "removePendingNotificationRequests". However, since the new "setBadgeCount" action requires iOS 16, please ensure that there is explicit fallback behavior or clear documentation for devices running iOS versions lower than 16. For example, in the Swift implementation in packages/react-native-device-activity/ios/Shared.swift (around lines 191 and 197), there is no visible conditional check (such as using if #available(iOS 16, *)) to handle fallback scenarios. Kindly verify that either appropriate version checks or descriptive documentation is in place so that developers and users understand how the feature behaves on older iOS versions.

packages/react-native-device-activity/ios/Shared.swift (3)

157-161: Clean approach to clearing the whitelist and updating.
This block looks solid and aligns with the existing pattern for block/whitelist modifications.


192-200:

Details

❓ Verification inconclusive

Ensure fallback for devices below iOS 16.
UNUserNotificationCenter.setBadgeCount is iOS 16+ only, so confirm that older iOS versions still function as expected without error.


🏁 Script executed:

#!/bin/bash
# Searching for setBadgeCount usage to confirm fallback handling.
rg "setBadgeCount"

Length of output: 304


Fallback Compatibility for iOS Versions Below 16

The current implementation only updates the badge count when running on iOS 16+ (inside the #available(iOS 16.0, *) block). For devices running earlier iOS versions, there’s no explicit fallback or alternative handling. Please verify if the omission of badge count updates on older iOS versions is acceptable or if a fallback mechanism (such as logging or an alternative update method) should be implemented.

  • Location: packages/react-native-device-activity/ios/Shared.swift (lines 192–200)
  • Observation: No fallback branch exists for devices that do not meet the iOS 16 requirement despite the type being defined in ReactNativeDeviceActivity.types.ts.

141-156:

Details

❓ Verification inconclusive

Double-check parse behavior.
parseActivitySelectionInput may return an empty selection if parsing fails. Ensure the calling logic or downstream code can handle that gracefully to avoid silent failures.


🏁 Script executed:

#!/bin/bash
# Description: Check for usage sites of parseActivitySelectionInput and verify error handling.
ast-grep --pattern $'parseActivitySelectionInput($_)' 

Length of output: 2898


Verify empty selection handling in parseActivitySelectionInput

The code in Shared.swift (lines 141–156) calls parseActivitySelectionInput(input:) without an explicit check for an empty result. Since this function may return an empty selection upon failure, please ensure that both the functions invoked here (namely addSelectionToWhitelistAndUpdateBlock and removeSelectionFromWhitelistAndUpdateBlock) and other similar usage sites in ReactNativeDeviceActivityModule.swift handle an empty selection appropriately. This will help prevent silent failures and ensure that any parsing errors are either logged or otherwise managed.

packages/react-native-device-activity/targets/ActivityMonitorExtension/DeviceActivityMonitorExtension.swift (2)

12-12: Import of NotificationCenter.
This allows removing or scheduling notification requests. Looks appropriate for the new actions introduced.


103-103: Adoption of the generic action executor is a good step.
Replacing any specialized implementation with executeGenericAction unifies the logic and reduces duplication.

packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (3)

12-14: LGTM: Function renamed for better semantics and added placeholders support

The function has been appropriately renamed from handleAction to handleShieldAction to better reflect its purpose and the new placeholders parameter enables dynamic substitution in actions.


24-24: LGTM: Correct condition update

The condition has been properly updated to use else if to account for the new actions array check.


194-197: LGTM: Correctly calling renamed function with placeholders

The function call has been updated to use the renamed handleShieldAction function and properly passes the placeholders parameter.

Copy link
Contributor

@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.

Actionable comments posted: 5

🔭 Outside diff range comments (2)
packages/react-native-device-activity/targets/ActivityMonitorExtension/DeviceActivityMonitorExtension.swift (1)

57-67: 🧹 Nitpick (assertive)

Use descriptive triggeredBy naming.
The triggeredBy label reflects the originating event (e.g., "actions_for_<activityName>_<callbackName>"). That’s useful, but consider reverting to the standard snake/camel-case naming if your logs or analytics systems have established naming conventions.

packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (1)

33-165: 🧹 Nitpick (assertive)

Consider moving remaining action types to executeGenericAction

Now that you've implemented the executeGenericAction function and moved some action types there (like "addCurrentToWhitelist"), consider moving the remaining action types in this function to the generic handler for better consistency and maintainability.

This would make the code more consistent by having all action types handled in one place, making it easier to maintain and extend in the future.

♻️ Duplicate comments (4)
packages/react-native-device-activity/ios/Shared.swift (3)

100-112: 🧹 Nitpick (assertive)

Caution with synchronous sleeps.
Using sleep(ms:) on lines 110-112 (and elsewhere) can block the extension’s thread, potentially impacting performance or responsiveness. Consider an asynchronous approach or shorter waits, especially in an extension environment.

- if let sleepBefore = action["sleepBefore"] as? Int {
-   sleep(ms: sleepBefore)
- }
+ // Potential asynchronous approach if feasible:
+ // DispatchQueue.global().asyncAfter(deadline: .now() + .milliseconds(sleepBefore)) { ... }

210-217: 🧹 Nitpick (assertive)

Consider removing delivered notifications as well.
The code removes only pending notification requests. If you also intend to remove delivered notifications, call removeDeliveredNotifications similarly.

+ // If you want to remove delivered notifications too:
+ UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: identifiers)

231-239: ⚠️ Potential issue

Avoid blocking sleeps after sending HTTP requests.
Sleeping for 1 second immediately after sending a request may still leave asynchronous requests incomplete if the network is slow. Consider a callback-based or asynchronous approach.

- task = sendHttpRequest(with: url, config: config, placeholders: placeholders)
- sleep(ms: 1000)
+ task = sendHttpRequest(with: url, config: config, placeholders: placeholders)
+ // Possibly handle async completion or use OS background tasks.
packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (1)

192-201: Avoid force unwrapping optional tokens

The code force unwraps applicationToken! and webdomainToken! after checking if they're nil, which could potentially lead to runtime crashes if the token becomes unexpectedly nil after the check.

  let placeholders: [String: String?] = [
    "action": actionButton,
-   "applicationName": applicationToken != nil
-     ? Application(token: applicationToken!).localizedDisplayName : nil,
-   "webDomain": webdomainToken != nil
-     ? WebDomain(
-       token: webdomainToken!
-     ).domain : nil,
+   "applicationName": applicationToken.map { Application(token: $0).localizedDisplayName },
+   "webDomain": webdomainToken.map { WebDomain(token: $0).domain },
    "familyActivitySelectionId": familyActivitySelectionId?.id
  ]
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between ec957ed and fa4abb3.

📒 Files selected for processing (4)
  • packages/react-native-device-activity/ios/Shared.swift (1 hunks)
  • packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (3 hunks)
  • packages/react-native-device-activity/targets/ActivityMonitorExtension/DeviceActivityMonitorExtension.swift (4 hunks)
  • packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
packages/react-native-device-activity/targets/ActivityMonitorExtension/DeviceActivityMonitorExtension.swift (1)
packages/react-native-device-activity/ios/Shared.swift (1)
  • executeGenericAction (100-244)
packages/react-native-device-activity/ios/Shared.swift (1)
packages/react-native-device-activity/src/index.ts (9)
  • updateShield (569-584)
  • blockSelection (424-436)
  • unblockSelection (450-462)
  • addSelectionToWhitelistAndUpdateBlock (135-147)
  • removeSelectionFromWhitelistAndUpdateBlock (149-161)
  • clearWhitelist (105-107)
  • resetBlocks (446-448)
  • disableBlockAllMode (442-444)
  • enableBlockAllMode (438-440)
packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (1)
packages/react-native-device-activity/ios/Shared.swift (1)
  • executeGenericAction (100-244)
🔇 Additional comments (8)
packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (3)

160-163: Rename aligns with standardized action names.
Renaming "whitelistCurrent" to "addCurrentToWhitelist" is consistent with the new approach. No concerns here.


173-174: Confirm deprecation timeline.
Marking the type field as deprecated is appropriate, but consider scheduling removal or providing migration guidance to help consumers switch to actions.


182-182: New actions property is a clear improvement.
The addition of actions?: Action[]; allows more flexibility. Ensure that all internal references to type alone accommodate this array-based approach.

packages/react-native-device-activity/ios/Shared.swift (1)

193-198: Opening the app with a fixed URL.
Using "device-activity://" as a placeholder is fine for initial testing, but consider making the URL configurable or at least documented if you anticipate future changes.

Do you plan to externally configure or localize this URL? If so, I can help add that property.

packages/react-native-device-activity/targets/ActivityMonitorExtension/DeviceActivityMonitorExtension.swift (2)

12-12: New NotificationCenter import is appropriate.
Pulling in NotificationCenter usage is valid for handling or removing notifications. No concerns here.


70-70: Ensure robust null-checking of actions.
The optional array from user defaults can be omitted or invalid, so the current check is correct. Possibly add logs if no array is found.

packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (2)

12-31: Greatly improved action handling architecture!

The refactoring to support multiple actions through the executeGenericAction function provides a more flexible and maintainable approach. This will make it easier to add new action types in the future while keeping the code organized.


136-136: Good name improvement for action type

Renaming from "whitelistCurrent" to "addCurrentToWhitelist" is more descriptive and follows the verb-noun convention, improving code readability.

Copy link
Contributor

@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.

Actionable comments posted: 1

♻️ Duplicate comments (6)
packages/react-native-device-activity/ios/Shared.swift (6)

100-113: Introduce safer handling for missing “type” and reduce reliance on synchronous sleeps.
Currently, if the action["type"] is missing or malformed, the function silently skips. Consider throwing or logging an error. Also, calling sleep(ms:) blocks the thread, potentially impacting UI responsiveness and extension performance.


133-152: Consider removing the 50ms sleep to avoid brittle timing.
Using sleep(ms: 50) to wait on shield updates is fragile and may fail under slower conditions. An asynchronous callback or completion block might be more reliable.


153-166: Synchronize shield actions upon unblocking to maintain consistency.
Removing only the shield configuration for the selection in unblockSelection may leave stale shield actions. Consider removing the associated shield actions as well if the intention is a full unblock.


194-209: Replace “todo” and reconsider extra sleeps for openApp & enableBlockAllMode.
• The // todo: replace with general string can be addressed now to ensure maintainability.
• The 1s and 50ms sleeps risk blocking the main thread, particularly in an extension environment.


233-241: Avoid blocking sleeps after sending HTTP requests.
Sleeping for 1s is no guarantee of network completion and may freeze the extension. Prefer async callbacks.


243-246: Synchronous sleep may stall extension shutdown.
sleepAfter again blocks the thread. Consider asynchronous alternatives to improve performance.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between 6e130c2 and 6dd0ed5.

📒 Files selected for processing (2)
  • packages/react-native-device-activity/ios/Shared.swift (1 hunks)
  • packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/react-native-device-activity/ios/Shared.swift (1)
packages/react-native-device-activity/src/index.ts (9)
  • updateShield (569-584)
  • blockSelection (424-436)
  • unblockSelection (450-462)
  • addSelectionToWhitelistAndUpdateBlock (135-147)
  • removeSelectionFromWhitelistAndUpdateBlock (149-161)
  • clearWhitelist (105-107)
  • resetBlocks (446-448)
  • disableBlockAllMode (442-444)
  • enableBlockAllMode (438-440)
🔇 Additional comments (9)
packages/react-native-device-activity/ios/Shared.swift (4)

114-131: Looks consistent with intended whitelist logic.
The approach of retrieving the current whitelist and inserting tokens aligns with the new “addCurrentToWhitelist” action. No immediate issues found here.


167-174: Clear, focused addition to the whitelist.
This logic seamlessly parses the selection and updates the block state. No issues noted.


175-182: Remove selection from whitelist is straightforward.
The flow properly calls the core helper to mutate the whitelist and reapply blocking. Looks good.


183-187: ClearWhitelistAndUpdateBlock is properly sequenced.
The actions here ensure the whitelist is cleared first, then the block is updated. No concerns.

packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (5)

163-163: New “addCurrentToWhitelist” action type aligns with iOS code changes.
This syncs well with the new Swift logic.


182-182: Introducing a flexible actions array fosters better extensibility.
No issues noted. This helps unify different action flows under one property.


272-284: Added action types enhance coverage of notification management.
The expanded actions—like removePendingNotificationRequests—align with iOS capabilities.


285-286: “addCurrentToWhitelist” action matches Swift implementation.
This keeps type definitions consistent with native code changes.


288-288: “removeAllDeliveredNotifications” rounds out notification clearing.
This addition complements the pending notification removal, providing full coverage.

@robertherber robertherber merged commit 268550e into main Apr 22, 2025
1 check passed
@robertherber robertherber deleted the add-more-notification-actions-and-multiple-shield-actions branch April 22, 2025 16:12
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.

2 participants