Skip to content
This repository was archived by the owner on Dec 21, 2025. It is now read-only.

Conversation

@xanderlmk
Copy link
Owner

@xanderlmk xanderlmk commented Jun 17, 2025

Summary by Sourcery

Add card-list management options (copy, move, duplicate, delete), extract keyboard selection into its own repository, refactor DAOs and repositories for bulk operations, centralize review count updates in a reusable class, and streamline UI styling and platform utilities

New Features:

  • Enable copying, moving, and duplicating selected card lists across decks
  • Add composable dialogs for copy/move, duplicate, and delete actions in the card list UI
  • Introduce a KeyboardSelectionRepository to manage Katex keyboard visibility and selection state

Enhancements:

  • Extract updateCardsLeft logic into a reusable ReusedFunc
  • Refactor NavViewModel to delegate keyboard state and deck listings to repositories and simplify state flows
  • Extend CardTypesDao and repositories with bulk copy/move operations and optimize query naming
  • Simplify UI style functions to expression bodies and add disabled text color support
  • Improve navigation drawer and button components with ellipsis overflow and ContentIcons usage
  • Overload toast utility to support styled parameters

@sourcery-ai
Copy link

sourcery-ai bot commented Jun 17, 2025

Reviewer's Guide

This pull request implements card list duplicate, copy, and move workflows end-to-end, refactors repeated logic into a shared helper and expression bodies, centralizes keyboard state in a new repository, enhances UI theming and toast messaging, and cleans up DAO and repository interfaces for streamlined operations.

Class diagram for new and updated card list operations

classDiagram
    class NavViewModel {
        +suspend copyCardList(deckId: Int): Pair<Boolean, String>
        +suspend moveCardList(deckId: Int): Pair<Boolean, String>
        +suspend getAllDecks(): List<Deck>
        +deselectAll()
        +selectAll()
    }
    class CardTypeRepository {
        <<interface>>
        +suspend copyCardList(deck: Deck)
        +suspend moveCardList(deck: Deck)
        +deselectAll()
    }
    class OfflineCardTypeRepository {
        +suspend copyCardList(deck: Deck)
        +suspend moveCardList(deck: Deck)
        +deselectAll()
    }
    class CardTypesDao {
        +suspend copyCardList(cts: List<CT>, deck: Deck)
        +suspend moveCardList(cts: List<CT>, deck: Deck)
        +fun getMaxDCNumber(deckId: Int): Int?
    }
    class Deck
    class CT
    NavViewModel --> CardTypeRepository
    OfflineCardTypeRepository ..|> CardTypeRepository
    OfflineCardTypeRepository --> CardTypesDao
    CardTypesDao --> Deck
    CardTypesDao --> CT
    NavViewModel --> Deck
Loading

Class diagram for KeyboardSelectionRepository and related state

classDiagram
    class KeyboardSelectionRepository {
        <<interface>>
        +showKatexKeyboard: StateFlow<Boolean>
        +selectedKB: StateFlow<SelectedKeyboard?>
        +resetOffset: StateFlow<Boolean>
        +updateSelectedKB(selectedKeyboard: SelectedKeyboard)
        +resetSelectedKB()
        +retrieveKB(retrievedKB: SelectedKeyboard?)
        +toggleKeyboard()
        +resetOffset()
        +resetDone()
        +resetKeyboardStuff()
        +retrieveShowKB(show: Boolean)
    }
    class KeyboardSelectionRepoImpl {
        +showKatexKeyboard
        +selectedKB
        +resetOffset
        +updateSelectedKB(selectedKeyboard: SelectedKeyboard)
        +resetSelectedKB()
        +retrieveKB(retrievedKB: SelectedKeyboard?)
        +toggleKeyboard()
        +resetOffset()
        +resetDone()
        +resetKeyboardStuff()
        +retrieveShowKB(show: Boolean)
    }
    class SelectedKeyboard
    KeyboardSelectionRepoImpl ..|> KeyboardSelectionRepository
    KeyboardSelectionRepository --> SelectedKeyboard
Loading

Class diagram for new UI state and dialog models

classDiagram
    class Decision {
        <<sealed class>>
        Move
        Copy
        Idle
    }
    class Dialogs {
        +showDelete: Boolean
        +showMoveCopy: Boolean
        +showDuplicate: Boolean
    }
    Decision <|-- Move
    Decision <|-- Copy
    Decision <|-- Idle
    Dialogs --> Decision
Loading

File-Level Changes

Change Details Files
End-to-end support for duplicating, copying, and moving selected card lists
  • Added copyCardList and moveCardList methods to CardTypesDao with @transaction
  • Extended OfflineCardTypeRepository and CardTypeRepository to expose copy/move operations
  • Augmented NavViewModel with corresponding suspend functions and dialog triggers
  • Created Compose dialogs (DuplicateCards, CopyMoveCardList) and integrated into CardListOptions and ActionIconButton
.../CardTypesDao.kt
.../OfflineCardTypeRepository.kt
.../CardTypeRepository.kt
.../NavViewModel.kt
.../CardOnClickActions.kt
.../CardOptionsButtons.kt
.../ActionsIconButton.kt
Centralized KaTeX keyboard visibility and selection
  • Introduced KeyboardSelectionRepository interface and implementation
  • Wired kbRepository into AppContainer and NavViewModel constructor
  • Replaced local MutableStateFlows in NavViewModel with repository state flows
.../KeyboardSelectionRepository.kt
.../AppContainer.kt
.../NavViewModel.kt
Extracted updateCardsLeft logic into shared ReusedFunc helper
  • Created ReusedFunc class encapsulating card left/update logic
  • Replaced duplicated withContext/withTimeout blocks in AddCardViewModel and NavViewModel
.../ReusedFunc.kt
.../AddCardViewModel.kt
.../NavViewModel.kt
Refactored code to expression bodies and streamlined UI theme helpers
  • Converted many functions in GetUIStyle and TextProps to expression bodies
  • Added disabledTextColor theme values and TCProp.Disabled
  • Updated button/icon colors to use defaultIconColor and disabledTextColor
.../GetUIStyle.kt
.../Color.kt
.../TextProps.kt
.../Buttons.kt
Enhanced toast messaging to support bold parameters
  • Added overloaded showToastMessage with spannable bold parameter
  • Updated calls in ActionIconButton to use new overload with parameter insertion
.../ShowToastMessage.kt
.../ActionsIconButton.kt
Modeled dialog state and copy/move decisions in UI
  • Defined Parcelable Decision sealed class and Dialogs data class
  • Replaced primitive flags with Dialogs and Decision in CardListOptions and ActionIconButton
.../UiStates.kt
.../CardOptionsButtons.kt
.../ActionsIconButton.kt
Cleaned up DAO and repository interfaces
  • Renamed clearSelection to deselectAll and updated usages
  • Streamlined DAO insert/delete methods and removed redundant imports
  • Updated DeckDao to expose suspend getAllDecks and clarified stream signatures
.../CardTypesDao.kt
.../DeckDao.kt
.../OfflineCardTypeRepository.kt
Added new string resources for card list actions
  • Defined strings for select/deselect, copy, move, duplicate actions and dialog labels
  • Added ‘Okay’ button label
.../strings.xml
.../strings.xml (es)

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

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @xanderlmk - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • Infinite recursion in semiTransButtonColor default case (link)
  • Infinite recursion in choiceColor default branch (link)

General comments:

  • There’s a lot of duplicated code between your copyCardList and moveCardList methods in both the ViewModel and DAO—consider extracting the shared logic into a helper or service to reduce repetition.
  • The DAO now contains complex business logic (building new card entities, deck‐number calculations, etc.); it’d be better to push that heavy lifting into the repository layer so the DAO stays focused on straightforward database operations.
  • The showToastMessage hack of embedding and parsing "$$**" in strings is fragile—use Android’s string placeholders (e.g. %1$s) in your resources and let getString(R.string.some_format, param) handle formatting instead of manual substring logic.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- There’s a lot of duplicated code between your `copyCardList` and `moveCardList` methods in both the ViewModel and DAO—consider extracting the shared logic into a helper or service to reduce repetition.
- The DAO now contains complex business logic (building new card entities, deck‐number calculations, etc.); it’d be better to push that heavy lifting into the repository layer so the DAO stays focused on straightforward database operations.
- The `showToastMessage` hack of embedding and parsing `"$$**"` in strings is fragile—use Android’s string placeholders (e.g. `%1$s`) in your resources and let `getString(R.string.some_format, param)` handle formatting instead of manual substring logic.

## Individual Comments

### Comment 1
<location> `app/src/main/java/com/belmontCrest/cardCrafter/ui/theme/GetUIStyle.kt:51` </location>
<code_context>
-            ifDarkAndCute() -> semiTransDarkCuteButton
-            ifDarkAndNotCute() -> semiTransDarkButton
-            ifNotDarkAndCute() -> semiTransCuteButton
-            else -> semiTransButtonColor
-        }
+    fun semiTransButtonColor(): Color = when {
</code_context>

<issue_to_address>
Infinite recursion in semiTransButtonColor default case

The else branch should return the default color property, not call semiTransButtonColor() recursively.
</issue_to_address>

### Comment 2
<location> `app/src/main/java/com/belmontCrest/cardCrafter/ui/theme/GetUIStyle.kt:100` </location>
<code_context>
-                    if (isCuteTheme) {
-                        cuteChoiceColor
-                    } else {
-                        choiceColor
-                    }
+                    choiceColor
</code_context>

<issue_to_address>
Infinite recursion in choiceColor default branch

The else branch should return a default color constant, not call choiceColor() recursively.
</issue_to_address>

### Comment 3
<location> `app/src/main/java/com/belmontCrest/cardCrafter/localDatabase/dbInterface/daoInterfaces/deckAndCardDao/CardTypesDao.kt:208` </location>
<code_context>
+    /** Copy the selected cards into a new deck */
+    @Transaction
+    suspend fun copyCardList(cts: List<CT>, deck: Deck) {
+        cts.map { ct ->
+            val newDeckCardNumber = returnCardDeckNum(deck.id)
+            when (ct) {
</code_context>

<issue_to_address>
Use forEach instead of map for side-effect operations

map creates a list that's not used; forEach better indicates intent for side effects.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        cts.map { ct ->
            val newDeckCardNumber = returnCardDeckNum(deck.id)
            when (ct) {
=======
        cts.forEach { ct ->
            val newDeckCardNumber = returnCardDeckNum(deck.id)
            when (ct) {
>>>>>>> REPLACE

</suggested_fix>

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 on lines +208 to +210
cts.map { ct ->
val newDeckCardNumber = returnCardDeckNum(deck.id)
when (ct) {
Copy link

Choose a reason for hiding this comment

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

suggestion: Use forEach instead of map for side-effect operations

map creates a list that's not used; forEach better indicates intent for side effects.

Suggested change
cts.map { ct ->
val newDeckCardNumber = returnCardDeckNum(deck.id)
when (ct) {
cts.forEach { ct ->
val newDeckCardNumber = returnCardDeckNum(deck.id)
when (ct) {

@xanderlmk xanderlmk merged commit d8891a1 into main Jun 17, 2025
1 check passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants