Skip to content

Conversation

@wmontwe
Copy link
Member

@wmontwe wmontwe commented Jan 12, 2026

Part of #10209

This refactors the id and account id to simplify account handling and remove legacy abstractions. It includes removing support for handling multiple account types in backend factories, updating the dependency injection module to use simpler factories, and adapting the codebase to operate directly with account IDs instead of account objects. Several obsolete test and implementation files have been deleted as a result.

Id changes:

  • Core Architecture Primitives:

    • BaseIdentifier<T>: A generic abstract base class for all identifiers. It implements Comparable<BaseIdentifier<T>> to support natural sorting in collections and overrides equals/hashCode/toString to delegate to the underlying value.
    • BaseUuidIdentifier: A specialized base class for identifiers wrapping a kotlin.uuid.Uuid.
    • IdentifierFactory<T>: A standardized interface for ID creation and parsing, following a "fail-fast" principle for malformed input.
    • BaseUuidIdentifierFactory<T>: An abstract implementation for UUID-based factories that simplifies the creation of concrete ID factories.
  • Account Module Updates:

    • AccountId: Now extends BaseUuidIdentifier, ensuring it is treated as a distinct type from raw UUIDs or other ID types.
    • AccountIdFactory: Refactored to extend BaseUuidIdentifierFactory<AccountId>, centralizing ID generation and parsing logic.
    • UnifiedAccountId: Updated to integrate with the new hierarchy as the sentinel for "all accounts" views.
  • Naming Conventions:

    • Following the project's internal style guide, all abstract base classes have been renamed/introduced with the Base prefix (e.g., BaseIdentifier, BaseUuidIdentifier, BaseParser).
  • API Cleanup:

    • Removed the custom .asRaw() method in favor of the standard .toString(), simplifying the API surface while maintaining interoperability with legacy components that require string representations of IDs.

Impact

This refactoring improves Java interoperability, prevents accidental ID type mismatches at compile time, and provides a clear, extensible pattern for adding new types of identifiers (e.g., Long-based or Int-based IDs) in the future.

Refactoring and Simplification:

  • Removed the BaseAccountBackendStorageFactory, BaseAccountImapBackendFactory, and BaseAccountSpecialFolderUpdaterFactory classes, along with their associated test files, to eliminate unnecessary abstractions for handling both LegacyAccount and LegacyAccountDto types.
  • Updated the dependency injection setup in FeatureMailModule.kt to use the default SpecialFolderUpdater.Factory and a streamlined RemoteFolderCreator.Factory, removing references to the deleted factories and simplifying the module configuration.

Account Handling Updates:

  • Refactored RemoteFolderCreatorResolver to resolve accounts by AccountId using the LegacyAccountManager, and to create IMAP remote folder creators based on account ID rather than account instance.
  • Updated the method in DefaultLegacyAccountManager to use id.toString() when retrieving account flows, ensuring consistency with account ID handling.

Backend:

The backend module defined both java and kotlin source sets, which resulted in incomplete classpath visibility for dependent modules. Downstream Java/Android consumers were only able to access classes from the Kotlin compilation, while classes defined in the java source set were not consistently exposed.

To address this, all source files have been consolidated into the java source set, ensuring a single compilation path and correct visibility for dependent modules.

@wmontwe wmontwe requested a review from a team as a code owner January 12, 2026 09:07
@wmontwe wmontwe requested a review from dani-zilla January 12, 2026 09:07
@wmontwe wmontwe changed the title Refactor account id usage refactor: account id usage Jan 12, 2026
else -> NoOpRemoteFolderCreator
}
override fun create(accountId: AccountId): RemoteFolderCreator {
val account = runBlocking {
Copy link
Contributor

Choose a reason for hiding this comment

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

Only asking for clarity, saw this elsewhere and I assume runBlocking is necessary, but why? I assume we're fairly certain it wouldn't be called from the main thread anyway, just wondering why it's necessary

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