Skip to content

Add manga blacklist#1609

Open
thousandsofthem wants to merge 8 commits into
komikku-app:masterfrom
thousandsofthem:add-blacklist
Open

Add manga blacklist#1609
thousandsofthem wants to merge 8 commits into
komikku-app:masterfrom
thousandsofthem:add-blacklist

Conversation

@thousandsofthem

@thousandsofthem thousandsofthem commented Apr 23, 2026

Copy link
Copy Markdown

This PR adds ability to hide series you don't like from "Browse" section of the app.
Hiding works by title only and does not depend on any extension.

The UI to add/remove titles located at Settings -> Browse -> Series blacklist

Manga can be hidden via context menu (see screenshots)

Blacklist setting are checked to be backed up/restored properly

1 2 3
Screenshot_20260423_223714_app_komikku_dev_MainActivity Screenshot_20260423_223855_app_komikku_dev_MainActivity Screenshot_20260423_223741_app_komikku_dev_MainActivity
4 5
Screenshot_20260423_224258_app_komikku_dev_MainActivity Screenshot_20260423_224231_app_komikku_dev_MainActivity

Summary by Sourcery

Introduce a title-based series blacklist that hides selected manga from browse and search results and can be managed from settings or item actions.

New Features:

  • Add a persistent series blacklist preference with normalized title matching to hide selected manga across browse and global search flows.
  • Provide UI to manage blacklisted series, including a settings screen with search and add/delete dialogs, and per-manga action dialogs in browse and global search.
  • Enable bulk blacklisting of selected manga from existing bulk selection toolbars in browse, migration, recommendations, follows, and related manga screens.

Enhancements:

  • Normalize and sanitize manga titles for blacklist comparison using accent- and punctuation-insensitive matching to keep entries unique and sorted.

Tests:

  • Add unit tests for series blacklist defaults, title normalization, and storage of sorted, unique blacklist entries.

@sourcery-ai

sourcery-ai Bot commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Implements a user-managed series blacklist backed by source preferences, wires it into browse and global search flows to filter out matching manga by normalized title, and exposes management via a new settings screen and reusable manga-actions bottom sheet, including bulk-blacklist support and basic tests.

Sequence diagram for adding a manga title to the blacklist from browse

sequenceDiagram
    actor User
    participant BrowseSourceScreen as BrowseSourceScreen
    participant MangaActionsDialog as MangaActionsDialog
    participant SourcePreferences as SourcePreferences
    participant Toast as AndroidToast

    User->>BrowseSourceScreen: Long_press_manga_item
    BrowseSourceScreen->>BrowseSourceScreen: actionManga = selected_manga
    BrowseSourceScreen->>MangaActionsDialog: Show(manga)

    User->>MangaActionsDialog: Tap_Add_to_blacklist
    MangaActionsDialog->>SourcePreferences: addBlacklistedSeries(manga.title)
    alt title_added
        SourcePreferences-->>MangaActionsDialog: true
        MangaActionsDialog->>BrowseSourceScreen: onDismissRequest()
        BrowseSourceScreen->>BrowseSourceScreen: actionManga = null
        BrowseSourceScreen->>BrowseSourceScreen: blacklist_prefs_flow_emits_updated_list
    else title_already_exists
        SourcePreferences-->>MangaActionsDialog: false
        MangaActionsDialog->>Toast: context.toast(blacklist_title_exists)
    end

    Note over SourcePreferences,BrowseSourceScreen: Updated blacklist is serialized in preferences and propagated via blacklistedSeries().changes() and enableSeriesBlacklist().changes() flows to BrowseSourceScreenModel, which updates state.blacklistedTitles and filters listings.
Loading

Sequence diagram for filtering browse and global search results by blacklist

sequenceDiagram
    participant SourcePreferences as SourcePreferences
    participant BrowseSourceScreenModel as BrowseSourceScreenModel
    participant SearchScreenModel as SearchScreenModel
    participant PagingFlow as BrowsePagingFlow
    participant GlobalSearchState as GlobalSearchState

    SourcePreferences-->>BrowseSourceScreenModel: enableSeriesBlacklist().get()
    SourcePreferences-->>BrowseSourceScreenModel: blacklistedSeries().get()
    BrowseSourceScreenModel->>BrowseSourceScreenModel: init blacklistedTitles = normalizedTitles

    SourcePreferences-->>SearchScreenModel: enableSeriesBlacklist().get()
    SourcePreferences-->>SearchScreenModel: blacklistedSeries().get()
    SearchScreenModel->>SearchScreenModel: init blacklistedTitles = normalizedTitles

    par reactive_updates
        SourcePreferences-->>BrowseSourceScreenModel: enableSeriesBlacklist().changes()
        SourcePreferences-->>BrowseSourceScreenModel: blacklistedSeries().changes()
        BrowseSourceScreenModel->>BrowseSourceScreenModel: combine(...) -> update state.blacklistedTitles
    and
        SourcePreferences-->>SearchScreenModel: enableSeriesBlacklist().changes()
        SourcePreferences-->>SearchScreenModel: blacklistedSeries().changes()
        SearchScreenModel->>SearchScreenModel: combine(...) -> update state.blacklistedTitles
    end

    BrowseSourceScreenModel->>PagingFlow: Pager(...).flow
    PagingFlow-->>BrowseSourceScreenModel: PagingData~Flow~StateFlow~Pair~Manga, Metadata?~~~~
    BrowseSourceScreenModel->>PagingFlow: filter { !hideInLibraryItems || !favorite }
    BrowseSourceScreenModel->>PagingFlow: blacklistedTitles.flatMapLatest { titles -> if (titles.isNotEmpty()) filter { manga.title.toBlacklistNormalizedTitle() !in titles } }

    SearchScreenModel->>GlobalSearchState: compute filteredItems
    GlobalSearchState->>GlobalSearchState: for each Success result, filter result.result where manga.title.toBlacklistNormalizedTitle() !in blacklistedTitles

    Note over PagingFlow,GlobalSearchState: Both browse paging and global search<br/>use the same normalized-title blacklist to hide matching series from results.
Loading

Class diagram for series blacklist domain and preferences

classDiagram
    class BlacklistedSeriesEntry {
        <<data>>
        +String originalTitle
        +String normalizedTitle
    }

    class SourcePreferences {
        -PreferenceStore preferenceStore
        -ListSerializer~BlacklistedSeriesEntry~ blacklistSerializer
        +Preference~List~BlacklistedSeriesEntry~~ blacklistedSeries()
        +Boolean addBlacklistedSeries(title: String)
        +Unit removeBlacklistedSeries(normalizedTitle: String)
        +Preference~Boolean~ enableSeriesBlacklist()
        -List~BlacklistedSeriesEntry~ sanitizeBlacklistedSeries(entries: List~BlacklistedSeriesEntry~)
    }

    class BrowseSourceScreenModelState {
        +Set~String~ blacklistedTitles
    }

    class BrowseSourceScreenModel {
        -SourcePreferences sourcePreferences
        -MutableStateFlow~BrowseSourceScreenModelState~ mutableState
        +StateFlow~BrowseSourceScreenModelState~ state
        +Unit init
        +Flow~Flow~StateFlow~Pair~Manga, RaisedSearchMetadata?~~~~ mangaPagerFlowFlow
    }

    class SearchScreenModelState {
        +Set~String~ blacklistedTitles
        +PersistentMap~CatalogueSource, SearchItemResult~ items
        +PersistentMap~CatalogueSource, SearchItemResult~ filteredItems
    }

    class SearchScreenModel {
        -SourcePreferences preferences
        -MutableStateFlow~SearchScreenModelState~ mutableState
        +StateFlow~SearchScreenModelState~ state
        +Unit init
    }

    class BulkFavoriteScreenModelState {
        +Set~Manga~ selection
        +Boolean selectionMode
        +Boolean isRunning
    }

    class BulkFavoriteScreenModel {
        -SourcePreferences sourcePreferences
        -MutableStateFlow~BulkFavoriteScreenModelState~ state
        +Unit massBlacklist()
    }

    class StringExtensions {
        +String toBlacklistNormalizedTitle()
    }

    SourcePreferences --> BlacklistedSeriesEntry : stores
    BrowseSourceScreenModel --> SourcePreferences : reads_blacklistedSeries
    BrowseSourceScreenModel --> BrowseSourceScreenModelState : updates
    BrowseSourceScreenModelState --> BlacklistedSeriesEntry : holds_normalized_titles

    SearchScreenModel --> SourcePreferences : reads_blacklistedSeries
    SearchScreenModel --> SearchScreenModelState : updates

    BulkFavoriteScreenModel --> SourcePreferences : addBlacklistedSeries
    BulkFavoriteScreenModel --> BulkFavoriteScreenModelState : updates

    StringExtensions <.. BlacklistedSeriesEntry : uses_to_normalize_titles
    StringExtensions <.. SourcePreferences : uses_to_sanitize_entries
    StringExtensions <.. BrowseSourceScreenModel : uses_to_filter_paged_results
    StringExtensions <.. SearchScreenModel : uses_to_filter_search_results
Loading

File-Level Changes

Change Details Files
Add persistent series blacklist storage, normalization utilities, and preference wiring.
  • Introduce BlacklistedSeriesEntry @serializable model for storing original and normalized titles.
  • Extend SourcePreferences with blacklistedSeries(), addBlacklistedSeries(), removeBlacklistedSeries(), enableSeriesBlacklist(), and internal sanitizeBlacklistedSeries().
  • Implement String.toBlacklistNormalizedTitle() to normalize titles by trimming, standardizing punctuation, removing accents, and stripping non-alphanumerics.
  • Ensure blacklist entries are deduplicated by normalized title and sorted by original title using natural, case-insensitive comparison.
  • Add SourcePreferencesTest to validate default enablement, normalization behavior, and storage semantics of the blacklist.
app/src/main/java/eu/kanade/domain/source/model/BlacklistedSeriesEntry.kt
app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt
core/common/src/main/kotlin/eu/kanade/tachiyomi/util/lang/BlacklistNormalization.kt
app/src/test/java/eu/kanade/domain/source/service/SourcePreferencesTest.kt
Filter browse and global search results using the series blacklist and propagate blacklist state through screen models.
  • Extend BrowseSourceScreenModel.State and SearchScreenModel.State with blacklistedTitles and initialize from SourcePreferences when enabled.
  • Subscribe to enableSeriesBlacklist() and blacklistedSeries() changes using combine() to keep blacklistedTitles in state updated reactively.
  • Wrap browse Pager flow so that loaded items are additionally filtered by manga.title.toBlacklistNormalizedTitle() against blacklistedTitles.
  • In SearchScreenModel, post-process SearchItemResult.Success items to drop blacklisted manga before visibility filtering.
  • Remove unnecessary runBlocking when restoring saved search in BrowseSourceScreenModel by using suspend awaitOne directly.
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt
Introduce a reusable manga actions bottom sheet and integrate blacklist actions in browse and global search UIs, including bulk operations.
  • Create MangaActionsDialog composable with AdaptiveSheet and TextPreferenceWidget entries for add/remove favorite and add to blacklist, plus a cancel button.
  • In BrowseSourceScreen and GlobalSearchScreen, track a selected actionManga on long-press and show MangaActionsDialog instead of directly favoriting; wire favorite flows to existing duplicate handling or bulk favorite logic.
  • On blacklist action from the dialog, call SourcePreferences.addBlacklistedSeries(manga.title) and show a toast if the title is already present.
  • Extend BulkFavoriteScreenModel with massBlacklist() to add selected mangas’ titles to the blacklist in a non-cancellable job and reset selection afterwards.
  • Update BulkSelectionToolbar to accept an optional onBlacklistClick, display a Block icon action, and invoke massBlacklist from browse, global search, migrate search, source feeds, related manga, MangaDex follows, and browse recommendations screens.
app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceDialogs.kt
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt
app/src/main/java/eu/kanade/presentation/components/BulkSelectionToolbar.kt
app/src/main/java/eu/kanade/tachiyomi/ui/browse/BulkFavoriteScreenModel.kt
app/src/main/java/eu/kanade/presentation/browse/GlobalSearchScreen.kt
app/src/main/java/eu/kanade/presentation/browse/MigrateSearchScreen.kt
app/src/main/java/eu/kanade/presentation/browse/SourceFeedScreen.kt
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSourceSearchScreen.kt
app/src/main/java/eu/kanade/tachiyomi/ui/manga/RelatedMangasScreen.kt
app/src/main/java/exh/md/follows/MangaDexFollowsScreen.kt
app/src/main/java/exh/recs/BrowseRecommendsScreen.kt
Add a dedicated Series blacklist settings screen with search, enable toggle, and add/remove dialogs, and surface its entry in Browse settings.
  • Create BlacklistScreen, a Voyager Screen that lists BlacklistedSeriesEntry items from SourcePreferences, supports in-list search, and allows enabling/disabling the feature via a CheckboxItem bound to enableSeriesBlacklist().
  • Implement ElevatedCard-based BlacklistItem rows with label icon and delete button to trigger a confirmation dialog.
  • Add AddBlacklistEntryDialog with validation using toBlacklistNormalizedTitle() and user feedback via toasts for invalid or duplicate titles.
  • Add DeleteBlacklistEntryDialog to confirm and remove an entry via removeBlacklistedSeries(normalizedTitle).
  • Wire SettingsBrowseScreen to observe blacklistedSeries changes, show a new TextPreference with a pluralized count of hidden titles, and navigate to BlacklistScreen on click.
app/src/main/java/eu/kanade/presentation/more/settings/screen/browse/BlacklistScreen.kt
app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsBrowseScreen.kt
Add localized strings and plurals for the series blacklist feature and related UI texts.
  • Define new strings for blacklist preferences, empty state, add/delete flows, duplicate title warning, and the manga actions label.
  • Introduce num_blacklisted_series plural to show the count of hidden titles in settings.
  • Use KMR and MR resources appropriately across dialogs, toolbar actions, and toasts.
i18n-kmk/src/commonMain/moko-resources/base/strings.xml
i18n-kmk/src/commonMain/moko-resources/base/plurals.xml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a series blacklist feature to the application, enabling users to filter out unwanted manga titles from their browsing experience. The implementation includes a new UI for managing these entries, backend logic for title normalization to ensure accurate matching, and seamless integration with existing preference management for data persistence.

Highlights

  • Manga Blacklist Feature: Introduced a new series blacklist functionality that allows users to hide specific manga titles from the 'Browse' section.
  • UI/UX Improvements: Added a new context menu for manga items to easily add titles to the blacklist, along with a dedicated settings screen to manage the blacklist.
  • Normalization Logic: Implemented robust title normalization to ensure consistent matching by removing punctuation, accents, and handling case-insensitivity.
  • Data Persistence: Integrated blacklist storage into the existing preference system, ensuring settings are correctly backed up and restored.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.


A title you wish not to see, Is hidden away, set to be free. With logic so sound, No matches are found, In browse, it will no longer be.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • Both BrowseSourceScreenModel and SearchScreenModel map blacklistedSeries() to a Set<String> of normalized titles in the same way; consider extracting this into a shared helper/extension to avoid duplication and keep blacklist handling consistent.
  • Filtering out blacklisted manga currently normalizes each manga title on-the-fly via toBlacklistNormalizedTitle() in both browse and global search flows; if this becomes a hotspot with large lists, consider caching the normalized title per manga or precomputing it at the boundary to avoid repeated normalization work.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Both `BrowseSourceScreenModel` and `SearchScreenModel` map `blacklistedSeries()` to a `Set<String>` of normalized titles in the same way; consider extracting this into a shared helper/extension to avoid duplication and keep blacklist handling consistent.
- Filtering out blacklisted manga currently normalizes each manga title on-the-fly via `toBlacklistNormalizedTitle()` in both browse and global search flows; if this becomes a hotspot with large lists, consider caching the normalized title per manga or precomputing it at the boundary to avoid repeated normalization work.

## Individual Comments

### Comment 1
<location path="app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt" line_range="73-81" />
<code_context>
+        },
+    )
+
+    fun addBlacklistedSeries(title: String): Boolean {
+        val originalTitle = title.trim()
+        val normalizedTitle = originalTitle.toBlacklistNormalizedTitle()
+        if (originalTitle.isBlank() || normalizedTitle.isBlank()) return false
+
+        val entries = blacklistedSeries().get()
+        if (entries.any { it.normalizedTitle == normalizedTitle }) return false
+
+        blacklistedSeries().set(
+            entries + BlacklistedSeriesEntry(
+                originalTitle = originalTitle,
</code_context>
<issue_to_address>
**issue (bug_risk):** Consider using a read-modify-write helper to avoid races when updating the blacklist preference.

`addBlacklistedSeries` does a `get()` followed by `set(entries + ...)`, which can drop updates if multiple callers run concurrently (the last `set` wins). If the `Preference` API supports an atomic `update`/`transform` (e.g. `blacklistedSeries().update { ... }`), prefer that to perform the read-modify-write in one step and keep the deduplication aligned with the sanitizer.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread app/src/main/java/eu/kanade/domain/source/service/SourcePreferences.kt Outdated

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a series blacklist feature, allowing users to hide specific titles from browse and search results. It includes a new management screen, preference settings, and title normalization logic to ensure consistent filtering. Feedback focuses on improving state persistence during configuration changes, optimizing the Paging flow to prevent unnecessary reloads when the blacklist updates, and refining UI details such as handling long titles and avoiding hardcoded font sizes.

Comment thread app/src/main/java/eu/kanade/presentation/browse/components/BrowseSourceDialogs.kt Outdated
@thousandsofthem

thousandsofthem commented Apr 24, 2026

Copy link
Copy Markdown
Author

Tested it on ~2k blacklisted titles - no noticable slowdowns or issues

More images:

Image 1 Image 2 Image 3
Screenshot Screenshot Screenshot
Screenshot Screenshot Screenshot
Screenshot

@Turhvjbufv

Turhvjbufv commented May 1, 2026

Copy link
Copy Markdown

Can wild cards be used?
Eg. I don't want anything with "regression" in the title
So I'll add a title .*regression.*

@cuong-tran

Copy link
Copy Markdown
Collaborator

This is something, thanks.

@thousandsofthem

Copy link
Copy Markdown
Author

So I'll add a title .*regression.*

No, current PR works on exact titles. Adding regex support is possible but it will make UX much more complex and hard to explain for newcomers without technical skills.

@cuong-tran

Copy link
Copy Markdown
Collaborator

@sourcery-ai summary

@cuong-tran

Copy link
Copy Markdown
Collaborator

@sourcery-ai guide

@thousandsofthem

Copy link
Copy Markdown
Author

added enable/disable flag, sorting

Image 1 Image 2 Image 3

@thousandsofthem

Copy link
Copy Markdown
Author

@cuong-tran any chance of this PR being merged anytime soon?

@cuong-tran

Copy link
Copy Markdown
Collaborator

Sorry for the long waiting, I will look at the pending PRs soon.

@thousandsofthem

thousandsofthem commented Jun 4, 2026

Copy link
Copy Markdown
Author

merged upstream; added missing KMK markers (no real code changes)

@rpcarvalheira

Copy link
Copy Markdown

So I'll add a title .*regression.*

No, current PR works on exact titles. Adding regex support is possible but it will make UX much more complex and hard to explain for newcomers without technical skills.

My two unsolicited cents and a biased opinion: regex/wildcards in advanced settings should work, as it doesn't mess with UX and improves speed of lookup for heavy users, since one regex rule would be way less demanding than 2k blocklisted titles, generally speaking. For those that handle many extensions and like 5k titles (such as myself), it would be godsend.

@thousandsofthem

thousandsofthem commented Jun 6, 2026

Copy link
Copy Markdown
Author

since one regex rule would be way less demanding than 2k blocklisted titles, generally speaking.

well, more demanding in terms of performance. current implementation does simple inclusion in a set which is plenty performant. with 2k blocklist regex lines it would be a slow check line by line for every manga title.

Also, regex is not compatible with current flow - block directly in the list by selecting some manga and clicking "block"

It cloud make sense to add regex in addition to that this PR already does, assuming it will contain small amount of hand-crafted rules made by advanced users. I don't want to increase complexity too much though.

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.

4 participants