Skip to content

[ECO-5491] Remove Implementation nested class - #342

Merged
maratal merged 3 commits into
mainfrom
339-remove-implementation-class
Aug 18, 2025
Merged

[ECO-5491] Remove Implementation nested class#342
maratal merged 3 commits into
mainfrom
339-remove-implementation-class

Conversation

@maratal

@maratal maratal commented Jul 26, 2025

Copy link
Copy Markdown
Contributor

Closes #339

Edited in a browser GH Copilot with GPT-4o model.

Prompt used:

Find all nested classes named `Implementation` and extract method implementations into container class, then remove `Implementation` class, but keep all comments intact.

No manual edits before PR creation.

UPDATE:
See compile error fixes in the second commit 6bed297.

Summary by CodeRabbit

Summary by CodeRabbit

  • Refactor

    • Simplified several chat-related classes by removing internal helper classes and consolidating logic directly into the main classes for messages, occupancy, presence, reactions, and typing features.
    • Improved error handling and logging throughout chat operations.
    • Streamlined event subscription and state management for chat events, presence updates, reactions, and typing indicators.
  • Bug Fixes

    • Enhanced reliability and consistency of chat event handling, presence operations, and typing notifications.

@coderabbitai

coderabbitai Bot commented Jul 26, 2025

Copy link
Copy Markdown

Walkthrough

This change refactors several Default* classes in the AblyChat module by removing their nested Implementation helper classes. The logic previously delegated to these helpers is now inlined directly within each Default* class, consolidating subscription, event handling, and API method implementations. All affected classes now manage dependencies and event subscriptions internally.

Changes

File(s) Change Summary
Sources/AblyChat/DefaultMessages.swift Removed Implementation class; inlined all subscription, message handling, and API methods directly into DefaultMessages.
Sources/AblyChat/DefaultOccupancy.swift Removed Implementation class; inlined occupancy event subscription and retrieval logic into DefaultOccupancy.
Sources/AblyChat/DefaultPresence.swift Removed Implementation class; inlined all presence operations and event subscription logic into DefaultPresence.
Sources/AblyChat/DefaultRoomReactions.swift Removed Implementation class; inlined reaction sending and event subscription logic into DefaultRoomReactions.
Sources/AblyChat/DefaultTyping.swift Removed Implementation class; inlined typing indicator event subscription, state management, and sending logic.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant DefaultMessages
    participant RealtimeChannel
    participant ChatAPI

    Client->>DefaultMessages: subscribe(callback)
    DefaultMessages->>RealtimeChannel: subscribe to chatMessage events
    RealtimeChannel-->>DefaultMessages: chatMessage event
    DefaultMessages->>DefaultMessages: Validate & parse message
    DefaultMessages->>Client: callback(ChatMessageEvent)
    Client->>DefaultMessages: unsubscribe (via closure)
    DefaultMessages->>RealtimeChannel: remove event listener

    Client->>DefaultMessages: send(params)
    DefaultMessages->>ChatAPI: send(params)
    ChatAPI-->>DefaultMessages: Message or error
    DefaultMessages-->>Client: Message or error
Loading
sequenceDiagram
    participant Client
    participant DefaultPresence
    participant RoomLifecycleManager
    participant RealtimeChannel

    Client->>DefaultPresence: enter/update/leave/get/subscribe
    DefaultPresence->>RoomLifecycleManager: await presence allowed
    RoomLifecycleManager-->>DefaultPresence: allowed
    DefaultPresence->>RealtimeChannel: perform presence op or subscribe
    RealtimeChannel-->>DefaultPresence: presence event(s)
    DefaultPresence->>Client: callback(PresenceEvent)
Loading
sequenceDiagram
    participant Client
    participant DefaultTyping
    participant RealtimeChannel

    Client->>DefaultTyping: keystroke()
    DefaultTyping->>DefaultTyping: Check heartbeat timer
    DefaultTyping->>RealtimeChannel: publish typing.started
    DefaultTyping->>DefaultTyping: Start heartbeat timer

    Client->>DefaultTyping: stop()
    DefaultTyping->>RealtimeChannel: publish typing.stopped
    DefaultTyping->>DefaultTyping: Cancel heartbeat timer

    RealtimeChannel-->>DefaultTyping: typing.started / typing.stopped event
    DefaultTyping->>DefaultTyping: Update typing state
    DefaultTyping->>Client: callback(TypingSetEvent)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • lawrence-forooghian
  • umair-ably

Poem

In the warren of code, helpers once nested,
Now all the logic is neatly ingested.
No more indirection, the classes stand tall,
Handling events, messages, presence, and all.
🐇 With a hop and a refactor, the code’s now concise—
Reviewing these changes will surely suffice!

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6bed297 and fb914a1.

📒 Files selected for processing (1)
  • Sources/AblyChat/DefaultTyping.swift (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: maratal
PR: ably/ably-chat-swift#165
File: Sources/AblyChat/Reaction.swift:14-14
Timestamp: 2024-12-10T01:59:02.065Z
Learning: For the 'ably-chat-swift' repository, documentation-only PRs should focus exclusively on public methods and properties. Avoid suggesting changes to internal comments or private methods in such PRs.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Example/AblyChatExample/Mocks/MockClients.swift:0-0
Timestamp: 2025-05-16T21:04:26.244Z
Learning: In the ably-chat-swift project, mock implementations (like those in MockClients.swift) are intentionally kept simple, sometimes omitting parameter-based filtering behavior for testing simplicity.
Learnt from: maratal
PR: ably/ably-chat-swift#165
File: docs-coverage-report:5-8
Timestamp: 2024-12-10T01:59:12.404Z
Learning: In the AblyChat Swift project, documentation coverage should focus on public methods and properties. Private and internal entities do not require documentation.
Learnt from: maratal
PR: ably/ably-chat-swift#249
File: Tests/AblyChatTests/DefaultMessagesTests.swift:45-48
Timestamp: 2025-05-22T19:17:21.392Z
Learning: The `let doIt = {}` closures in DefaultMessagesTests.swift are temporary workarounds for compiler crashes (related to issue #233) and will be removed once Xcode 16.3 is released, so they should not be flagged for missing async/throws annotations.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The `Occupancy` protocol in the Ably Chat Swift SDK is annotated with `@MainActor`, making all conforming types like `DefaultOccupancy` automatically main actor-isolated without requiring explicit annotations on their methods.
Learnt from: maratal
PR: ably/ably-chat-swift#293
File: Tests/AblyChatTests/Mocks/MockRealtime.swift:41-47
Timestamp: 2025-06-14T15:18:17.427Z
Learning: In the MockRealtime class in Tests/AblyChatTests/Mocks/MockRealtime.swift, the body parameter in the request method is constrained to dictionary or array types, but currently only dictionary types are used. Arrays are not yet used for this method, so the current implementation assumes dictionary-only for simplicity.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with `[weak self]` to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The `Typing` protocol in the Ably Chat Swift SDK is annotated with `@MainActor`, making all conforming types like `DefaultTyping` automatically main actor-isolated without requiring explicit annotations on their methods.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The `Typing` protocol in the Ably Chat Swift SDK is annotated with `@MainActor`, making all conforming types like `DefaultTyping` automatically main actor-isolated without requiring explicit annotations on their methods.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/RoomReactions.swift:42-56
Timestamp: 2025-05-16T21:35:46.634Z
Learning: In the AblyChat framework, all subscription callbacks are annotated with @MainActor, ensuring they always execute on the main actor thread without requiring additional Task wrappers.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/SubscriptionHandleStorage.swift:37-40
Timestamp: 2025-05-12T21:02:28.274Z
Learning: In the AblyChat Swift codebase, the `SubscriptionHandle` struct has an `unsubscribe()` method for terminating subscriptions, not a `cancel()` method.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription callbacks continue to work even when the handle is not stored, as the underlying services maintain their own storage of callbacks that remain registered until explicitly unsubscribed via the handle's unsubscribe() method.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription continues to work even if the handle is not stored, as the underlying services maintain references to the callbacks until explicitly unsubscribed via the handle's unsubscribe() method.
Sources/AblyChat/DefaultTyping.swift (11)

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The Occupancy protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultOccupancy automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with [weak self] to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.

Learnt from: maratal
PR: #249
File: Tests/AblyChatTests/DefaultMessagesTests.swift:45-48
Timestamp: 2025-05-22T19:17:21.392Z
Learning: The let doIt = {} closures in DefaultMessagesTests.swift are temporary workarounds for compiler crashes (related to issue #233) and will be removed once Xcode 16.3 is released, so they should not be flagged for missing async/throws annotations.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/SubscriptionAsyncSequence.swift:36-41
Timestamp: 2025-06-29T16:02:43.988Z
Learning: In the AblyChat Swift codebase, the fatalError in SubscriptionAsyncSequence.swift's mock async sequence handling (around line 39) is intentional and should not be flagged. This fatalError catches programmer errors when a throwing AsyncSequence is incorrectly passed to the mock initializer, which is meant for testing/development purposes.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/RoomLifecycleManager.swift:611-624
Timestamp: 2025-05-22T20:57:48.147Z
Learning: In AblyChat Swift, when using continuations with subscription callbacks, the continuation object is captured directly by the closure and doesn't depend on self. Even with [weak self] capture, the continuation will still be resumed properly.

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/Mocks/MockClients.swift:0-0
Timestamp: 2025-05-16T21:04:26.244Z
Learning: In the ably-chat-swift project, mock implementations (like those in MockClients.swift) are intentionally kept simple, sometimes omitting parameter-based filtering behavior for testing simplicity.

Learnt from: maratal
PR: #293
File: Example/AblyChatExample/ContentView.swift:94-99
Timestamp: 2025-06-14T21:47:20.509Z
Learning: In the Ably Chat Swift example app, using fatalError for missing clientID is intentional and appropriate since it represents a programmer error rather than a recoverable runtime condition. The clientID is considered an essential configuration requirement.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (34)
  • GitHub Check: Example app, iOS (Xcode 16.2)
  • GitHub Check: Xcode, iOS (Xcode 16.1)
  • GitHub Check: Example app, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, tvOS (Xcode 16.3)
  • GitHub Check: Example app, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.1)
  • GitHub Check: Example app, iOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.1)
  • GitHub Check: Xcode, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.2)
  • GitHub Check: Xcode, iOS (Xcode 16.3)
  • GitHub Check: Xcode, macOS (Xcode 16.2)
  • GitHub Check: Example app, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, macOS (Xcode 16.1)
  • GitHub Check: Example app, macOS (Xcode 16.3)
  • GitHub Check: Xcode, iOS (Xcode 16.2)
  • GitHub Check: Xcode, macOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, tvOS (Xcode 16.2)
  • GitHub Check: Example app, iOS (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.3)
  • GitHub Check: SPM, release configuration (Xcode 16.3)
  • GitHub Check: SPM, release configuration (Xcode 16.2)
  • GitHub Check: SPM, release configuration (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.2)
  • GitHub Check: Generate code coverage
🔇 Additional comments (6)
Sources/AblyChat/DefaultTyping.swift (6)

4-34: LGTM: Clean property management and initialization

The refactor properly extracts all dependencies into explicit private properties and initializes them correctly. The gracePeriod constant follows the CHA-T10a specification requirement.


38-108: LGTM: Proper event subscription with correct memory management

The subscription logic correctly uses [weak self] captures to avoid retain cycles, consistent with the established patterns in the AblyChat codebase. The event handling properly integrates with the timer manager and follows the specification requirements.


110-113: LGTM: Simple and correct getter implementation

The method properly delegates to the timer manager and maintains API consistency.


115-135: LGTM: Thread-safe keystroke implementation with proper throttling

The method correctly uses the operation queue for thread safety and implements the throttling logic as specified. Error handling is consistent with the codebase patterns.


137-149: LGTM: Clean helper method for publishing started events

The method correctly publishes ephemeral messages and manages the heartbeat timer as specified.


151-181: LGTM: Well-implemented stop method with proper state management

The method correctly handles both active and inactive typing states, uses thread-safe operation queuing, and maintains consistent error handling patterns.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 339-remove-implementation-class

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f5c6ff5 and 904e455.

📒 Files selected for processing (5)
  • Sources/AblyChat/DefaultMessages.swift (1 hunks)
  • Sources/AblyChat/DefaultOccupancy.swift (1 hunks)
  • Sources/AblyChat/DefaultPresence.swift (1 hunks)
  • Sources/AblyChat/DefaultRoomReactions.swift (1 hunks)
  • Sources/AblyChat/DefaultTyping.swift (1 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: maratal
PR: ably/ably-chat-swift#165
File: Sources/AblyChat/Reaction.swift:14-14
Timestamp: 2024-12-10T01:59:02.065Z
Learning: For the 'ably-chat-swift' repository, documentation-only PRs should focus exclusively on public methods and properties. Avoid suggesting changes to internal comments or private methods in such PRs.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Example/AblyChatExample/Mocks/MockClients.swift:0-0
Timestamp: 2025-05-16T21:04:26.244Z
Learning: In the ably-chat-swift project, mock implementations (like those in MockClients.swift) are intentionally kept simple, sometimes omitting parameter-based filtering behavior for testing simplicity.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The `Occupancy` protocol in the Ably Chat Swift SDK is annotated with `@MainActor`, making all conforming types like `DefaultOccupancy` automatically main actor-isolated without requiring explicit annotations on their methods.
Learnt from: maratal
PR: ably/ably-chat-swift#165
File: docs-coverage-report:5-8
Timestamp: 2024-12-10T01:59:12.404Z
Learning: In the AblyChat Swift project, documentation coverage should focus on public methods and properties. Private and internal entities do not require documentation.
Learnt from: maratal
PR: ably/ably-chat-swift#249
File: Tests/AblyChatTests/DefaultMessagesTests.swift:45-48
Timestamp: 2025-05-22T19:17:21.392Z
Learning: The `let doIt = {}` closures in DefaultMessagesTests.swift are temporary workarounds for compiler crashes (related to issue #233) and will be removed once Xcode 16.3 is released, so they should not be flagged for missing async/throws annotations.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with `[weak self]` to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The `Typing` protocol in the Ably Chat Swift SDK is annotated with `@MainActor`, making all conforming types like `DefaultTyping` automatically main actor-isolated without requiring explicit annotations on their methods.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The `Typing` protocol in the Ably Chat Swift SDK is annotated with `@MainActor`, making all conforming types like `DefaultTyping` automatically main actor-isolated without requiring explicit annotations on their methods.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/RoomReactions.swift:42-56
Timestamp: 2025-05-16T21:35:46.634Z
Learning: In the AblyChat framework, all subscription callbacks are annotated with @MainActor, ensuring they always execute on the main actor thread without requiring additional Task wrappers.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Sources/AblyChat/SubscriptionHandleStorage.swift:37-40
Timestamp: 2025-05-12T21:02:28.274Z
Learning: In the AblyChat Swift codebase, the `SubscriptionHandle` struct has an `unsubscribe()` method for terminating subscriptions, not a `cancel()` method.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription callbacks continue to work even when the handle is not stored, as the underlying services maintain their own storage of callbacks that remain registered until explicitly unsubscribed via the handle's unsubscribe() method.
Learnt from: maratal
PR: ably/ably-chat-swift#286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription continues to work even if the handle is not stored, as the underlying services maintain references to the callbacks until explicitly unsubscribed via the handle's unsubscribe() method.
Sources/AblyChat/DefaultRoomReactions.swift (13)

Learnt from: maratal
PR: #293
File: Sources/AblyChat/Message.swift:163-175
Timestamp: 2025-06-14T21:58:57.802Z
Learning: In the AblyChat Swift SDK, the JSON key "reactions" is used for parsing reaction summaries in the Chat SDK layer, while "summary" is used in the ably-cocoa layer. Reactions can be sourced from either the realtime message's summary property or directly from the "reactions" dictionary in the JSON.

Learnt from: maratal
PR: #293
File: Example/AblyChatExample/MessageViews/MessageReactionsSheet.swift:15-31
Timestamp: 2025-06-14T16:18:47.038Z
Learning: In the AblyChat Swift SDK, there are three message reaction types: unique (one reaction per client per message), distinct (one reaction of each type per client per message), and multiple (any number of reactions including repeats, with counts). The MessageReactionsSheet specifically handles unique/distinct reactions where the count is always 1 per client per emoji. Only the "multiple" reaction type would have accumulating counts.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The Occupancy protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultOccupancy automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #165
File: Sources/AblyChat/Reaction.swift:14-14
Timestamp: 2024-12-10T01:59:02.065Z
Learning: For the 'ably-chat-swift' repository, documentation-only PRs should focus exclusively on public methods and properties. Avoid suggesting changes to internal comments or private methods in such PRs.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with [weak self] to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/Mocks/MockClients.swift:0-0
Timestamp: 2025-05-16T21:04:26.244Z
Learning: In the ably-chat-swift project, mock implementations (like those in MockClients.swift) are intentionally kept simple, sometimes omitting parameter-based filtering behavior for testing simplicity.

Learnt from: maratal
PR: #293
File: Tests/AblyChatTests/Mocks/MockRealtime.swift:41-47
Timestamp: 2025-06-14T15:18:17.427Z
Learning: In the MockRealtime class in Tests/AblyChatTests/Mocks/MockRealtime.swift, the body parameter in the request method is constrained to dictionary or array types, but currently only dictionary types are used. Arrays are not yet used for this method, so the current implementation assumes dictionary-only for simplicity.

Learnt from: maratal
PR: #249
File: Tests/AblyChatTests/DefaultMessagesTests.swift:45-48
Timestamp: 2025-05-22T19:17:21.392Z
Learning: The let doIt = {} closures in DefaultMessagesTests.swift are temporary workarounds for compiler crashes (related to issue #233) and will be removed once Xcode 16.3 is released, so they should not be flagged for missing async/throws annotations.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/SubscriptionAsyncSequence.swift:36-41
Timestamp: 2025-06-29T16:02:43.988Z
Learning: In the AblyChat Swift codebase, the fatalError in SubscriptionAsyncSequence.swift's mock async sequence handling (around line 39) is intentional and should not be flagged. This fatalError catches programmer errors when a throwing AsyncSequence is incorrectly passed to the mock initializer, which is meant for testing/development purposes.

Sources/AblyChat/DefaultTyping.swift (11)

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The Occupancy protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultOccupancy automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with [weak self] to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.

Learnt from: maratal
PR: #249
File: Tests/AblyChatTests/DefaultMessagesTests.swift:45-48
Timestamp: 2025-05-22T19:17:21.392Z
Learning: The let doIt = {} closures in DefaultMessagesTests.swift are temporary workarounds for compiler crashes (related to issue #233) and will be removed once Xcode 16.3 is released, so they should not be flagged for missing async/throws annotations.

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/Mocks/MockClients.swift:0-0
Timestamp: 2025-05-16T21:04:26.244Z
Learning: In the ably-chat-swift project, mock implementations (like those in MockClients.swift) are intentionally kept simple, sometimes omitting parameter-based filtering behavior for testing simplicity.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/SubscriptionAsyncSequence.swift:36-41
Timestamp: 2025-06-29T16:02:43.988Z
Learning: In the AblyChat Swift codebase, the fatalError in SubscriptionAsyncSequence.swift's mock async sequence handling (around line 39) is intentional and should not be flagged. This fatalError catches programmer errors when a throwing AsyncSequence is incorrectly passed to the mock initializer, which is meant for testing/development purposes.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/RoomLifecycleManager.swift:611-624
Timestamp: 2025-05-22T20:57:48.147Z
Learning: In AblyChat Swift, when using continuations with subscription callbacks, the continuation object is captured directly by the closure and doesn't depend on self. Even with [weak self] capture, the continuation will still be resumed properly.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #293
File: Example/AblyChatExample/ContentView.swift:94-99
Timestamp: 2025-06-14T21:47:20.509Z
Learning: In the Ably Chat Swift example app, using fatalError for missing clientID is intentional and appropriate since it represents a programmer error rather than a recoverable runtime condition. The clientID is considered an essential configuration requirement.

Sources/AblyChat/DefaultOccupancy.swift (15)

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The Occupancy protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultOccupancy automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with [weak self] to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #165
File: docs-coverage-report:5-8
Timestamp: 2024-12-10T01:59:12.404Z
Learning: In the AblyChat Swift project, documentation coverage should focus on public methods and properties. Private and internal entities do not require documentation.

Learnt from: maratal
PR: #165
File: Sources/AblyChat/Reaction.swift:14-14
Timestamp: 2024-12-10T01:59:02.065Z
Learning: For the 'ably-chat-swift' repository, documentation-only PRs should focus exclusively on public methods and properties. Avoid suggesting changes to internal comments or private methods in such PRs.

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/Mocks/MockClients.swift:0-0
Timestamp: 2025-05-16T21:04:26.244Z
Learning: In the ably-chat-swift project, mock implementations (like those in MockClients.swift) are intentionally kept simple, sometimes omitting parameter-based filtering behavior for testing simplicity.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/SubscriptionHandleStorage.swift:37-40
Timestamp: 2025-05-12T21:02:28.274Z
Learning: In the AblyChat Swift codebase, the SubscriptionHandle struct has an unsubscribe() method for terminating subscriptions, not a cancel() method.

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription callbacks continue to work even when the handle is not stored, as the underlying services maintain their own storage of callbacks that remain registered until explicitly unsubscribed via the handle's unsubscribe() method.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/RoomLifecycleManager.swift:611-624
Timestamp: 2025-05-22T20:57:48.147Z
Learning: In AblyChat Swift, when using continuations with subscription callbacks, the continuation object is captured directly by the closure and doesn't depend on self. Even with [weak self] capture, the continuation will still be resumed properly.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/SubscriptionAsyncSequence.swift:36-41
Timestamp: 2025-06-29T16:02:43.988Z
Learning: In the AblyChat Swift codebase, the fatalError in SubscriptionAsyncSequence.swift's mock async sequence handling (around line 39) is intentional and should not be flagged. This fatalError catches programmer errors when a throwing AsyncSequence is incorrectly passed to the mock initializer, which is meant for testing/development purposes.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #293
File: Example/AblyChatExample/Mocks/MockRealtime.swift:348-384
Timestamp: 2025-06-14T16:19:29.327Z
Learning: The MockRealtime class in Example/AblyChatExample/Mocks/MockRealtime.swift is specifically for example app construction, not for testing. The actual test mocks are located in the Tests directory. If example app mocks are unused, fatalError calls are appropriate to catch accidental usage.

Learnt from: maratal
PR: #293
File: Example/AblyChatExample/ContentView.swift:94-99
Timestamp: 2025-06-14T21:47:20.509Z
Learning: In the Ably Chat Swift example app, using fatalError for missing clientID is intentional and appropriate since it represents a programmer error rather than a recoverable runtime condition. The clientID is considered an essential configuration requirement.

Sources/AblyChat/DefaultMessages.swift (14)

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The Occupancy protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultOccupancy automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with [weak self] to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.

Learnt from: maratal
PR: #249
File: Tests/AblyChatTests/DefaultMessagesTests.swift:45-48
Timestamp: 2025-05-22T19:17:21.392Z
Learning: The let doIt = {} closures in DefaultMessagesTests.swift are temporary workarounds for compiler crashes (related to issue #233) and will be removed once Xcode 16.3 is released, so they should not be flagged for missing async/throws annotations.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/SubscriptionHandleStorage.swift:37-40
Timestamp: 2025-05-12T21:02:28.274Z
Learning: In the AblyChat Swift codebase, the SubscriptionHandle struct has an unsubscribe() method for terminating subscriptions, not a cancel() method.

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/Mocks/MockClients.swift:0-0
Timestamp: 2025-05-16T21:04:26.244Z
Learning: In the ably-chat-swift project, mock implementations (like those in MockClients.swift) are intentionally kept simple, sometimes omitting parameter-based filtering behavior for testing simplicity.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/RoomReactions.swift:42-56
Timestamp: 2025-05-16T21:35:46.634Z
Learning: In the AblyChat framework, all subscription callbacks are annotated with @mainactor, ensuring they always execute on the main actor thread without requiring additional Task wrappers.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/RoomLifecycleManager.swift:611-624
Timestamp: 2025-05-22T20:57:48.147Z
Learning: In AblyChat Swift, when using continuations with subscription callbacks, the continuation object is captured directly by the closure and doesn't depend on self. Even with [weak self] capture, the continuation will still be resumed properly.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/SubscriptionAsyncSequence.swift:36-41
Timestamp: 2025-06-29T16:02:43.988Z
Learning: In the AblyChat Swift codebase, the fatalError in SubscriptionAsyncSequence.swift's mock async sequence handling (around line 39) is intentional and should not be flagged. This fatalError catches programmer errors when a throwing AsyncSequence is incorrectly passed to the mock initializer, which is meant for testing/development purposes.

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription callbacks continue to work even when the handle is not stored, as the underlying services maintain their own storage of callbacks that remain registered until explicitly unsubscribed via the handle's unsubscribe() method.

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription continues to work even if the handle is not stored, as the underlying services maintain references to the callbacks until explicitly unsubscribed via the handle's unsubscribe() method.

Sources/AblyChat/DefaultPresence.swift (13)

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultOccupancy.swift:10-13
Timestamp: 2025-05-12T21:01:14.109Z
Learning: The Occupancy protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultOccupancy automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:11-14
Timestamp: 2025-05-12T21:03:31.914Z
Learning: The Typing protocol in the Ably Chat Swift SDK is annotated with @MainActor, making all conforming types like DefaultTyping automatically main actor-isolated without requiring explicit annotations on their methods.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/DefaultTyping.swift:131-138
Timestamp: 2025-05-12T21:04:36.263Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle closures should capture self weakly with [weak self] to avoid potential retain cycles, particularly when calling channel.unsubscribe() within the closure.

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/Mocks/MockClients.swift:0-0
Timestamp: 2025-05-16T21:04:26.244Z
Learning: In the ably-chat-swift project, mock implementations (like those in MockClients.swift) are intentionally kept simple, sometimes omitting parameter-based filtering behavior for testing simplicity.

Learnt from: maratal
PR: #165
File: Sources/AblyChat/Reaction.swift:14-14
Timestamp: 2024-12-10T01:59:02.065Z
Learning: For the 'ably-chat-swift' repository, documentation-only PRs should focus exclusively on public methods and properties. Avoid suggesting changes to internal comments or private methods in such PRs.

Learnt from: maratal
PR: #165
File: docs-coverage-report:5-8
Timestamp: 2024-12-10T01:59:12.404Z
Learning: In the AblyChat Swift project, documentation coverage should focus on public methods and properties. Private and internal entities do not require documentation.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #262
File: Tests/AblyChatTests/DefaultRoomReactionsTests.swift:0-0
Timestamp: 2025-05-23T16:29:39.712Z
Learning: In the ably-chat-swift project, MockRealtimeChannel processes messages synchronously when subscribe is called, immediately delivering the configured messages to the callback.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/SubscriptionAsyncSequence.swift:36-41
Timestamp: 2025-06-29T16:02:43.988Z
Learning: In the AblyChat Swift codebase, the fatalError in SubscriptionAsyncSequence.swift's mock async sequence handling (around line 39) is intentional and should not be flagged. This fatalError catches programmer errors when a throwing AsyncSequence is incorrectly passed to the mock initializer, which is meant for testing/development purposes.

Learnt from: maratal
PR: #293
File: Example/AblyChatExample/Mocks/MockRealtime.swift:348-384
Timestamp: 2025-06-14T16:19:29.327Z
Learning: The MockRealtime class in Example/AblyChatExample/Mocks/MockRealtime.swift is specifically for example app construction, not for testing. The actual test mocks are located in the Tests directory. If example app mocks are unused, fatalError calls are appropriate to catch accidental usage.

Learnt from: maratal
PR: #286
File: Sources/AblyChat/RoomLifecycleManager.swift:611-624
Timestamp: 2025-05-22T20:57:48.147Z
Learning: In AblyChat Swift, when using continuations with subscription callbacks, the continuation object is captured directly by the closure and doesn't depend on self. Even with [weak self] capture, the continuation will still be resumed properly.

Learnt from: maratal
PR: #286
File: Example/AblyChatExample/ContentView.swift:203-209
Timestamp: 2025-05-12T21:11:08.937Z
Learning: In the AblyChat Swift codebase, SubscriptionHandle doesn't need to be retained/stored to keep subscriptions active. The subscription callbacks continue to work even when the handle is not stored, as the underlying services maintain their own storage of callbacks that remain registered until explicitly unsubscribed via the handle's unsubscribe() method.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (34)
  • GitHub Check: Example app, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.2)
  • GitHub Check: Example app, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.3)
  • GitHub Check: Example app, tvOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.3)
  • GitHub Check: Example app, iOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.1)
  • GitHub Check: Example app, iOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.2)
  • GitHub Check: Xcode, tvOS (Xcode 16.1)
  • GitHub Check: Example app, iOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.2)
  • GitHub Check: Example app, macOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.1)
  • GitHub Check: Xcode, macOS (Xcode 16.1)
  • GitHub Check: Xcode, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, iOS (Xcode 16.3)
  • GitHub Check: Xcode, macOS (Xcode 16.3)
  • GitHub Check: Xcode, iOS (Xcode 16.2)
  • GitHub Check: Xcode, macOS (Xcode 16.2)
  • GitHub Check: Xcode, iOS (Xcode 16.1)
  • GitHub Check: SPM, release configuration (Xcode 16.3)
  • GitHub Check: Xcode, tvOS (Xcode 16.2)
  • GitHub Check: SPM, release configuration (Xcode 16.2)
  • GitHub Check: SPM, release configuration (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.2)
  • GitHub Check: SPM (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.3)
  • GitHub Check: Generate code coverage
🔇 Additional comments (20)
Sources/AblyChat/DefaultOccupancy.swift (4)

4-8: LGTM! Property declarations correctly implement the refactoring.

The properties are properly declared with correct types and access control, successfully replacing the nested Implementation class pattern.


10-16: Initializer correctly implements direct property assignment.

The refactored initializer properly assigns all dependencies to instance properties, maintaining the same interface while eliminating the nested Implementation class.


19-53: Excellent subscription implementation with proper memory management.

The method correctly implements all subscription logic with:

  • Appropriate error handling using fatalError for programmer errors
  • Proper [weak self] capture to prevent retain cycles
  • Safe message parsing with nil coalescing
  • Correct cleanup via the returned Subscription object

The implementation follows established patterns from the codebase.


56-63: Get method correctly maintains functionality.

The method properly implements direct API calls while preserving the same interface, error handling, and logging patterns as the original nested Implementation approach.

Sources/AblyChat/DefaultRoomReactions.swift (3)

4-14: LGTM! Clean property extraction and initialization.

The refactoring successfully moves the properties from the nested Implementation class directly into DefaultRoomReactions. The properties are appropriately encapsulated as private and the initialization is straightforward and correct.


18-32: LGTM! Proper error handling and logging in the send method.

The method correctly handles the reaction sending flow:

  • Creates the RoomReactionDTO from parameters
  • Publishes to the channel with proper data/extras conversion
  • Includes appropriate debug logging
  • Properly converts errors to ARTErrorInfo for consistent error handling

37-79: LGTM! Well-implemented subscription with proper memory management.

The subscribe method correctly handles the entire subscription lifecycle:

  • Proper weak self capture in both the event listener and subscription disposal to prevent retain cycles
  • Comprehensive message data extraction with appropriate fallbacks per spec requirements (CHA-ER4e1-4)
  • Graceful DTO parsing with try? to handle potential parsing failures
  • Correct isSelf determination using clientID comparison
  • Returns a proper Subscription object for cleanup

The implementation follows the established patterns from the AblyChat Swift codebase learnings.

Sources/AblyChat/DefaultTyping.swift (6)

4-19: LGTM! Clean refactoring of properties.

The properties have been properly extracted from the nested class and are now directly owned by DefaultTyping. The initialization of typingTimerManager is correctly placed.


21-34: LGTM! Proper initialization of dependencies.

The initializer correctly assigns all dependencies and creates the TypingTimerManager with appropriate parameters.


38-108: LGTM! Well-structured subscription implementation.

The refactored subscription logic correctly:

  • Uses weak self capture to prevent retain cycles
  • Properly handles both started and stopped typing events
  • Returns a Subscription that correctly unsubscribes both event listeners
  • Preserves all the original timer management logic

110-113: LGTM! Simple and correct implementation.

The get method correctly returns the currently typing client IDs from the timer manager.


115-135: LGTM! Correct async operation handling.

The keystroke method properly:

  • Enqueues operations on the mutex queue
  • Uses weak self capture appropriately
  • Correctly implements throttling logic
  • Handles errors by converting to ARTErrorInfo

137-181: LGTM! Well-structured stop method and helper.

The implementation correctly:

  • Follows the same async pattern as keystroke
  • Properly checks typing state before publishing events
  • Includes appropriate logging and error handling
  • Good extraction of publishStartedEvent as a private helper method
Sources/AblyChat/DefaultMessages.swift (2)

84-115: LGTM! Clean API method implementations.

The API methods correctly:

  • Delegate to the chatAPI instance
  • Convert errors to ARTErrorInfo consistently
  • Maintain the same public interface

117-152: LGTM! Correct subscription point resolution logic.

The resolveSubscriptionStart method properly:

  • Handles channel state transitions
  • Correctly determines subscription points based on resumed status
  • Includes appropriate error handling and logging
Sources/AblyChat/DefaultPresence.swift (5)

4-18: LGTM! Properties properly extracted.

All dependencies are correctly declared as private properties and properly initialized.


20-95: LGTM! Consistent presence query implementations.

The get methods and isUserPresent correctly:

  • Wait for room lifecycle to allow operations
  • Handle errors with proper logging
  • Convert InternalError to ARTErrorInfo

97-191: LGTM! Well-structured presence state methods.

The enter/update/leave methods are properly implemented with:

  • Public methods delegating to private implementations
  • Consistent error handling and logging
  • Proper lifecycle checks before operations

193-249: LGTM! Robust subscription implementations.

The subscription methods correctly:

  • Enforce enableEvents requirement with appropriate fatal error
  • Use weak self capture in unsubscribe closures
  • Handle both single and multiple event subscriptions
  • Process presence messages appropriately

251-281: LGTM! Helper methods preserved correctly.

The processPresenceGet and processPresenceSubscribe helper methods are properly implemented with appropriate logging and data transformation.

Comment thread Sources/AblyChat/DefaultMessages.swift
Comment thread Sources/AblyChat/DefaultMessages.swift
…l tests began to fail. I then fetched the branch locally and saw that it lacks vars in "DefaultMessages.swift". I asked Copilot to "get all variables back" and it ended up with these changes. I've copied them locally and it compiled and tests then succeeded.

I have no idea why it failed to commit these lines into the repo, although I remember I saw `updateCurrentSubscriptionPoint` before commiting changes at the very least.
@github-actions
github-actions Bot temporarily deployed to staging/pull/342/AblyChat July 26, 2025 20:00 Inactive
@maratal maratal changed the title 339-remove-implementation-class [ECO-5491] Remove Implementation nested class Jul 26, 2025

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

nice, good use of an llm

Base automatically changed from 301-rest-of-errors-via-ChatError to main August 18, 2025 11:29
@maratal
maratal merged commit c32f6a5 into main Aug 18, 2025
41 checks passed
@maratal
maratal deleted the 339-remove-implementation-class branch August 18, 2025 11:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Remove Implementation helper classes inside Default... implementations

2 participants