Skip to content

add activitySelectionMetadata and set functions#45

Merged
robertherber merged 89 commits into
mainfrom
add-set-functions
Apr 8, 2025
Merged

add activitySelectionMetadata and set functions#45
robertherber merged 89 commits into
mainfrom
add-set-functions

Conversation

@robertherber

@robertherber robertherber commented Feb 14, 2025

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Introduced new navigation tabs—“Set ops” and “Whitelist”—replacing the former Shield tab to offer enhanced controls for managing activity selections.
    • Added interactive activity pickers that simplify selection management and display set operation results (union, intersection, difference, symmetric difference) for improved user experience.
    • Implemented a new component for managing whitelists, allowing users to toggle block modes and view activity selection metadata.
    • Added a new test plan configuration for improved test management in Xcode.
    • Introduced new test suites to validate functionality for family activity selection management and shield activation scenarios.
    • Added a new DeviceActivitySelectionViewPersisted component for improved integration with device activity features.
    • Enhanced the ReactNativeDeviceActivityModule with new functions for managing activity selections and their metadata.
  • Refactor

    • Streamlined the user interface for activity and whitelist management, ensuring a more intuitive and responsive experience.
    • Updated project structure and paths to align with the new organization of files and directories.
  • Tests

    • Added tests for set operations on family activity selections to ensure correctness in various scenarios.
    • Added tests for string replacement functionality and event comparisons to enhance coverage.
    • Introduced new test suites for validating the functionality of the shield activation and family selection management.
  • Chores

    • Expanded .gitignore to cover a broader range of files and directories relevant to various development environments and tools.
    • Updated iOS deployment target to 15.1 across various configuration files.

@coderabbitai

coderabbitai Bot commented Feb 14, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This pull request updates CI workflows to replace Node.js with Bun, refines directory paths and linting configurations, and reorganizes the project structure. In the mobile app, legacy shield components are replaced by new UI components for set operations and whitelisting, along with updated navigation. Significant enhancements are made to the native iOS module for device activity selection through new set operation functions, type definitions, and view components. Several test suites and configuration files have been added, removed, or modified to support these changes.

Changes

File(s) Change Summary
.github/workflows/pr.yml, .github/workflows/test.yml, .husky/pre-commit, .swiftlint.yml, .github/workflows/npm-publish.yml Updated CI workflows: removed Node.js setup; switched to Bun; adjusted working-directory paths; updated linting rules and paths; modified npm publish process for new structure.
apps/example/Monitoring.tsx, apps/example/app.json, apps/example/components/ActivityPicker.tsx, apps/example/index.js, apps/example/metro.config.js, apps/example/package.json, apps/example/screens/AllTheThings.tsx, apps/example/tsconfig.json, apps/example/webpack.config.js, apps/example/App.tsx, apps/example/screens/WhiteList.tsx, apps/example/screens/SetOps.tsx Modified app configuration and components: updated entry points, dependencies, and JSON configs; introduced new UI components (ActivityPicker, SetOpsTab, WhiteListTab); restructured navigation (renaming Shield to Set ops).
packages/react-native-device-activity/** (all files in this package) Enhanced the native module: updated import paths, added new config files, introduced new Swift structs, functions (set operations, block/unblock methods), view components (including persisted views), and updated type definitions and exports.
package.json (root) and removal of files in example/ (e.g., metro.config.js, ShieldTab.tsx, tsconfig.json, webpack.config.js, expo-module.config.json) Renamed package (to “react-native-device-activity-mono”), bumped version, added workspaces, and removed redundant dependencies and obsolete example configuration files.
apps/example/Tests.xctestplan, apps/example/ios/Tests/**, apps/example/ios/reactnativedeviceactivityexample.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme Introduced new test plans and suites; restructured and renamed test classes to better cover activity selection, set operations, and placeholder replacement functionality.
.gitignore, .vscode/settings.json, .vscode/extensions.json Added new ignore patterns; updated SwiftLint configuration and specified the iPhoneOS SDK path; revised recommended VS Code extension for Swift.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SetOpsTab
    participant ActivityPicker
    participant DeviceActivityModule

    User->>SetOpsTab: Request family activity selection (Family A)
    SetOpsTab->>ActivityPicker: Open selection view
    ActivityPicker-->>SetOpsTab: Return Family A selection
    SetOpsTab->>DeviceActivityModule: Compute set operations (intersection, union, etc.)
    DeviceActivityModule-->>SetOpsTab: Return computed results
    Note over SetOpsTab: UI updated with set operation results
Loading
sequenceDiagram
    participant ExternalTrigger
    participant DeviceActivityMonitorExtension
    participant ReactNativeDeviceActivityModule

    ExternalTrigger->>DeviceActivityMonitorExtension: executeAction(action, placeholders, eventKey)
    DeviceActivityMonitorExtension->>ReactNativeDeviceActivityModule: Process action (e.g., blockSelection, enableBlockAllMode)
    ReactNativeDeviceActivityModule-->>DeviceActivityMonitorExtension: Return action result or error
    DeviceActivityMonitorExtension-->>ExternalTrigger: Action execution completed
Loading

Poem

Oh, I’m a bunny with a joyful hop,
Leaping through changes that never stop.
Set ops and whitelists now take the stage,
Swift code and tests, all crisp on the page.
With each new commit, I dance in delight—
CodeRabbit’s vault shines ever so bright!
🐇💻 Hop on, dear coder, into the night!


📜 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 a68bef7 and c2d82ab.

📒 Files selected for processing (1)
  • packages/react-native-device-activity/ios/ReactNativeDeviceActivity.podspec (1 hunks)

🪧 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

pkg-pr-new Bot commented Feb 14, 2025

Copy link
Copy Markdown

Open in StackBlitz

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

commit: c2d82ab

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between dda0025 and ca0f3da.

📒 Files selected for processing (3)
  • ios/ReactNativeDeviceActivityModule.swift (2 hunks)
  • src/ReactNativeDeviceActivity.types.ts (2 hunks)
  • src/ReactNativeDeviceActivityModule.ts (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Swift Test (example project)
  • GitHub Check: Expo Bundle (example project)
🔇 Additional comments (7)
src/ReactNativeDeviceActivityModule.ts (2)

26-34: LGTM!

The function correctly implements a mock for iOS-specific functionality, providing appropriate default values and warning messages.


46-50: LGTM!

The mock module correctly implements all the new set operation functions and metadata retrieval using the warning function.

src/ReactNativeDeviceActivity.types.ts (3)

25-30: LGTM!

The type definition correctly captures all required metadata properties with appropriate types.


32-32: LGTM!

The type is correctly updated to use the new ActivitySelectionWithMetadata type.


251-269: LGTM!

The method signatures are correctly defined with appropriate parameter types and return types for all set operations and metadata retrieval.

ios/ReactNativeDeviceActivityModule.swift (2)

58-63: LGTM!

The struct definition correctly captures all required metadata properties with appropriate Swift types.


630-643: LGTM!

The function correctly processes the activity selection and returns appropriate metadata.

Comment thread ios/ReactNativeDeviceActivityModule.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 36

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ca0f3da and bf9c866.

⛔ Files ignored due to path filters (34)
  • apps/example/android/app/src/main/res/drawable-hdpi/splashscreen_image.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/drawable-mdpi/splashscreen_image.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/drawable/kingstinct.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • apps/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png is excluded by !**/*.png
  • apps/example/android/gradle/wrapper/gradle-wrapper.jar is excluded by !**/*.jar
  • apps/example/assets/adaptive-icon.png is excluded by !**/*.png
  • apps/example/assets/favicon.png is excluded by !**/*.png
  • apps/example/assets/icon.png is excluded by !**/*.png
  • apps/example/assets/kingstinct.png is excluded by !**/*.png
  • apps/example/assets/splash.png is excluded by !**/*.png
  • apps/example/ios/Podfile.lock is excluded by !**/*.lock
  • apps/example/ios/reactnativedeviceactivityexample/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png is excluded by !**/*.png
  • apps/example/ios/reactnativedeviceactivityexample/Images.xcassets/SplashScreen.imageset/image.png is excluded by !**/*.png
  • apps/example/ios/reactnativedeviceactivityexample/Images.xcassets/SplashScreenBackground.imageset/image.png is excluded by !**/*.png
  • apps/example/ios/reactnativedeviceactivityexample/Images.xcassets/kingstinct.imageset/kingstinct.png is excluded by !**/*.png
  • bun.lock is excluded by !**/*.lock
  • example/bun.lock is excluded by !**/*.lock
📒 Files selected for processing (39)
  • .github/workflows/pr.yml (1 hunks)
  • .github/workflows/test.yml (6 hunks)
  • .husky/pre-commit (1 hunks)
  • .swiftlint.yml (1 hunks)
  • apps/example/Monitoring.tsx (2 hunks)
  • apps/example/app.json (2 hunks)
  • apps/example/components/ActivityPicker.tsx (1 hunks)
  • apps/example/index.js (1 hunks)
  • apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (3 hunks)
  • apps/example/metro.config.js (1 hunks)
  • apps/example/package.json (3 hunks)
  • apps/example/screens/AllTheThings.tsx (6 hunks)
  • apps/example/screens/ShieldTab.tsx (1 hunks)
  • apps/example/tsconfig.json (1 hunks)
  • apps/example/webpack.config.js (1 hunks)
  • example/metro.config.js (0 hunks)
  • example/screens/ShieldTab.tsx (0 hunks)
  • example/tsconfig.json (0 hunks)
  • example/webpack.config.js (0 hunks)
  • expo-module.config.json (0 hunks)
  • package.json (2 hunks)
  • packages/react-native-device-activity/app.plugin.js (1 hunks)
  • packages/react-native-device-activity/config-plugin/getAppGroupFromExpoConfig.js (1 hunks)
  • packages/react-native-device-activity/config-plugin/withCopyTargetFolder.js (2 hunks)
  • packages/react-native-device-activity/expo-module.config.json (1 hunks)
  • packages/react-native-device-activity/ios/ReactNativeDeviceActivityModule.swift (6 hunks)
  • packages/react-native-device-activity/ios/ReactNativeDeviceActivityView.swift (1 hunks)
  • packages/react-native-device-activity/ios/ReactNativeDeviceActivityViewPersisted.swift (1 hunks)
  • packages/react-native-device-activity/ios/ScreenTimeActivityPicker.swift (1 hunks)
  • packages/react-native-device-activity/ios/Shared.swift (12 hunks)
  • packages/react-native-device-activity/package.json (1 hunks)
  • packages/react-native-device-activity/src/DeviceActivitySelectionViewPersisted.ios.tsx (1 hunks)
  • packages/react-native-device-activity/src/DeviceActivitySelectionViewPersisted.tsx (1 hunks)
  • packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (6 hunks)
  • packages/react-native-device-activity/src/ReactNativeDeviceActivityModule.ts (2 hunks)
  • packages/react-native-device-activity/src/index.ts (5 hunks)
  • packages/react-native-device-activity/targets/ActivityMonitorExtension/DeviceActivityMonitorExtension.swift (1 hunks)
  • packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (3 hunks)
  • packages/react-native-device-activity/targets/ShieldConfiguration/ShieldConfigurationExtension.swift (7 hunks)
💤 Files with no reviewable changes (5)
  • example/tsconfig.json
  • example/metro.config.js
  • example/webpack.config.js
  • expo-module.config.json
  • example/screens/ShieldTab.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
apps/example/webpack.config.js

[error] 3-3: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)

apps/example/metro.config.js

[error] 4-4: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)

apps/example/screens/ShieldTab.tsx

[error] 296-296: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 297-297: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 298-298: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 300-301: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)


[error] 304-305: Template literals are preferred over string concatenation.

Unsafe fix: Use a template literal.

(lint/style/useTemplate)

packages/react-native-device-activity/src/index.ts

[error] 362-362: The function should not return a value because its return type is void.

The function is here:

'void' signals the absence of value. The returned value is likely to be ignored by the caller.

(lint/correctness/noVoidTypeReturn)


[error] 367-367: The function should not return a value because its return type is void.

The function is here:

'void' signals the absence of value. The returned value is likely to be ignored by the caller.

(lint/correctness/noVoidTypeReturn)

🪛 YAMLlint (1.35.1)
.github/workflows/test.yml

[error] 119-119: trailing spaces

(trailing-spaces)


[error] 158-158: trailing spaces

(trailing-spaces)


[error] 161-161: trailing spaces

(trailing-spaces)

.github/workflows/pr.yml

[error] 27-27: no new line character at the end of file

(new-line-at-end-of-file)

.swiftlint.yml

[error] 14-14: wrong indentation: expected 2 but found 0

(indentation)


[error] 16-16: no new line character at the end of file

(new-line-at-end-of-file)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Swift Test (example project)
  • GitHub Check: SwiftLint (example project)
🔇 Additional comments (84)
packages/react-native-device-activity/expo-module.config.json (1)

1-6: Expo module configuration is properly structured.

This configuration correctly defines the iOS platform support and specifies the two modules that are part of the package. The JSON is well-formatted and provides clear information about module integration.

apps/example/tsconfig.json (1)

1-11: Well-configured TypeScript setup with proper path aliases.

The TypeScript configuration properly extends Expo's base configuration and includes important compiler options:

  • Enabling strict type checking is a good practice for catching potential type errors
  • Custom path mappings for the react-native-device-activity module will simplify imports
  • The configuration properly handles both direct module imports and submodule imports

This configuration will improve development experience and code maintainability.

apps/example/index.js (1)

1-5: Standard Expo entry point implementation.

This file correctly:

  • Imports the necessary registerRootComponent function from Expo
  • Imports the main App component from the local file
  • Registers the App component as the root component for the application

This follows the recommended pattern for Expo applications and serves as a proper entry point.

packages/react-native-device-activity/config-plugin/withCopyTargetFolder.js (1)

11-11: Remove empty line.

This is just a blank line that was added - no impact on functionality.

.husky/pre-commit (1)

1-2:

Details

❓ Verification inconclusive

Verify that both paths align with the project structure.

The paths have been updated to reflect the new project structure. Ensure that all Swift files in the specified directories will be processed by the format and lint commands.


🏁 Script executed:

#!/bin/bash
# Verify that the specified directories exist in the project
echo "Checking if the Swift directories exist..."
ls -la ./packages/react-native-device-activity/ios
ls -la ./packages/react-native-device-activity/targets
ls -la ./apps/example/ios
echo "Checking if the SwiftLint binary exists at the specified path..."
ls -la apps/example/ios/Pods/SwiftLint/swiftlint

Length of output: 2191


Action Required: Verify SwiftLint Binary Path

  • The directory paths used for the Swift formatting command (i.e., for the react-native-device-activity and example/ios directories) correctly reflect the current project structure.
  • However, the specified SwiftLint binary at apps/example/ios/Pods/SwiftLint/swiftlint was not found. Please verify if:
    • SwiftLint is installed through CocoaPods in a different path, or
    • The command should point to a globally installed binary or another location.
  • Update the pre-commit script accordingly to ensure that all Swift files are linted as intended.
apps/example/app.json (1)

37-37: Bracket formatting aligned with surrounding code style.

The closing bracket has been moved to the same line as the closing curly brace, which aligns with the formatting style used throughout the file.

packages/react-native-device-activity/package.json (1)

1-54:

Details

❓ Verification inconclusive

Verify package version and name consistency

The package version is set to "0.4.13", but the PR title suggests this is adding new functionality. Consider whether this warrants a version bump following semantic versioning principles, especially if introducing new ActivitySelectionWithMetadata features.

Also, the AI summary mentioned this package might be renamed to "react-native-device-activity-mono", but it's still "react-native-device-activity" here. Please confirm this is intentional.


🏁 Script executed:

#!/bin/bash
# Check for references to package name in the codebase
echo "Checking for references to package name..."
rg -l "react-native-device-activity-mono" || echo "No references to react-native-device-activity-mono found"

# Check if this is a version bump from a previous version
echo "Checking git history for previous package version..."
git log -p -- packages/react-native-device-activity/package.json | grep -A 2 -B 2 "version" | head -n 10 || echo "No previous version found in git history"

Length of output: 264


Action Required: Confirm Version Bump and Package Naming Consistency

  • The package version remains "0.4.13" even though the PR introduces new functionality (e.g., ActivitySelectionWithMetadata). Please verify if this change requires a semantic version bump.
  • A repository-wide search returned a reference to "react-native-device-activity-mono" (in at least one "package.json"), yet the package name here is "react-native-device-activity". Confirm that this naming decision is intentional or update accordingly.
apps/example/Monitoring.tsx (1)

10-13: Good use of named imports for better code organization

Using named imports from the library improves code readability and allows better IDE autocompletion. Consider using only named imports throughout the file for consistency.

apps/example/metro.config.js (2)

1-42: Well-structured Metro configuration for monorepo workspaces

The Metro configuration is well-structured for a monorepo workspace, properly resolving modules from both the project and workspace root. The configuration to explicitly include the react-native-device-activity package in watchFolders and extraNodeModules ensures Metro will properly handle the package during development.

🧰 Tools
🪛 Biome (1.9.4)

[error] 4-4: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)


4-4: 🧹 Nitpick (assertive)

✅ Verification successful

Use Node.js import protocol for built-in modules

Use the node: protocol when importing Node.js built-in modules for better clarity and to follow modern best practices.

- const path = require("path");
+ const path = require("node:path");

🌐 Web query:

Why should I use node: protocol for Node.js built-in modules?

💡 Result:

Using the node: protocol for Node.js built-in modules offers key advantages in code clarity and reliability:

1. Explicit Module Identification

  • The node: prefix clearly distinguishes built-in modules from third-party or local modules. For example:
    import fs from 'node:fs/promises';  // Explicit built-in
    import lodash from 'lodash';        // Third-party module
    This eliminates ambiguity, especially for developers unfamiliar with Node.js's core modules[1][3][6].

2. Prevents Module Overrides

  • Without node:, a malicious or accidental node_modules package named fs could override the built-in fs module. The protocol ensures Node.js prioritizes its native modules[1][3][6].

3. Tooling and Ecosystem Support

  • Linting: Tools like eslint-plugin-unicorn and Biome enforce node: usage for built-ins via rules like prefer-node-protocol[8][10].
  • TypeScript: Supported via @types/node (v16+)[1][6].

Compatibility

Node.js Version Support Scope
≥ v16.0.0 Full (ESM + CommonJS)
≥ v14.18.0 Full (ESM + CommonJS)
≥ v12.20.0 ESM only

Practical Usage

CommonJS

const fs = require('node:fs');  // Preferred
const crypto = require('crypto');  // Legacy (risks override)

ES Modules

import { readFile } from 'node:fs/promises';  // Explicit
import { readFile } from 'fs/promises';       // Implicit (avoid)

By adopting node:, developers reduce ambiguity, enhance security, and align with modern tooling standards[1][3][8].

Citations:


Refactor: Use node: protocol for built-in modules in apps/example/metro.config.js

The updated code should explicitly use the Node.js import protocol. This change clarifies that the module comes from Node.js built-ins and protects against potential module overrides. Based on the research, using the node: prefix improves code clarity, aligns with modern best practices, and supports tooling such as ESLint plugins and TypeScript definitions.

  • Location: apps/example/metro.config.js, line 4
  • Proposed Diff:
    - const path = require("path");
    + const path = require("node:path");
🧰 Tools
🪛 Biome (1.9.4)

[error] 4-4: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)

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

14-14: Replace ScreenTimeSelectAppsContentView with ActivityPicker type

Good update to change the contentView type to use the new ActivityPicker component. This alignment ensures type safety.


20-20: Initialize contentView with ActivityPicker

The initialization has been correctly updated to use ActivityPicker instead of ScreenTimeSelectAppsContentView, maintaining the same model parameter.


59-64:

Details

✅ Verification successful

Ensure ActivitySelectionWithMetadata structure matches TypeScript definition

The event data structure being passed to onSelectionChange includes application, category, and web domain counts. Verify that the ActivitySelectionWithMetadata TypeScript interface in the React Native code matches this structure exactly, especially the property names and types.


🏁 Script executed:

#!/bin/bash
# Check the TypeScript interface definition
echo "Checking TypeScript interface for ActivitySelectionWithMetadata..."
rg -A 10 "export (type|interface) ActivitySelectionWithMetadata" packages/react-native-device-activity/

Length of output: 1492


Verified TypeScript-Swift Structure Alignment

The TypeScript definition for ActivitySelectionWithMetadata (found in packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts) combines the familyActivitySelection property with the additional metadata (from ActivitySelectionMetadata) that is expected to include the applicationCount, categoryCount, and webDomainCount properties. The Swift event payload sent via onSelectionChange uses exactly these keys. No further action is required.

.github/workflows/test.yml (2)

51-51: Working directory correctly updated to match new project structure

The update to use apps/example as the working directory for the typecheck command aligns with the project's reorganization, ensuring the command executes in the correct context.


66-66: Working directories properly updated for Expo commands

The working directory paths for Expo commands (export, config, prebuild) have been consistently updated to match the new project structure with the app now residing in the apps/example directory.

Also applies to: 81-81, 96-96

apps/example/components/ActivityPicker.tsx (4)

1-8: Import structure looks good

The imports are well organized, clearly separating React Native core components, the device activity library components, and the UI library imports.


28-47: Props interface is well defined

The props for ActivityPicker are clearly typed with appropriate use of TypeScript for the event structure and optionality.


86-141: ActivityPickerPersisted implements enhanced functionality

The persisted version of the picker correctly uses the ActivitySelectionMetadata type for the event and adds support for the includeEntireCategory option, which aligns with the changes in the Swift code.

The same style duplication issue exists here as mentioned in the previous comment about the ActivityPicker component.


63-79:

Details

❓ Verification inconclusive

Verify the pointerEvents setting

The pointerEvents: "none" property on the DeviceActivitySelectionView will prevent user interaction with this component. Ensure this is intentional and doesn't conflict with the selection functionality.

If users are expected to interact with the selection view, you should remove this property. If there's another interaction mechanism at work, consider adding a comment explaining why interactions are disabled.


🏁 Script executed:

#!/bin/bash
# Search for other instances of DeviceActivitySelectionView to understand the interaction pattern
rg -A 5 "DeviceActivitySelectionView" --type tsx --type ts

Length of output: 86


I'm noticing that the previous search command failed because the "tsx" file type wasn’t recognized. To gather more context about how DeviceActivitySelectionView is used (and whether disabling pointer events is intentional), please run a new search that adds support for TSX files. For example, you could try:

Once you’ve confirmed whether this component ever appears with a different pointerEvents setting or has any inline comments explaining why interactions are disabled, please verify manually that this behavior is intentional.


Action Required: Verify the Disabled Interactions
• Confirm that pointerEvents: "none" on the <DeviceActivitySelectionView> in apps/example/components/ActivityPicker.tsx (lines 63–79) is intended for the final UI behavior.
• If user interaction with this component is expected, remove or adjust the property and add a corresponding comment. Otherwise, ensure the current implementation won’t cause unexpected issues.


🏁 Script executed:

#!/bin/bash
# Search for references to DeviceActivitySelectionView across TSX files by adding a TSX file type
rg "DeviceActivitySelectionView" --type-add 'tsx:*.tsx' --type tsx .

Length of output: 3030


Action Required: Confirm Intentional Disabled Interactivity in DeviceActivitySelectionView

  • In apps/example/components/ActivityPicker.tsx (lines 63–79), the <DeviceActivitySelectionView> is rendered with the style property pointerEvents: "none", which completely disables user interaction with it.
  • Our search across the codebase shows multiple references to DeviceActivitySelectionView (e.g., in Monitoring and CreateActivity components) without any accompanying comments or variations in the pointerEvents setting.
  • Please verify that disabling pointer events is intentional. If user interaction is meant to be enabled in this context, remove or modify the property and add an inline comment explaining the change. If the current behavior is intended, consider adding a comment clarifying why interactions are disabled to avoid confusion in the future.
packages/react-native-device-activity/ios/ScreenTimeActivityPicker.swift (3)

21-24: New properties added for enhanced selection control

The addition of activitySelectionId and includeEntireCategory properties to the model is a good enhancement that provides more flexibility in how activities are selected and persisted.


30-30: Renamed struct for better clarity

Renaming from Picker to ActivityPicker improves the specificity and makes the purpose of this struct clearer. This is a good change that follows Swift naming conventions.


36-37: Simplified property access

Simplifying the access of headerText and footerText from $model.headerText.wrappedValue to model.headerText makes the code cleaner and more readable.

apps/example/package.json (4)

10-10: New bundling script added

A new script for bundling the application has been added, which is useful for generating deployable builds. This is a good addition.


24-24: Updated dependency reference to use workspace

Changing the dependency reference from a relative path to a workspace reference is appropriate for a monorepo structure. This aligns with the project reorganization.


35-35: Updated native modules directory path

The nativeModulesDir path has been adjusted to reflect the new project structure, which is necessary for proper auto-linking.


4-4:

Details

✅ Verification successful

Main entry point updated

The main entry point has been changed from "expo/AppEntry.js" to "index.js". This change should align with the project's file structure.

Make sure that the index.js file exists and properly initializes the application:


🏁 Script executed:

#!/bin/bash
# Check if index.js exists in the apps/example directory
ls -l apps/example/index.js

# Check the content of the index.js file to ensure it's properly initializing the app
cat apps/example/index.js

Length of output: 228


Main entry point verified and updated

The change to using "index.js" in the package.json has been confirmed. The file apps/example/index.js exists and correctly initializes the application by importing App and calling registerRootComponent(App).

package.json (1)

2-32: No major issues noted.

These changes look consistent with a monorepo setup, and setting "private": true is appropriate if this package isn’t intended for public distribution.

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

1-97: Overall logic appears solid.

The combination of Combine debouncing and local event dispatching is well-structured. Marking this as approved.

apps/example/screens/AllTheThings.tsx (4)

187-190: LGTM! Code simplification.

The implementation now directly fetches the family activity selection using the selection ID rather than maintaining it in component state, which reduces state management complexity.


200-200: LGTM! Proper state management.

Good addition of state for controlling the visibility of the activity picker component.


251-277: API usage improved with more intuitive methods.

The changes replace the old blocking/unblocking implementation with more descriptive and function-specific methods: blockAllApps, unblockAllApps, blockAppsWithSelectionId, and unblockSelectedApps. This improves code readability and maintainability.


332-363: LGTM! Enhanced UI with proper activity selection.

The implementation of the activity picker with visibility control and appropriate callbacks is well done. The ability to reload the picker through the onReload callback provides a good user experience when changes need to be refreshed.

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

23-33: LGTM! Enhanced URL handling with flexible options.

The addition of both openUrl and openUrlWithDispatch options provides good flexibility in URL handling, allowing for both immediate and asynchronous URL opening depending on the use case.


42-42: LGTM! Improved code maintainability.

Using a constant (CURRENT_UNBLOCKED_SELECTION) instead of a hardcoded string improves code maintainability and reduces the risk of typo errors.


59-59: LGTM! Consistent use of constants.

Consistently using the same constant for retrieving and storing data ensures data integrity and improves code maintainability.


80-87: LGTM! Improved configuration retrieval.

The use of getActivitySelectionPrefixedConfigFromUserDefaults with multiple parameters provides more flexibility in configuration retrieval, allowing for context-specific configurations based on application and web domain tokens.

packages/react-native-device-activity/src/ReactNativeDeviceActivityModule.ts (3)

26-34: LGTM! Well-structured mock implementation.

The warnFnActivitySelectionWithMetadata function provides a consistent and structured mock response for activity selection metadata, which is important for testing and for providing fallback behavior on unsupported platforms.


47-51: LGTM! Consistent API mocking.

These mock implementations for activity selection operations ensure the module provides consistent behavior across platforms, with appropriate warnings when used on unsupported platforms.


59-61: LGTM! Additional mock methods for app control.

Adding mock implementations for blockAllApps, unblockAllApps, and unblockSelectedApps ensures API consistency across platforms and provides appropriate warnings when used in unsupported environments.

packages/react-native-device-activity/targets/ShieldConfiguration/ShieldConfigurationExtension.swift (5)

34-47: LGTM! Well-implemented image loading utility.

The loadImageFromAppGroupDirectory function provides a clean way to load images from the app group directory with proper error handling, returning nil when the image cannot be loaded.


59-61: Image loading implementation now uses the new utility function.

The code now uses the newly created loadImageFromAppGroupDirectory function for loading images from the app group directory, which provides consistent image loading behavior.


70-120: LGTM! Improved function signature and flexibility.

Renaming getShieldConfiguration to buildShield and modifying it to accept an external configuration parameter improves function flexibility and testability by decoupling the configuration retrieval from the shield building logic.


138-145: LGTM! Consistent approach to configuration retrieval.

The updated function call uses the new buildShield function with configuration retrieved from getActivitySelectionPrefixedConfigFromUserDefaults, providing a standardized approach to configuration handling.


163-171: LGTM! Consistent pattern application.

The same pattern is correctly applied to all shield configuration scenarios, ensuring consistent behavior across different contexts (applications, web domains, and categories).

Also applies to: 186-193, 211-219

apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (2)

874-874: Confirm the updated REACT_NATIVE_PATH.

Ensure that "${PODS_ROOT}/../../../../node_modules/react-native" accurately reflects the updated monorepo structure and won’t break local developer environments or CI/CD pipelines.


936-936: Re-check path alignment across environments.

Similar to the previous line, verify that this path modification does not disrupt or conflict with other build steps. Be sure that all references to react-native across the project remain consistent.

packages/react-native-device-activity/ios/ReactNativeDeviceActivityModule.swift (5)

10-28: Shield state-check function looks good.

The logic cleanly checks multiple shielded item types. Just ensure store is properly synchronized or locked if accessed concurrently. Otherwise, no immediate concerns.


572-587: Intersection function clarity.

This function is straightforward, taking two serialized selections and returning metadata. Ensure you handle potential decoding errors in the underlying deserializeFamilyActivitySelection to avoid partial data or crashes.


588-603: Union operation.

The union logic is correct. As with the intersection function, confirm that invalid or null inputs have a graceful handling path to avoid runtime exceptions.


620-635: Symmetric difference.

Implementation follows the typical symmetricDifference pattern. No immediate concerns. Use test coverage for boundary cases.


713-715: blockAllApps helper.

Implements a catch-all blocking scenario. Ensure reusability by referencing it from higher-level functions that block multiple categories.

packages/react-native-device-activity/src/index.ts (8)

6-6: Imported persisted view.

Importing the persisted variant is a logical addition. Verify that you’re consistently exposing it to consumers.


9-9: Added ActivitySelectionWithMetadata in import.

Great for typed set operations. Ensure other modules or code referencing it remain in sync with any future changes.


18-18: Newly exported props interface.

Exposing DeviceActivitySelectionViewPersistedProps is beneficial for typed usage. Keep it consistent with the actual persisted component’s required properties.


143-151: Intersection utility.

Well-defined wrapper that delegates to the native module. Confirm that invalid or empty selections are handled gracefully to prevent unexpected null returns.


163-171: Difference utility.

Straightforward difference operation. As with intersection and union, confirm you have coverage for duplicate tokens or large sets.


183-189: Retrieve selection metadata.

Neat function to gather selection stats. Validate that the string is always properly serialized in calling code before usage.


507-508: Exporting both device activity selection views.

Exposing these for broader usage in the app is helpful. Keep them properly documented for clarity on differences between the normal and persisted versions.


509-513: Export typed props for both views.

Name alignment is good. The renaming clarifies usage in your codebase. No issues noted.

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

25-29: Type definition for ActivitySelectionMetadata looks good.

Declaring these numeric properties is straightforward, and these counts intuitively capture the observed selection metadata. No further corrections needed here.


31-33: Ensure nullable type is appropriate for familyActivitySelection.

By defining familyActivitySelection as string | null, you handle situations where no family activity selection is active. Confirm that all call sites can handle null values gracefully.


35-35: Renaming to ActivitySelectionWithMetadata aligns well with the new structure.

Good job unifying the event type with the added metadata, ensuring consistency.


47-56: New DeviceActivitySelectionViewPersistedProps provides richer configuration.

The added properties (like includeEntireCategory) appear beneficial for more flexible UI handling, especially if entire categories need toggling.


211-213: Adding type "unblockSelection" with an explicit familyActivitySelectionId is clear.

This design improves clarity by tying the unblock action directly to a specific selection identifier.


215-215: Introducing the "unblockAllApps" type is consistent with the other block/unblock methods.

Nicely distinguishes between unblocking all apps vs. a subset.


246-260: Expanded doc comments for AuthorizationStatus are comprehensive.

These comments improve clarity and help eliminate confusion around authorization states.


278-281: Exposing unblockSelectedApps with typed parameters encourages correct usage.

The familyActivitySelectionId parameter ensures the call site supplies the appropriate identifier to target the selection.


284-303: New utility methods for activity selection metadata and set operations look solid.

Methods like intersection, union, difference, and symmetricDifference provide clear, modular manipulation of user selections. Verify that these are fully tested for edge cases.


311-311: blockAllApps method is clearly named and consistent with similar methods.

This helps unify the approach to blocking logic within the module.


317-317: unblockAllApps method aligns nicely with the new blockAllApps approach.

It extends the same clarity for comprehensive unblocking across the entire selection range.

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

16-22: New user defaults keys improve clarity for selection-based configurations.

Defining separate prefixes and flags helps avoid collisions and keeps the code more organized.


35-71: updateShield now supports activitySelectionId, enhancing fine-grained updates.

Saving shield settings to both a default key and a selection-specific key fosters better reuse and scoping.


318-332: getFamilyActivitySelectionIds returns a non-optional array, reducing null checks.

This change consolidates selection retrieval logic and ensures an always-initialized collection.


336-346: getFamilyActivitySelectionById neatly deserializes the stored selection.

This allows calling code to retrieve specific family activity selections by identifier. Good usage of user defaults references.


349-364: setFamilyActivitySelectionById function organizes selection storage.

Storing serialized selection strings per ID greatly simplifies future lookups and modifications.


367-413: getActivitySelectionPrefixedConfigFromUserDefaults is a robust way to look up per-selection configs.

It dynamically finds a matching selection entry before falling back to the default key. This approach should handle multi-selection environments well.


415-446: getPossibleFamilyActivitySelectionId function adds valuable reverse lookup ability.

This method helps in quickly finding a selection ID related to a specific token or category.


526-547: intersection function is straightforward and properly merges tokens.

Clean set-based logic, ensuring only overlapping activity tokens remain.


550-572: symmetricDifference function correctly captures tokens exclusive to each selection.

This helps highlight items that don’t appear in both sets simultaneously.


575-596: difference function reliably subtracts tokens from the first selection.

The return type is straightforward and fosters easy composition with other set operations.


599-620: union function properly combines tokens from both selections.

This enables aggregate blocking or unblocking across multiple sets in a concise manner.


623-690: blockSelectedApps effectively coordinates partial blocking states with user defaults.

By preserving CURRENT_BLOCKED_SELECTION and CURRENT_UNBLOCKED_SELECTION, the function ensures consistent store updates for new or merged selections.


693-760: unblockSelectedApps aligns with blockSelectedApps, maintaining consistent store usage.

Swapping from blocked to unblocked sets, especially when partially blocking or unblocking, appears well handled.


975-994: Refined logic in shouldExecuteAction for skipIfLargerEventRecordedSinceIntervalStarted is clear.

The code gracefully checks interval start triggers to ensure actions are not overshadowed by higher-priority events.

Comment thread packages/react-native-device-activity/app.plugin.js
Comment thread .github/workflows/pr.yml Outdated
Comment thread packages/react-native-device-activity/src/index.ts
Comment thread packages/react-native-device-activity/src/index.ts
Comment thread packages/react-native-device-activity/src/index.ts Outdated
Comment thread packages/react-native-device-activity/src/index.ts Outdated
Comment thread packages/react-native-device-activity/src/index.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
.github/workflows/pr.yml (1)

27-28: 🧹 Nitpick (assertive)

Add newline at the end of the file.

The file is missing a newline character at the end, which is causing the YAMLlint error.

      - run: bunx pkg-pr-new publish
        working-directory: packages/react-native-device-activity
+
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 28-28: no new line character at the end of file

(new-line-at-end-of-file)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bf9c866 and 376a653.

📒 Files selected for processing (2)
  • .github/workflows/pr.yml (1 hunks)
  • apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (3 hunks)
🧰 Additional context used
🪛 YAMLlint (1.35.1)
.github/workflows/pr.yml

[error] 26-26: trailing spaces

(trailing-spaces)


[error] 28-28: no new line character at the end of file

(new-line-at-end-of-file)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Swift Test (example project)
  • GitHub Check: SwiftLint (example project)
🔇 Additional comments (2)
.github/workflows/pr.yml (1)

25-25: Using working directory ensures commands run in the correct context.

Specifying the working directory for the prepublishOnly command is good practice and ensures it runs in the correct context after project reorganization.

apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (1)

105-108: Good move from absolute to relative paths.

The change from absolute paths to relative paths for Swift files improves project portability. The paths now correctly reflect the reorganized project structure, making the project more robust when cloned on different machines.

Comment thread .github/workflows/pr.yml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 20

🔭 Outside diff range comments (1)
apps/example/ios/Tests/SkipTests.swift (1)

98-304: 🧹 Nitpick (assertive)

Well-organized test suite for interval-based skipping
The SkipIfAlreadyTriggeredBetweenTests class effectively demonstrates a time-window-based skip condition. Consider adding edge-case tests around boundary timestamps.

♻️ Duplicate comments (2)
.github/workflows/pr.yml (2)

21-21: 🧹 Nitpick (assertive)

Remove trailing spaces.

There are trailing spaces at the end of line 21 that should be removed, as flagged by YAMLlint.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 21-21: trailing spaces

(trailing-spaces)


22-22: 🧹 Nitpick (assertive)

Add newline at end of file.

Add a newline at the end of the file to fix the YAMLlint error.

      - run: npx pkg-pr-new publish './packages/*'
+
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 22-22: no new line character at the end of file

(new-line-at-end-of-file)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 376a653 and e64dea7.

📒 Files selected for processing (11)
  • .github/workflows/pr.yml (1 hunks)
  • apps/example/Tests.xctestplan (1 hunks)
  • apps/example/ios/Tests/ComparisonTests.swift (1 hunks)
  • apps/example/ios/Tests/FamilySelectionIdTests.swift (1 hunks)
  • apps/example/ios/Tests/SkipTests.swift (4 hunks)
  • apps/example/ios/Tests/TextReplacementTests.swift (1 hunks)
  • apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (4 hunks)
  • apps/example/ios/reactnativedeviceactivityexample.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme (1 hunks)
  • packages/react-native-device-activity/ios/ReactNativeDeviceActivityView.swift (2 hunks)
  • packages/react-native-device-activity/ios/ReactNativeDeviceActivityViewPersisted.swift (1 hunks)
  • packages/react-native-device-activity/ios/Shared.swift (12 hunks)
🧰 Additional context used
🪛 YAMLlint (1.35.1)
.github/workflows/pr.yml

[error] 21-21: trailing spaces

(trailing-spaces)


[error] 22-22: no new line character at the end of file

(new-line-at-end-of-file)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Swift Test (example project)
  • GitHub Check: SwiftLint (example project)
🔇 Additional comments (36)
.github/workflows/pr.yml (2)

20-20: Working directory properly specified.

Adding the working directory ensures the prepublishOnly script runs in the correct context for the react-native-device-activity package. This is important for proper package preparation during the publishing process.


22-22: Path argument correctly specifies target packages.

The addition of the './packages/*' path argument to the pkg-pr-new publish command ensures that all packages in the packages directory are properly targeted, which aligns with the project's reorganized structure.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 22-22: no new line character at the end of file

(new-line-at-end-of-file)

apps/example/ios/reactnativedeviceactivityexample.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme (1)

14-20: Test plan correctly integrated into the scheme.

The addition of the TestPlans section with a reference to the new test plan file is appropriate. Marking it as the default test plan ensures it will be used automatically when running tests through this scheme.

apps/example/ios/Tests/FamilySelectionIdTests.swift (1)

11-16:

Details

❓ Verification inconclusive

Ensure userDefaults is properly initialized.

The code uses userDefaults? with an optional chaining operator, but the variable isn't defined in the visible code. Make sure userDefaults is properly declared and initialized, or consider using UserDefaults.standard directly if appropriate.


🏁 Script executed:

#!/bin/bash
# Search for userDefaults declaration in the codebase
rg -t swift "var\s+userDefaults\s*[:=]" 

Length of output: 149


Verify the initialization and usage of the shared userDefaults in tests

The test file uses userDefaults? without a local declaration. Our search shows a global declaration in packages/react-native-device-activity/ios/Shared.swift:

var userDefaults = UserDefaults(suiteName: appGroup)

Please verify that the test target properly imports and accesses this global instance. If test isolation is a concern, or if the shared instance isn’t intended for test use, consider initializing a local instance (e.g., using UserDefaults.standard) within the test.

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

20-23: Ensure consistent lifecycle management for SwiftUI views.

ActivityPicker initialization within a UIHostingController is appropriate. Verify that the model data flow remains consistent if you plan to dynamically supply or modify any additional SwiftUI states/properties (e.g., environment objects).

apps/example/ios/Tests/TextReplacementTests.swift (6)

12-16: Avoid reliance on implicitly unwrapped optionals for userDefaults.

Ensure userDefaults is properly initialized and consistently referenced. If userDefaults is an optional, consider handling failures or applying dependency injection to reduce potential runtime issues.


24-30: Good coverage of basic string replacement.

The test effectively validates a simple placeholder. Adding additional placeholders or edge cases (e.g., partial placeholder patterns) can strengthen coverage.


37-42: Consider verifying numeric edge cases.

"{asNumber:value}" works for "42", but a test for a non-numeric string, negative numbers, or floating-point strings (e.g., "3.14") may further confirm robust handling.


44-56: Comprehensive testing of multiple placeholders.

The test covers multiple placeholder types in one input. This is well-structured and demonstrates correct usage of the placeholder engine. Good job.


58-70: Maintain consistent type checks.

Verifying that non-string values remain unchanged is solid. Continuing to confirm that only valid placeholders are replaced ensures high reliability. No issues here.


72-84: Excellent edge case coverage for nonexistent placeholders.

The logic properly preserves placeholders with unrecognized or absent keys. This approach mitigates accidental data corruption.

apps/example/ios/Tests/ComparisonTests.swift (1)

12-20: Clarify numeric comparison behavior.

isHigherEvent(eventName: "5", higherThan: "10") returning false implies string-to-integer conversion. Confirm robust error handling or fallback for non-numeric strings (e.g., "abc") if the function is used beyond these tests.

packages/react-native-device-activity/ios/ReactNativeDeviceActivityViewPersisted.swift (2)

18-44: Debounce approach looks correct, verify potential side effects.

The 0.1s debounce is reasonable, but double-check that no user interactions get lost due to short toggles within the debounce window.


46-48: Ensure proper sizing constraints for hosted SwiftUI.

The layoutSubviews override sets the frame to bounds. If the view hierarchy changes size frequently, confirm that any auto layout constraints or parent resizing triggers re-layout as expected.

apps/example/ios/Tests/SkipTests.swift (3)

3-46: Good test class naming for clarity
Renaming and structuring these tests with concise class names like NeverTriggerBeforeTests helps improve readability.


48-49: Ensure coverage of new test class
This new SkipIfTriggeredBeforeTests class is clearly named. Double-check that its tests cover both positive (skips) and negative (does not skip) scenarios.


306-307: SkipIfLargerTests class introduction
This class provides another dimension of skip logic based on comparing recorded events. Ensure large-event tests and borderline thresholds are fully exercised.

apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (5)

105-108: Refactor relative paths for improved portability
These file references now use deeper relative paths. Verify that the new ../../../ structure resolves correctly in all development and CI environments.


109-109: Test plan file addition
Including Tests.xctestplan in the project is a good step toward structured testing. Confirm that all relevant test targets are part of this plan.


226-226: Ensuring the new test plan group reference is valid
A9F920792D7988D400A179B2 /* Tests.xctestplan */ was added to the group children. Double-check that the file is present and recognized by Xcode.


870-871: Inconsistent OTHER_LDFLAGS formatting
The single string format OTHER_LDFLAGS = "$(inherited) "; still includes extra spacing. This comment repeats a past review concern.


929-930: Inconsistent OTHER_LDFLAGS formatting
Same as above: OTHER_LDFLAGS contains extra spaces and differs from other build configurations.

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

16-22: New constant definitions
These added constants (SHIELD_CONFIGURATION_FOR_SELECTION_PREFIX, SHIELD_ACTIONS_FOR_SELECTION_PREFIX, etc.) improve clarity around activity selection data. Usage looks straightforward and consistent with naming conventions.


35-71: Extended updateShield with activitySelectionId
The extra parameter and corresponding user defaults logic provide a convenient way to store shield configurations per activity selection. Ensure any callers have been updated in the codebase to supply the correct activitySelectionId.


256-260: Refined placeholder handling
Reformatting the return statement improves readability. No issues identified.


318-332: Non-optional return for getFamilyActivitySelectionIds
Switching from an optional array to a guaranteed empty array if no items exist is a safer, more consistent API design. Make sure callers are aware they’ll always receive a valid array.


336-337: getFamilyActivitySelectionById uses new dictionary key
The function now references FAMILY_ACTIVITY_SELECTION_ID_KEY. Validate that all references align with the updated naming and that no old key usage remains.


359-376: setFamilyActivitySelectionById ensures dictionary updates
The function merges into an existing dictionary or creates a new one. This approach seems correct; just ensure concurrency safety if multiple threads might write the same entries.


428-458: getPossibleFamilyActivitySelectionId
This function scans the stored selections to locate the first matching token. Consider clarifying the behavior if multiple selections match—currently it returns the first one.


490-511: unblockAllApps cleanup
Removing keys from user defaults and clearing the store is correct. Confirm that external logic does not rely on these keys once removed.


513-529: blockAllApps
The approach is consistent with other shield toggles. The user defaults IS_BLOCKING_ALL is toggled, while category sets are fully blocked. This is straightforward.


531-553: intersection
Combining tokens with intersection clarifies which apps or categories apply across both sets. Implementation is clean.


555-579: symmetricDifference
Your approach using set operations is correct. This function ensures projects can handle partial overlaps in tokens.


581-603: difference
Subtracts tokens from one selection based on another. Straightforward usage of the set API.


605-627: union
Rectifies tokens from two selections by uniting them. Implementation is consistent with the other set-based functions.


698-766: unblockSelectedApps
Expands the set of unblocked tokens, adjusting the categories accordingly. Similar logic to the block flow. Double-check partial unblocking edge cases for categories.

Comment thread apps/example/Tests.xctestplan
Comment thread apps/example/ios/Tests/FamilySelectionIdTests.swift
Comment thread apps/example/ios/Tests/FamilySelectionIdTests.swift
Comment thread apps/example/ios/Tests/FamilySelectionIdTests.swift
Comment thread packages/react-native-device-activity/ios/Shared.swift Outdated
Comment thread packages/react-native-device-activity/ios/Shared.swift
Comment thread packages/react-native-device-activity/ios/Shared.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (1)
.github/workflows/pr.yml (1)

21-21: 🧹 Nitpick (assertive)

Remove Trailing Spaces
YAMLlint flagged trailing spaces on this line. Please remove any trailing whitespace to adhere to project style guidelines.

Suggested Diff:

-      
+      

(Ensure no whitespace remains on this otherwise blank line.)

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 21-21: trailing spaces

(trailing-spaces)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e64dea7 and 8d18dae.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • .github/workflows/pr.yml (1 hunks)
🧰 Additional context used
🪛 YAMLlint (1.35.1)
.github/workflows/pr.yml

[error] 21-21: trailing spaces

(trailing-spaces)


[error] 22-22: no new line character at the end of file

(new-line-at-end-of-file)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Swift Test (example project)
  • GitHub Check: SwiftLint (example project)
🔇 Additional comments (1)
.github/workflows/pr.yml (1)

19-20: Working Directory Configuration for Prepublish Command
The addition of the working-directory: packages/react-native-device-activity under the bun run prepublishOnly step correctly targets the subdirectory where the command must execute. Please ensure this path remains accurate as the project structure evolves.

Comment thread .github/workflows/pr.yml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8d18dae and f73af82.

📒 Files selected for processing (1)
  • .gitignore (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Swift Test (example project)
  • GitHub Check: SwiftLint (example project)
🔇 Additional comments (6)
.gitignore (6)

68-69: Verify the inclusion of Yarn version files.
The addition of !.yarn/versions ensures that Yarn version files are tracked rather than ignored. Please confirm that this exemption is intentional and aligns with your version management strategy.


82-89: Good addition: Native sensitive file patterns.
The new "Native" section correctly ignores file patterns such as *.orig.*, *.jks, *.p8, *.p12, *.key, and *.mobileprovision. This is a useful security measure to prevent accidental commits of sensitive data.


90-92: Approved: Metro health check ignore rule.
The ignore pattern for .metro-health-check* is appropriate to filter out temporary or health check files generated by Metro.


93-97: Clarify debug log patterns.
The "debug" section now includes wildcards for npm-debug.*, yarn-debug.*, and yarn-error.*. Since similar log files (e.g., npm-debug.log) are already excluded earlier, please confirm that this broader pattern is intentional to capture all variants.
[nitpick, verify]


102-104: Approved: Local environment files exclusion.
Ignoring .env*.local files is a sound security practice to prevent local configuration details from being committed.


105-107: Approved: TypeScript build info is properly excluded.
The addition of *.tsbuildinfo in the "typescript" section ensures that TypeScript build artifacts are not committed to the repository.

Comment thread .gitignore Outdated
Comment thread .gitignore Outdated
Comment thread .gitignore

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (2)
packages/react-native-device-activity/package.json (2)

33-38: 🧹 Nitpick (assertive)

Dependency Version Specification
Within the dependencies block, note that "@kingstinct/expo-apple-targets" is set to "0". It is advisable to specify a version range (for example, "^0.0.0") to allow for compatible updates while avoiding unintended major changes.

Proposed diff:

-    "@kingstinct/expo-apple-targets": "0",
+    "@kingstinct/expo-apple-targets": "^0.0.0",

48-52: 🛠️ Refactor suggestion

Specify Peer Dependency Version Ranges
The peerDependencies are currently defined with "*" which allows any version. For better compatibility control and to prevent consumers from accidentally using unsupported versions, consider specifying minimum version ranges. For instance:

-  "peerDependencies": {
-    "expo": "*",
-    "react": "*",
-    "react-native": "*"
-  }
+  "peerDependencies": {
+    "expo": ">=51.0.0",
+    "react": ">=18.0.0",
+    "react-native": ">=0.70.0"
+  }

This change helps ensure that users install versions known to work with your module.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f73af82 and ddb0478.

📒 Files selected for processing (1)
  • packages/react-native-device-activity/package.json (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Swift Test (example project)
  • GitHub Check: SwiftLint (example project)
🔇 Additional comments (3)
packages/react-native-device-activity/package.json (3)

7-17: Scripts Configuration Check
The scripts section is well organized and includes commands for build, cleanup, linting, testing, and opening platform-specific project folders. Ensure that the paths (e.g., "xed example/ios" and "open -a \"Android Studio\" example/android") remain valid as the project structure evolves.


24-32: Repository and Related Metadata
The repository, bugs, author, license, and homepage fields are correctly set. No changes required here.


39-47: DevDependencies Pinning
The devDependencies are currently pinned to specific versions. This is generally acceptable for development tooling. Just ensure these versions are compatible with your overall build and test environments.

Comment thread packages/react-native-device-activity/package.json
Comment thread packages/react-native-device-activity/package.json Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (1)
apps/example/screens/AllTheThings.tsx (1)

332-371: 🧹 Nitpick (assertive)

Well-implemented user interface for activity selection.

The addition of a Pressable component with the ActivityPickerPersisted modal provides a clear and intuitive interface for users to select applications. The implementation includes proper visibility handling and event callbacks.

However, consider adding error handling for the selection change operation:

onSelectionChange={(event) => {
  console.log("selection changed", event.nativeEvent);
+ try {
    console.log(
      JSON.stringify(
        ReactNativeDeviceActivity.userDefaultsGet(
          "familyActivitySelectionIds",
        ),
        null,
        2,
      ),
    );
+ } catch (error) {
+   console.error("Failed to retrieve selection IDs:", error);
+ }
}}
♻️ Duplicate comments (2)
.github/workflows/pr.yml (2)

24-24: 🧹 Nitpick (assertive)

Remove trailing spaces.

There are trailing spaces at the end of line 24 that should be removed.

-      
+
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 24-24: trailing spaces

(trailing-spaces)


26-26: 🧹 Nitpick (assertive)

Add newline at end of file.

The file is missing a newline character at the end, which is a common linting requirement.

-        run: bunx pkg-pr-new@latest publish './packages/*'
+        run: bunx pkg-pr-new@latest publish './packages/*'
+
🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 26-26: no new line character at the end of file

(new-line-at-end-of-file)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ddb0478 and b133144.

📒 Files selected for processing (5)
  • .github/workflows/pr.yml (1 hunks)
  • .vscode/settings.json (1 hunks)
  • apps/example/ios/Tests/UnionTests.swift (1 hunks)
  • apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (6 hunks)
  • apps/example/screens/AllTheThings.tsx (6 hunks)
🧰 Additional context used
🪛 YAMLlint (1.35.1)
.github/workflows/pr.yml

[error] 24-24: trailing spaces

(trailing-spaces)


[error] 26-26: no new line character at the end of file

(new-line-at-end-of-file)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Swift Test (example project)
  • GitHub Check: SwiftLint (example project)
🔇 Additional comments (25)
.vscode/settings.json (1)

5-5: Configuration Path Updated for SwiftLint
The SwiftLint executable path has been updated to "apps/example/ios/Pods/SwiftLint/swiftlint", which aligns with the new directory structure. This change ensures consistency with the related updates in the CI/CD and pre-commit configurations.

.github/workflows/pr.yml (1)

19-24: New build steps look good!

The additional build steps properly prepare the package before publishing by ensuring the build and prepublishOnly scripts run in the correct context.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 24-24: trailing spaces

(trailing-spaces)

apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (6)

105-108: Swift file path updates look good.

The file paths have been correctly updated to reflect the new project structure with packages and apps directories. Using SOURCE_ROOT instead of absolute paths improves portability.


870-871: Verify React Native path accessibility.

The React Native path has been updated to accommodate the deeper directory structure, but a previous verification indicated this path might not resolve correctly in all environments.

Run the following script to verify if the React Native module can be found at the specified path:

#!/bin/bash
# Check if the React Native path exists with the new directory structure

echo "Checking if React Native module exists at the specified path..."
EXPECTED_PATH="node_modules/react-native"

# Check from multiple potential root locations
for dir in . .. ../.. ../../.. ../../../..; do
  if [ -d "$dir/$EXPECTED_PATH" ]; then
    echo "✅ Found React Native at $dir/$EXPECTED_PATH"
    exit 0
  fi
done

echo "❌ React Native not found at expected locations relative to current directory"

# Specifically check the exact path format in the project file
if [ -d "${PODS_ROOT}/../../../../node_modules/react-native" ]; then
  echo "✅ Path with PODS_ROOT variable would resolve correctly"
else
  echo "❌ Path with PODS_ROOT variable would not resolve correctly"
fi

929-930: Inconsistent OTHER_LDFLAGS formatting.

The OTHER_LDFLAGS value has been updated to a single string with trailing space ("$(inherited) "), which is inconsistent with other build configurations in the file that use array notation.

This inconsistency was previously identified and should be addressed to maintain a consistent configuration style throughout the project file.


621-621: SwiftLint path has been updated correctly.

The SwiftLint configuration path now correctly points to the root of the project with the new directory structure.


639-639: SwiftLint path updated consistently.

The SwiftLint configuration path has been consistently updated in both build phases.


109-109: New test plan file added.

The addition of the Tests.xctestplan file supports proper test configuration for the reorganized project.

apps/example/screens/AllTheThings.tsx (5)

31-31: Consider using a more descriptive identifier or moving to constants.

The selectionId is hardcoded as "some-id-3" which could make maintenance difficult. For better code organization and readability, consider moving this to a constants file or providing a more descriptive name that indicates its purpose.

-const selectionId = "some-id-3";
+// Consider moving to a constants file
+const ACTIVITY_SELECTION_ID = "example-activity-selection";

185-198: Improved state management for activity selection.

The refactored implementation directly retrieves the family activity selection ID rather than maintaining it in component state, which simplifies the code and reduces potential state synchronization issues.


250-277: Clear API improvements for app blocking/unblocking functionality.

The updated implementation uses more explicit and descriptive API methods:

  • blockAllApps() and unblockAllApps() for managing all applications
  • blockAppsWithSelectionId() and unblockSelectedApps() for managing selected applications

These changes make the code's intent clearer and provide better separation of concerns.


15-15: Good modularization with component imports.

Adding Pressable from react-native and importing the ActivityPickerPersisted component from a separate file shows good modularity and separation of concerns.

Also applies to: 25-26


200-200: Clear state management for UI visibility.

The addition of a dedicated state variable for picker visibility follows React best practices for controlling component visibility.

apps/example/ios/Tests/UnionTests.swift (12)

26-32: LGTM! Good test for empty intersection.

The test correctly verifies that the intersection of two empty selections results in no tokens.


34-40: LGTM! Good test for empty union.

The test correctly verifies that the union of two empty selections results in no tokens.


42-51: LGTM! Good test for union with all categories.

The test correctly verifies that the union of a selection with all categories and an empty selection contains the expected tokens.


53-65: LGTM! Good test for union of two different selections.

The test correctly verifies that the union of two distinct selections (social and games categories) contains the expected tokens.


67-79: LGTM! Good test for difference between equivalent selections.

The test correctly verifies that the difference between two selections containing all categories results in no tokens.


81-90: LGTM! Good test for empty difference.

The test correctly verifies that the difference of two empty selections results in no tokens.


92-107: LGTM! Good test for difference of non-overlapping selections.

The test correctly verifies that the difference between two non-overlapping selections (social and games) contains the expected tokens.


109-124: LGTM! Good test for difference between all categories and games.

The test correctly verifies that the difference between a selection with all categories and one with only games contains the expected tokens.


126-135: LGTM! Good test for empty symmetric difference.

The test correctly verifies that the symmetric difference of two empty selections results in no tokens.


137-152: LGTM! Good test for symmetric difference of non-overlapping selections.

The test correctly verifies that the symmetric difference of two non-overlapping selections (social and games) contains the expected tokens.


154-169: LGTM! Good test for symmetric difference between games and all categories.

The test correctly verifies that the symmetric difference between a selection with only games and one with all categories contains the expected tokens.


8-11:

Details

❓ Verification inconclusive

Verify utility function visibility.

The tests depend on utility functions (deserializeFamilyActivitySelection, intersection, union, difference, symmetricDifference), but these aren't defined in this file. Make sure these functions are properly exposed and accessible to these tests.


🏁 Script executed:

#!/bin/bash
# Check if the required utility functions are defined and accessible

# Look for the implementation of set operation functions
rg -A 1 "func (intersection|union|difference|symmetricDifference)\(" --type swift

# Look for deserializeFamilyActivitySelection implementation
rg -A 1 "func deserializeFamilyActivitySelection" --type swift

Length of output: 1291


Action: Confirm that shared utility functions are accessible in the test target.

The utility functions (deserializeFamilyActivitySelection, intersection, union, difference, and symmetricDifference) are implemented in packages/react-native-device-activity/ios/Shared.swift. Please ensure that these functions are exposed to your tests in apps/example/ios/Tests/UnionTests.swift—for example, by marking them with the appropriate access modifiers (or by using @testable import) so that the test target can reference them.

  • The functions are present in Shared.swift as verified by the grep output.
  • Confirm that the module containing these functions is properly imported into your test target.

Comment thread apps/example/screens/AllTheThings.tsx
Comment thread apps/example/ios/Tests/UnionTests.swift
Comment thread apps/example/ios/Tests/UnionTests.swift
Comment thread apps/example/ios/Tests/UnionTests.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 27

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

416-426: 🛠️ Refactor suggestion

Prevent accidental overwriting during ID renaming.

renameFamilyActivitySelectionId(previousId:newId:) copies data from previousId to newId without checking if newId already exists. Existing data at newId will be overwritten silently.

Use a guard or condition to handle collisions gracefully:

if var familyActivitySelectionIds = userDefaults?.dictionary(forKey: FAMILY_ACTIVITY_SELECTION_ID_KEY) {
+   if familyActivitySelectionIds[newId] != nil {
+     logger.log(level: .error, "renameFamilyActivitySelectionId: key '\(newId)' already in use.")
+     return
+   }
    familyActivitySelectionIds[newId] = familyActivitySelectionIds[previousId]
    ...
 }
packages/react-native-device-activity/targets/ShieldConfiguration/ShieldConfigurationExtension.swift (1)

34-47: ⚠️ Potential issue

Guard against nil appGroupDirectory

The new loadImageFromAppGroupDirectory function forcibly unwraps appGroupDirectory! on line 37, which could cause a runtime crash if the app group directory is not available or properly configured.

Consider safely unwrapping the optional value:

-  let fileURL = appGroupDirectory!.appendingPathComponent(relativeFilePath)
+  guard let appGroupDirectory = appGroupDirectory else {
+    print("Error: No app group directory found.")
+    return nil
+  }
+  let fileURL = appGroupDirectory.appendingPathComponent(relativeFilePath)
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6b52cf0 and 37d0118.

⛔ Files ignored due to path filters (2)
  • apps/example/ios/Podfile.lock is excluded by !**/*.lock
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • README.md (1 hunks)
  • apps/example/app.json (2 hunks)
  • apps/example/ios/Podfile (1 hunks)
  • apps/example/ios/Podfile.properties.json (1 hunks)
  • apps/example/ios/Tests/FamilySelectionIdTests.swift (1 hunks)
  • apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (7 hunks)
  • apps/example/package.json (1 hunks)
  • 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 (8 hunks)
  • packages/react-native-device-activity/src/ReactNativeDeviceActivityModule.ios.ts (1 hunks)
  • packages/react-native-device-activity/src/ReactNativeDeviceActivityModule.ts (1 hunks)
  • packages/react-native-device-activity/src/index.ts (10 hunks)
  • packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (1 hunks)
  • packages/react-native-device-activity/targets/ShieldConfiguration/ShieldConfigurationExtension.swift (4 hunks)
🧰 Additional context used
🧬 Code Definitions (6)
packages/react-native-device-activity/src/ReactNativeDeviceActivityModule.ios.ts (1)
packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (1)
  • ReactNativeDeviceActivityNativeModule (343-448)
packages/react-native-device-activity/targets/ShieldConfiguration/ShieldConfigurationExtension.swift (1)
packages/react-native-device-activity/ios/Shared.swift (1)
  • getAppGroupDirectory (1246-1253)
packages/react-native-device-activity/targets/ShieldAction/ShieldActionExtension.swift (2)
packages/react-native-device-activity/src/index.ts (5)
  • disableBlockAllMode (442-445)
  • unblockSelection (451-463)
  • addSelectionToWhitelistAndUpdateBlock (135-147)
  • resetBlocks (447-449)
  • SHIELD_ACTIONS_KEY (536-536)
packages/react-native-device-activity/ios/Shared.swift (2)
  • openUrl (81-90)
  • sendNotification (100-174)
packages/react-native-device-activity/src/ReactNativeDeviceActivityModule.ts (1)
packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (1)
  • ReactNativeDeviceActivityNativeModule (343-448)
packages/react-native-device-activity/src/index.ts (1)
packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (8)
  • ActivitySelectionInput (305-317)
  • ActivitySelectionInputWithBlocks (319-332)
  • SetOperationOptions (338-341)
  • ActivitySelectionMetadata (26-31)
  • OnDeviceActivityDetectedListener (602-604)
  • EventListenerMap (606-612)
  • OnAuthorizationStatusChange (450-454)
  • DeviceActivityMonitorEventPayload (13-15)
packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (1)
packages/react-native-device-activity/src/index.ts (2)
  • DeviceActivitySelectionViewProps (625-625)
  • DeviceActivitySelectionViewPersistedProps (626-626)
🔇 Additional comments (60)
packages/react-native-device-activity/package.json (1)

2-3: Update Package Metadata for Rebranding
The current metadata uses "name": "react-native-device-activity" with version "0.4.19", which conflicts with previous rebranding suggestions (e.g., "react-native-device-activity-mono" and version "1.0.0"). Please confirm if the rebranding should be applied here or if the current metadata is intentional.

apps/example/package.json (4)

4-4: Confirm Main Entry Point Change
The main entry point has been updated to "index.js", which aligns with the new restructuring of the project. Verify that this change is intentional and that the new entry point correctly initializes the example app.


10-10: New Bundling Script Added
The inclusion of the "bundle": "INTERNALLY_TEST_EXAMPLE_PROJECT=true expo export" script indicates a new bundling process. Please ensure that this command is thoroughly tested and that it produces the expected bundle output in the new project structure.


15-24: Review Dependency Version Updates
The dependency versions for Expo, React, React Native, and related packages have been updated. The change of "react-native-device-activity" to "workspace:*" is consistent with workspace management. Please verify that these updates are aligned with the stability and compatibility requirements for the target platforms.


35-36: Validate Native Modules Directory Path
The "nativeModulesDir" path has been updated from ".." to "../.." in the Expo configuration. Confirm that this updated directory structure correctly resolves the native modules for the example app in the reorganized project layout.

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

26-31: Documentation for new metadata fields already addressed.
This addition mirrors a previous suggestion to add doc comments for newly introduced metadata properties and to clarify usage details for includeEntireCategory.


33-37: Type composition approach looks good.
Combining familyActivitySelection with ActivitySelectionMetadata is a clean way to strengthen type safety without introducing extra boilerplate.


49-62: Persisted selection view props look consistent.
The doc comment for includeEntireCategory and optional style prop usage are well-defined. No further issues noted.


160-168: Ensure thorough testing of new shield action types.
These action types align well with previous additions to the shield logic. Confirm that these branches are covered by tests.


176-179: Looks good.
No immediate concerns. The property appears self-explanatory, but you might consider adding a short doc comment in the future if usage scenarios become more complex.


219-249: Whitelist management logic previously addressed.
These whitelist-related action types were discussed in an earlier comment about fallback scenarios (e.g., empty whitelists) and return values for success/failure.


276-295: Authorization status docstring is clear.
The descriptive comments for AuthorizationStatusType align with recommended best practices. Looks good.


305-318: Exclusivity checks for ActivitySelectionInput were previously recommended.
Ensure runtime checks or other guards exist to handle scenarios where both IDs or tokens are provided.


319-333: Broad usage of ActivitySelectionInputWithBlocks continues to look fine.
Past recommendations covered verifying downstream usage and tests for these extended fields.


334-342: SetOperationOptions documentation previously noted.
Narrow scoping looks good; earlier suggestions to expand doc coverage or clarify token-stripping logic remain relevant at your discretion.


393-396: Renaming logic previously reviewed.
Prior commentary covered concurrency and caching concerns for renameActivitySelection. No new issues.


405-429: Add/remove selection to/from block/whitelist coverage previously discussed.
Confirm fallback handling and success/failure signals, if relevant to app state updates.


433-434: Managed settings store concurrency was already flagged.
Earlier feedback referenced ensuring concurrency safety for heavy usage. No new concerns here.


436-448: Monitor methods appear sound.
Stopping, starting, and retrieving monitored activities is well-declared. No immediate improvements needed.

apps/example/ios/Podfile.properties.json (1)

4-4: Deployment target version increment looks fine.
Changing from iOS 15.0 to 15.1 is minor but ensure your CI and build pipelines align to this requirement across the project.

README.md (1)

91-91: Updated iOS deployment target in docs.
Raising the target to iOS 15.1 matches the new project requirements. This change is consistent with other updated configurations.

apps/example/ios/Podfile (1)

31-31: Updated iOS deployment target to 15.1

This change increases the minimum iOS version from 15.0 to 15.1. This is consistent with the updates in other project files (like app.json) and ensures a unified minimum iOS version requirement across the project.

packages/react-native-device-activity/src/ReactNativeDeviceActivityModule.ios.ts (1)

8-8: Type assertion added for better type safety

Adding the explicit type assertion ensures that the module is treated exactly as the ReactNativeDeviceActivityNativeModule type, even if TypeScript's inference from the generic parameter is slightly different. This provides better type checking and IDE support.

apps/example/app.json (2)

35-35: Updated iOS deployment target to 15.1

This change increases the minimum iOS version requirement from 15.0 to 15.1, consistent with the update in Podfile. This is a coordinated change across the project files.


47-47: Plugin file missing from updated path

Our checks indicate that the new plugin path referenced in apps/example/app.json does not point to an existing file, which may break the build process. Specifically:

  • The file at ../../packages/react-native-device-activity/app.plugin.js was not found.
  • References to this file also appear in packages/react-native-device-activity/config-plugin/getAppGroupFromExpoConfig.js.

Please verify the correct new location of app.plugin.js in your restructured project and update all references accordingly.

#!/bin/bash
# Verify that the plugin file exists at the specified path
echo "Checking if the plugin file exists at the specified path..."
ls -la ../../packages/react-native-device-activity/app.plugin.js || echo "File not found"

# Check for any app.plugin.js files in the project to find potential correct locations
echo "Searching for app.plugin.js files in the project..."
find ../../ -name "app.plugin.js" -type f
packages/react-native-device-activity/targets/ShieldConfiguration/ShieldConfigurationExtension.swift (5)

70-120: Improved function design with explicit config parameter

Renaming from getShieldConfiguration to buildShield and adding a separate config parameter improves the function's design by:

  1. Making it more descriptive of what it actually does (builds a shield)
  2. Decoupling it from a specific data source, making it more reusable and testable
  3. Making the configuration source explicit rather than implied

This is a good architectural improvement.


129-147: Updated function calls to match new signature

The function calls have been correctly updated to use the renamed buildShield function with the new configuration parameter. The configuration is now retrieved separately and passed explicitly to the function.


155-175: Updated function calls to match new signature

The function calls have been correctly updated to use the renamed buildShield function with the new configuration parameter, maintaining the same behavior while using the improved function design.


181-199: Updated function calls to match new signature

The function calls have been correctly updated to use the renamed buildShield function with the new configuration parameter, preserving the functionality while benefiting from the improved function design.


207-227: Updated function calls to match new signature

The function calls have been correctly updated to use the renamed buildShield function with the new configuration parameter, properly adapting to the new signature while maintaining the same behavior.

apps/example/ios/Tests/FamilySelectionIdTests.swift (4)

2-2: Follow Swift naming conventions for the test file.

Swift filenames typically begin with an uppercase letter. This recommendation was also made previously.


28-34: Good coverage for a non-existent ID scenario.

This test properly ensures that the function returns nil for unknown IDs.


36-54: Duplicate family activity selection IDs reduce the intended test coverage.

As previously noted, using "my-id" again before "my-id-2" overwrites the first selection rather than creating two distinct selections.


66-77: Removal and validation logic looks correct.

This test thoroughly checks that the selection is removed and IDs list is updated.

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

12-23: Block-all mode naming is consistent.

Handling the "disableBlockAllMode" action by calling disableBlockAllMode matches expectations. Code readability is good.


30-61: Confirm concurrency safety when unblocking multiple selections.

If multiple “unblockAllPossibleFamilyActivitySelections” actions run concurrently, user defaults or blocking logic could collide. Verify thread safety or add synchronization if needed.


103-114: Validate user-provided URLs for safety.

As noted in a previous review, opening arbitrary URLs can lead to potential misuse or errors. Consider adding strong validation before calling openUrl(...).


121-133: Consider concurrency on whitelisting.

Whitelisting the current app is written to user defaults. If other simultaneous updates occur, potentially ensure safe reads/writes (e.g., atomic merges or locking).

apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (5)

105-109: Relative path references are well-aligned.

Switching to relative paths (e.g., ../../../packages/...) removes the risk of absolute path breakage.


228-228: Tests.xctestplan inclusion is beneficial.

Adding a test plan simplifies maintaining and running multiple test configurations.


879-879: Active compilation conditions updated successfully.

Including DEBUG in the inherited Swift compilation conditions is standard, aiding debug builds without apparent issues.


754-789:

Details

❓ Verification inconclusive

Confirm iOS deployment target bump.

Raising IPHONEOS_DEPLOYMENT_TARGET to 15.1 may exclude older devices or require additional validations. Verify the impact on supported iOS versions.


🏁 Script executed:

#!/bin/bash
# Checking references to IPHONEOS_DEPLOYMENT_TARGET in the project file
grep -n "IPHONEOS_DEPLOYMENT_TARGET" apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj

Length of output: 635


Action Required: Confirm Consistency of iOS Deployment Targets

The Debug/Release configurations for the main target have been updated to use IPHONEOS_DEPLOYMENT_TARGET = 15.1 (lines 754 and 789). However, other sections in the project file still reference higher deployment targets (16.6, 17.6, and 18.0). Please verify that the mixed deployment targets are intentional and won’t lead to compatibility issues across different build configurations.


623-641:

Details

❓ Verification inconclusive

Verify SwiftLint configuration path.

Confirm that "${PROJECT_DIR}/../../../.swiftlint.yml" resolves correctly in all build environments and CI.


🏁 Script executed:

#!/bin/bash
# Check if the .swiftlint.yml file is accessible from the computed path
ls -l "${PROJECT_DIR}/../../../.swiftlint.yml"

Length of output: 104


SwiftLint configuration path requires manual verification

The executed shell script returned:

ls: cannot access '/../../../.swiftlint.yml': No such file or directory

This error suggests that the computed path (${PROJECT_DIR}/../../../.swiftlint.yml) did not resolve correctly in the current shell environment—likely because the PROJECT_DIR variable isn’t set as it would be in a typical Xcode build environment. Please manually confirm the following:

  • Verify that PROJECT_DIR is correctly defined in all build environments (local and CI) so that the relative path resolves as expected.
  • Ensure that the .swiftlint.yml file exists at the computed location relative to the project directory.

Adjust the configuration if necessary, keeping in mind the differences in environment setups between your local shell and Xcode/CI.

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

58-104: Mock implementation is consistent.

The structure for mockModule fields aligns well with the declared interface. This no-op fallback is a clean approach for non-iOS platforms. No issues found.


106-106: No concerns.

packages/react-native-device-activity/src/index.ts (15)

6-12: Imports look good.

These updated imports align well with the new set operation features and DeviceActivitySelectionViewPersisted. No issues found.

Also applies to: 21-21, 23-23, 26-27


109-125: Good specialized error handling.

This function neatly logs known error messages for block mode conflicts and whitelist category issues, improving debug visibility. No concerns with the approach.


127-129: Optional: consider wrapping in try/catch.

If refreshManagedSettingsStore() might fail in the native layer, capturing the error helps maintain consistent error handling across the module.

Do we have any known cases of refreshManagedSettingsStore failing? If so, let's adopt consistent error handling.


135-147: Well-handled bridging call.

Error handling is in place to catch potential native exceptions. This approach fosters a more stable user experience.


149-161: Consistent approach to error handling.

Similarly well-handled bridging call with try/catch. Great job.


249-259: Final set operation function.

Completes the standard set operations (intersection, union, difference, symmetricDifference). Looks correct.


269-275: Direct bridging function.

Matches the native module signature. No issues found.


424-436: Well-structured bridging call.

Using a try/catch block for consistent screen time error handling is a good approach.


451-463: Consistent bridging pattern.

Error handling is included, matching other block-related calls.


473-473: Emitter instantiation check.

This lazy load approach is typical for bridging. No issues found.


352-359: Listener for device activity detection.

Guarding against a missing emitter is good practice. Implementation is consistent with the rest of the code.


578-592: Simplistic equality check.

Using symmetricDifference to confirm no difference is a concise and effective approach within this domain.


594-612: Implementation clarity.

Comparing the intersection result to the subset’s metadata is straightforward and clear. No issues found.


622-622: Exporting new component.

Ensures DeviceActivitySelectionViewPersisted is publicly available. No issues found.


624-627: Consistency in type exports.

Renaming or re-exporting to maintain uniform naming is a good approach.

Comment thread packages/react-native-device-activity/package.json
Comment thread packages/react-native-device-activity/ios/Shared.swift
Comment thread packages/react-native-device-activity/ios/Shared.swift
Comment thread packages/react-native-device-activity/ios/Shared.swift
Comment thread packages/react-native-device-activity/ios/Shared.swift
Comment thread packages/react-native-device-activity/src/index.ts
Comment thread packages/react-native-device-activity/src/index.ts
Comment thread packages/react-native-device-activity/src/index.ts
Comment thread packages/react-native-device-activity/src/index.ts
Comment thread packages/react-native-device-activity/src/index.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 37d0118 and 9d85cd5.

📒 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)

1-3: Clarify Package Naming and Version
The package metadata currently uses "name": "react-native-device-activity" and "version": "0.4.20". However, previous review comments and rebranding requirements suggested changing the name to "react-native-device-activity-mono" and updating the version to "1.0.0". Please confirm whether to proceed with the rebranding, or if the current metadata is intentional.

Comment thread packages/react-native-device-activity/package.json
Comment thread packages/react-native-device-activity/package.json
Comment thread packages/react-native-device-activity/package.json Outdated
Comment thread packages/react-native-device-activity/package.json

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

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

76-82: 🛠️ Refactor suggestion

Avoid blocking the current thread with dispatch group wait.

If called on the main thread, this can freeze the UI. Consider using a non-blocking delay, such as Thread.sleep(forTimeInterval:) or asynchronous approaches.

-func sleep(ms: Int) {
-  let delay = DispatchTimeInterval.milliseconds(ms)
-  let group = DispatchGroup()
-  group.enter()
-  _ = group.wait(timeout: .now() + delay)
+func sleep(ms: Int) {
+  Thread.sleep(forTimeInterval: Double(ms) / 1000.0)
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9d85cd5 and f623968.

📒 Files selected for processing (2)
  • apps/example/ios/Tests/FamilySelectionIdTests.swift (1 hunks)
  • packages/react-native-device-activity/ios/Shared.swift (1 hunks)
🧰 Additional context used
🪛 SwiftLint (0.57.0)
packages/react-native-device-activity/ios/Shared.swift

[Warning] 41-41: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 58-58: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 181-181: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 225-225: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 288-288: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 291-291: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 319-319: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 328-328: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 367-367: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 385-385: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 399-399: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 415-415: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 432-432: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 577-577: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 624-624: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 639-639: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 703-703: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 735-735: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 1034-1034: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 1156-1156: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 1181-1181: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 1214-1214: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 1232-1232: Opening braces should be preceded by a single space and on the same line as the declaration

(opening_brace)


[Warning] 949-949: Collection literals should not have trailing commas

(trailing_comma)

🔇 Additional comments (12)
apps/example/ios/Tests/FamilySelectionIdTests.swift (12)

2-2: Rename the file to follow Swift conventions.

This was previously flagged: Swift filenames typically start with an uppercase letter and match the test class name (e.g., FamilySelectionIdTests.swift).


18-26: Looks good!

The test correctly adds one selection and verifies the resulting count is 1.


28-34: Looks good!

Retrieving a non-existent selection returns nil as expected.


36-54: Fix duplicate ID usage in this test.

This was previously flagged: you’re adding the same ID ("my-id") twice before adding a different ID, which overwrites the original selection, so the test incorrectly expects 2 distinct selections.


56-64: Test logic is correct.

Verifying the retrieved selection matches the saved one is handled properly.


66-77: Test removal verification looks good.

Removing the selection and confirming the ID is gone and count is zero is well done.


79-100: No concerns here.

Configuration prefix retrieval test is coherent and passes an empty dictionary as expected.


102-120: Test logic is consistent.

Properly verifies that no config is found under the specified ID.


122-133: Good negative test scenario.

Correctly ensures that when there's no activity selection ID, the config is nil.


135-155: Correct sorting test.

It confirms the sorted order (“social”, “everything”) as intended.


157-182: Approach is solid.

Filtering only matches for “games” plus verifying “everything” is also included is correct.


184-219: Approval for multiple-category sorting.

Ensures “games”, “social-and-games”, then “everything” appears in the expected order.

Comment thread packages/react-native-device-activity/ios/Shared.swift
Comment thread packages/react-native-device-activity/ios/Shared.swift
Comment thread packages/react-native-device-activity/ios/Shared.swift
Comment thread packages/react-native-device-activity/ios/Shared.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f623968 and 6334bfd.

📒 Files selected for processing (1)
  • packages/react-native-device-activity/ios/Shared.swift (1 hunks)
🔇 Additional comments (7)
packages/react-native-device-activity/ios/Shared.swift (7)

16-23: Add short documentation for newly introduced constants.

This is a previously raised suggestion. Each of these user defaults keys and prefixes (FALLBACK_SHIELD_CONFIGURATION_KEY, SHIELD_CONFIGURATION_FOR_SELECTION_PREFIX, etc.) would benefit from brief doc comments or usage clarifications so future maintainers can easily identify their purpose.


36-72: Handle missing or incompatible shield configuration gracefully.

This is a previously raised suggestion. If either shieldConfiguration_\(shieldId) or shieldActions_\(shieldId) is missing from user defaults, consider logging or providing a fallback. Silent failures can cause confusion and make debugging difficult.


74-79: Avoid blocking the current thread with dispatch group wait.

This is a previously raised suggestion. Using dispatch groups to force a synchronous delay blocks the current thread, which can freeze your app if called on the main thread. Consider a safer or asynchronous approach to prevent potential UI hangs.


178-181: Prevent potential runtime crash by safely unwrapping the URL.

This is a previously raised suggestion. Force-unwrapping URL(string: url)! can crash if the string is invalid. Use conditional binding or early returns to avoid runtime errors.

-  let url = URL(string: url)!
+  guard let validUrl = URL(string: url) else {
+    logger.log(level: .error, "Invalid URL: \(url)")
+    return URLSessionDataTask() // or a safer fallback
+  }

879-885: Add more context to these custom error structs.

This is a previously raised suggestion. WhitelistSelectionWithoutEntireCategoryError and TryingToBlockSelectionWhenBlockModeIsEnabledError are empty. Adding a message or localized description can help with debugging and error reporting.


916-939: Guard against concurrent calls to updateBlock().

This is a previously raised suggestion. Multiple rapid calls to updateBlock(triggeredBy:) can lead to race conditions with user defaults and ManagedSettingsStore. You might want to wrap these calls in a dispatch queue or lock to prevent state corruption.


656-682:

Details

❓ Verification inconclusive

Verify test coverage for set operations like symmetricDifference.

Although the logic appears sound, set operations can have edge cases (e.g., sets with overlapping tokens). Ensure you have unit tests covering typical, empty, and maximal sets to confirm correctness.


🏁 Script executed:

#!/bin/bash
# Searches for test references to symmetricDifference in the codebase
# and displays those lines for review. Modify if needed.
rg -A 8 'func test.*symmetricDifference'

Length of output: 42


Please verify that unit tests adequately cover the set operations used in this file. Although the code logic for computing the symmetric differences on applicationTokens, webDomainTokens, and categoryTokens appears correct, the initial search did not return any tests confirming that edge cases—such as overlapping sets, empty sets, and maximal sets—are handled correctly.

  • Confirm that tests exist (or add new tests) to validate the behavior of symmetricDifference for typical, empty, and full set scenarios.
  • Revisit related test files and ensure that all these cases are covered to guarantee robustness.

Comment thread packages/react-native-device-activity/ios/Shared.swift
Comment thread packages/react-native-device-activity/ios/Shared.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 19

🔭 Outside diff range comments (2)
scripts/nail-workspace-dependency-versions.ts (1)

1-56: 🧹 Nitpick (assertive)

Preserve original formatting of package.json files.

The current implementation might change the formatting of the package.json files. Consider using a solution that preserves the original formatting.

You might want to consider using a library like jsonfile or json-stringify-pretty-compact that can preserve the original formatting when writing back to the file. Alternatively, you could read the original file as a string, parse it, make your changes, and then use string manipulation to apply the changes while preserving the original format.

README.md (1)

1-184: 🧹 Nitpick (assertive)

Alignment with PR Objective: Referencing New Functions

The PR title mentions the addition of activitySelectionMetadata and related set functions. However, these new functionalities are not explicitly documented or referenced in the README updates provided in this diff. It would be beneficial to add a dedicated section or update existing examples to include usage details for the new activitySelectionMetadata and set functions so that users can readily understand and apply these features.

♻️ Duplicate comments (8)
packages/react-native-device-activity/src/index.ts (5)

424-435: Returning in a void-typed function.
This pattern was flagged in past comments. Removing the return from a void function helps maintain clarity and meets typical lint rules.


438-448: Likewise, consider removing return statements within void functions.
Matches prior feedback.


450-462: Same note: unblockSelection typed as void but returns a native call.
This was already noted — removing the return is recommended for consistency.


105-107: 🛠️ Refactor suggestion

Add error handling for parity with similar bridging calls.
This function, like clearWhitelistAndUpdateBlock, should consider handling errors for consistency.

Example fix:

-export const clearWhitelist = () => {
-  return ReactNativeDeviceActivityModule?.clearWhitelist();
+export const clearWhitelist = (): void => {
+  try {
+    return ReactNativeDeviceActivityModule?.clearWhitelist();
+  } catch (error) {
+    handleScreenTimeError(error);
+  }
};

99-103: 🛠️ Refactor suggestion

Consider adding error handling for consistency.
Currently, this function returns the native call directly but does not wrap it in a try/catch. Other similar functions (e.g., addSelectionToWhitelistAndUpdateBlock) handle errors gracefully using handleScreenTimeError. Aligning these conventions can help maintain consistent error handling throughout.

Below is a possible adjustment:

-export function clearWhitelistAndUpdateBlock(triggeredBy?: string) {
-  return ReactNativeDeviceActivityModule?.clearWhitelistAndUpdateBlock(triggeredBy);
+export function clearWhitelistAndUpdateBlock(triggeredBy?: string) {
+  try {
+    return ReactNativeDeviceActivityModule?.clearWhitelistAndUpdateBlock(triggeredBy);
+  } catch (error) {
+    handleScreenTimeError(error);
+  }
}
packages/react-native-device-activity/package.json (3)

2-3: Verify Package Name and Version Rebranding Requirement
There is an inconsistency between prior rebranding suggestions and the current metadata. If rebranding is intended, please update the package name and version as follows:

-  "name": "react-native-device-activity",
-  "version": "0.4.20",
+  "name": "react-native-device-activity-mono",
+  "version": "1.0.0",

If the current naming/versioning is intentional, a brief confirmation or rationale in the PR description would help clarify.


18-24: 🧹 Nitpick (assertive)

Augment Keywords for Improved Discoverability
To better reflect the newly added functionalities, consider including keywords such as "activitySelectionMetadata" and "set functions". For example:

 "keywords": [
-    "react-native",
-    "expo",
-    "react-native-device-activity",
-    "device-activity",
-    "screen-time"
+    "react-native",
+    "expo",
+    "react-native-device-activity",
+    "device-activity",
+    "screen-time",
+    "activitySelectionMetadata",
+    "set functions"
 ]

This change would improve the package’s discoverability.


34-39: 🧹 Nitpick (assertive)

Improve Dependency Version Specification
The dependencies are mostly well defined. However, for "@kingstinct/expo-apple-targets", using a version range can be beneficial to allow compatible bugfix and minor updates. Consider updating the version as suggested below:

-    "@kingstinct/expo-apple-targets": "0.1.19",
+    "@kingstinct/expo-apple-targets": "^0.1.19",

This change helps prevent potential compatibility issues in the future.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0d05065 and 67d683a.

📒 Files selected for processing (5)
  • README.md (4 hunks)
  • apps/example/ios/reactnativedeviceactivityexample/AppDelegate.mm (1 hunks)
  • packages/react-native-device-activity/package.json (1 hunks)
  • packages/react-native-device-activity/src/index.ts (11 hunks)
  • scripts/nail-workspace-dependency-versions.ts (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
packages/react-native-device-activity/src/index.ts (1)
packages/react-native-device-activity/src/ReactNativeDeviceActivity.types.ts (10)
  • ActivitySelectionInput (305-317)
  • ActivitySelectionInputWithBlocks (319-332)
  • SetOperationOptions (338-341)
  • ActivitySelectionMetadata (26-31)
  • OnDeviceActivityDetectedListener (602-604)
  • EventListenerMap (606-612)
  • AuthorizationStatusType (292-295)
  • AuthorizationStatus (276-283)
  • OnAuthorizationStatusChange (450-454)
  • DeviceActivityMonitorEventPayload (13-15)
🔇 Additional comments (26)
apps/example/ios/reactnativedeviceactivityexample/AppDelegate.mm (2)

11-14: Optimization for test execution - good approach!

Adding this conditional check to bypass React Native initialization during unit tests is a good optimization. This will significantly improve test performance by skipping the unnecessary React Native setup when running unit tests, reducing test execution time.


3-3: Added whitespace - no impact

This is just a whitespace change with no functional impact.

README.md (1)

91-91: Deployment Target Update: Confirm iOS Version Compatibility

The iOS deployment target has been updated from "15.0" to "15.1" in the expo-build-properties configuration. This change appears to align with the updated requirements in your project files. Please double-check that all native modules and documentation reflect this update to avoid compatibility issues on devices running iOS 15.1 and above.

packages/react-native-device-activity/src/index.ts (17)

1-1: No issues noted for this import.


6-6: Straightforward import of DeviceActivitySelectionViewPersisted.


9-12: Additional imports look appropriate.


21-21: Importing DeviceActivitySelectionViewPersistedProps is consistent with the new usage below.


23-23: Successfully importing EventListenerMap for typed event handling.


26-27: No concerns with importing OnDeviceActivityDetectedListener and SetOperationOptions.


135-147: Ensure the function’s return type matches its usage.
If addSelectionToWhitelistAndUpdateBlock can return a promise or perform asynchronous work, consider typing it accordingly (e.g., Promise<void>). Otherwise, ensure the bridging call is truly synchronous.


149-161: Similarly verify return type correctness.
Same rationale as addSelectionToWhitelistAndUpdateBlock: confirm whether to declare an async return or keep it synchronous.


472-472: Instantiation of EventEmitter with a generic is correct.
No concerns here.


497-498: Reasonable default values for polling attempts and interval.


500-501: Utility function wait: no concerns.


502-526: Polling authorization status logic appears correct.
Checks status, waits, and exits on final attempt or if no longer not-determined. Looks fine.


548-549: Revised signature for event subscription is consistent.


563-563: Clean event listener bridging.


652-652: Export statement updated to include DeviceActivitySelectionViewPersisted.


653-653: Extended type export is valid.


654-657: Re-exporting types with aliases is consistent with project patterns.

packages/react-native-device-activity/package.json (6)

7-17: Scripts Section Review
The scripts provided (for building, cleaning, linting, type checking, testing, and opening project directories) are clear and appear to be appropriate. No changes are necessary here.


25-30: Repository and Issue Tracker Configuration
The repository and bugs URLs are correctly set up. They point to the appropriate GitHub locations.


31-33: Author, License, and Homepage Details
The author information, license, and homepage entries appear accurate and well-formatted.


40-48: DevDependencies Configuration Check
The devDependencies section appears appropriate for local development. Although "react": "*" and "react-native": "*" are quite permissive, if these are intentional to rely on the Expo-managed versions or for test environments, they are acceptable as-is.


49-53: Peer Dependencies Verification
The peerDependencies are correctly specified with minimum version requirements, ensuring compatibility with Expo, React, and React Native.


2-4:

Details

❓ Verification inconclusive

Enhance Package Metadata with New Feature Details
The package’s basic metadata is set up correctly. However, since the PR objectives indicate additions such as activitySelectionMetadata and set functions, it would be beneficial to update the description so that users immediately understand the new functionality.

A suggested change for the description:

-  "description": "Provides access to Apples DeviceActivity API",
+  "description": "Provides access to Apple's DeviceActivity API, featuring activitySelectionMetadata and set functions",

Additionally, please confirm if any rebranding is planned. Previous review comments suggested updating the package name and version (e.g., to "react-native-device-activity-mono" and "1.0.0"), but the current metadata uses "react-native-device-activity" and "0.4.20".


Enhance Package Metadata & Confirm Rebranding Intent

The current metadata in packages/react-native-device-activity/package.json correctly declares the package name, version, and description. However, since the PR objectives include new functionalities—such as activitySelectionMetadata and set functions—it would be beneficial to update the description so that users are immediately aware of the enhanced capabilities.

Suggested change for the description:

-  "description": "Provides access to Apples DeviceActivity API",
+  "description": "Provides access to Apple's DeviceActivity API, featuring activitySelectionMetadata and set functions",

Additionally, please confirm if any rebranding is planned. Earlier review comments mentioned a potential update to the package name (e.g., to "react-native-device-activity-mono") and version (e.g., "1.0.0"). The current metadata still reflects "react-native-device-activity" and "0.4.20", so clarification on this point is needed.

Comment thread scripts/nail-workspace-dependency-versions.ts
Comment thread scripts/nail-workspace-dependency-versions.ts
Comment thread scripts/nail-workspace-dependency-versions.ts
Comment thread scripts/nail-workspace-dependency-versions.ts
Comment thread README.md
Comment thread packages/react-native-device-activity/src/index.ts
Comment thread packages/react-native-device-activity/src/index.ts
Comment thread packages/react-native-device-activity/src/index.ts
Comment thread packages/react-native-device-activity/src/index.ts
Comment thread packages/react-native-device-activity/src/index.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (2)
apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (2)

105-108: Proper use of relative paths improves project portability.

The paths to Swift files have been updated to use relative paths with SOURCE_ROOT instead of absolute paths. This change improves project portability across different development environments.


838-839: React Native path and linker flags formatting concerns.

The React Native path has been updated to a deeper relative path structure, and OTHER_LDFLAGS includes an extra trailing space.

The verification scripts from previous reviews indicate that:

  1. The React Native path may not resolve correctly in all environments
  2. The OTHER_LDFLAGS formatting is inconsistent across build configurations

Consider standardizing the OTHER_LDFLAGS format across all configurations and verifying the React Native path resolves correctly in your CI environment.

Also applies to: 899-900

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3ed2a54 and 372813a.

📒 Files selected for processing (2)
  • apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (8 hunks)
  • packages/react-native-device-activity/ios/ReactNativeDeviceActivity.podspec (1 hunks)
🔇 Additional comments (5)
apps/example/ios/reactnativedeviceactivityexample.xcodeproj/project.pbxproj (5)

109-109: Test plan file added for structured testing.

The addition of a test plan file indicates improved testing infrastructure, which is a good practice for maintaining code quality.


722-722: iOS deployment target update from 15.0 to 15.1.

This change updates the minimum iOS version requirement. While it's a minor update, ensure this aligns with your app's compatibility requirements.

Please verify that this minimum iOS version change is intentional and consistent with your app's target audience and feature requirements.

Also applies to: 756-756


841-842: Swift compilation conditions added and version handling updated.

Adding explicit Swift compilation conditions for debug builds is a good practice. The Swift version is now consistently set to 5.8 in both debug and release configurations.

Also applies to: 902-902


596-606: Updated resource copy script phase.

The shell script phase for copying Pod resources has been updated with empty input/output paths. This is likely an automatic change from CocoaPods.


615-622: Updated framework embedding script phase.

The shell script phase for embedding Pod frameworks has been updated with empty input/output paths. This is likely an automatic change from CocoaPods.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

♻️ Duplicate comments (2)
apps/example/ios/Tests/FamilySelectionIdTests.swift (2)

2-2: Fix filename casing to follow Swift conventions.

The filename "familySelectionIdTests.swift" starts with a lowercase letter, which doesn't follow Swift naming conventions. Swift filenames typically start with an uppercase letter. Consider renaming to "FamilySelectionIdTests.swift" to match the class name and follow standard Swift conventions.


36-54: Fix duplicate ID in testShouldHaveTwo.

This test intends to verify that two distinct selections are properly counted, but you're setting the same ID ("my-id") twice before adding a different ID. This doesn't properly test the scenario since the first selection would be overwritten by the second.

func testShouldHaveTwo() {
  setFamilyActivitySelectionById(
    id: "my-id",
    activitySelection: FamilyActivitySelection()
  )

- setFamilyActivitySelectionById(
-   id: "my-id",
-   activitySelection: FamilyActivitySelection()
- )
-
  setFamilyActivitySelectionById(
    id: "my-id-2",
    activitySelection: FamilyActivitySelection()
  )

  let ids = getFamilyActivitySelectionIds()
  XCTAssertEqual(ids.count, 2)
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 372813a and a68bef7.

📒 Files selected for processing (2)
  • .github/workflows/test.yml (10 hunks)
  • apps/example/ios/Tests/FamilySelectionIdTests.swift (1 hunks)
🔇 Additional comments (22)
apps/example/ios/Tests/FamilySelectionIdTests.swift (2)

192-192:

Details

✅ Verification successful

Verify the union function implementation.

The union function is used here to combine two activity selections, but it's not defined in this file. Ensure it properly combines the selections with appropriate handling of duplicate entries.


🏁 Script executed:

#!/bin/bash
# Search for the union function definition
echo "Searching for union function definition..."
rg "func\s+union\s*\(" --type swift -A 15

Length of output: 1494


Union function verified

After verifying the implementation in packages/react-native-device-activity/ios/Shared.swift, the union function correctly combines two FamilyActivitySelection instances by performing set unions on applicationTokens, webDomainTokens, and categoryTokens. The use of the built-in union operations ensures duplicate entries are properly handled. No further modifications are required. Please ensure that any future changes to the structure of FamilyActivitySelection continue to align with this union behavior.


82-82:

Details

❓ Verification inconclusive

Verify that tokenIncludingSocial is defined.

The variable tokenIncludingSocial is used here but doesn't appear to be defined in this file. Ensure it's properly defined elsewhere and available to this test class.


🏁 Script executed:

#!/bin/bash
# Search for the definition of tokenIncludingSocial
echo "Searching for tokenIncludingSocial definition..."
rg "tokenIncludingSocial\s*=" --type swift

Length of output: 218


Ensuring Shared Token Accessibility:
The search confirms that tokenIncludingSocial is defined in apps/example/ios/Tests/UnionTests.swift (using let tokenIncludingSocial = ...). Please verify that this token is accessible in FamilySelectionIdTests.swift—either through an explicit import, a shared test helper file, or by being declared at a scope common to both test files—to prevent hidden dependencies.

.github/workflows/test.yml (20)

13-13: Set Timeout for Lint Job
The addition of timeout-minutes: 10 ensures that the lint job will be automatically stopped if it runs excessively long, which helps in keeping CI runs efficient.


28-28: Enforce Time Limit for Typecheck Job
Adding a 10‑minute timeout prevents the typecheck step from hanging indefinitely, aligning with overall CI best practices.


43-43: Timeout for Typecheck (Example Project) Job
A 10‑minute timeout has been set for the typecheck job of the example project. This appears consistent with other jobs.


54-54: Update Working Directory for Typecheck (Example Project)
Changing the working directory to apps/example correctly reflects the new project structure. Please verify that all related file paths are updated accordingly.


59-59: Set Timeout for Expo Bundle Job
A 10‑minute timeout is now specified for the Expo Bundle job, which should help mitigate runaway processes.


70-70: Correct Working Directory for Expo Export
The update of the working directory to apps/example for the expo export step ensures consistency with the new directory layout.


74-74: Timeout for Expo Config Job
The addition of a 10‑minute timeout for the Expo Config job is consistent with other examples and helps maintain predictable CI durations.


86-86: Set Working Directory for Expo Config
Updating the working directory to apps/example for the expo config command aligns with the broader reorganization of the project structure.


91-91: Timeout for Expo Prebuild Job
Applying a 10‑minute timeout here prevents the Expo Prebuild job from overrunning, which is in line with the other project jobs.


102-102: Update Working Directory for Expo Prebuild
The change to working-directory: apps/example correctly reflects the new project layout for the expo prebuild command.


107-107: Set Timeout for SwiftLint Job
A 10‑minute timeout is now applied to the SwiftLint job (running on macOS), which is prudent given the potentially variable runtime of linting.


123-123: Confirm Installation Step in SwiftLint Job
The inclusion of the bun install command here helps ensure dependencies are up to date before linting. Verify that this remains consistent with dependency management practices across jobs.


125-125: Update Working Directory for Pod Install in SwiftLint
Changing the working directory to apps/example/ios for the pod installation reflects the updated project structure and should help avoid path-related errors.


127-127: Explicit SwiftLint Command Path
Using the explicit path apps/example/ios/Pods/SwiftLint/swiftlint lint ensures that the locally installed SwiftLint is executed. This is a good move to avoid potential conflicts with any globally installed versions.


132-132: Extended Timeout for Swift Test Job
Setting the timeout to 25 minutes for the Swift Test job appears reasonable, likely accommodating longer-running tests in the iOS environment.


136-139: Node Setup in Swift Test Job – Verify Necessity
Although the project is transitioning to a Bun environment, the swift-test job still includes a step using actions/setup-node@v4 with Node version 22. Please confirm whether this Node.js setup is still required for the tests or if it can be removed in favor of a fully Bun‑based workflow.


169-170: Update Xcode Version for Swift Test Job
The Xcode version has been updated to Xcode_16.2 using sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer. Make sure that all iOS build and test configurations are compatible with this version upgrade.


175-175: Update Working Directory for Pod Install in Swift Test
Updating the working-directory to apps/example/ios for pod installation in the swift-test job is consistent with similar changes in the swift-lint job and the new project structure.


180-180: Confirm Working Directory for Xcodebuild Test
The working-directory: apps/example/ios specified for the xcodebuild test command ensures the correct context for running tests. Verify that all related paths (e.g., the workspace and scheme names) are updated to match the new environment.


146-149:

Details

❓ Verification inconclusive

Start Bundler in Swift Test Job – Process Management
The new "Start bundler" step runs bun start & with the working directory set to apps/example. While this change initiates the bundler process asynchronously, please ensure that:

  • The background process is properly managed (e.g., that it does not remain hanging after tests complete).
  • Subsequent steps that depend on bundler availability include proper synchronization (for example, adding a brief wait or health check).

A possible refinement could be:

-      - name: Start bundler
-        run: bun start &
-        working-directory: apps/example
+      - name: Start bundler
+        run: |
+          nohup bun start &
+          sleep 5  # Allow bundler time to initialize
+        working-directory: apps/example

Consider this adjustment if tests are sensitive to the bundler startup timing.


Bundler Process Management – Ensure Proper Synchronization and Clean-Up

The current workflow step starts the bundler asynchronously using bun start & in apps/example, which might leave a lingering process if not properly handled. To avoid potential issues during or after the test execution, please ensure:

  • The background bundler process is terminated once tests finish.
  • Steps dependent on bundler startup include a delay or health check to confirm it’s running (e.g., using sleep or a polling mechanism).

A suggested improvement is as follows:

-      - name: Start bundler
-        run: bun start &
-        working-directory: apps/example
+      - name: Start bundler
+        run: |
+          nohup bun start &
+          sleep 5  # Allow bundler time to initialize
+        working-directory: apps/example

This adjustment provides a basic synchronization mechanism, but please verify that it meets your test environment’s requirements and that the bundler process is cleaned up after tests complete.

Comment thread apps/example/ios/Tests/FamilySelectionIdTests.swift
Comment thread apps/example/ios/Tests/FamilySelectionIdTests.swift
Comment thread apps/example/ios/Tests/FamilySelectionIdTests.swift
Comment thread .github/workflows/test.yml
Comment thread .github/workflows/test.yml
@robertherber
robertherber merged commit 38f2068 into main Apr 8, 2025
@robertherber
robertherber deleted the add-set-functions branch April 8, 2025 06:43
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