Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#264 Copy Branch Name #267

Merged
merged 3 commits into from
Feb 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/kotlin/com/jetpackduba/gitnuro/di/AppComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.jetpackduba.gitnuro.ui.VerticalSplitPaneConfig
import com.jetpackduba.gitnuro.updates.UpdatesRepository
import com.jetpackduba.gitnuro.viewmodels.SettingsViewModel
import dagger.Component
import org.jetbrains.skiko.ClipboardManager
import javax.inject.Singleton

@Singleton
Expand Down Expand Up @@ -50,4 +51,6 @@ interface AppComponent {
fun updatesRepository(): UpdatesRepository

fun credentialsCacheRepository(): CredentialsCacheRepository

fun clipboardManager(): ClipboardManager
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ import dagger.Provides
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import org.jetbrains.skiko.ClipboardManager

@Module
class AppModule {
@Provides
@AppCoroutineScope
fun provideAppScope(): CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)

@Provides
fun provideClipboardManager(): ClipboardManager = ClipboardManager()
}
13 changes: 10 additions & 3 deletions src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,9 @@ fun LazyListScope.localBranches(
onMergeBranch = { branchesViewModel.mergeBranch(branch) },
onRebaseBranch = { branchesViewModel.rebaseBranch(branch) },
onDeleteBranch = { branchesViewModel.deleteBranch(branch) },
) { onChangeDefaultUpstreamBranch(branch) }
onChangeDefaultUpstreamBranch = { onChangeDefaultUpstreamBranch(branch) },
onCopyBranchNameToClipboard = { branchesViewModel.copyBranchNameToClipboard(branch) },
)
}
}
}
Expand Down Expand Up @@ -288,7 +290,7 @@ fun LazyListScope.remotes(
onEditRemote = {
val wrapper = remote.remoteInfo.remoteConfig.toRemoteWrapper()
onShowAddEditRemoteDialog(wrapper)
},
},
onDeleteRemote = { remotesViewModel.deleteRemote(remote.remoteInfo.remoteConfig.name) },
onRemoteClicked = { remotesViewModel.onRemoteClicked(remote) },
)
Expand All @@ -306,6 +308,7 @@ fun LazyListScope.remotes(
onPullRemoteBranch = { remotesViewModel.pullFromRemoteBranch(remoteBranch) },
onRebaseRemoteBranch = { remotesViewModel.rebaseBranch(remoteBranch) },
onMergeRemoteBranch = { remotesViewModel.mergeBranch(remoteBranch) },
onCopyBranchNameToClipboard = { remotesViewModel.copyBranchNameToClipboard(remoteBranch) }
)
}
}
Expand Down Expand Up @@ -453,6 +456,7 @@ private fun Branch(
onRebaseBranch: () -> Unit,
onDeleteBranch: () -> Unit,
onChangeDefaultUpstreamBranch: () -> Unit,
onCopyBranchNameToClipboard: () -> Unit,
) {
val isCurrentBranch = currentBranch?.name == branch.name

Expand All @@ -469,7 +473,8 @@ private fun Branch(
onRebaseBranch = onRebaseBranch,
onPushToRemoteBranch = {},
onPullFromRemoteBranch = {},
onChangeDefaultUpstreamBranch = onChangeDefaultUpstreamBranch
onChangeDefaultUpstreamBranch = onChangeDefaultUpstreamBranch,
onCopyBranchNameToClipboard = onCopyBranchNameToClipboard
)
}
) {
Expand Down Expand Up @@ -531,6 +536,7 @@ private fun RemoteBranches(
onPullRemoteBranch: () -> Unit,
onRebaseRemoteBranch: () -> Unit,
onMergeRemoteBranch: () -> Unit,
onCopyBranchNameToClipboard: () -> Unit
) {
ContextMenu(
items = {
Expand All @@ -547,6 +553,7 @@ private fun RemoteBranches(
onPushToRemoteBranch = onPushRemoteBranch,
onPullFromRemoteBranch = onPullRemoteBranch,
onChangeDefaultUpstreamBranch = {},
onCopyBranchNameToClipboard = onCopyBranchNameToClipboard
)
}
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import androidx.compose.ui.res.painterResource
import com.jetpackduba.gitnuro.AppIcons
import com.jetpackduba.gitnuro.extensions.isHead
import com.jetpackduba.gitnuro.extensions.simpleLogName
import com.jetpackduba.gitnuro.extensions.simpleName
import com.jetpackduba.gitnuro.models.Notification
import com.jetpackduba.gitnuro.models.positiveNotification
import org.eclipse.jgit.lib.Ref
import org.jetbrains.skiko.ClipboardManager

fun branchContextMenuItems(
branch: Ref,
Expand All @@ -19,7 +23,9 @@ fun branchContextMenuItems(
onPushToRemoteBranch: () -> Unit,
onPullFromRemoteBranch: () -> Unit,
onChangeDefaultUpstreamBranch: () -> Unit,
onCopyBranchNameToClipboard: () -> Unit
): List<ContextMenuElement> {

return mutableListOf<ContextMenuElement>().apply {
if (!isCurrentBranch) {
add(
Expand Down Expand Up @@ -90,8 +96,23 @@ fun branchContextMenuItems(
)
}

if (lastOrNull() == ContextMenuElement.ContextSeparator) {
removeLast()
}
add(
ContextMenuElement.ContextTextEntry(
label = "Copy branch name",
icon = { painterResource(AppIcons.COPY) },
onClick = {
onCopyBranchNameToClipboard()
}
)
)
}
}

internal fun copyBranchNameToClipboardAndGetNotification(
branch: Ref,
clipboardManager: ClipboardManager
): Notification {
val branchName = branch.simpleName
clipboardManager.setText(branchName)
return positiveNotification("\"${branchName}\" copied to clipboard")
}
10 changes: 9 additions & 1 deletion src/main/kotlin/com/jetpackduba/gitnuro/ui/log/Log.kt
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ private fun LogLoaded(
onDeleteTag = { logViewModel.deleteTag(it) },
onPushToRemoteBranch = { logViewModel.pushToRemoteBranch(it) },
onPullFromRemoteBranch = { logViewModel.pullFromRemoteBranch(it) },
onCopyBranchNameToClipboard = { ref -> logViewModel.copyBranchNameToClipboard(ref) }
)

val density = LocalDensity.current.density
Expand Down Expand Up @@ -505,6 +506,7 @@ fun CommitsList(
onPushToRemoteBranch: (Ref) -> Unit,
onPullFromRemoteBranch: (Ref) -> Unit,
onShowLogDialog: (LogDialog) -> Unit,
onCopyBranchNameToClipboard: (Ref) -> Unit,
graphWidth: Dp,
horizontalScrollState: ScrollState,
) {
Expand Down Expand Up @@ -584,6 +586,7 @@ fun CommitsList(
onCherryPickCommit = { onCherryPickCommit(graphNode) },
onCheckoutRemoteBranch = onCheckoutRemoteBranch,
onCheckoutRef = onCheckoutRef,
onCopyBranchNameToClipboard = onCopyBranchNameToClipboard,
)
}

Expand Down Expand Up @@ -824,6 +827,7 @@ private fun CommitLine(
onCheckoutRemoteBranch: (Ref) -> Unit,
onCheckoutRef: (Ref) -> Unit,
onChangeDefaultUpstreamBranch: (Ref) -> Unit,
onCopyBranchNameToClipboard: (Ref) -> Unit,
horizontalScrollState: ScrollState,
) {
val isLastCommitOfCurrentBranch = currentBranch?.objectId?.name == graphNode.id.name
Expand Down Expand Up @@ -918,6 +922,7 @@ private fun CommitLine(
onPushRemoteBranch = { ref -> onPushToRemoteBranch(ref) },
onPullRemoteBranch = { ref -> onPullFromRemoteBranch(ref) },
onChangeDefaultUpstreamBranch = { ref -> onChangeDefaultUpstreamBranch(ref) },
onCopyBranchNameToClipboard = { ref -> onCopyBranchNameToClipboard(ref) },
)
}
}
Expand All @@ -940,6 +945,7 @@ fun CommitMessage(
onPushRemoteBranch: (ref: Ref) -> Unit,
onPullRemoteBranch: (ref: Ref) -> Unit,
onChangeDefaultUpstreamBranch: (ref: Ref) -> Unit,
onCopyBranchNameToClipboard: (ref: Ref) -> Unit,
) {
Row(
modifier = Modifier.fillMaxSize()
Expand Down Expand Up @@ -981,6 +987,7 @@ fun CommitMessage(
onPullRemoteBranch = { onPullRemoteBranch(ref) },
onPushRemoteBranch = { onPushRemoteBranch(ref) },
onChangeDefaultUpstreamBranch = { onChangeDefaultUpstreamBranch(ref) },
onCopyBranchNameToClipboard = { onCopyBranchNameToClipboard(ref) },
)
}
}
Expand Down Expand Up @@ -1203,7 +1210,6 @@ fun UncommittedChangesGraphNode(
}
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun BranchChip(
modifier: Modifier = Modifier,
Expand All @@ -1218,6 +1224,7 @@ fun BranchChip(
onPushRemoteBranch: () -> Unit,
onPullRemoteBranch: () -> Unit,
onChangeDefaultUpstreamBranch: () -> Unit,
onCopyBranchNameToClipboard: () -> Unit,
color: Color,
) {
val contextMenuItemsList = {
Expand All @@ -1234,6 +1241,7 @@ fun BranchChip(
onPushToRemoteBranch = onPushRemoteBranch,
onPullFromRemoteBranch = onPullRemoteBranch,
onChangeDefaultUpstreamBranch = onChangeDefaultUpstreamBranch,
onCopyBranchNameToClipboard = onCopyBranchNameToClipboard,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.jetpackduba.gitnuro.git.workspace.StatusSummary
import com.jetpackduba.gitnuro.models.positiveNotification
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
import com.jetpackduba.gitnuro.ui.SelectedItem
import com.jetpackduba.gitnuro.ui.context_menu.copyBranchNameToClipboardAndGetNotification
import com.jetpackduba.gitnuro.ui.log.LogDialog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.*
Expand All @@ -30,6 +31,7 @@ import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.errors.CheckoutConflictException
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.revwalk.RevCommit
import org.jetbrains.skiko.ClipboardManager
import javax.inject.Inject

/**
Expand Down Expand Up @@ -63,6 +65,7 @@ class LogViewModel @Inject constructor(
private val tabState: TabState,
private val appSettingsRepository: AppSettingsRepository,
private val tabScope: CoroutineScope,
private val clipboardManager: ClipboardManager,
sharedStashViewModel: SharedStashViewModel,
sharedBranchesViewModel: SharedBranchesViewModel,
sharedRemotesViewModel: SharedRemotesViewModel,
Expand Down Expand Up @@ -136,7 +139,6 @@ class LogViewModel @Inject constructor(
}
}


private suspend fun loadLog(git: Git) = delayedStateChange(
delayMs = LOG_MIN_TIME_IN_MS_TO_SHOW_LOAD,
onDelayTriggered = {
Expand Down Expand Up @@ -418,6 +420,16 @@ class LogViewModel @Inject constructor(
_logStatus.value =
LogStatus.Loaded(hasUncommittedChanges, log, currentBranch, statusSummary)
}

override fun copyBranchNameToClipboard(branch: Ref) = tabState.safeProcessing(
refreshType = RefreshType.NONE,
taskType = TaskType.UNSPECIFIED
) {
copyBranchNameToClipboardAndGetNotification(
branch,
clipboardManager
)
}
}

sealed interface LogStatus {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,21 @@ import com.jetpackduba.gitnuro.git.rebase.RebaseBranchUseCase
import com.jetpackduba.gitnuro.models.positiveNotification
import com.jetpackduba.gitnuro.models.warningNotification
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
import com.jetpackduba.gitnuro.ui.context_menu.copyBranchNameToClipboardAndGetNotification
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.eclipse.jgit.lib.Ref
import org.jetbrains.skiko.ClipboardManager
import javax.inject.Inject

interface ISharedBranchesViewModel {
fun mergeBranch(ref: Ref): Job
fun deleteBranch(branch: Ref): Job
fun checkoutRef(ref: Ref): Job
fun rebaseBranch(ref: Ref): Job
fun copyBranchNameToClipboard(branch: Ref): Job
}

class SharedBranchesViewModel @Inject constructor(
Expand All @@ -29,6 +35,7 @@ class SharedBranchesViewModel @Inject constructor(
private val mergeBranchUseCase: MergeBranchUseCase,
private val deleteBranchUseCase: DeleteBranchUseCase,
private val checkoutRefUseCase: CheckoutRefUseCase,
private val clipboardManager: ClipboardManager
) : ISharedBranchesViewModel {

override fun mergeBranch(ref: Ref) = tabState.safeProcessing(
Expand Down Expand Up @@ -80,4 +87,14 @@ class SharedBranchesViewModel @Inject constructor(
positiveNotification("\"${ref.simpleName}\" rebased")
}
}

override fun copyBranchNameToClipboard(branch: Ref) = tabState.safeProcessing(
refreshType = RefreshType.NONE,
taskType = TaskType.UNSPECIFIED
) {
copyBranchNameToClipboardAndGetNotification(
branch,
clipboardManager
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@ import com.jetpackduba.gitnuro.git.remote_operations.PullFromSpecificBranchUseCa
import com.jetpackduba.gitnuro.git.remote_operations.PushToSpecificBranchUseCase
import com.jetpackduba.gitnuro.models.positiveNotification
import com.jetpackduba.gitnuro.models.warningNotification
import com.jetpackduba.gitnuro.ui.context_menu.copyBranchNameToClipboardAndGetNotification
import kotlinx.coroutines.Job
import org.eclipse.jgit.lib.Ref
import org.jetbrains.skiko.ClipboardManager
import javax.inject.Inject

interface ISharedRemotesViewModel {
fun deleteRemoteBranch(ref: Ref): Job
fun checkoutRemoteBranch(remoteBranch: Ref): Job
fun pushToRemoteBranch(branch: Ref): Job
fun pullFromRemoteBranch(branch: Ref): Job
fun copyBranchNameToClipboard(branch: Ref): Job
}

class SharedRemotesViewModel @Inject constructor(
Expand All @@ -27,7 +30,9 @@ class SharedRemotesViewModel @Inject constructor(
private val checkoutRefUseCase: CheckoutRefUseCase,
private val pushToSpecificBranchUseCase: PushToSpecificBranchUseCase,
private val pullFromSpecificBranchUseCase: PullFromSpecificBranchUseCase,
private val clipboardManager: ClipboardManager,
) : ISharedRemotesViewModel {

override fun deleteRemoteBranch(ref: Ref) = tabState.safeProcessing(
refreshType = RefreshType.ALL_DATA,
title = "Deleting remote branch",
Expand Down Expand Up @@ -76,4 +81,14 @@ class SharedRemotesViewModel @Inject constructor(
positiveNotification("Pulled from \"${branch.simpleName}\"")
}
}

override fun copyBranchNameToClipboard(branch: Ref) = tabState.safeProcessing(
refreshType = RefreshType.NONE,
taskType = TaskType.UNSPECIFIED
) {
copyBranchNameToClipboardAndGetNotification(
branch,
clipboardManager
)
}
}
Loading