From ddea1c0a18e8fe9e0e3eda3fec39059826115aad Mon Sep 17 00:00:00 2001 From: Oluwadara Abijo Date: Tue, 21 Apr 2026 20:12:01 +0100 Subject: [PATCH 1/2] fix(ADFA-3790): Reset push/pull state after internet error --- .../viewmodel/GitBottomSheetViewModel.kt | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt b/app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt index 4e04772785..0c1612ccdb 100644 --- a/app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt +++ b/app/src/main/java/com/itsaky/androidide/viewmodel/GitBottomSheetViewModel.kt @@ -175,14 +175,14 @@ class GitBottomSheetViewModel(private val credentialsManager: GitCredentialsMana fun push(username: String?, token: String?) { pushResetJob?.cancel() - if (!NetworkUtils.isConnected()){ - _pushState.value = PushUiState.Error(errorResId = R.string.no_internet_connection) - return - } - viewModelScope.launch { - _pushState.value = PushUiState.Pushing try { + if (!NetworkUtils.isConnected()){ + _pushState.value = PushUiState.Error(errorResId = R.string.no_internet_connection) + return@launch + } + + _pushState.value = PushUiState.Pushing val repository = currentRepository ?: return@launch val credentials = buildCredentials(username, token) val results = repository.push(credentialsProvider = credentials) @@ -245,14 +245,14 @@ class GitBottomSheetViewModel(private val credentialsManager: GitCredentialsMana fun pull(username: String?, token: String?) { pullResetJob?.cancel() - if (!NetworkUtils.isConnected()){ - _pullState.value = PullUiState.Error(errorResId = R.string.no_internet_connection) - return - } - viewModelScope.launch { - _pullState.value = PullUiState.Pulling try { + if (!NetworkUtils.isConnected()){ + _pullState.value = PullUiState.Error(errorResId = R.string.no_internet_connection) + return@launch + } + + _pullState.value = PullUiState.Pulling val repository = currentRepository ?: return@launch val credentials = buildCredentials(username, token) val result = repository.pull(credentialsProvider = credentials) From 38faf193923ae11a3cf6047b92299e20173654cb Mon Sep 17 00:00:00 2001 From: Oluwadara Abijo Date: Tue, 21 Apr 2026 21:28:10 +0100 Subject: [PATCH 2/2] fix(ADFA-3795): Validate Git credentials input --- .../fragments/git/GitBottomSheetFragment.kt | 32 +++-------- .../fragments/git/GitCommitHistoryDialog.kt | 29 +++------- .../fragments/git/GitDialogUtils.kt | 53 +++++++++++++++++++ 3 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/com/itsaky/androidide/fragments/git/GitDialogUtils.kt diff --git a/app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt b/app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt index f77c4411df..20a38cd548 100644 --- a/app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt +++ b/app/src/main/java/com/itsaky/androidide/fragments/git/GitBottomSheetFragment.kt @@ -17,7 +17,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.itsaky.androidide.R import com.itsaky.androidide.activities.PreferencesActivity import com.itsaky.androidide.activities.editor.EditorHandlerActivity -import com.itsaky.androidide.databinding.DialogGitCredentialsBinding import com.itsaky.androidide.databinding.FragmentGitBottomSheetBinding import com.itsaky.androidide.fragments.git.adapter.GitFileChangeAdapter import com.itsaky.androidide.git.core.GitCredentialsManager @@ -313,36 +312,17 @@ class GitBottomSheetFragment : Fragment(R.layout.fragment_git_bottom_sheet) { if (!username.isNullOrBlank() && !token.isNullOrBlank()) { viewModel.pull(username, token) } else { - showCredentialsDialog() + showGitCredentialsDialog( + credentialsManager = credentialsManager, + positiveButtonTextResId = R.string.pull + ) { user, accessToken -> + viewModel.pull(user, accessToken) + } } } } } - private fun showCredentialsDialog() { - val context = requireContext() - val dialogBinding = DialogGitCredentialsBinding.inflate(layoutInflater) - - dialogBinding.username.setText(credentialsManager.getUsername()) - dialogBinding.token.setText(credentialsManager.getToken()) - - MaterialAlertDialogBuilder(context) - .setTitle(R.string.git_credentials_title) - .setView(dialogBinding.root) - .setPositiveButton(R.string.pull) { _, _ -> - val username = dialogBinding.username.text?.toString()?.trim() - val token = dialogBinding.token.text?.toString()?.trim() - if (!username.isNullOrBlank() && !token.isNullOrBlank()) { - viewModel.pull(username, token) - } - } - .setNeutralButton(R.string.git_credentials_clear) { _, _ -> - credentialsManager.clearCredentials() - } - .setNegativeButton(android.R.string.cancel, null) - .show() - } - private fun refreshEditorContent(force: Boolean = false) { val activity = requireActivity() if (activity is EditorHandlerActivity) { diff --git a/app/src/main/java/com/itsaky/androidide/fragments/git/GitCommitHistoryDialog.kt b/app/src/main/java/com/itsaky/androidide/fragments/git/GitCommitHistoryDialog.kt index 841ff279cc..eeec556aa2 100644 --- a/app/src/main/java/com/itsaky/androidide/fragments/git/GitCommitHistoryDialog.kt +++ b/app/src/main/java/com/itsaky/androidide/fragments/git/GitCommitHistoryDialog.kt @@ -11,7 +11,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.itsaky.androidide.R import com.itsaky.androidide.databinding.DialogGitCommitHistoryBinding -import com.itsaky.androidide.databinding.DialogGitCredentialsBinding import com.itsaky.androidide.fragments.git.adapter.GitCommitHistoryAdapter import com.itsaky.androidide.git.core.GitCredentialsManager import com.itsaky.androidide.git.core.models.CommitHistoryUiState @@ -100,7 +99,12 @@ class GitCommitHistoryDialog : DialogFragment() { if (!username.isNullOrBlank() && !token.isNullOrBlank()) { viewModel.push(username, token) } else { - showCredentialsDialog() + showGitCredentialsDialog( + credentialsManager = credentialsManager, + positiveButtonTextResId = R.string.push + ) { user, accessToken -> + viewModel.push(user, accessToken) + } } } @@ -149,28 +153,7 @@ class GitCommitHistoryDialog : DialogFragment() { } - private fun showCredentialsDialog() { - val dialogBinding = DialogGitCredentialsBinding.inflate(layoutInflater) - - dialogBinding.username.setText(credentialsManager.getUsername()) - dialogBinding.token.setText(credentialsManager.getToken()) - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.git_credentials_title) - .setView(dialogBinding.root) - .setPositiveButton(R.string.push) { _, _ -> - val username = dialogBinding.username.text?.toString()?.trim() - val token = dialogBinding.token.text?.toString()?.trim() - if (!username.isNullOrBlank() && !token.isNullOrBlank()) { - viewModel.push(username, token) - } - } - .setNeutralButton(R.string.git_credentials_clear) { _, _ -> - credentialsManager.clearCredentials() - } - .setNegativeButton(android.R.string.cancel, null) - .show() - } override fun onDestroyView() { super.onDestroyView() diff --git a/app/src/main/java/com/itsaky/androidide/fragments/git/GitDialogUtils.kt b/app/src/main/java/com/itsaky/androidide/fragments/git/GitDialogUtils.kt new file mode 100644 index 0000000000..990aa38b69 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/fragments/git/GitDialogUtils.kt @@ -0,0 +1,53 @@ +package com.itsaky.androidide.fragments.git + +import androidx.appcompat.app.AlertDialog +import androidx.core.widget.doAfterTextChanged +import androidx.fragment.app.Fragment +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.itsaky.androidide.R +import com.itsaky.androidide.databinding.DialogGitCredentialsBinding +import com.itsaky.androidide.git.core.GitCredentialsManager + +fun Fragment.showGitCredentialsDialog( + credentialsManager: GitCredentialsManager, + positiveButtonTextResId: Int, + onPositiveClick: (username: String, token: String) -> Unit +) { + val dialogBinding = DialogGitCredentialsBinding.inflate(layoutInflater) + + dialogBinding.username.setText(credentialsManager.getUsername()) + dialogBinding.token.setText(credentialsManager.getToken()) + + val dialog = MaterialAlertDialogBuilder(requireContext()) + .setTitle(R.string.git_credentials_title) + .setView(dialogBinding.root) + .setPositiveButton(positiveButtonTextResId) { _, _ -> + val username = dialogBinding.username.text?.toString()?.trim() + val token = dialogBinding.token.text?.toString()?.trim() + if (!username.isNullOrBlank() && !token.isNullOrBlank()) { + onPositiveClick(username, token) + } + } + .setNeutralButton(R.string.git_credentials_clear) { _, _ -> + credentialsManager.clearCredentials() + } + .setNegativeButton(android.R.string.cancel, null) + .create() + + dialog.setOnShowListener { + val positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE) + + val validate = { + val user = dialogBinding.username.text?.toString()?.trim() + val token = dialogBinding.token.text?.toString()?.trim() + positiveButton.isEnabled = !user.isNullOrBlank() && !token.isNullOrBlank() + } + + dialogBinding.username.doAfterTextChanged { validate() } + dialogBinding.token.doAfterTextChanged { validate() } + + validate() + } + + dialog.show() +}