pachli-android/core/navigation/build.gradle.kts

44 lines
1.6 KiB
Plaintext
Raw Permalink Normal View History

refactor: Break navigation dependency cycles with :core:navigation (#305) The previous code generally started an activity by having the activity provide a method in a companion object that returns the relevant intent, possibly taking additional parameters that will be included in the intent as extras. E.g., if A wants to start B, B provides the method that returns the intent that starts B. This introduces a dependency between A and B. This is worse if B also wants to start A. For example, if A is `StatusListActivity` and B is`ViewThreadActivity`. The user might click a status in `StatusListActivity` to view the thread, starting `ViewThreadActivity`. But from the thread they might click a hashtag to view the list of statuses with that hashtag. Now `StatusListActivity` and `ViewThreadActivity` have a circular dependency. Even if that doesn't happen the dependency means that any changes to B will trigger a rebuild of A, even if the changes to B are not relevant. Break this dependency by adding a `:core:navigation` module with an `app.pachli.core.navigation` package that contains `Intent` subclasses that should be used instead. The `quadrant` plugin is used to generate constants that can be used to launch activities by name instead of by class, breaking the dependency chain. The plugin uses the `Activity` names from the manifest, so when an activity is moved in the future the constant will automatically update to reflect the new package name. If the activity's intent requires specific extras those are passed via the constructor, with companion object methods to extract them from the intent. Using the intent classes from this package is enforced by a lint `IntentDetector` which will warn if any intents are created using a class literal. See #291
2023-12-07 18:36:00 +01:00
/*
* Copyright 2023 Pachli Association
*
* This file is a part of Pachli.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Pachli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Pachli; if not,
* see <http://www.gnu.org/licenses>.
*/
plugins {
alias(libs.plugins.pachli.android.library)
alias(libs.plugins.kotlin.parcelize)
alias(libs.plugins.quadrant)
}
android {
namespace = "app.pachli.core.navigation"
defaultConfig {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
}
dependencies {
change: Implement more of FiltersRepository (#816) The previous code had a number of problems, including: - Calls to the filters API were scattered through UI and viewmodel code. - Repeated places where the differences between the v1 and v2 Mastodon filters API had to be handled. - UI and viewmodel code using the network filter classes, which tied them to the API implementation. - Error handling was inconsistent. Fix this. ## FiltersRepository - All filter management now goes through `FiltersRepository`. - `FiltersRepository` exposes the current set of filters as a `StateFlow`, and automatically updates it when the current server changes or any changes to filters are made. This makes `FilterChangeEvent` obsolete. - Other operations on filters are exposed through `FiltersRepository` as functions for viewmodels to call. - Within the bulk of the app a new `Filter` class is used to represent a filter; handling the differences between the v1 and v2 APIs is encapsulated in `FiltersRepository`. - Represent errors when handling filters as subclasses of `PachliError`, and use `Result<V, E>` throughout, including using `ApiResult` for all filter API results. - Provide different types to distinguish between new-and-unsaved filters, new-and-unsaved keywords, and in-progress edits to filters. ## Editing filters - Accept an optional complete filter, or filter ID, as parameters in the intent that launches `EditFilterActivity`. Pass those to the viewmodel using assisted injection so the viewmodel has the info immediately. - In the viewmodel use a new `FilterViewData` type to model the data used to display and edit the filter. - Start using the UiSuccess/UiError model. Refrain from cutting over to full the action implementation as that would be a much larger change. - Use `FiltersRepository` instead of making any API calls directly. ## Listing filters - Use `FiltersRepository` instead of making any API calls directly. ## EventHub - Remove `FilterChangedEvent`. Update everywhere that used it to use the flow from `FiltersRepository`.
2024-07-14 15:36:52 +02:00
implementation(projects.core.data)
refactor: Break navigation dependency cycles with :core:navigation (#305) The previous code generally started an activity by having the activity provide a method in a companion object that returns the relevant intent, possibly taking additional parameters that will be included in the intent as extras. E.g., if A wants to start B, B provides the method that returns the intent that starts B. This introduces a dependency between A and B. This is worse if B also wants to start A. For example, if A is `StatusListActivity` and B is`ViewThreadActivity`. The user might click a status in `StatusListActivity` to view the thread, starting `ViewThreadActivity`. But from the thread they might click a hashtag to view the list of statuses with that hashtag. Now `StatusListActivity` and `ViewThreadActivity` have a circular dependency. Even if that doesn't happen the dependency means that any changes to B will trigger a rebuild of A, even if the changes to B are not relevant. Break this dependency by adding a `:core:navigation` module with an `app.pachli.core.navigation` package that contains `Intent` subclasses that should be used instead. The `quadrant` plugin is used to generate constants that can be used to launch activities by name instead of by class, breaking the dependency chain. The plugin uses the `Activity` names from the manifest, so when an activity is moved in the future the constant will automatically update to reflect the new package name. If the activity's intent requires specific extras those are passed via the constructor, with companion object methods to extract them from the intent. Using the intent classes from this package is enforced by a lint `IntentDetector` which will warn if any intents are created using a class literal. See #291
2023-12-07 18:36:00 +01:00
implementation(projects.core.database) // For DraftAttachment, used in ComposeOptions
implementation(projects.core.model)
refactor: Break navigation dependency cycles with :core:navigation (#305) The previous code generally started an activity by having the activity provide a method in a companion object that returns the relevant intent, possibly taking additional parameters that will be included in the intent as extras. E.g., if A wants to start B, B provides the method that returns the intent that starts B. This introduces a dependency between A and B. This is worse if B also wants to start A. For example, if A is `StatusListActivity` and B is`ViewThreadActivity`. The user might click a status in `StatusListActivity` to view the thread, starting `ViewThreadActivity`. But from the thread they might click a hashtag to view the list of statuses with that hashtag. Now `StatusListActivity` and `ViewThreadActivity` have a circular dependency. Even if that doesn't happen the dependency means that any changes to B will trigger a rebuild of A, even if the changes to B are not relevant. Break this dependency by adding a `:core:navigation` module with an `app.pachli.core.navigation` package that contains `Intent` subclasses that should be used instead. The `quadrant` plugin is used to generate constants that can be used to launch activities by name instead of by class, breaking the dependency chain. The plugin uses the `Activity` names from the manifest, so when an activity is moved in the future the constant will automatically update to reflect the new package name. If the activity's intent requires specific extras those are passed via the constructor, with companion object methods to extract them from the intent. Using the intent classes from this package is enforced by a lint `IntentDetector` which will warn if any intents are created using a class literal. See #291
2023-12-07 18:36:00 +01:00
implementation(projects.core.network) // For Attachment, used in AttachmentViewData
implementation(libs.androidx.core.ktx) // IntentCompat
}
// ktlint checks generated files (https://github.com/JLLeitschuh/ktlint-gradle/issues/580) so
// ensure it's run after the navigation files have been created.
tasks.named("runKtlintCheckOverMainSourceSet").configure { dependsOn(":core:navigation:generateActivityClassNameConstants") }