Skip to content

ADFA-2880: Git commit operations#1074

Open
dara-abijo-adfa wants to merge 22 commits intostagefrom
ADFA-2880-git-commit-operations
Open

ADFA-2880: Git commit operations#1074
dara-abijo-adfa wants to merge 22 commits intostagefrom
ADFA-2880-git-commit-operations

Conversation

@dara-abijo-adfa
Copy link
Contributor

  • Stage and commit selected files
  • View commit history

@dara-abijo-adfa dara-abijo-adfa self-assigned this Mar 16, 2026
@dara-abijo-adfa dara-abijo-adfa requested review from Daniel-ADFA, itsaky-adfa, jatezzz and jomen-adfa and removed request for Daniel-ADFA and itsaky-adfa March 16, 2026 17:30
@dara-abijo-adfa dara-abijo-adfa marked this pull request as ready for review March 16, 2026 18:42
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 16, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds commit creation UI and flow, commit history dialog and adapter, Git user preferences, repository staging/commit APIs and JGit implementation, plus related layouts, strings, and styles. ViewModel exposes commitHistory and commitChanges to coordinate UI, preferences, and repository operations.

Changes

Cohort / File(s) Summary
Git UI Fragment & Adapters
app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt, app/src/main/java/com/itsaky/androidide/fragments/git/adapter/GitFileChangeAdapter.kt
Adds fileChangeAdapter with selection callback; wires commit UI (summary/description inputs, author warning/popup, commit button enablement), commit action calling viewModel.commitChanges, and commit-history trigger.
Commit History Dialog & Adapter
app/src/main/java/com/itsaky/androidide/fragments/git/GitCommitHistoryDialog.kt, app/src/main/java/com/itsaky/androidide/fragments/git/adapter/GitCommitHistoryAdapter.kt
New GitCommitHistoryDialog and GitCommitHistoryAdapter; collects commitHistory from ViewModel and renders list with Loading/Empty/Error states and not-pushed indicator.
ViewModel & Models
app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt, git-core/src/main/java/com/itsaky/androidide/git/core/models/GitCommit.kt, git-core/src/main/java/com/itsaky/androidide/git/core/models/CommitHistoryUiState.kt
Adds commitHistory StateFlow and CommitHistoryUiState; implements commitChanges (staging + commit with optional author) and getCommitHistoryList; extends GitCommit with hasBeenPushed.
Repository API & JGit Implementation
git-core/src/main/java/com/itsaky/androidide/git/core/GitRepository.kt, git-core/src/main/java/com/itsaky/androidide/git/core/JGitRepository.kt
Adds stageFiles and commit to GitRepository; JGitRepository implements staging, author-aware commit, and computes push status when building history.
Preferences & Preference Screen
preferences/src/main/java/com/itsaky/androidide/preferences/internal/GitPreferences.kt, app/src/main/java/com/itsaky/androidide/preferences/gitPrefExts.kt, app/src/main/java/com/itsaky/androidide/preferences/rootPrefExts.kt
Adds GitPreferences singleton (userName/userEmail) and preference UI classes (GitPreferencesScreen, GitAuthorConfig, GitUserName, GitUserEmail); registers Git preferences in root preferences.
Layouts & Resources
app/src/main/res/layout/fragment_git_bottom_sheet.xml, app/src/main/res/layout/dialog_git_commit_history.xml, app/src/main/res/layout/item_git_commit.xml
Converts bottom sheet to ConstraintLayout; adds commit inputs, avatar, author warning, commit button group; adds commit history dialog and commit item layouts.
Strings & Styles
resources/src/main/res/values/strings.xml, app/src/main/res/values/strings.xml, resources/src/main/res/values/styles.xml
Adds commit-related and Git preference strings, author warnings, helper texts, and a circular shape appearance style.
Minor wiring
app/src/main/res/layout/fragment_git_bottom_sheet.xml (layout changes)
Layout constraints updated and new views grouped for conditional visibility (commit_section group).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Fragment as GitBottomSheetFragment
    participant Prefs as GitPreferences
    participant ViewModel
    participant Repo as GitRepository

    User->>Fragment: Click Commit
    Fragment->>Prefs: hasAuthorInfo()?
    alt author missing
        Fragment->>Fragment: showAuthorPopup()
        Fragment-->>User: show warning / link to Preferences
    else author present
        Fragment->>Fragment: gather summary, desc, selectedPaths
        Fragment->>ViewModel: commitChanges(summary, desc, paths)
        ViewModel->>Repo: stageFiles(paths)
        Repo-->>ViewModel: staged
        ViewModel->>Repo: commit(message, authorName, authorEmail)
        Repo-->>ViewModel: GitCommit?
        ViewModel-->>Fragment: update status / commitHistory
        Fragment->>Fragment: clear inputs / selections
        Fragment-->>User: commit complete
    end
Loading
sequenceDiagram
    participant User
    participant Fragment as GitBottomSheetFragment
    participant Dialog as GitCommitHistoryDialog
    participant ViewModel
    participant Repo as GitRepository
    participant Adapter as GitCommitHistoryAdapter

    User->>Fragment: Click View History
    Fragment->>Dialog: show()
    Dialog->>ViewModel: getCommitHistoryList()
    ViewModel->>Repo: getHistory()
    Repo-->>ViewModel: List<GitCommit>
    ViewModel-->>Dialog: commitHistory StateFlow emits
    Dialog->>Adapter: submitList(commits)
    Adapter->>Adapter: DiffCallback updates RecyclerView
    Dialog-->>User: display history
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • ADFA-2879: View git status #1038: Overlaps modifications to GitBottomSheetFragment, GitFileChangeAdapter, and ViewModel—likely related to prior Git UI and commit handling work.

Suggested reviewers

  • Daniel-ADFA
  • jomen-adfa
  • itsaky-adfa

Poem

🐇 I hop through code with whiskers bright,
Staging files beneath the moonlight.
I sign my name and press commit,
History hops back, neat and lit.
Rejoice — the repo's feeling light!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'ADFA-2880: Git commit operations' directly reflects the main changes: adding git commit and history viewing capabilities.
Description check ✅ Passed The description 'Stage and commit selected files' and 'View commit history' accurately relates to the changeset's core functionality additions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ADFA-2880-git-commit-operations
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt (1)

104-106: Consider narrowing exception handling as specific exceptions are identified.

The broad catch (e: Exception) works for initial implementation, but per project guidelines, prefer narrowing to specific exception types as they're identified through crash reports. This aligns with fail-fast behavior during development.

Additionally, the commit operation silently fails without notifying the UI. Consider exposing a result state or callback so users know whether the commit succeeded or failed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt`
around lines 104 - 106, The catch-all in GitBottomSheetViewModel around the
commit operation should be narrowed to concrete exception types (e.g.,
IOException, org.eclipse.jgit.api.errors.GitAPIException or whatever your Git
library throws) instead of catch (e: Exception); replace the broad catch in the
commit method with specific catches and preserve logging (log.error(..., e)) for
each type. Also surface the operation outcome to the UI by adding a state or
callback on the ViewModel (for example a LiveData/StateFlow named commitResult
or a sealed Result type) and set success/failure there inside the try/catch so
callers can react instead of failing silently; update any call sites to
observe/handle commitResult accordingly.
app/src/main/res/layout/fragment_git_bottom_sheet.xml (1)

6-6: Remove obsolete android:orientation attribute.

The android:orientation="vertical" attribute has no effect on ConstraintLayout (it's only applicable to LinearLayout). This appears to be a leftover from when the layout was a LinearLayout.

🧹 Proposed fix
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
     android:padding="16dp">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/res/layout/fragment_git_bottom_sheet.xml` at line 6, Remove the
obsolete android:orientation="vertical" attribute from the ConstraintLayout in
fragment_git_bottom_sheet.xml: locate the root ConstraintLayout element (or any
ConstraintLayout in that file) and delete the android:orientation attribute
since it only applies to LinearLayout and has no effect here; confirm no other
layout behavior depends on that attribute and run a quick lint/compile to ensure
no side effects.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt`:
- Around line 103-118: The current click handler clears commitSummary,
commitDescription, and fileChangeAdapter.selectedFiles immediately after calling
viewModel.commitChanges; change this so inputs and selections are only cleared
after the commit actually succeeds and the status refresh completes by observing
the commit result or the viewModel.gitStatus StateFlow/LiveData. Update the
commit flow in GitBottomSheetFragment: call viewModel.commitChanges(summary,
description, selectedPaths) but remove immediate clearing; instead
collect/observe viewModel.commit result or viewModel.gitStatus and on a
successful state (or a commit-success event) clear binding.commitSummary.text,
binding.commitDescription.text, and fileChangeAdapter.selectedFiles and then
notify the adapter to rebind so UI checkboxes match the cleared selection.
Ensure failure cases do not clear inputs so the user can retry.

In
`@app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt`:
- Around line 111-116: getCommitHistoryList currently launches a coroutine that
calls currentRepository?.getHistory() without error handling; wrap the
repository call in a try-catch (mirroring refreshStatus()) so any exceptions
from getHistory() are caught, log or surface the error appropriately (e.g., via
processLogger or an existing error LiveData) and ensure _commitHistory.value is
set to history on success or to emptyList() on failure to avoid crashing the
coroutine and leaving the UI without feedback; update the implementation in
getCommitHistoryList and reference currentRepository?.getHistory(),
_commitHistory, and refreshStatus() as the pattern to follow.

---

Nitpick comments:
In
`@app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt`:
- Around line 104-106: The catch-all in GitBottomSheetViewModel around the
commit operation should be narrowed to concrete exception types (e.g.,
IOException, org.eclipse.jgit.api.errors.GitAPIException or whatever your Git
library throws) instead of catch (e: Exception); replace the broad catch in the
commit method with specific catches and preserve logging (log.error(..., e)) for
each type. Also surface the operation outcome to the UI by adding a state or
callback on the ViewModel (for example a LiveData/StateFlow named commitResult
or a sealed Result type) and set success/failure there inside the try/catch so
callers can react instead of failing silently; update any call sites to
observe/handle commitResult accordingly.

In `@app/src/main/res/layout/fragment_git_bottom_sheet.xml`:
- Line 6: Remove the obsolete android:orientation="vertical" attribute from the
ConstraintLayout in fragment_git_bottom_sheet.xml: locate the root
ConstraintLayout element (or any ConstraintLayout in that file) and delete the
android:orientation attribute since it only applies to LinearLayout and has no
effect here; confirm no other layout behavior depends on that attribute and run
a quick lint/compile to ensure no side effects.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d3cacf5b-d0f2-407f-8802-5291a5b4f7f6

📥 Commits

Reviewing files that changed from the base of the PR and between 5034825 and 3712a0c.

📒 Files selected for processing (17)
  • app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt
  • app/src/main/java/com/itsaky/androidide/fragments/git/GitCommitHistoryDialog.kt
  • app/src/main/java/com/itsaky/androidide/fragments/git/adapter/GitCommitHistoryAdapter.kt
  • app/src/main/java/com/itsaky/androidide/fragments/git/adapter/GitFileChangeAdapter.kt
  • app/src/main/java/com/itsaky/androidide/preferences/gitPrefExts.kt
  • app/src/main/java/com/itsaky/androidide/preferences/rootPrefExts.kt
  • app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt
  • app/src/main/res/layout/dialog_git_commit_history.xml
  • app/src/main/res/layout/fragment_git_bottom_sheet.xml
  • app/src/main/res/layout/item_git_commit.xml
  • app/src/main/res/values/strings.xml
  • git-core/src/main/java/com/itsaky/androidide/git/core/GitRepository.kt
  • git-core/src/main/java/com/itsaky/androidide/git/core/JGitRepository.kt
  • git-core/src/main/java/com/itsaky/androidide/git/core/models/GitCommit.kt
  • preferences/src/main/java/com/itsaky/androidide/preferences/internal/GitPreferences.kt
  • resources/src/main/res/values/strings.xml
  • resources/src/main/res/values/styles.xml

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/src/main/res/layout/item_git_commit.xml (1)

17-50: Cap text lines to prevent oversized history rows.

On Line 17, Line 28, and Line 40, these fields can grow unbounded with long commit metadata. Consider adding maxLines + ellipsize so one long commit doesn’t dominate the list.

Suggested diff
     <TextView
         android:id="@+id/tv_commit_message"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
+        android:ellipsize="end"
+        android:maxLines="2"
         android:textAppearance="@style/TextAppearance.AppCompat.Medium"
         android:textStyle="bold"
         app:layout_constraintEnd_toStartOf="@id/barrier"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         tools:text="This is a commit message" />

     <TextView
         android:id="@+id/tv_commit_author"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_marginTop="8dp"
+        android:ellipsize="end"
+        android:maxLines="1"
         android:textAppearance="@style/TextAppearance.AppCompat.Body2"
         android:textColor="?android:textColorSecondary"
         app:layout_constraintEnd_toStartOf="@id/barrier"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@id/tv_commit_message"
         tools:text="Author Name" />

     <TextView
         android:id="@+id/tv_commit_time"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_marginTop="8dp"
+        android:ellipsize="end"
+        android:maxLines="1"
         android:textAppearance="@style/TextAppearance.AppCompat.Body2"
         android:textColor="?android:textColorSecondary"
         app:layout_constraintEnd_toStartOf="@id/barrier"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@id/tv_commit_author"
         tools:text="12 Mar 2026, 22:53" />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/res/layout/item_git_commit.xml` around lines 17 - 50, The three
TextViews (tv_commit_message, tv_commit_author, tv_commit_time) can grow
unbounded; update each element to limit displayed lines by adding maxLines
(e.g., maxLines="1" or "2" for message and 1 for author/time) and set
android:ellipsize="end" so long commit messages/metadata are truncated with an
ellipsis instead of expanding the row.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/src/main/res/layout/item_git_commit.xml`:
- Around line 17-50: The three TextViews (tv_commit_message, tv_commit_author,
tv_commit_time) can grow unbounded; update each element to limit displayed lines
by adding maxLines (e.g., maxLines="1" or "2" for message and 1 for author/time)
and set android:ellipsize="end" so long commit messages/metadata are truncated
with an ellipsis instead of expanding the row.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e97e993e-4f9e-41ef-b1e5-9ab242793df3

📥 Commits

Reviewing files that changed from the base of the PR and between 3712a0c and 020432d.

📒 Files selected for processing (1)
  • app/src/main/res/layout/item_git_commit.xml

@dara-abijo-adfa dara-abijo-adfa requested a review from jatezzz March 18, 2026 14:12
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt (1)

106-122: ⚠️ Potential issue | 🟡 Minor

Checkbox UI not refreshed after clearing selections.

After a successful commit, fileChangeAdapter.selectedFiles.clear() clears the internal set, but the adapter's checkbox views are not notified to update. The checkboxes will remain visually checked until the status refresh triggers submitList() with a new list.

🛠️ Suggested fix
                 ) {
                     // Clear the inputs on successful commit
                     binding.commitSummary.text?.clear()
                     binding.commitDescription.text?.clear()
                     fileChangeAdapter.selectedFiles.clear()
+                    fileChangeAdapter.notifyDataSetChanged()
                 }

Alternatively, consider adding a clearSelections() helper method in the adapter that clears the set and notifies the adapter.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt`
around lines 106 - 122, The commit button handler clears the adapter's
selectedFiles set but does not notify the RecyclerView to update checkbox views,
so the UI stays checked; update the code to call an adapter method that both
clears the selection set and refreshes views (e.g., add and call
fileChangeAdapter.clearSelections() or clearSelectionsNotify() after
fileChangeAdapter.selectedFiles.clear()), or implement clearSelections() inside
the adapter to clear its internal selection state and call
notifyDataSetChanged()/notifyItemRangeChanged() so checkboxes visually uncheck
after a successful commit (refer to binding.commitButton click listener and
fileChangeAdapter).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt`:
- Around line 52-70: The adapter's internal selection
(fileChangeAdapter.selectedFiles) can contain paths not present after calling
fileChangeAdapter.submitList(allChanges), causing stale selections; inside the
viewModel.gitStatus.collectLatest block, before calling submitList(allChanges)
update the selection set to match the new list by either clearing selections or
filtering fileChangeAdapter.selectedFiles to the intersection of the new
allChanges paths (derive paths from
status.staged/unstaged/untracked/conflicted), then call submitList(allChanges)
and update commit-button state accordingly; locate this logic around the
collectLatest lambda that currently computes allChanges and calls
fileChangeAdapter.submitList.

In
`@app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt`:
- Around line 82-112: The commitChanges function currently swallows failures
(only log.error) and doesn't inform callers or undo partial work; change its
signature to accept an onError callback (e.g., onError: (Throwable) -> Unit)
alongside onSuccess, and update callers; inside commitChanges, detect and
preserve filesToStage, and if commit(...) throws, call onError(e) and attempt to
revert the partial staging by calling
currentRepository?.unstageFiles(filesToStage) (or an appropriate unstaging
method) before returning; ensure the catch block calls onError(e) after
unstage/cleanup and still logs the error, and keep refreshStatus()/onSuccess()
only on the successful path.

---

Duplicate comments:
In
`@app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt`:
- Around line 106-122: The commit button handler clears the adapter's
selectedFiles set but does not notify the RecyclerView to update checkbox views,
so the UI stays checked; update the code to call an adapter method that both
clears the selection set and refreshes views (e.g., add and call
fileChangeAdapter.clearSelections() or clearSelectionsNotify() after
fileChangeAdapter.selectedFiles.clear()), or implement clearSelections() inside
the adapter to clear its internal selection state and call
notifyDataSetChanged()/notifyItemRangeChanged() so checkboxes visually uncheck
after a successful commit (refer to binding.commitButton click listener and
fileChangeAdapter).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 61dbd0a9-4519-4960-961e-5ffbdd65ec14

📥 Commits

Reviewing files that changed from the base of the PR and between 020432d and edc90aa.

📒 Files selected for processing (6)
  • app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt
  • app/src/main/java/com/itsaky/androidide/fragments/git/GitCommitHistoryDialog.kt
  • app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt
  • app/src/main/res/layout/dialog_git_commit_history.xml
  • git-core/src/main/java/com/itsaky/androidide/git/core/models/CommitHistoryUiState.kt
  • resources/src/main/res/values/strings.xml
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/src/main/res/layout/dialog_git_commit_history.xml
  • resources/src/main/res/values/strings.xml
  • app/src/main/java/com/itsaky/androidide/fragments/git/GitCommitHistoryDialog.kt

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
app/src/main/java/com/itsaky/androidide/preferences/gitPrefExts.kt (2)

60-67: Normalize blank input before persisting Git identity values.

Line 60 and Line 96 currently persist empty strings. The UI treats blank as “unset” (fallback summary), so storing null for blank keeps behavior consistent and avoids downstream ambiguity.

Proposed fix
@@
     override fun onPreferenceChanged(preference: Preference, newValue: Any?): Boolean {
-        val name = newValue as? String
-        GitPreferences.userName = name
-        if (!name.isNullOrBlank()) {
-            preference.summary = name
+        val name = (newValue as? String)?.trim()?.takeIf { it.isNotEmpty() }
+        GitPreferences.userName = name
+        if (name != null) {
+            preference.summary = name
         } else {
             preference.summary = preference.context.getString(R.string.idepref_git_user_name_summary)
         }
         return true
     }
@@
     override fun onPreferenceChanged(preference: Preference, newValue: Any?): Boolean {
-        val email = newValue as? String
-        GitPreferences.userEmail = email
-        if (!email.isNullOrBlank()) {
-            preference.summary = email
+        val email = (newValue as? String)?.trim()?.takeIf { it.isNotEmpty() }
+        GitPreferences.userEmail = email
+        if (email != null) {
+            preference.summary = email
         } else {
             preference.summary = preference.context.getString(R.string.idepref_git_user_email_summary)
         }
         return true
     }

Also applies to: 96-103

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/itsaky/androidide/preferences/gitPrefExts.kt` around
lines 60 - 67, The preference handler should normalize blank strings to null
before saving so blank input is treated as “unset”: in onPreferenceChanged cast
newValue to String? then set GitPreferences.userName = name?.takeIf {
it.isNotBlank() } and update preference.summary to either the name when not
blank or the fallback string via preference.context.getString(...); apply the
same change for the email handling block (GitPreferences.userEmail / its
preference.summary) so empty input is persisted as null rather than an empty
string.

44-53: Consider extracting shared Git identity preference behavior.

GitUserName and GitUserEmail duplicate create-view, input-prefill, and summary fallback logic. A small shared base/helper would reduce repetition and drift risk.

Also applies to: 55-58, 80-89, 91-94

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/itsaky/androidide/preferences/gitPrefExts.kt` around
lines 44 - 53, The GitUserName and GitUserEmail preference classes duplicate the
same create-view, input prefill, and summary-fallback logic (see onCreateView
using GitPreferences.userName and pref.summary with context.getString(...)).
Extract that shared behavior into a small helper or base class (e.g.,
GitIdentityPreferenceBase or updateGitPrefView(pref, value, fallbackRes) helper)
that: reads the appropriate GitPreferences field, sets the Preference summary to
the value or the provided fallback string resource, and exposes a single place
to prefill the input dialog. Replace the duplicated code in GitUserName and
GitUserEmail to call the new base/helper from their onCreateView (and any
dialog/input-prefill handlers) so both preferences reuse the logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/src/main/java/com/itsaky/androidide/preferences/gitPrefExts.kt`:
- Around line 60-67: The preference handler should normalize blank strings to
null before saving so blank input is treated as “unset”: in onPreferenceChanged
cast newValue to String? then set GitPreferences.userName = name?.takeIf {
it.isNotBlank() } and update preference.summary to either the name when not
blank or the fallback string via preference.context.getString(...); apply the
same change for the email handling block (GitPreferences.userEmail / its
preference.summary) so empty input is persisted as null rather than an empty
string.
- Around line 44-53: The GitUserName and GitUserEmail preference classes
duplicate the same create-view, input prefill, and summary-fallback logic (see
onCreateView using GitPreferences.userName and pref.summary with
context.getString(...)). Extract that shared behavior into a small helper or
base class (e.g., GitIdentityPreferenceBase or updateGitPrefView(pref, value,
fallbackRes) helper) that: reads the appropriate GitPreferences field, sets the
Preference summary to the value or the provided fallback string resource, and
exposes a single place to prefill the input dialog. Replace the duplicated code
in GitUserName and GitUserEmail to call the new base/helper from their
onCreateView (and any dialog/input-prefill handlers) so both preferences reuse
the logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 816d12b3-b07f-4bb3-94b8-dab44d332d31

📥 Commits

Reviewing files that changed from the base of the PR and between edc90aa and 29e7f34.

📒 Files selected for processing (1)
  • app/src/main/java/com/itsaky/androidide/preferences/gitPrefExts.kt

@jatezzz jatezzz self-requested a review March 19, 2026 17:17
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt (1)

82-111: ⚠️ Potential issue | 🟠 Major

Commit failures can leave files staged and provide no caller-visible error path.

If repository.stageFiles(filesToStage) succeeds but repository.commit(...) fails, the staged state is left behind and the caller gets no failure callback (the catch only logs). Please add an error callback and rollback staged files in the failure path.

🛠️ Suggested fix
 fun commitChanges(
     summary: String,
     description: String? = null,
     selectedPaths: List<String>,
-    onSuccess: () -> Unit
+    onSuccess: () -> Unit,
+    onError: (String) -> Unit = {}
 ) {
     viewModelScope.launch {
-        try {
-            if (selectedPaths.isEmpty()) return@launch
-
-            val repository = currentRepository ?: return@launch
+        if (selectedPaths.isEmpty()) {
+            onError("No files selected")
+            return@launch
+        }
+        val repository = currentRepository ?: run {
+            onError("Repository unavailable")
+            return@launch
+        }
 
-            val projectDir = File(IProjectManager.getInstance().projectDirPath)
-            val filesToStage = selectedPaths.map { File(projectDir, it) }
+        val projectDir = File(IProjectManager.getInstance().projectDirPath)
+        val filesToStage = selectedPaths.map { File(projectDir, it) }
 
+        try {
             repository.stageFiles(filesToStage)
 
             val message =
                 if (!description.isNullOrBlank()) "$summary\n\n$description" else summary
             repository.commit(
@@
             refreshStatus()
             onSuccess()
         } catch (e: Exception) {
+            runCatching { repository.unstageFiles(filesToStage) }
+                .onFailure { rollbackError ->
+                    log.warn("Failed to rollback staged files", rollbackError)
+                }
             log.error("Failed to commit changes", e)
+            onError(e.message ?: "Failed to commit changes")
         }
-
     }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt`
around lines 82 - 111, The commitChanges function currently stages files via
repository.stageFiles(filesToStage) and then commits with
repository.commit(...), but on commit failure it only logs the exception and
leaves files staged and the caller uninformed; update commitChanges to accept an
onError: (Throwable) -> Unit (or reuse an existing error callback), and in the
catch block call onError(e) and attempt to rollback the staged state by calling
repository.unstageFiles(filesToStage) (or repository.resetFiles/appropriate
unstaging method) before logging; ensure existing happy-path still calls
onSuccess() and call refreshStatus() after rollback to update state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt`:
- Around line 120-123: currentRepository being null is currently treated as
empty history; before calling currentRepository.getHistory() check for null and
handle it as an error (or trigger repository reinitialization) instead of
mapping to CommitHistoryUiState.Empty. Specifically, in the code using
currentRepository and getHistory() update the branch that sets
_commitHistory.value: if currentRepository == null set _commitHistory.value =
CommitHistoryUiState.Error (or call the repo init routine) rather than calling
getHistory() and falling through to CommitHistoryUiState.Empty; ensure you still
set CommitHistoryUiState.Empty only when getHistory() returns an empty list.

---

Duplicate comments:
In
`@app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt`:
- Around line 82-111: The commitChanges function currently stages files via
repository.stageFiles(filesToStage) and then commits with
repository.commit(...), but on commit failure it only logs the exception and
leaves files staged and the caller uninformed; update commitChanges to accept an
onError: (Throwable) -> Unit (or reuse an existing error callback), and in the
catch block call onError(e) and attempt to rollback the staged state by calling
repository.unstageFiles(filesToStage) (or repository.resetFiles/appropriate
unstaging method) before logging; ensure existing happy-path still calls
onSuccess() and call refreshStatus() after rollback to update state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 020282a3-abaa-426c-b065-314ea3d1b406

📥 Commits

Reviewing files that changed from the base of the PR and between 29e7f34 and 4b5f63e.

📒 Files selected for processing (3)
  • app/src/main/java/com/itsaky/androidide/fragments/git/GitCommitHistoryDialog.kt
  • app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt
  • resources/src/main/res/values/strings.xml
✅ Files skipped from review due to trivial changes (1)
  • resources/src/main/res/values/strings.xml

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