diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/Icons.kt b/src/main/kotlin/com/jetpackduba/gitnuro/Icons.kt index 066d085..d01c950 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/Icons.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/Icons.kt @@ -22,6 +22,7 @@ object AppIcons { const val DOWNLOAD = "download.svg" const val DRAG = "drag.svg" const val DROPDOWN = "dropdown.svg" + const val EDIT = "edit.svg" const val ERROR = "error.svg" const val EXPAND_MORE = "expand_more.svg" const val FETCH = "fetch.svg" diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/git/remote_operations/FetchAllBranchesUseCase.kt b/src/main/kotlin/com/jetpackduba/gitnuro/git/remote_operations/FetchAllRemotesUseCase.kt similarity index 97% rename from src/main/kotlin/com/jetpackduba/gitnuro/git/remote_operations/FetchAllBranchesUseCase.kt rename to src/main/kotlin/com/jetpackduba/gitnuro/git/remote_operations/FetchAllRemotesUseCase.kt index 3e8f376..9ef404d 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/git/remote_operations/FetchAllBranchesUseCase.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/git/remote_operations/FetchAllRemotesUseCase.kt @@ -14,7 +14,7 @@ import javax.inject.Inject private const val TAG = "FetchAllBranchesUseCase" -class FetchAllBranchesUseCase @Inject constructor( +class FetchAllRemotesUseCase @Inject constructor( private val handleTransportUseCase: HandleTransportUseCase, ) { suspend operator fun invoke(git: Git) = withContext(Dispatchers.IO) { diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/models/RemoteWrapper.kt b/src/main/kotlin/com/jetpackduba/gitnuro/models/RemoteWrapper.kt new file mode 100644 index 0000000..2d1dfbc --- /dev/null +++ b/src/main/kotlin/com/jetpackduba/gitnuro/models/RemoteWrapper.kt @@ -0,0 +1,32 @@ +package com.jetpackduba.gitnuro.models + +import org.eclipse.jgit.transport.RemoteConfig + +data class RemoteWrapper constructor( + val remoteName: String, + val fetchUri: String, + val pushUri: String, + val isNew: Boolean, +) + +fun RemoteConfig.toRemoteWrapper(): RemoteWrapper { + val fetchUri = this.urIs.firstOrNull() + val pushUri = this.pushURIs.firstOrNull() + ?: this.urIs.firstOrNull() // If push URI == null, take fetch URI + + return RemoteWrapper( + remoteName = this.name, + fetchUri = fetchUri?.toString().orEmpty(), + pushUri = pushUri?.toString().orEmpty(), + isNew = false, + ) +} + +fun newRemoteWrapper(): RemoteWrapper { + return RemoteWrapper( + remoteName = "", + fetchUri = "", + pushUri = "", + isNew = true, + ) +} \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt index ff4f8eb..e3d867f 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt @@ -17,12 +17,18 @@ import com.jetpackduba.gitnuro.extensions.handOnHover import com.jetpackduba.gitnuro.extensions.isLocal import com.jetpackduba.gitnuro.extensions.isValid import com.jetpackduba.gitnuro.extensions.simpleName +import com.jetpackduba.gitnuro.models.RemoteWrapper +import com.jetpackduba.gitnuro.models.newRemoteWrapper +import com.jetpackduba.gitnuro.models.toRemoteWrapper import com.jetpackduba.gitnuro.theme.onBackgroundSecondary -import com.jetpackduba.gitnuro.ui.components.* +import com.jetpackduba.gitnuro.ui.components.AdjustableOutlinedTextField +import com.jetpackduba.gitnuro.ui.components.ScrollableLazyColumn +import com.jetpackduba.gitnuro.ui.components.SideMenuHeader +import com.jetpackduba.gitnuro.ui.components.SideMenuSubentry import com.jetpackduba.gitnuro.ui.components.tooltip.DelayedTooltip import com.jetpackduba.gitnuro.ui.context_menu.* +import com.jetpackduba.gitnuro.ui.dialogs.AddEditRemoteDialog import com.jetpackduba.gitnuro.ui.dialogs.AddSubmodulesDialog -import com.jetpackduba.gitnuro.ui.dialogs.EditRemotesDialog import com.jetpackduba.gitnuro.ui.dialogs.SetDefaultUpstreamBranchDialog import com.jetpackduba.gitnuro.viewmodels.ChangeDefaultUpstreamBranchViewModel import com.jetpackduba.gitnuro.viewmodels.sidepanel.* @@ -50,7 +56,7 @@ fun SidePanel( val stashesState by stashesViewModel.stashesState.collectAsState() val submodulesState by submodulesViewModel.submodules.collectAsState() - var showEditRemotesDialog by remember { mutableStateOf(false) } + val (showAddEditRemote, setShowAddEditRemote) = remember { mutableStateOf(null) } val (branchToChangeUpstream, setBranchToChangeUpstream) = remember { mutableStateOf(null) } var showEditSubmodulesDialog by remember { mutableStateOf(false) } @@ -80,7 +86,7 @@ fun SidePanel( remotes( remotesState = remotesState, remotesViewModel = remotesViewModel, - onShowEditRemotesDialog = { showEditRemotesDialog = true }, + onShowAddEditRemoteDialog = { setShowAddEditRemote(it) }, ) tags( @@ -103,11 +109,12 @@ fun SidePanel( } } - if (showEditRemotesDialog) { - EditRemotesDialog( + if (showAddEditRemote != null) { + AddEditRemoteDialog( remotesViewModel = remotesViewModel, + remoteWrapper = showAddEditRemote, onDismiss = { - showEditRemotesDialog = false + setShowAddEditRemote(null) }, ) } @@ -218,7 +225,7 @@ fun LazyListScope.localBranches( fun LazyListScope.remotes( remotesState: RemotesState, remotesViewModel: RemotesViewModel, - onShowEditRemotesDialog: () -> Unit, + onShowAddEditRemoteDialog: (RemoteWrapper) -> Unit, ) { val isExpanded = remotesState.isExpanded val remotes = remotesState.remotes @@ -230,14 +237,14 @@ fun LazyListScope.remotes( itemsCount = remotes.count(), hoverIcon = { IconButton( - onClick = onShowEditRemotesDialog, + onClick = { onShowAddEditRemoteDialog(newRemoteWrapper()) }, modifier = Modifier .padding(end = 16.dp) .size(16.dp) .handOnHover(), ) { Icon( - painter = painterResource(AppIcons.SETTINGS), + painter = painterResource(AppIcons.ADD), contentDescription = null, modifier = Modifier .fillMaxSize(), @@ -255,7 +262,12 @@ fun LazyListScope.remotes( item { Remote( remote = remote, - onRemoteClicked = { remotesViewModel.onRemoteClicked(remote) } + onEditRemote = { + val wrapper = remote.remoteInfo.remoteConfig.toRemoteWrapper() + onShowAddEditRemoteDialog(wrapper) + }, + onDeleteRemote = { remotesViewModel.deleteRemote(remote.remoteInfo.remoteConfig.name) }, + onRemoteClicked = { remotesViewModel.onRemoteClicked(remote) }, ) } @@ -461,14 +473,25 @@ private fun Branch( @Composable private fun Remote( remote: RemoteView, + onEditRemote: () -> Unit, + onDeleteRemote: () -> Unit, onRemoteClicked: () -> Unit, ) { - SideMenuSubentry( - text = remote.remoteInfo.remoteConfig.name, - iconResourcePath = AppIcons.CLOUD, - onClick = onRemoteClicked, - isSelected = false, - ) + ContextMenu( + items = { + remoteContextMenu( + onEdit = onEditRemote, + onDelete = onDeleteRemote, + ) + } + ) { + SideMenuSubentry( + text = remote.remoteInfo.remoteConfig.name, + iconResourcePath = AppIcons.CLOUD, + onClick = onRemoteClicked, + isSelected = false, + ) + } } diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/RemoteContextMenu.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/RemoteContextMenu.kt index d205e00..0e09d4f 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/RemoteContextMenu.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/RemoteContextMenu.kt @@ -1,10 +1,20 @@ package com.jetpackduba.gitnuro.ui.context_menu +import androidx.compose.ui.res.painterResource +import com.jetpackduba.gitnuro.AppIcons + fun remoteContextMenu( - onEditRemotes: () -> Unit, + onEdit: () -> Unit, + onDelete: () -> Unit, ): List = listOf( ContextMenuElement.ContextTextEntry( - label = "Edit remotes", - onClick = onEditRemotes + label = "Edit", + icon = { painterResource(AppIcons.EDIT) }, + onClick = onEdit + ), + ContextMenuElement.ContextTextEntry( + label = "Delete", + icon = { painterResource(AppIcons.DELETE) }, + onClick = onDelete ), ) \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/AddEditRemoteDialog.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/AddEditRemoteDialog.kt new file mode 100644 index 0000000..0863a0e --- /dev/null +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/AddEditRemoteDialog.kt @@ -0,0 +1,159 @@ +package com.jetpackduba.gitnuro.ui.dialogs + +import androidx.compose.foundation.layout.* +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Clear +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import com.jetpackduba.gitnuro.extensions.handOnHover +import com.jetpackduba.gitnuro.models.RemoteWrapper +import com.jetpackduba.gitnuro.theme.outlinedTextFieldColors +import com.jetpackduba.gitnuro.ui.components.AdjustableOutlinedTextField +import com.jetpackduba.gitnuro.ui.components.PrimaryButton +import com.jetpackduba.gitnuro.viewmodels.sidepanel.RemotesViewModel +import kotlinx.coroutines.flow.collectLatest + +@Composable +fun AddEditRemoteDialog( + remotesViewModel: RemotesViewModel, + remoteWrapper: RemoteWrapper, + onDismiss: () -> Unit, +) { + var remote: RemoteWrapper by remember(remoteWrapper) { mutableStateOf(remoteWrapper) } + + LaunchedEffect(Unit) { + remotesViewModel.remoteUpdated.collectLatest { onDismiss() } + } + + MaterialDialog( + paddingVertical = 8.dp, + paddingHorizontal = 16.dp, + background = MaterialTheme.colors.surface, + onCloseRequested = onDismiss + ) { + Column( + modifier = Modifier + .width(600.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + Row( + modifier = Modifier, + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = if (remote.isNew) "New remote" else "Edit remote \"${remote.remoteName}\"", + color = MaterialTheme.colors.onBackground, + style = MaterialTheme.typography.h3, + modifier = Modifier + .padding(start = 8.dp, top = 8.dp, bottom = 8.dp) + .fillMaxWidth(), + ) + } + Row( + modifier = Modifier + .padding(bottom = 8.dp) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 8.dp) + ) { + Column { + if (remote.isNew) { + Text( + text = "Remote name", + color = MaterialTheme.colors.onBackground, + modifier = Modifier.padding(top = 8.dp), + ) + + AdjustableOutlinedTextField( + value = remote.remoteName, + onValueChange = { newValue -> + remote = remote.copy(remoteName = newValue) + }, + singleLine = true, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp) + ) + } + + Text( + text = "Fetch URL", + color = MaterialTheme.colors.onBackground, + modifier = Modifier.padding(top = 8.dp), + ) + + AdjustableOutlinedTextField( + value = remote.fetchUri, + onValueChange = { newValue -> + remote = remote.copy(fetchUri = newValue) + }, + singleLine = true, + colors = outlinedTextFieldColors(), + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp) + ) + + Text( + text = "Push URL", + color = MaterialTheme.colors.onBackground, + modifier = Modifier.padding(top = 8.dp), + ) + + AdjustableOutlinedTextField( + value = remote.pushUri, + onValueChange = { newValue -> + remote = remote.copy(pushUri = newValue) + }, + singleLine = true, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp) + ) + + Row( + modifier = Modifier + .padding(top = 32.dp) + .align(Alignment.End), + verticalAlignment = Alignment.CenterVertically, + ) { + Spacer(modifier = Modifier.weight(1f)) + + PrimaryButton( + text = "Cancel", + modifier = Modifier.padding(end = 8.dp), + onClick = onDismiss, + backgroundColor = Color.Transparent, + backgroundDisabled = Color.Transparent, + textColor = MaterialTheme.colors.onBackground, + disabledTextColor = MaterialTheme.colors.onBackground.copy(alpha = 0.5f), + ) + + + PrimaryButton( + modifier = Modifier, + onClick = { + if (remote.isNew) + remotesViewModel.addRemote(remote) + else + remotesViewModel.updateRemote(remote) + }, + text = "Save changes", + ) + } + } + } + } + } + } +} diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/EditRemotesDialog.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/EditRemotesDialog.kt deleted file mode 100644 index b3acf51..0000000 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/EditRemotesDialog.kt +++ /dev/null @@ -1,371 +0,0 @@ -package com.jetpackduba.gitnuro.ui.dialogs - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Clear -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp -import com.jetpackduba.gitnuro.AppIcons -import com.jetpackduba.gitnuro.extensions.handMouseClickable -import com.jetpackduba.gitnuro.extensions.handOnHover -import com.jetpackduba.gitnuro.theme.backgroundSelected -import com.jetpackduba.gitnuro.theme.onBackgroundSecondary -import com.jetpackduba.gitnuro.theme.outlinedTextFieldColors -import com.jetpackduba.gitnuro.ui.components.AdjustableOutlinedTextField -import com.jetpackduba.gitnuro.ui.components.PrimaryButton -import com.jetpackduba.gitnuro.viewmodels.sidepanel.RemotesViewModel -import org.eclipse.jgit.transport.RemoteConfig - -@Composable -fun EditRemotesDialog( - remotesViewModel: RemotesViewModel, - onDismiss: () -> Unit, -) { - var remotesEditorData by remember { - mutableStateOf( - RemotesEditorData( - emptyList(), - null, - ) - ) - } - - val remotesState by remotesViewModel.remoteState.collectAsState() - val remotes = remotesState.remotes - var remoteChanged by remember { mutableStateOf(false) } - val selectedRemote = remotesEditorData.selectedRemote - - - LaunchedEffect(remotes) { - val newRemotesWrappers = remotes.map { - val remoteConfig = it.remoteInfo.remoteConfig - remoteConfig.toRemoteWrapper() - } - - val safeSelectedRemote = remotesEditorData.selectedRemote - var newSelectedRemote: RemoteWrapper? = null - - if (safeSelectedRemote != null) { - newSelectedRemote = newRemotesWrappers.firstOrNull { it.remoteName == safeSelectedRemote.remoteName } - } - - remoteChanged = newSelectedRemote?.haveUrisChanged ?: false - - remotesEditorData = remotesEditorData.copy( - listRemotes = newRemotesWrappers, - selectedRemote = newSelectedRemote, - ) - } - - MaterialDialog( - paddingVertical = 8.dp, - paddingHorizontal = 16.dp, - background = MaterialTheme.colors.surface, - onCloseRequested = onDismiss - ) { - Column( - modifier = Modifier - .size(width = 900.dp, height = 600.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - Row( - modifier = Modifier, - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - text = "Remotes", - color = MaterialTheme.colors.onBackground, - style = MaterialTheme.typography.h3, - modifier = Modifier.padding(vertical = 8.dp), - ) - - Spacer(modifier = Modifier.weight(1f)) - - IconButton( - onClick = onDismiss, - modifier = Modifier - .handOnHover() - ) { - Icon( - imageVector = Icons.Default.Clear, - contentDescription = null, - tint = MaterialTheme.colors.onBackground, - ) - } - } - Row( - modifier = Modifier - .padding(bottom = 8.dp) - ) { - Column( - modifier = Modifier - .width(200.dp) - .fillMaxHeight() - .background(MaterialTheme.colors.background), - ) { - if (remotesEditorData.listRemotes.isNotEmpty()) { - LazyColumn( - modifier = Modifier.weight(1f) - ) { - items(remotesEditorData.listRemotes) { remote -> - val background = if (remote == selectedRemote) { - MaterialTheme.colors.backgroundSelected - } else - MaterialTheme.colors.background - - Text( - text = remote.remoteName, - color = MaterialTheme.colors.onBackground, - modifier = Modifier - .fillMaxWidth() - .handMouseClickable { - remotesEditorData = remotesEditorData.copy(selectedRemote = remote) - } - .background(background) - .padding(horizontal = 16.dp, vertical = 8.dp) - ) - } - } - } else { - Box( - modifier = Modifier - .weight(1f) - .fillMaxWidth(), - contentAlignment = Alignment.Center, - ) { - Text( - text = "No available remotes", - style = MaterialTheme.typography.body2.copy(color = MaterialTheme.colors.onBackgroundSecondary) - ) - } - } - - Row( - modifier = Modifier - .fillMaxWidth() - ) { - IconButton( - modifier = Modifier - .size(36.dp) - .handOnHover(), - onClick = { - val remotesWithNew = remotesEditorData.listRemotes.toMutableList() - val newRemote = RemoteWrapper( - remoteName = "new_remote", - fetchUri = "", - originalFetchUri = "", - pushUri = "", - originalPushUri = "", - isNew = true - ) - - remotesWithNew.add(newRemote) - - remotesEditorData = remotesEditorData.copy( - listRemotes = remotesWithNew, - selectedRemote = newRemote - ) - } - ) { - Icon( - painter = painterResource(AppIcons.ADD), - contentDescription = null, - tint = MaterialTheme.colors.onBackground, - ) - } - IconButton( - modifier = Modifier - .size(36.dp) - .handOnHover(), - enabled = selectedRemote != null, - onClick = { - if (selectedRemote != null) - remotesViewModel.deleteRemote(selectedRemote.remoteName, selectedRemote.isNew) - } - ) { - Icon( - painter = painterResource(AppIcons.REMOVE), - contentDescription = null, - tint = if (selectedRemote != null) - MaterialTheme.colors.onBackground - else - MaterialTheme.colors.onBackgroundSecondary, - ) - } - } - } - - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - ) { - if (selectedRemote != null) { - Column { - if (selectedRemote.isNew) { - Text( - text = "New remote name", - color = MaterialTheme.colors.onBackground, - modifier = Modifier.padding(top = 8.dp), - ) - - AdjustableOutlinedTextField( - value = selectedRemote.remoteName, - onValueChange = { newValue -> - val newSelectedRemoteConfig = selectedRemote.copy(remoteName = newValue) - val listRemotes = remotesEditorData.listRemotes.toMutableList() - val newRemoteToBeReplacedIndex = listRemotes.indexOfFirst { it.isNew } - listRemotes[newRemoteToBeReplacedIndex] = newSelectedRemoteConfig - - remotesEditorData = remotesEditorData.copy( - listRemotes = listRemotes, - selectedRemote = newSelectedRemoteConfig - ) - }, - singleLine = true, - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp) - ) - } - - Text( - text = "Fetch URL", - color = MaterialTheme.colors.onBackground, - modifier = Modifier.padding(top = 8.dp), - ) - - AdjustableOutlinedTextField( - value = selectedRemote.fetchUri, - onValueChange = { newValue -> - val newSelectedRemoteConfig = selectedRemote.copy(fetchUri = newValue) - remotesEditorData = remotesEditorData.copy(selectedRemote = newSelectedRemoteConfig) - remoteChanged = newSelectedRemoteConfig.haveUrisChanged - }, - singleLine = true, - colors = outlinedTextFieldColors(), - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp) - ) - - Text( - text = "Push URL", - color = MaterialTheme.colors.onBackground, - modifier = Modifier.padding(top = 8.dp), - ) - - AdjustableOutlinedTextField( - value = selectedRemote.pushUri, - onValueChange = { newValue -> - val newSelectedRemoteConfig = selectedRemote.copy(pushUri = newValue) - remotesEditorData = remotesEditorData.copy(selectedRemote = newSelectedRemoteConfig) - remoteChanged = newSelectedRemoteConfig.haveUrisChanged - }, - singleLine = true, - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp) - ) - - Spacer(modifier = Modifier.weight(1f)) - - Row( - modifier = Modifier - .padding(top = 16.dp) - .align(Alignment.End), - verticalAlignment = Alignment.CenterVertically, - ) { - Spacer(modifier = Modifier.weight(1f)) - - if (!selectedRemote.isNew) { - PrimaryButton( - text = "Discard changes", - modifier = Modifier.padding(end = 8.dp), - onClick = { - remotesEditorData = remotesEditorData.copy( - selectedRemote = selectedRemote.copy( - fetchUri = selectedRemote.originalFetchUri, - pushUri = selectedRemote.originalPushUri, - ) - ) - - remoteChanged = false - }, - backgroundColor = Color.Transparent, - backgroundDisabled = Color.Transparent, - enabled = remoteChanged, - textColor = MaterialTheme.colors.onBackground, - disabledTextColor = MaterialTheme.colors.onBackground.copy(alpha = 0.5f), - ) - } - - val text = if (selectedRemote.isNew) - "Add new remote" - else - "Save ${selectedRemote.remoteName} changes" - PrimaryButton( - modifier = Modifier, - enabled = remoteChanged, - onClick = { - if (selectedRemote.isNew) - remotesViewModel.addRemote(selectedRemote) - else - remotesViewModel.updateRemote(selectedRemote) - }, - text = text, - ) - } - } - } - } - } - - } - } -} - -data class RemoteWrapper( - val remoteName: String, - val fetchUri: String, - val originalFetchUri: String, - val pushUri: String, - val originalPushUri: String, - val isNew: Boolean = false, -) { - val haveUrisChanged: Boolean = isNew || - fetchUri != originalFetchUri || - pushUri != originalPushUri -} - - -data class RemotesEditorData( - val listRemotes: List, - val selectedRemote: RemoteWrapper?, -) - -fun RemoteConfig.toRemoteWrapper(): RemoteWrapper { - val fetchUri = this.urIs.firstOrNull() - val pushUri = this.pushURIs.firstOrNull() - ?: this.urIs.firstOrNull() // If push URI == null, take fetch URI - - return RemoteWrapper( - remoteName = this.name, - fetchUri = fetchUri?.toString().orEmpty(), - originalFetchUri = fetchUri?.toString().orEmpty(), - pushUri = pushUri?.toString().orEmpty(), - originalPushUri = pushUri?.toString().orEmpty(), - ) -} \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/MenuViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/MenuViewModel.kt index 3601494..da2ebc3 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/MenuViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/MenuViewModel.kt @@ -3,7 +3,7 @@ package com.jetpackduba.gitnuro.viewmodels import com.jetpackduba.gitnuro.TaskType import com.jetpackduba.gitnuro.git.RefreshType import com.jetpackduba.gitnuro.git.TabState -import com.jetpackduba.gitnuro.git.remote_operations.FetchAllBranchesUseCase +import com.jetpackduba.gitnuro.git.remote_operations.FetchAllRemotesUseCase import com.jetpackduba.gitnuro.git.remote_operations.PullBranchUseCase import com.jetpackduba.gitnuro.git.remote_operations.PullType import com.jetpackduba.gitnuro.git.remote_operations.PushBranchUseCase @@ -19,7 +19,7 @@ class MenuViewModel @Inject constructor( private val tabState: TabState, private val pullBranchUseCase: PullBranchUseCase, private val pushBranchUseCase: PushBranchUseCase, - private val fetchAllBranchesUseCase: FetchAllBranchesUseCase, + private val fetchAllRemotesUseCase: FetchAllRemotesUseCase, private val popLastStashUseCase: PopLastStashUseCase, private val stashChangesUseCase: StashChangesUseCase, private val stageUntrackedFileUseCase: StageUntrackedFileUseCase, @@ -50,7 +50,7 @@ class MenuViewModel @Inject constructor( taskType = TaskType.FETCH, positiveFeedbackText = "Fetch all completed", ) { git -> - fetchAllBranchesUseCase(git) + fetchAllRemotesUseCase(git) } fun push(force: Boolean = false, pushTags: Boolean = false) = tabState.safeProcessing( diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/RemotesViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/RemotesViewModel.kt index 9dbe20d..c4c2f01 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/RemotesViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/RemotesViewModel.kt @@ -6,15 +6,11 @@ import com.jetpackduba.gitnuro.extensions.lowercaseContains import com.jetpackduba.gitnuro.extensions.simpleName import com.jetpackduba.gitnuro.git.RefreshType import com.jetpackduba.gitnuro.git.TabState -import com.jetpackduba.gitnuro.git.branches.CheckoutRefUseCase import com.jetpackduba.gitnuro.git.branches.DeleteLocallyRemoteBranchesUseCase import com.jetpackduba.gitnuro.git.branches.GetCurrentBranchUseCase import com.jetpackduba.gitnuro.git.branches.GetRemoteBranchesUseCase -import com.jetpackduba.gitnuro.git.remote_operations.DeleteRemoteBranchUseCase -import com.jetpackduba.gitnuro.git.remote_operations.PullFromSpecificBranchUseCase -import com.jetpackduba.gitnuro.git.remote_operations.PushToSpecificBranchUseCase import com.jetpackduba.gitnuro.git.remotes.* -import com.jetpackduba.gitnuro.ui.dialogs.RemoteWrapper +import com.jetpackduba.gitnuro.models.RemoteWrapper import com.jetpackduba.gitnuro.viewmodels.ISharedRemotesViewModel import com.jetpackduba.gitnuro.viewmodels.SharedRemotesViewModel import dagger.assisted.Assisted @@ -45,6 +41,9 @@ class RemotesViewModel @AssistedInject constructor( private val remotes = MutableStateFlow>(listOf()) private val currentBranch = MutableStateFlow(null) + private val _remoteUpdated = MutableSharedFlow() + val remoteUpdated = _remoteUpdated.asSharedFlow() + val remoteState: StateFlow = combine(remotes, isExpanded, filter, currentBranch) { remotes, isExpanded, filter, currentBranch -> val remotesFiltered = remotes.map { remote -> @@ -115,8 +114,8 @@ class RemotesViewModel @AssistedInject constructor( tabState.newSelectedRef(ref, ref.objectId) } - fun deleteRemote(remoteName: String, isNew: Boolean) = tabState.safeProcessing( - refreshType = if (isNew) RefreshType.REMOTES else RefreshType.ALL_DATA, + fun deleteRemote(remoteName: String) = tabState.safeProcessing( + refreshType = RefreshType.ALL_DATA, taskType = TaskType.DELETE_REMOTE, positiveFeedbackText = "Remote $remoteName deleted", ) { git -> @@ -176,6 +175,8 @@ class RemotesViewModel @AssistedInject constructor( uri = selectedRemoteConfig.pushUri, uriType = RemoteSetUrlCommand.UriType.PUSH ) + + _remoteUpdated.emit(Unit) } } diff --git a/src/main/resources/edit.svg b/src/main/resources/edit.svg new file mode 100644 index 0000000..4f941d9 --- /dev/null +++ b/src/main/resources/edit.svg @@ -0,0 +1 @@ + \ No newline at end of file