From aadbe659782c583c66ff08848c2ee78de33c0d81 Mon Sep 17 00:00:00 2001 From: Paul Spiesberger Date: Sun, 8 Jun 2025 16:58:57 +0200 Subject: [PATCH 1/6] #303 Open File in Folder - Add function to context menu for unstaged, staged and commited files - Add File extention function to open a folder --- .../gitnuro/extensions/FileExtensions.kt | 42 +++++++++++++++++++ .../gitnuro/git/workspace/Status.kt | 7 +++- .../jetpackduba/gitnuro/ui/CommitChanges.kt | 4 ++ .../gitnuro/ui/UncommitedChanges.kt | 12 ++++-- .../CommitedChangesEntriesContextMenu.kt | 10 +++++ .../context_menu/StatusEntriesContextMenu.kt | 9 ++++ .../viewmodels/CommitChangesViewModel.kt | 8 ++++ .../gitnuro/viewmodels/StatusViewModel.kt | 14 ++++++- 8 files changed, 101 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt b/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt index 18589c3e..6cf28cc7 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt @@ -1,6 +1,9 @@ package com.jetpackduba.gitnuro.extensions +import kotlinx.io.IOException +import java.awt.Desktop import java.io.File +import java.util.* fun File.openDirectory(dirName: String): File { val newDir = File(this, dirName) @@ -10,4 +13,43 @@ fun File.openDirectory(dirName: String): File { } return newDir +} + +fun File.openFileInFolder() { + + if (!exists() || !isDirectory) { + println("Folder with path $path does not exist or is not a folder") + return + } + + try { + if (Desktop.isDesktopSupported()) { + val desktop = Desktop.getDesktop() + if (desktop.isSupported(Desktop.Action.OPEN)) { + desktop.open(this) + return + } + } + } catch (e: Exception) { + println("Desktop API failed: ${e.message}") + } + + // Fallback + val os = System.getProperty("os.name").lowercase(Locale.getDefault()) + val command = when { + os.contains("linux") -> listOf("xdg-open", absolutePath) + os.contains("mac") -> listOf("open", absolutePath) + os.contains("windows") -> listOf("explorer", absolutePath) + else -> null + } + + if (command != null) { + try { + ProcessBuilder(command).start() + } catch (ex: IOException) { + println("Failed to open file explorer: ${ex.message}") + } + } else { + println("Unsupported OS: $os") + } } \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt b/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt index c6620a76..7e3e03b0 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt @@ -5,8 +5,13 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import com.jetpackduba.gitnuro.extensions.icon import com.jetpackduba.gitnuro.extensions.iconColor +import kotlin.io.path.Path +import kotlin.io.path.pathString -data class StatusEntry(val filePath: String, val statusType: StatusType) { +data class StatusEntry( + val filePath: String, + val statusType: StatusType +) { val icon: ImageVector get() = statusType.icon diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/CommitChanges.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/CommitChanges.kt index 098bdd00..0b9d1fa8 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/CommitChanges.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/CommitChanges.kt @@ -87,6 +87,7 @@ fun CommitChanges( commitChangesStatus = commitChangesStatus, onBlame = onBlame, onHistory = onHistory, + onOpenFileInFolder = { commitChangesViewModel.openFileInFolder(it) }, showSearch = showSearch, showAsTree = showAsTree, changesListScroll = changesListScroll, @@ -121,6 +122,7 @@ private fun CommitChangesView( searchFilter: TextFieldValue, onBlame: (String) -> Unit, onHistory: (String) -> Unit, + onOpenFileInFolder: (String) -> Unit, onDiffSelected: (DiffEntry) -> Unit, onSearchFilterToggled: (Boolean) -> Unit, onSearchFocused: () -> Unit, @@ -167,6 +169,7 @@ private fun CommitChangesView( diffEntry, onBlame = { onBlame(diffEntry.filePath) }, onHistory = { onHistory(diffEntry.filePath) }, + onOpenFileInFolder = { onOpenFileInFolder(diffEntry.parentDirectoryPath) }, ) } ) @@ -183,6 +186,7 @@ private fun CommitChangesView( diffEntry, onBlame = { onBlame(diffEntry.filePath) }, onHistory = { onHistory(diffEntry.filePath) }, + onOpenFileInFolder = { onOpenFileInFolder(diffEntry.parentDirectoryPath) }, ) }, onDirectoryClicked = onDirectoryClicked, diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/UncommitedChanges.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/UncommitedChanges.kt index b648e55a..efa15736 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/UncommitedChanges.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/UncommitedChanges.kt @@ -165,6 +165,7 @@ fun UncommittedChanges( onHistoryFile = onHistoryFile, onReset = { statusViewModel.resetStaged(it) }, onDelete = { statusViewModel.deleteFile(it) }, + onOpenFileInFolder = { statusViewModel.openFileInFolder(it) }, onAllAction = { statusViewModel.unstageAll() }, onAlternateShowAsTree = { statusViewModel.alternateShowAsTree() }, onTreeDirectoryClicked = { statusViewModel.stagedTreeDirectoryClicked(it) }, @@ -189,6 +190,7 @@ fun UncommittedChanges( onHistoryFile = onHistoryFile, onReset = { statusViewModel.resetUnstaged(it) }, onDelete = { statusViewModel.deleteFile(it) }, + onOpenFileInFolder = { statusViewModel.openFileInFolder(it) }, onAllAction = { statusViewModel.stageAll() }, onAlternateShowAsTree = { statusViewModel.alternateShowAsTree() }, onTreeDirectoryClicked = { statusViewModel.stagedTreeDirectoryClicked(it) }, @@ -359,6 +361,7 @@ fun ColumnScope.StagedView( onHistoryFile: (String) -> Unit, onReset: (StatusEntry) -> Unit, onDelete: (StatusEntry) -> Unit, + onOpenFileInFolder: (String?) -> Unit, onAllAction: () -> Unit, onAlternateShowAsTree: () -> Unit, onTreeDirectoryClicked: (String) -> Unit, @@ -393,6 +396,7 @@ fun ColumnScope.StagedView( onHistoryFile = onHistoryFile, onReset = onReset, onDelete = onDelete, + onOpenFileInFolder = onOpenFileInFolder, onAllAction = onAllAction, onAlternateShowAsTree = onAlternateShowAsTree, onTreeDirectoryClicked = onTreeDirectoryClicked, @@ -431,6 +435,7 @@ fun ColumnScope.UnstagedView( onHistoryFile: (String) -> Unit, onReset: (StatusEntry) -> Unit, onDelete: (StatusEntry) -> Unit, + onOpenFileInFolder: (String?) -> Unit, onAllAction: () -> Unit, onAlternateShowAsTree: () -> Unit, onTreeDirectoryClicked: (String) -> Unit, @@ -465,6 +470,7 @@ fun ColumnScope.UnstagedView( onHistoryFile = onHistoryFile, onReset = onReset, onDelete = onDelete, + onOpenFileInFolder = onOpenFileInFolder, onAllAction = onAllAction, onAlternateShowAsTree = onAlternateShowAsTree, onTreeDirectoryClicked = onTreeDirectoryClicked, @@ -512,6 +518,7 @@ fun ColumnScope.NeutralView( onHistoryFile: (String) -> Unit, onReset: (StatusEntry) -> Unit, onDelete: (StatusEntry) -> Unit, + onOpenFileInFolder: (String?) -> Unit, onAllAction: () -> Unit, onAlternateShowAsTree: () -> Unit, onTreeDirectoryClicked: (String) -> Unit, @@ -548,6 +555,7 @@ fun ColumnScope.NeutralView( onHistory = { onHistoryFile(statusEntry.filePath) }, onReset = { onReset(statusEntry) }, onDelete = { onDelete(statusEntry) }, + onOpenFileInFolder = { onOpenFileInFolder(statusEntry.parentDirectoryPath) }, ) }, onAllAction = onAllAction, @@ -588,6 +596,7 @@ fun ColumnScope.NeutralView( onHistory = { onHistoryFile(statusEntry.filePath) }, onReset = { onReset(statusEntry) }, onDelete = { onDelete(statusEntry) }, + onOpenFileInFolder = { onOpenFileInFolder(statusEntry.parentDirectoryPath) }, ) }, onAllAction = onAllAction, @@ -1079,8 +1088,6 @@ fun EntriesHeader( ) } - - if (showSearch) { SearchTextField( searchFilter = searchFilter, @@ -1097,7 +1104,6 @@ fun EntriesHeader( requestFocus = false } } - } } diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/CommitedChangesEntriesContextMenu.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/CommitedChangesEntriesContextMenu.kt index 79a46345..b2074a0b 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/CommitedChangesEntriesContextMenu.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/CommitedChangesEntriesContextMenu.kt @@ -3,6 +3,7 @@ package com.jetpackduba.gitnuro.ui.context_menu import androidx.compose.foundation.ExperimentalFoundationApi import com.jetpackduba.gitnuro.generated.resources.Res import com.jetpackduba.gitnuro.generated.resources.blame +import com.jetpackduba.gitnuro.generated.resources.folder_open import com.jetpackduba.gitnuro.generated.resources.history import org.eclipse.jgit.diff.DiffEntry import org.jetbrains.compose.resources.painterResource @@ -12,6 +13,7 @@ fun committedChangesEntriesContextMenuItems( diffEntry: DiffEntry, onBlame: () -> Unit, onHistory: () -> Unit, + onOpenFileInFolder: () -> Unit, ): List { return mutableListOf().apply { if (diffEntry.changeType != DiffEntry.ChangeType.ADD || @@ -31,6 +33,14 @@ fun committedChangesEntriesContextMenuItems( onClick = onHistory, ) ) + + add( + ContextMenuElement.ContextTextEntry( + label = "Open file in folder", + icon = { painterResource(Res.drawable.folder_open) }, + onClick = onOpenFileInFolder, + ) + ) } } } \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/StatusEntriesContextMenu.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/StatusEntriesContextMenu.kt index 71ba17e6..b484b0a4 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/StatusEntriesContextMenu.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/StatusEntriesContextMenu.kt @@ -12,6 +12,7 @@ fun statusEntriesContextMenuItems( onDelete: () -> Unit = {}, onBlame: () -> Unit, onHistory: () -> Unit, + onOpenFileInFolder: () -> Unit, ): List { return mutableListOf().apply { if (statusEntry.statusType != StatusType.ADDED) { @@ -54,6 +55,14 @@ fun statusEntriesContextMenuItems( ) ) } + + add( + ContextMenuElement.ContextTextEntry( + label = "Open file in folder", + icon = { painterResource(Res.drawable.folder_open) }, + onClick = onOpenFileInFolder, + ) + ) } } diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt index 95c93700..d3adacfe 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt @@ -7,6 +7,7 @@ import com.jetpackduba.gitnuro.extensions.delayedStateChange import com.jetpackduba.gitnuro.extensions.filePath import com.jetpackduba.gitnuro.extensions.fullData import com.jetpackduba.gitnuro.extensions.lowercaseContains +import com.jetpackduba.gitnuro.extensions.openFileInFolder import com.jetpackduba.gitnuro.git.CloseableView import com.jetpackduba.gitnuro.git.RefreshType import com.jetpackduba.gitnuro.git.TabState @@ -19,6 +20,7 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import org.eclipse.jgit.diff.DiffEntry import org.eclipse.jgit.revwalk.RevCommit +import java.io.File import javax.inject.Inject private const val MIN_TIME_IN_MS_TO_SHOW_LOAD = 300L @@ -159,6 +161,12 @@ class CommitChangesViewModel @Inject constructor( appSettingsRepository.showChangesAsTree = !appSettingsRepository.showChangesAsTree } + fun openFileInFolder(folderPath: String?) = tabState.runOperation( + refreshType = RefreshType.UNCOMMITTED_CHANGES, + ) { + folderPath?.let { File(it).openFileInFolder() } + } + fun onDirectoryClicked(directoryPath: String) { val contractedDirectories = treeContractedDirectories.value diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt index 475a7648..87dbc99f 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt @@ -28,10 +28,13 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import kotlinx.io.IOException import org.eclipse.jgit.api.Git import org.eclipse.jgit.lib.PersonIdent import org.eclipse.jgit.lib.RepositoryState +import java.awt.Desktop import java.io.File +import java.util.* import javax.inject.Inject private const val MIN_TIME_IN_MS_TO_SHOW_LOAD = 500L @@ -128,7 +131,10 @@ class StatusViewModel @Inject constructor( stageStateFiltered.unstaged, contractedDirectories ) { it.filePath }, - filteredStaged = entriesToTreeEntry(stageStateFiltered.filteredStaged, contractedDirectories) { it.filePath }, + filteredStaged = entriesToTreeEntry( + stageStateFiltered.filteredStaged, + contractedDirectories + ) { it.filePath }, filteredUnstaged = entriesToTreeEntry( stageStateFiltered.filteredUnstaged, contractedDirectories @@ -509,6 +515,12 @@ class StatusViewModel @Inject constructor( fileToDelete.deleteRecursively() } + fun openFileInFolder(folderPath: String?) = tabState.runOperation( + refreshType = RefreshType.UNCOMMITTED_CHANGES, + ) { + folderPath?.let { File(it).openFileInFolder() } + } + fun updateCommitMessage(message: String) { savedCommitMessage = savedCommitMessage.copy(message = message) persistMessage() From 06aa3db545e349d8ce0986b0f3b16126f1fcfda5 Mon Sep 17 00:00:00 2001 From: Paul Spiesberger Date: Sun, 8 Jun 2025 22:37:13 +0200 Subject: [PATCH 2/6] #303 - Remove unused Imports --- .../kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt | 2 -- .../gitnuro/viewmodels/CommitChangesViewModel.kt | 6 +----- .../com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt | 3 --- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt b/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt index 7e3e03b0..b399c12a 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt @@ -5,8 +5,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import com.jetpackduba.gitnuro.extensions.icon import com.jetpackduba.gitnuro.extensions.iconColor -import kotlin.io.path.Path -import kotlin.io.path.pathString data class StatusEntry( val filePath: String, diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt index d3adacfe..8a370c3f 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt @@ -3,11 +3,7 @@ package com.jetpackduba.gitnuro.viewmodels import androidx.compose.foundation.ScrollState import androidx.compose.foundation.lazy.LazyListState import androidx.compose.ui.text.input.TextFieldValue -import com.jetpackduba.gitnuro.extensions.delayedStateChange -import com.jetpackduba.gitnuro.extensions.filePath -import com.jetpackduba.gitnuro.extensions.fullData -import com.jetpackduba.gitnuro.extensions.lowercaseContains -import com.jetpackduba.gitnuro.extensions.openFileInFolder +import com.jetpackduba.gitnuro.extensions.* import com.jetpackduba.gitnuro.git.CloseableView import com.jetpackduba.gitnuro.git.RefreshType import com.jetpackduba.gitnuro.git.TabState diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt index 87dbc99f..083b3d28 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt @@ -28,13 +28,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import kotlinx.io.IOException import org.eclipse.jgit.api.Git import org.eclipse.jgit.lib.PersonIdent import org.eclipse.jgit.lib.RepositoryState -import java.awt.Desktop import java.io.File -import java.util.* import javax.inject.Inject private const val MIN_TIME_IN_MS_TO_SHOW_LOAD = 500L From a383ccf917418362da4ee7b203a4d5a08bb3130f Mon Sep 17 00:00:00 2001 From: Paul Spiesberger Date: Sun, 29 Jun 2025 22:37:40 +0200 Subject: [PATCH 3/6] Respond to PR review: - Use printError instead of println - Revert formatting of Status.kt - Change RefreshType to NONE --- .../gitnuro/extensions/FileExtensions.kt | 24 +++++++++++-------- .../gitnuro/git/workspace/Status.kt | 5 +--- .../viewmodels/CommitChangesViewModel.kt | 2 +- .../gitnuro/viewmodels/StatusViewModel.kt | 2 +- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt b/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt index 6cf28cc7..ac0bdb51 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt @@ -1,9 +1,13 @@ package com.jetpackduba.gitnuro.extensions +import com.jetpackduba.gitnuro.logging.printError +import com.jetpackduba.gitnuro.system.OS +import com.jetpackduba.gitnuro.system.currentOs import kotlinx.io.IOException import java.awt.Desktop import java.io.File -import java.util.* + +private const val TAG = "FileExtensions" fun File.openDirectory(dirName: String): File { val newDir = File(this, dirName) @@ -18,7 +22,7 @@ fun File.openDirectory(dirName: String): File { fun File.openFileInFolder() { if (!exists() || !isDirectory) { - println("Folder with path $path does not exist or is not a folder") + printError(TAG, "Folder with path $path does not exist or is not a folder") return } @@ -31,15 +35,15 @@ fun File.openFileInFolder() { } } } catch (e: Exception) { - println("Desktop API failed: ${e.message}") + printError(TAG, "Desktop API failed: ${e.message}") } // Fallback - val os = System.getProperty("os.name").lowercase(Locale.getDefault()) - val command = when { - os.contains("linux") -> listOf("xdg-open", absolutePath) - os.contains("mac") -> listOf("open", absolutePath) - os.contains("windows") -> listOf("explorer", absolutePath) + val os = currentOs + val command = when (os) { + OS.LINUX -> listOf("xdg-open", absolutePath) + OS.MAC -> listOf("open", absolutePath) + OS.WINDOWS -> listOf("explorer", absolutePath) else -> null } @@ -47,9 +51,9 @@ fun File.openFileInFolder() { try { ProcessBuilder(command).start() } catch (ex: IOException) { - println("Failed to open file explorer: ${ex.message}") + printError(TAG, "Failed to open file explorer: ${ex.message}") } } else { - println("Unsupported OS: $os") + printError(TAG, "Unsupported OS: $os") } } \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt b/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt index b399c12a..c6620a76 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/git/workspace/Status.kt @@ -6,10 +6,7 @@ import androidx.compose.ui.graphics.vector.ImageVector import com.jetpackduba.gitnuro.extensions.icon import com.jetpackduba.gitnuro.extensions.iconColor -data class StatusEntry( - val filePath: String, - val statusType: StatusType -) { +data class StatusEntry(val filePath: String, val statusType: StatusType) { val icon: ImageVector get() = statusType.icon diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt index 8a370c3f..290896d2 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt @@ -158,7 +158,7 @@ class CommitChangesViewModel @Inject constructor( } fun openFileInFolder(folderPath: String?) = tabState.runOperation( - refreshType = RefreshType.UNCOMMITTED_CHANGES, + refreshType = RefreshType.NONE, ) { folderPath?.let { File(it).openFileInFolder() } } diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt index 083b3d28..e6df8259 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt @@ -513,7 +513,7 @@ class StatusViewModel @Inject constructor( } fun openFileInFolder(folderPath: String?) = tabState.runOperation( - refreshType = RefreshType.UNCOMMITTED_CHANGES, + refreshType = RefreshType.NONE, ) { folderPath?.let { File(it).openFileInFolder() } } From 057256e608d16e2315663a83d0c80ab4162ae3f8 Mon Sep 17 00:00:00 2001 From: Paul Spiesberger Date: Sun, 12 Oct 2025 20:00:07 +0200 Subject: [PATCH 4/6] #303 - fix folder path --- .../com/jetpackduba/gitnuro/extensions/FileExtensions.kt | 2 +- .../jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt | 4 ++-- .../com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt b/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt index ac0bdb51..bd93f9f4 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/extensions/FileExtensions.kt @@ -22,7 +22,7 @@ fun File.openDirectory(dirName: String): File { fun File.openFileInFolder() { if (!exists() || !isDirectory) { - printError(TAG, "Folder with path $path does not exist or is not a folder") + printError(TAG, "Folder with path \"$path\" does not exist or is not a folder") return } diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt index 290896d2..b6a4408b 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt @@ -159,8 +159,8 @@ class CommitChangesViewModel @Inject constructor( fun openFileInFolder(folderPath: String?) = tabState.runOperation( refreshType = RefreshType.NONE, - ) { - folderPath?.let { File(it).openFileInFolder() } + ) { git -> + folderPath?.let { File(git.repository.workTree.absolutePath + File.separator + it).openFileInFolder() } } fun onDirectoryClicked(directoryPath: String) { diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt index e6df8259..d2c2f1ff 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt @@ -514,8 +514,8 @@ class StatusViewModel @Inject constructor( fun openFileInFolder(folderPath: String?) = tabState.runOperation( refreshType = RefreshType.NONE, - ) { - folderPath?.let { File(it).openFileInFolder() } + ) { git -> + folderPath?.let { File(git.repository.workTree.absolutePath + File.separator + it).openFileInFolder() } } fun updateCommitMessage(message: String) { From e48c7cf1ddba070df3b286853a5b97e41e20da04 Mon Sep 17 00:00:00 2001 From: Paul Spiesberger Date: Sun, 12 Oct 2025 20:05:42 +0200 Subject: [PATCH 5/6] #303 - improve if statement readability --- .../jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt | 5 ++++- .../com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt index b6a4408b..6f670b5e 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/CommitChangesViewModel.kt @@ -160,7 +160,10 @@ class CommitChangesViewModel @Inject constructor( fun openFileInFolder(folderPath: String?) = tabState.runOperation( refreshType = RefreshType.NONE, ) { git -> - folderPath?.let { File(git.repository.workTree.absolutePath + File.separator + it).openFileInFolder() } + if (folderPath != null) { + val file = File(git.repository.workTree.absolutePath + File.separator + folderPath) + file.openFileInFolder() + } } fun onDirectoryClicked(directoryPath: String) { diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt index d2c2f1ff..6c548f01 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StatusViewModel.kt @@ -515,7 +515,10 @@ class StatusViewModel @Inject constructor( fun openFileInFolder(folderPath: String?) = tabState.runOperation( refreshType = RefreshType.NONE, ) { git -> - folderPath?.let { File(git.repository.workTree.absolutePath + File.separator + it).openFileInFolder() } + if (folderPath != null) { + val file = File(git.repository.workTree.absolutePath + File.separator + folderPath) + file.openFileInFolder() + } } fun updateCommitMessage(message: String) { From 5f3e122262e6bb330150831de1da7ee9f1c17d29 Mon Sep 17 00:00:00 2001 From: Paul Spiesberger Date: Sun, 12 Oct 2025 20:52:11 +0200 Subject: [PATCH 6/6] #303 Remove hardcoded Strings --- src/main/composeResources/values/strings.xml | 1 + .../ui/context_menu/StatusEntriesContextMenu.kt | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/composeResources/values/strings.xml b/src/main/composeResources/values/strings.xml index 9a7a7817..8201a767 100644 --- a/src/main/composeResources/values/strings.xml +++ b/src/main/composeResources/values/strings.xml @@ -89,6 +89,7 @@ File history Blame file Discard file changes + Open file in folder Checkout branch diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/StatusEntriesContextMenu.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/StatusEntriesContextMenu.kt index ebf7e1c3..f6eaa49a 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/StatusEntriesContextMenu.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/StatusEntriesContextMenu.kt @@ -49,12 +49,10 @@ fun statusEntriesContextMenuItems( ) } - add( - ContextMenuElement.ContextTextEntry( - label = "Open file in folder", - icon = { painterResource(Res.drawable.folder_open) }, - onClick = onOpenFileInFolder, - ) + addContextMenu( + composableLabel = { stringResource(Res.string.status_entries_context_menu_open_file_in_folder) }, + icon = { painterResource(Res.drawable.folder_open) }, + onClick = onOpenFileInFolder, ) } }