Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 13:56:56 +01:00
parent 75dc487a7a
commit 39c29d175b
6317 changed files with 388324 additions and 2 deletions

View file

@ -0,0 +1,36 @@
# Descriptive Title in Title Case
- Issue: [#NNNN](https://github.com/thunderbird/thunderbird-android/issues/NNNN)
- Pull Request: [#NNNN](https://github.com/thunderbird/thunderbird-android/pull/NNNN)
<!-- optional in case there are follow-up issues
- Tracking Issue: [#NNNN](https://github.com/thunderbird/thunderbird-android/issues/NNNN)
-->
## Status
<!-- [Status from the options: proposed, accepted, rejected, deprecated, superseded] -->
- **Status**
## Context
<!-- [Description of the context and problem statement that the decision is addressing. It should contain any relevant factors that influenced the decision.] -->
## Decision
<!-- [Description of the decision that was made. Detail the change that will be implemented.] -->
## Consequences
<!-- [Explanation of the consequences of the decision. This includes both the positive and negative effects, and any potential risks.] -->
### Positive Consequences
- consequence 1
- consequence 2
### Negative Consequences
- consequence 1
- consequence 2

View file

@ -0,0 +1,32 @@
# Switch from Java to Kotlin
- Pull Request: [#7221](https://github.com/thunderbird/thunderbird-android/pull/7221)
## Status
- **Accepted**
## Context
We've been using Java as our primary language for Android development. While Java has served us well, it has certain
limitations in terms of null safety, verbosity, functional programming, and more. Kotlin, officially supported by
Google for Android development, offers solutions to many of these issues and provides more modern language features
that can improve productivity, maintainability, and overall code quality.
## Decision
Switch our primary programming language for Android development from Java to Kotlin. This will involve rewriting our
existing Java codebase in Kotlin and writing all new code in Kotlin. To facilitate the transition, we will gradually
refactor our existing Java codebase to Kotlin.
## Consequences
- **Positive Consequences**
- Improved null safety, reducing potential for null pointer exceptions.
- Increased code readability and maintainability due to less verbose syntax.
- Availability of modern language features such as coroutines for asynchronous programming, and extension functions.
- Officially supported by Google for Android development, ensuring future-proof development.
- **Negative Consequences**
- The process of refactoring existing Java code to Kotlin can be time-consuming.
- Potential for introduction of new bugs during refactoring.

View file

@ -0,0 +1,35 @@
# UI - Wrap Material Components in Atomic Design System
- Pull Request: [#7221](https://github.com/thunderbird/thunderbird-android/pull/7221)
## Status
- **Accepted**
## Context
As we continued developing our Jetpack Compose application, we found a need to increase the consistency, reusability,
and maintainability of our user interface (UI) components. We have been using Material components directly throughout our
application. This lead to a lack of uniformity and increases the complexity of changes as the same modifications had to
be implemented multiple times across different screens.
## Decision
To address these challenges, we've decided to adopt an
[Atomic Design System](../design-system.md) as a foundation for our application UI.
This system encapsulates Material components within our [own components](../../../core/ui/compose/designsystem/),
organized into categories of _atoms_, _molecules_, and _organisms_. We also defined _templates_ as layout structures
that can be flexibly combined to construct _pages_. These components collectively form the building blocks that we are
using to construct our application's UI.
## Consequences
- **Positive Consequences**
- Increased reusability of components across the application, reducing code duplication.
- More consistent UI and uniform styling across the entire application.
- Improved maintainability, as changes to a component only need to be made in one place.
- **Negative Consequences**
- Initial effort and time investment needed to implement the atomic design system.
- Developers need to adapt to the new system and learn how to use it effectively.
- Potential for over-complication if simple components are excessively broken down into atomic parts.

View file

@ -0,0 +1,37 @@
# Switch Test Assertions from Truth to assertk
- Pull Request: [#7242](https://github.com/thunderbird/thunderbird-android/pull/7242)
## Status
- **Accepted**
## Context
Our project has been using the Truth testing library for writing tests. While Truth has served us well, it is primarily
designed for Java and lacks some features that make our Kotlin tests more idiomatic and expressive. As our codebase is
[primarily Kotlin](0001-switch-from-java-to-kotlin.md), we have been looking for a testing library that is more aligned
with Kotlin's features and idioms.
## Decision
We have decided to use [assertk](https://github.com/willowtreeapps/assertk) as the default assertions framework for
writing tests in our project. assertk provides a fluent API that is very similar to Truth, making the transition easier.
Moreover, it is designed to work well with Kotlin, enabling us to leverage Kotlin-specific features in our tests.
We've further committed to converting all pre-existing tests from Truth to assertk.
## Consequences
**Note**: The migration of all Truth tests to assertk has already been completed.
- **Positive Consequences**
- **Ease of Transition**: The syntax of assertk is very similar to Truth, which makes the migration process smoother.
- **Kotlin-Friendly**: assertk is designed specifically for Kotlin, allowing us to write more idiomatic and
expressive Kotlin tests.
- **Negative Consequences**
- **Dependency**: While we are replacing one library with another, introducing a new library always carries the risk
of bugs or future deprecation.
- **Migration Effort**: Existing tests written using Truth will need to be migrated to use assertk, requiring some
effort, although mitigated by the similar syntax.

View file

@ -0,0 +1,43 @@
# Naming Conventions for Interfaces and Their Implementations
- Pull Request: [#7794](https://github.com/thunderbird/thunderbird-android/pull/7794)
## Status
- **Accepted**
## Context
When there's an interface that has multiple implementations it's often easy enough to give meaningful names to both the
interface and the implementations (e.g. the interface `Backend` with the implementations `ImapBackend` and
`Pop3Backend`). Naming becomes harder when the interface mainly exists to allow having isolated unit tests and the
production code contains exactly one implementation of the interface.
Prior to this ADR we didn't have any naming guidelines and the names varied widely. Often when there was only one
(production) implementation, the class name used one of the prefixes `Default`, `Real`, or `K9`. None of these had any
special meaning and it wasn't clear which one to pick when creating a new interface/class pair.
## Decision
We'll be using the following guidelines for naming interfaces and their implementation classes:
1. **Interface Naming:** Name interfaces as if they were classes, using a clear and descriptive name. Avoid using the
"IInterface" pattern.
2. **Implementation Naming:** Use a prefix that clearly indicates the relationship between the interface and
implementation, such as `DatabaseMessageStore` or `InMemoryMessageStore` for the `MessageStore` interface.
3. **Descriptive Names:** Use descriptive names for interfaces and implementing classes that accurately reflect their
purpose and functionality.
4. **Platform-specific Implementations:** Use the platform name as a prefix for interface implementations specific to
that platform, e.g. `AndroidPowerManager`.
5. **App-specific Implementations:** Use the prefix `K9` for K-9 Mail and `Tb` for Thunderbird when app-specific
implementations are needed, e.g. `K9AppNameProvider` and `TbAppNameProvider`.
6. **Flexibility:** If no brief descriptive name fits and there is only one production implementation, use the prefix
`Default`, like `DefaultImapFolder`.
## Consequences
- **Positive Consequences**
- Improved code readability and maintainability through consistent naming.
- Reduced confusion and misunderstandings by using clear and descriptive names.
- **Negative Consequences**
- Initial effort is required to rename existing classes that do not follow these naming conventions.

View file

@ -0,0 +1,34 @@
# Central Management of Android Project Dependencies and Gradle Configurations via Build-Plugin Module
- Pull Request: [#7803](https://github.com/thunderbird/thunderbird-android/pull/7803)
## Status
- **Accepted**
## Context
In our Android project, managing dependencies and configurations directly within each module's `build.gradle.kts` file has historically led to inconsistencies, duplication, and difficulty in updates. This challenge was particularly noticeable when maintaining the project configuration. By centralizing this setup in a `build-plugin` module, we can encapsulate and reuse Gradle logic, streamline the build process, and ensure consistency across all project modules and ease maintainability of our codebase.
## Decision
To address these challenges, we have decided to establish a `build-plugin` module within our project. This module will serve as the foundation for all common Gradle configurations, dependency management, and custom plugins, allowing for simplified configuration across various project modules and plugins. Key components of this module include:
- **Custom Plugins:** A suite of custom plugins that configure Gradle for different project aspects, ensuring each project type has tailored and streamlined build processes. These plugins should cover Android application, Android library, Jetpack Compose and Java modules.
- **Dependency Management:** Utilizing the [Gradle Version Catalog](https://docs.gradle.org/current/userguide/platforms.html) to centrally manage and update all dependencies and plugins, ensuring that every module uses the same versions and reduces the risk of conflicts.
- **Common Configuration Settings:** Establishing common configurations for Java, Kotlin, and Android to reduce the complexity and variability in setup across different modules.
## Consequences
### Positive Consequences
1. **Consistency Across Modules:** All project modules will use the same versions of dependencies and plugins, reducing the risk of conflicts and enhancing uniformity. They will also share common configurations, ensuring consistency in the build process.
2. **Ease of Maintenance:** Centralizing dependency versions in the Gradle Version Catalog allows for simple and quick updates to libraries and tools across all project modules from a single source.
3. **Simplified Configuration Process:** The custom plugins within the `build-plugin` module provides a streamlined way to apply settings and dependencies uniformly, enhancing productivity and reducing setup complexity.
### Negative Consequences
1. **Initial Overhead:** The setup of the build-plugin module with a Gradle Version Catalog and the migration of existing configurations required an initial investment of time and resources, but this has been completed.
2. **Complexity for New Developers:** The centralized build architecture, particularly with the use of a Gradle Version Catalog, may initially seem daunting to new team members who are unfamiliar with this level of abstraction.
3. **Dependency on the Build-Plugin Module:** The entire project becomes reliant on the stability and accuracy of the `build-plugin` module. Errors within this module or the catalog could impact the build process across all modules.

View file

@ -0,0 +1,37 @@
# White Label Architecture
- Issue: [#7807](https://github.com/thunderbird/thunderbird-android/issues/7807)
- Pull Request: [#7805](https://github.com/thunderbird/thunderbird-android/pull/7805)
## Status
- **Accepted**
## Context
Our project hosts two separate applications, K-9 Mail and Thunderbird for Android, which share a significant amount of functionality. Despite their common features, each app requires distinct branding elements such as app names, themes, and specific strings.
## Decision
We have decided to adopt a modular white-label architecture, where each application is developed as a separate module that relies on a shared codebase. This structure allows us to streamline configuration details specific to each brand either during build or at runtime. This is how we structure the modules:
### Application Modules
There will be 2 separate modules for each of the two applications: **Thunderbird for Android** will be located in `app-thunderbird` and **K-9 Mail** in `app-k9mail`. These modules will contain app-specific implementations, configurations, resources, and startup logic. They should solely depend on the `app-common` module for shared functionalities and may selectively integrate other modules when needed to configure app-specific functionality.
### App Common Module
A central module named `app-common` acts as the central integration point for shared code among the applications. This module contains the core functionality, shared resources, and configurations that are common to both apps. It should be kept as lean as possible to avoid unnecessary dependencies and ensure that it remains focused on shared functionality.
## Consequences
### Positive Consequences
- Enhanced maintainability due to a shared codebase for common functionalities, reducing code duplication.
- Increased agility in developing and deploying new features across both applications, as common enhancements need to be implemented only once.
## Negative Consequences
- Potential for configuration complexities as differentiations increase between the two applications.
- Higher initial setup time and learning curve for new developers due to the modular and decoupled architecture.

View file

@ -0,0 +1,158 @@
# Project Structure
- Issue: [#7852](https://github.com/thunderbird/thunderbird-android/issues/7852)
- Pull Request: [#7829](https://github.com/thunderbird/thunderbird-android/pull/7829)
## Status
- **Accepted**
## Context
The project consists of two distinct applications. To improve maintainability and streamline development, we propose a modular structure using Gradle. This structure is designed to enable clear separation of concerns, facilitate scalable growth, and ensure efficient dependency management. It consists of various module types such as `app`, `app-common`, `feature`, `core`, and `library` modules, promoting enhanced modular reusability.
## Decision
To achieve the goals outlined in the context, we have decided to adopt the following modular structure:
1. **App Modules**:
- `app-thunderbird` and `app-k9mail` are the modules for the two applications, Thunderbird for Android and K-9 Mail respectively. These modules will contain app-specific implementations, configurations, resources, and startup logic. They should solely depend on the `app-common` module for shared functionalities and may selectively integrate `feature` and `core` to setup app-specific needs.
2. **App Common Module**:
- `app-common`: Acts as the central hub for shared code between both applications. This module serves as the primary "glue" that binds various `feature` modules together, providing a seamless integration point. While it can depend on `library` modules for additional functionalities, its main purpose is to orchestrate the interactions among the `feature` and `core` modules, ensuring similar functionality across both applications. This module should be kept lean to avoid unnecessary dependencies and ensure it remains focused on shared functionality.
3. **Feature Modules**:
- `feature:*`: These are independent feature modules, that encapsulate distinct user-facing features. They are designed to be reusable and can be integrated into any application module as needed. They maintain dependencies on `core` modules and may interact with other `feature` or `library` modules.
4. **Core Module**:
- `core:*`: The core modules contain essential utilities and base classes used across the entire project. These modules are grouped by their functionality (e.g., networking, database management, theming, common utilities). This segmentation allows for cleaner dependency management and specialization within foundational aspects.
5. **Library Modules**:
- `library:*` These modules are for specific implementations that might be used across various features or applications. They could be third-party integrations or complex utilities and eventually shared across multiple projects.
```mermaid
graph TD
subgraph APP[App]
APP_K9["`
**:app-k9mail**
K-9 Mail
`"]
APP_TB["`
**:app-thunderbird**
Thunderbird for Android
`"]
end
subgraph COMMON[App Common]
APP_COMMON["`
**:app-common**
Integration Code
`"]
end
subgraph FEATURE[Feature]
FEATURE1[Feature 1]
FEATURE2[Feature 2]
end
subgraph CORE[Core]
CORE1[Core 1]
CORE2[Core 2]
end
subgraph LIBRARY[Library]
LIB1[Library 1]
LIB2[Library 2]
end
APP --> |depends on| COMMON
COMMON --> |integrates| FEATURE
FEATURE --> |uses| CORE
FEATURE --> |uses| LIBRARY
classDef module fill:yellow
classDef app fill:azure
classDef app_common fill:#ddd
class APP_K9 app
class APP_TB app
class APP_COMMON app_common
```
### Legacy Modules
Modules that are still required for the project to function, but don't follow the new project structure.
These modules should not be used for new development.
The goal is to migrate the functionality of these modules to the new structure over time. By placing them under the `legacy` module, we can easily identify and manage them.
```mermaid
graph TD
subgraph APP[App]
APP_K9["`
**:app-k9mail**
K-9 Mail
`"]
APP_TB["`
**:app-thunderbird**
Thunderbird for Android
`"]
end
subgraph COMMON[App Common]
APP_COMMON["`
**:app-common**
Integration Code
`"]
end
subgraph FEATURE[Feature]
FEATURE1[Feature 1]
FEATURE2[Feature 2]
FEATURE3[Feature from Legacy]
end
subgraph CORE[Core]
CORE1[Core 1]
CORE2[Core 2]
CORE3[Core from Legacy]
end
subgraph LIBRARY[Library]
LIB1[Library 1]
LIB2[Library 2]
end
APP --> |depends on| COMMON
COMMON --> |integrates| FEATURE
FEATURE --> |uses| CORE
FEATURE --> |uses| LIBRARY
subgraph LEGACY[Legacy]
LEG[Legacy Code]
end
COMMON -.-> |integrates| LEGACY
LEG -.-> |migrate to| FEATURE3
LEG -.-> |migrate to| CORE3
classDef module fill:yellow
classDef app fill:azure
classDef app_common fill:#ddd
classDef legacy fill:#F99
class APP_K9 app
class APP_TB app
class APP_COMMON app_common
class LEGACY legacy
```
## Consequences
### Positive Consequences
- Improved modularity facilitates easier code maintenance and scaling.
- Clear separation of concerns reduces dependencies and potential conflicts between modules.
- Enhanced reusability of the `feature`, `core` and `library` modules across different parts of the application or even in different projects.
### Negative Consequences
- Initial complexity in setting up and managing multiple modules may increase the learning curve and setup time for new developers.
- Over-modularization can lead to excessive abstraction, potentially impacting runtime performance and complicating the debugging process.
- Legacy modules may require additional effort to migrate to the new structure, potentially causing delays in the adoption of the new architecture.

View file

@ -0,0 +1,51 @@
# Change Shared Modules package to `net.thunderbird`
- Issue: [#9012](https://github.com/thunderbird/thunderbird-android/issues/9012)
## Status
- **Accepted**
## Context
The Thunderbird Android project is a white-label version of K-9 Mail, and both apps — `app-thunderbird` and `app-kmail`
— coexist in the same repository. They have distinct application IDs and branding, but share a significant portion of
the code through common modules.
These shared modules currently use the `app.k9mail` or `com.fsck` package name, which are legacy artifacts from
K-9 Mail. While K-9 will remain available for some time, the projects primary focus has shifted toward Thunderbird.
To reflect this shift, establish clearer ownership, and prepare for future development (including cross-platform code
integration), we will rename the packages in shared modules from `app.k9mail` and `com.fsck` to `net.thunderbird`.
The actual application IDs and package names of `app-thunderbird` and `app-k9mail` must remain **unchanged**.
## Decision
We decided to rename the base package in all shared modules from `app.k9mail` and `com.fsck` to `net.thunderbird`.
Specifically:
- All Kotlin/Java packages in shared modules will be refactored to use `net.thunderbird` as the base
- This must not affect the application IDs or packages of `app-thunderbird` or `app-kmail`, which will remain as-is
- All references, imports, and configuration references will be updated accordingly
- Tests, resources, and Gradle module settings will be adjusted to match the new package structure
This change will establish a clearer identity for the shared code, align with Thunderbird's branding, and prepare the
project for cross-platform development.
## Consequences
## Positive Consequences
- Shared code reflects Thunderbird branding and identity
- Reduces confusion when navigating codebase shared by both apps
- Sets the foundation for cross-platform compatibility and future modularization
- Helps reinforce long-term direction of the project toward Thunderbird
## Negative Consequences
- Large-scale refactoring required across multiple modules
- Risk of introducing regressions during package renaming
- Potential for disruption in local development setups (e.g., IDE caching, broken imports)
- Contributors familiar with the old structure may need time to adjust

View file

@ -0,0 +1,83 @@
# Architecture Decision Records
The [docs/architecture/adr](/docs/architecture/adr) folder contains the architecture decision records (ADRs) for our project.
ADRs are short text documents that serve as a historical context for the architecture decisions we make over the
course of the project.
## What is an ADR?
An Architecture Decision Record (ADR) is a document that captures an important architectural decision made along
with its context and consequences. ADRs record the decision making process and allow others to understand the
rationale behind decisions, providing insight and facilitating future decision-making processes.
## Format of an ADR
We adhere to Michael Nygard's [ADR format proposal](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions),
where each ADR document should contain:
1. **Title**: A short descriptive name for the decision.
1. **Link to Issue**: A link to the issue that prompted the decision.
2. **Link to Pull Request**: A link to the pull request that implements the ADR.
3. **Link to Tracking Issue**: A link to the tracking issue, if applicable.
2. **Status**: The current status of the decision (proposed, accepted, rejected, deprecated, superseded)
3. **Context**: The context that motivates this decision.
4. **Decision**: The change that we're proposing and/or doing.
5. **Consequences**: What becomes easier or more difficult to do and any risks introduced as a result of the decision.
## Creating a new ADR
When creating a new ADR, please follow the provided [ADR template file](0000-adr-template.md) and ensure that your
document is clear and concise.
Once you are ready to propose your ADR, you should:
1. Create an issue in the repository, get consensus from at least one other project contributor.
2. Make a post on [the mobile-planning list](https://thunderbird.topicbox.com/groups/mobile-planning)
to announce your ADR. You can use the below template as needed.
3. Create a pull request in the repository linking the issue.
4. Make a decision together with mobile module owners, the PR will be merged when accepted.
## Directory Structure
The ADRs will be stored in a directory named `docs/adr`, and each ADR will be a file named `NNNN-title-with-dashes.md`
where `NNNN` is a four-digit number that is increased by 1 for every new adr.
## ADR Life Cycle
The life cycle of an ADR is as follows:
1. **Proposed**: The ADR is under consideration.
2. **Accepted**: The decision described in the ADR has been accepted and should be adhered to, unless it is superseded by another ADR.
3. **Rejected**: The decision described in the ADR has been rejected.
4. **Deprecated**: The decision described in the ADR is no longer relevant due to changes in system context.
5. **Superseded**: The decision described in the ADR has been replaced by another decision.
Each ADR will have a status indicating its current life-cycle stage. An ADR can be updated over time, either to change
the status or to add more information.
## Contributions
We welcome contributions in the form of new ADRs or updates to existing ones. Please ensure all contributions follow
the standard format and provide clear and concise information.
## Appendix: Intent to Adopt Template
You may use this template in your Intent to Adopt email as noted above. Tweak it as you feel is useful.
> Hello everyone,
>
> Im writing to share an intent to adopt a new architecture decision: [ADR-[Number]] [Title of ADR]
>
> This change addresses [brief summary of the problem] and proposes [brief description of the approach].
>
> This decision is based on [briefly mention motivating factors, constraints, or technical context].
>
> You can read the full proposal here: [link to ADR]
>
> If you have feedback or concerns, please respond in the linked issue. We plan to finalize the
> decision after [proposed date], factoring in discussion at that time.
>
> Thanks,
> [Your Name]