diff --git a/README.md b/README.md index b646025..e82d0ac 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,10 @@ A FOSS Git client based on (Jetbrains) Compose and JGit. -The main goal of Gitnuro is to provide a multiplatform open source Git client without any kind of constraint to how you can use it nor relying on web technologies. +The main goal of Gitnuro is to provide a multiplatform open source Git client without any kind of constraint to how you +can use it nor relying on web technologies. -The project it is still in alpha and many features are lacking or missing, but can be good for basic usage. +The project it is still in alpha and many features are lacking or missing, but can be good for basic usage. Right now you CAN: @@ -46,20 +47,19 @@ Right now you CAN'T: I'll create releases once we hit beta stage. - ## Steps to build Note: Requires minimum JDK 16. - Clone the project - Open terminal/shell in the project folder -- `./gradlew run` to run the project +- `./gradlew run` to run the project - `./gradlew tasks` to view other build options (native building requires java >=15) - Feel free to open issues for bugs or sugestions. ## Screenshots (latest update: 01 feb 2022) + ![Example 1](/res/img/gitnuro_example_1.png) ![Example 2](/res/img/gitnuro_example_2.png) ![Example 3](/res/img/gitnuro_example_3.png) diff --git a/src/main/kotlin/app/App.kt b/src/main/kotlin/app/App.kt index 669d6f9..cf15469 100644 --- a/src/main/kotlin/app/App.kt +++ b/src/main/kotlin/app/App.kt @@ -49,7 +49,7 @@ class App { private val tabsFlow = MutableStateFlow>(emptyList()) - fun start(){ + fun start() { appStateManager.loadRepositoriesTabs() loadTabs() diff --git a/src/main/kotlin/app/di/AppComponent.kt b/src/main/kotlin/app/di/AppComponent.kt index 78eed0b..cab13ef 100644 --- a/src/main/kotlin/app/di/AppComponent.kt +++ b/src/main/kotlin/app/di/AppComponent.kt @@ -1,7 +1,7 @@ package app.di -import app.AppStateManager import app.App +import app.AppStateManager import dagger.Component import javax.inject.Singleton diff --git a/src/main/kotlin/app/di/TabComponent.kt b/src/main/kotlin/app/di/TabComponent.kt index 0d7e172..7bb798d 100644 --- a/src/main/kotlin/app/di/TabComponent.kt +++ b/src/main/kotlin/app/di/TabComponent.kt @@ -4,7 +4,7 @@ import app.ui.components.TabInformation import dagger.Component @TabScope -@Component(dependencies = [ AppComponent::class ]) +@Component(dependencies = [AppComponent::class]) interface TabComponent { fun inject(tabInformation: TabInformation) } \ No newline at end of file diff --git a/src/main/kotlin/app/extensions/StringExtensions.kt b/src/main/kotlin/app/extensions/StringExtensions.kt index 37f025b..8d2af62 100644 --- a/src/main/kotlin/app/extensions/StringExtensions.kt +++ b/src/main/kotlin/app/extensions/StringExtensions.kt @@ -31,6 +31,6 @@ val String.dirPath: String } val String.withoutLineEnding: String -get() = this - .removeSuffix("\n") - .removeSuffix("\r\n") \ No newline at end of file + get() = this + .removeSuffix("\n") + .removeSuffix("\r\n") \ No newline at end of file diff --git a/src/main/kotlin/app/git/BranchesManager.kt b/src/main/kotlin/app/git/BranchesManager.kt index 4435f6d..22187d4 100644 --- a/src/main/kotlin/app/git/BranchesManager.kt +++ b/src/main/kotlin/app/git/BranchesManager.kt @@ -4,7 +4,9 @@ import app.extensions.isBranch import app.extensions.simpleName import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.eclipse.jgit.api.* +import org.eclipse.jgit.api.CreateBranchCommand +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.api.ListBranchCommand import org.eclipse.jgit.lib.Ref import org.eclipse.jgit.revwalk.RevCommit import javax.inject.Inject diff --git a/src/main/kotlin/app/git/DiffManager.kt b/src/main/kotlin/app/git/DiffManager.kt index da858ed..3d69b83 100644 --- a/src/main/kotlin/app/git/DiffManager.kt +++ b/src/main/kotlin/app/git/DiffManager.kt @@ -4,7 +4,6 @@ import app.di.HunkDiffGeneratorFactory import app.di.RawFileManagerFactory import app.extensions.fullData import app.git.diff.DiffResult -import app.git.diff.Hunk import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.eclipse.jgit.api.Git diff --git a/src/main/kotlin/app/git/LogManager.kt b/src/main/kotlin/app/git/LogManager.kt index 26aa6c1..46948ac 100644 --- a/src/main/kotlin/app/git/LogManager.kt +++ b/src/main/kotlin/app/git/LogManager.kt @@ -1,16 +1,10 @@ package app.git -import app.extensions.isBranch -import app.extensions.isMerging -import app.extensions.simpleName import app.git.graph.GraphCommitList import app.git.graph.GraphWalk import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ensureActive -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.withContext -import org.eclipse.jgit.api.CreateBranchCommand import org.eclipse.jgit.api.Git import org.eclipse.jgit.api.ResetCommand import org.eclipse.jgit.lib.Constants @@ -26,7 +20,7 @@ class LogManager @Inject constructor( val commitList = GraphCommitList() val repositoryState = git.repository.repositoryState println("Repository state ${repositoryState.description}") - if(currentBranch != null || repositoryState.isRebasing) { // Current branch is null when there is no log (new repo) or rebasing + if (currentBranch != null || repositoryState.isRebasing) { // Current branch is null when there is no log (new repo) or rebasing val logList = git.log().setMaxCount(2).call().toList() val walk = GraphWalk(git.repository) diff --git a/src/main/kotlin/app/git/MergeManager.kt b/src/main/kotlin/app/git/MergeManager.kt index 7c3fefa..41a3b23 100644 --- a/src/main/kotlin/app/git/MergeManager.kt +++ b/src/main/kotlin/app/git/MergeManager.kt @@ -22,10 +22,10 @@ class MergeManager @Inject constructor() { .call() } - suspend fun abortBranch(git: Git) = withContext(Dispatchers.IO) { - git.repository.writeMergeCommitMsg(null); - git.repository.writeMergeHeads(null); + suspend fun abortMerge(git: Git) = withContext(Dispatchers.IO) { + git.repository.writeMergeCommitMsg(null) + git.repository.writeMergeHeads(null) - git.reset().setMode(ResetCommand.ResetType.HARD).call(); + git.reset().setMode(ResetCommand.ResetType.HARD).call() } } \ No newline at end of file diff --git a/src/main/kotlin/app/git/RawFileManager.kt b/src/main/kotlin/app/git/RawFileManager.kt index e07cfb2..0f6ff95 100644 --- a/src/main/kotlin/app/git/RawFileManager.kt +++ b/src/main/kotlin/app/git/RawFileManager.kt @@ -61,14 +61,18 @@ class RawFileManager @AssistedInject constructor( return try { EntryContent.Text(RawText.load(ldr, DEFAULT_BINARY_FILE_THRESHOLD)) } catch (ex: BinaryBlobException) { - if(isImage(entry)) { + if (isImage(entry)) { generateImageBinary(ldr, entry, side) } else EntryContent.Binary } } - private fun generateImageBinary(ldr: ObjectLoader, entry: DiffEntry, side: DiffEntry.Side): EntryContent.ImageBinary { + private fun generateImageBinary( + ldr: ObjectLoader, + entry: DiffEntry, + side: DiffEntry.Side + ): EntryContent.ImageBinary { println("Data's size is ${ldr.size}") val tempDir = createTempDirectory("gitnuro${repository.directory.absolutePath.replace("/", "_")}") @@ -99,11 +103,11 @@ class RawFileManager @AssistedInject constructor( } sealed class EntryContent { - object Missing: EntryContent() - object InvalidObjectBlob: EntryContent() - data class Text(val rawText: RawText): EntryContent() + object Missing : EntryContent() + object InvalidObjectBlob : EntryContent() + data class Text(val rawText: RawText) : EntryContent() sealed class BinaryContent() : EntryContent() - data class ImageBinary(val tempFilePath: Path): BinaryContent() - object Binary: BinaryContent() - object TooLargeEntry: EntryContent() + data class ImageBinary(val tempFilePath: Path) : BinaryContent() + object Binary : BinaryContent() + object TooLargeEntry : EntryContent() } \ No newline at end of file diff --git a/src/main/kotlin/app/git/RemotesManager.kt b/src/main/kotlin/app/git/RemotesManager.kt index afbe4a9..a892f9e 100644 --- a/src/main/kotlin/app/git/RemotesManager.kt +++ b/src/main/kotlin/app/git/RemotesManager.kt @@ -1,8 +1,6 @@ package app.git import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.withContext import org.eclipse.jgit.api.Git import org.eclipse.jgit.lib.Ref diff --git a/src/main/kotlin/app/git/StashManager.kt b/src/main/kotlin/app/git/StashManager.kt index 43fa254..b1eef14 100644 --- a/src/main/kotlin/app/git/StashManager.kt +++ b/src/main/kotlin/app/git/StashManager.kt @@ -1,8 +1,6 @@ package app.git import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.withContext import org.eclipse.jgit.api.Git import javax.inject.Inject diff --git a/src/main/kotlin/app/git/StatusManager.kt b/src/main/kotlin/app/git/StatusManager.kt index 76e6f35..c4d8f46 100644 --- a/src/main/kotlin/app/git/StatusManager.kt +++ b/src/main/kotlin/app/git/StatusManager.kt @@ -60,7 +60,7 @@ class StatusManager @Inject constructor( val rawFileManager = rawFileManagerFactory.create(git.repository) val entryContent = rawFileManager.getRawContent(DiffEntry.Side.OLD, diffEntry) - if(entryContent !is EntryContent.Text) + if (entryContent !is EntryContent.Text) return@withContext val textLines = getTextLines(entryContent.rawText).toMutableList() @@ -103,7 +103,7 @@ class StatusManager @Inject constructor( val rawFileManager = rawFileManagerFactory.create(git.repository) val entryContent = rawFileManager.getRawContent(DiffEntry.Side.NEW, diffEntry) - if(entryContent !is EntryContent.Text) + if (entryContent !is EntryContent.Text) return@withContext val textLines = getTextLines(entryContent.rawText).toMutableList() @@ -224,33 +224,34 @@ class StatusManager @Inject constructor( .call() } - suspend fun getStaged(git: Git, currentBranch: Ref?, repositoryState: RepositoryState) = withContext(Dispatchers.IO) { - return@withContext git - .diff() - .setShowNameAndStatusOnly(true).apply { - if (currentBranch == null && !repositoryState.isMerging && !repositoryState.isRebasing) - setOldTree(EmptyTreeIterator()) // Required if the repository is empty + suspend fun getStaged(git: Git, currentBranch: Ref?, repositoryState: RepositoryState) = + withContext(Dispatchers.IO) { + return@withContext git + .diff() + .setShowNameAndStatusOnly(true).apply { + if (currentBranch == null && !repositoryState.isMerging && !repositoryState.isRebasing) + setOldTree(EmptyTreeIterator()) // Required if the repository is empty - setCached(true) - } - .call() - // TODO: Grouping and fitlering allows us to remove duplicates when conflicts appear, requires more testing (what happens in windows? /dev/null is a unix thing) - // TODO: Test if we should group by old path or new path - .groupBy { - if(it.newPath != "/dev/null") - it.newPath - else - it.oldPath - } - .map { - val entries = it.value + setCached(true) + } + .call() + // TODO: Grouping and fitlering allows us to remove duplicates when conflicts appear, requires more testing (what happens in windows? /dev/null is a unix thing) + // TODO: Test if we should group by old path or new path + .groupBy { + if (it.newPath != "/dev/null") + it.newPath + else + it.oldPath + } + .map { + val entries = it.value - val hasConflicts = - (entries.count() > 1 && (repositoryState.isMerging || repositoryState.isRebasing)) + val hasConflicts = + (entries.count() > 1 && (repositoryState.isMerging || repositoryState.isRebasing)) - StatusEntry(entries.first(), isConflict = hasConflicts) - } - } + StatusEntry(entries.first(), isConflict = hasConflicts) + } + } suspend fun getUnstaged(git: Git, repositoryState: RepositoryState) = withContext(Dispatchers.IO) { return@withContext git @@ -258,7 +259,7 @@ class StatusManager @Inject constructor( .setShowNameAndStatusOnly(true) .call() .groupBy { - if(it.oldPath != "/dev/null") + if (it.oldPath != "/dev/null") it.oldPath else it.newPath diff --git a/src/main/kotlin/app/git/TabState.kt b/src/main/kotlin/app/git/TabState.kt index 96e3127..56fa599 100644 --- a/src/main/kotlin/app/git/TabState.kt +++ b/src/main/kotlin/app/git/TabState.kt @@ -1,8 +1,8 @@ package app.git import app.ErrorsManager -import app.newErrorNow import app.di.TabScope +import app.newErrorNow import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob @@ -95,22 +95,23 @@ class TabState @Inject constructor( } } - fun runOperation(showError: Boolean = false, block: suspend (git: Git) -> RefreshType) = managerScope.launch(Dispatchers.IO) { - operationRunning = true - try { - val refreshType = block(safeGit) + fun runOperation(showError: Boolean = false, block: suspend (git: Git) -> RefreshType) = + managerScope.launch(Dispatchers.IO) { + operationRunning = true + try { + val refreshType = block(safeGit) - if (refreshType != RefreshType.NONE) - _refreshData.emit(refreshType) - } catch (ex: Exception) { - ex.printStackTrace() + if (refreshType != RefreshType.NONE) + _refreshData.emit(refreshType) + } catch (ex: Exception) { + ex.printStackTrace() - if (showError) - errorsManager.addError(newErrorNow(ex, ex.localizedMessage)) - } finally { - operationRunning = false + if (showError) + errorsManager.addError(newErrorNow(ex, ex.localizedMessage)) + } finally { + operationRunning = false + } } - } } enum class RefreshType { diff --git a/src/main/kotlin/app/git/TagsManager.kt b/src/main/kotlin/app/git/TagsManager.kt index 12646d3..2d57d0e 100644 --- a/src/main/kotlin/app/git/TagsManager.kt +++ b/src/main/kotlin/app/git/TagsManager.kt @@ -1,8 +1,6 @@ package app.git import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.withContext import org.eclipse.jgit.api.Git import org.eclipse.jgit.lib.Ref diff --git a/src/main/kotlin/app/git/diff/HunkDiffGenerator.kt b/src/main/kotlin/app/git/diff/HunkDiffGenerator.kt index d460dd5..7bc021e 100644 --- a/src/main/kotlin/app/git/diff/HunkDiffGenerator.kt +++ b/src/main/kotlin/app/git/diff/HunkDiffGenerator.kt @@ -14,7 +14,6 @@ import java.io.ByteArrayOutputStream import java.io.IOException import java.io.InvalidObjectException import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract import kotlin.math.max import kotlin.math.min @@ -48,7 +47,7 @@ class HunkDiffGenerator @AssistedInject constructor( val rawOld = rawFileManager.getRawContent(DiffEntry.Side.OLD, ent) val rawNew = rawFileManager.getRawContent(DiffEntry.Side.NEW, ent) - if(rawOld == EntryContent.InvalidObjectBlob || rawNew == EntryContent.InvalidObjectBlob) + if (rawOld == EntryContent.InvalidObjectBlob || rawNew == EntryContent.InvalidObjectBlob) throw InvalidObjectException("Invalid object in diff format") var diffResult: DiffResult = DiffResult.Text(emptyList()) @@ -84,7 +83,7 @@ class HunkDiffGenerator @AssistedInject constructor( else -> null } - return if(rawOldText != null && newOldText != null) { + return if (rawOldText != null && newOldText != null) { onText(rawOldText, newOldText) true } else diff --git a/src/main/kotlin/app/images/NetworkImageLoader.kt b/src/main/kotlin/app/images/NetworkImageLoader.kt index f5e8cf0..1356e7f 100644 --- a/src/main/kotlin/app/images/NetworkImageLoader.kt +++ b/src/main/kotlin/app/images/NetworkImageLoader.kt @@ -53,7 +53,7 @@ object NetworkImageLoader { fun rememberNetworkImageOrNull(url: String, placeHolderImageRes: String? = null): ImageBitmap? { val networkImageLoader = NetworkImageLoader var image by remember(url) { - val placeHolderImage = if(placeHolderImageRes != null) + val placeHolderImage = if (placeHolderImageRes != null) useResource(placeHolderImageRes) { Image.makeFromEncoded(it.toByteArray()).toComposeImageBitmap() } diff --git a/src/main/kotlin/app/theme/Theme.kt b/src/main/kotlin/app/theme/Theme.kt index 6e7f398..2edc3b0 100644 --- a/src/main/kotlin/app/theme/Theme.kt +++ b/src/main/kotlin/app/theme/Theme.kt @@ -109,8 +109,6 @@ val Colors.unstageButton: Color get() = error - - enum class Themes(val displayName: String) { LIGHT("Light"), DARK("Dark") diff --git a/src/main/kotlin/app/ui/AppTab.kt b/src/main/kotlin/app/ui/AppTab.kt index bb809dd..f64de3f 100644 --- a/src/main/kotlin/app/ui/AppTab.kt +++ b/src/main/kotlin/app/ui/AppTab.kt @@ -22,10 +22,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import app.LoadingRepository import app.credentials.CredentialsState -import app.viewmodels.TabViewModel -import app.viewmodels.RepositorySelectionStatus import app.ui.dialogs.PasswordDialog import app.ui.dialogs.UserPasswordDialog +import app.viewmodels.RepositorySelectionStatus +import app.viewmodels.TabViewModel import kotlinx.coroutines.delay // TODO onDispose sometimes is called when changing tabs, therefore losing the tab state diff --git a/src/main/kotlin/app/ui/CommitChanges.kt b/src/main/kotlin/app/ui/CommitChanges.kt index bcab981..877e092 100644 --- a/src/main/kotlin/app/ui/CommitChanges.kt +++ b/src/main/kotlin/app/ui/CommitChanges.kt @@ -1,20 +1,24 @@ package app.ui -import androidx.compose.foundation.* +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.foundation.verticalScroll import androidx.compose.material.* -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import app.extensions.* -import app.viewmodels.TabViewModel import app.theme.headerBackground import app.theme.headerText import app.theme.primaryTextColor @@ -34,7 +38,7 @@ fun CommitChanges( ) { val commitChangesStatusState = commitChangesViewModel.commitChangesStatus.collectAsState() - when(val commitChangesStatus = commitChangesStatusState.value) { + when (val commitChangesStatus = commitChangesStatusState.value) { CommitChangesStatus.Loading -> { LinearProgressIndicator(modifier = Modifier.fillMaxWidth()) } diff --git a/src/main/kotlin/app/ui/Diff.kt b/src/main/kotlin/app/ui/Diff.kt index 1d7cb8c..18883fd 100644 --- a/src/main/kotlin/app/ui/Diff.kt +++ b/src/main/kotlin/app/ui/Diff.kt @@ -6,8 +6,12 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.selection.DisableSelection import androidx.compose.foundation.text.selection.SelectionContainer -import androidx.compose.material.* -import androidx.compose.runtime.* +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -92,14 +96,14 @@ fun NonTextDiff(diffResult: DiffResult.NonText) { SideTitle("New") SideDiff(newBinaryContent) } - } else if(oldBinaryContent != EntryContent.Missing) { + } else if (oldBinaryContent != EntryContent.Missing) { Box( modifier = Modifier.fillMaxSize() .padding(all = 24.dp), ) { SideDiff(oldBinaryContent) } - } else if(newBinaryContent != EntryContent.Missing) { + } else if (newBinaryContent != EntryContent.Missing) { Column( modifier = Modifier.fillMaxSize() .padding(all = 24.dp), diff --git a/src/main/kotlin/app/ui/Menu.kt b/src/main/kotlin/app/ui/Menu.kt index c7a6417..94ebe39 100644 --- a/src/main/kotlin/app/ui/Menu.kt +++ b/src/main/kotlin/app/ui/Menu.kt @@ -2,7 +2,10 @@ package app.ui -import androidx.compose.foundation.* +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* @@ -18,13 +21,11 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import app.theme.primaryTextColor -import app.ui.context_menu.pullContextMenuItems -import app.viewmodels.MenuViewModel -import androidx.compose.runtime.getValue -import androidx.compose.runtime.setValue import app.ui.context_menu.DropDownContent import app.ui.context_menu.DropDownContentData +import app.ui.context_menu.pullContextMenuItems import app.ui.context_menu.pushContextMenuItems +import app.viewmodels.MenuViewModel // TODO Add tooltips to all the buttons @Composable @@ -199,7 +200,7 @@ fun ExtendedMenuButton( .border(ButtonDefaults.outlinedBorder, RoundedCornerShape(topEnd = 3.dp, bottomEnd = 3.dp)) .clickable { showDropDownMenu = true - }, + }, contentAlignment = Alignment.Center, ) { Icon( diff --git a/src/main/kotlin/app/ui/RepositoryOpen.kt b/src/main/kotlin/app/ui/RepositoryOpen.kt index 495cc52..a90d5d1 100644 --- a/src/main/kotlin/app/ui/RepositoryOpen.kt +++ b/src/main/kotlin/app/ui/RepositoryOpen.kt @@ -7,9 +7,9 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import app.git.DiffEntryType -import app.viewmodels.TabViewModel import app.ui.dialogs.NewBranchDialog import app.ui.log.Log +import app.viewmodels.TabViewModel import openRepositoryDialog import org.eclipse.jgit.revwalk.RevCommit import org.jetbrains.compose.splitpane.ExperimentalSplitPaneApi diff --git a/src/main/kotlin/app/ui/UncommitedChanges.kt b/src/main/kotlin/app/ui/UncommitedChanges.kt index 974fc33..0a2553e 100644 --- a/src/main/kotlin/app/ui/UncommitedChanges.kt +++ b/src/main/kotlin/app/ui/UncommitedChanges.kt @@ -58,7 +58,7 @@ fun UncommitedChanges( if (stageStatus is StageStatus.Loaded) { staged = stageStatus.staged unstaged = stageStatus.unstaged - + LaunchedEffect(staged) { if (selectedEntryType != null) { checkIfSelectedEntryShouldBeUpdated( @@ -154,7 +154,7 @@ fun UncommitedChanges( .padding(8.dp) .run { // When rebasing, we don't need a fixed size as we don't show the message TextField - if(!repositoryState.isRebasing) { + if (!repositoryState.isRebasing) { height(192.dp) } else this diff --git a/src/main/kotlin/app/ui/WelcomePage.kt b/src/main/kotlin/app/ui/WelcomePage.kt index c66b7f2..a27b8c2 100644 --- a/src/main/kotlin/app/ui/WelcomePage.kt +++ b/src/main/kotlin/app/ui/WelcomePage.kt @@ -20,11 +20,11 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import app.extensions.dirName import app.extensions.dirPath -import app.viewmodels.TabViewModel import app.theme.primaryTextColor import app.theme.secondaryTextColor import app.ui.dialogs.CloneDialog import app.ui.dialogs.MaterialDialog +import app.viewmodels.TabViewModel import openRepositoryDialog import java.awt.Desktop import java.net.URI diff --git a/src/main/kotlin/app/ui/components/AvatarImage.kt b/src/main/kotlin/app/ui/components/AvatarImage.kt index 8425483..5aef16e 100644 --- a/src/main/kotlin/app/ui/components/AvatarImage.kt +++ b/src/main/kotlin/app/ui/components/AvatarImage.kt @@ -28,7 +28,7 @@ fun AvatarImage( .clip(CircleShape) ) { val avatar = rememberAvatar(personIdent.emailAddress) - if(avatar == null) { + if (avatar == null) { Box( modifier = Modifier .fillMaxSize() diff --git a/src/main/kotlin/app/ui/components/RepositoriesTabPanel.kt b/src/main/kotlin/app/ui/components/RepositoriesTabPanel.kt index aa32a85..cf58cba 100644 --- a/src/main/kotlin/app/ui/components/RepositoriesTabPanel.kt +++ b/src/main/kotlin/app/ui/components/RepositoriesTabPanel.kt @@ -2,7 +2,10 @@ package app.ui.components import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items @@ -16,16 +19,15 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import app.AppStateManager import app.di.AppComponent import app.di.DaggerTabComponent import app.theme.primaryTextColor -import app.viewmodels.TabViewModel import app.theme.tabColorActive import app.theme.tabColorInactive import app.ui.AppTab +import app.viewmodels.TabViewModel import javax.inject.Inject import kotlin.io.path.Path import kotlin.io.path.name @@ -65,7 +67,7 @@ fun RepositoriesTabPanel( val index = tabs.indexOf(tab) val nextIndex = if (index == 0 && tabs.count() >= 2) { 1 // If the first tab is selected, select the next one - } else if (index == tabs.count() -1 && tabs.count() >= 2) + } else if (index == tabs.count() - 1 && tabs.count() >= 2) index - 1 // If the last tab is selected, select the previous one else if (tabs.count() >= 2) index + 1 // If any in between tab is selected, select the next one @@ -126,7 +128,7 @@ fun TabPanel( @Composable fun Tab(title: MutableState, selected: Boolean, onClick: () -> Unit, onCloseTab: () -> Unit) { - val elevation = if(selected) { + val elevation = if (selected) { 3.dp } else 0.dp @@ -194,7 +196,7 @@ class TabInformation( appStateManager.repositoryTabChanged(key, path) } } - if(path != null) + if (path != null) tabViewModel.openRepository(path) content = { AppTab(tabViewModel) diff --git a/src/main/kotlin/app/ui/components/SecondaryButton.kt b/src/main/kotlin/app/ui/components/SecondaryButton.kt index f0b8cc5..9025732 100644 --- a/src/main/kotlin/app/ui/components/SecondaryButton.kt +++ b/src/main/kotlin/app/ui/components/SecondaryButton.kt @@ -5,16 +5,13 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.MaterialTheme import androidx.compose.material.Text -import androidx.compose.material.contentColorFor import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import app.theme.primaryTextColor @Composable fun SecondaryButton( diff --git a/src/main/kotlin/app/ui/components/SideMenuEntry.kt b/src/main/kotlin/app/ui/components/SideMenuEntry.kt index c9cbf19..16bd272 100644 --- a/src/main/kotlin/app/ui/components/SideMenuEntry.kt +++ b/src/main/kotlin/app/ui/components/SideMenuEntry.kt @@ -1,6 +1,5 @@ package app.ui.components -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height diff --git a/src/main/kotlin/app/ui/components/SideMenuSubentry.kt b/src/main/kotlin/app/ui/components/SideMenuSubentry.kt index a4f6758..d598289 100644 --- a/src/main/kotlin/app/ui/components/SideMenuSubentry.kt +++ b/src/main/kotlin/app/ui/components/SideMenuSubentry.kt @@ -13,7 +13,6 @@ import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp diff --git a/src/main/kotlin/app/ui/dialogs/CloneDialog.kt b/src/main/kotlin/app/ui/dialogs/CloneDialog.kt index 53a7703..d39b2f6 100644 --- a/src/main/kotlin/app/ui/dialogs/CloneDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/CloneDialog.kt @@ -12,8 +12,8 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import app.git.CloneStatus -import app.viewmodels.TabViewModel import app.theme.primaryTextColor +import app.viewmodels.TabViewModel import java.io.File @Composable diff --git a/src/main/kotlin/app/ui/dialogs/RebaseDialog.kt b/src/main/kotlin/app/ui/dialogs/RebaseDialog.kt index b0b985c..ea27857 100644 --- a/src/main/kotlin/app/ui/dialogs/RebaseDialog.kt +++ b/src/main/kotlin/app/ui/dialogs/RebaseDialog.kt @@ -6,8 +6,11 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding -import androidx.compose.material.* -import androidx.compose.runtime.* +import androidx.compose.material.Button +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.material.TextButton +import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight diff --git a/src/main/kotlin/app/ui/log/Log.kt b/src/main/kotlin/app/ui/log/Log.kt index 8c078a7..6e72a6e 100644 --- a/src/main/kotlin/app/ui/log/Log.kt +++ b/src/main/kotlin/app/ui/log/Log.kt @@ -210,7 +210,7 @@ fun LogDialogs( } ) is LogDialog.RebaseBranch -> { - if(currentBranch != null) { + if (currentBranch != null) { RebaseDialog( currentBranchName = currentBranch.simpleName, rebaseBranchName = showLogDialog.ref.simpleName, diff --git a/src/main/kotlin/app/viewmodels/BranchesViewModel.kt b/src/main/kotlin/app/viewmodels/BranchesViewModel.kt index d4abdc9..a72e341 100644 --- a/src/main/kotlin/app/viewmodels/BranchesViewModel.kt +++ b/src/main/kotlin/app/viewmodels/BranchesViewModel.kt @@ -5,7 +5,6 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import org.eclipse.jgit.api.Git import org.eclipse.jgit.lib.Ref -import org.eclipse.jgit.revwalk.RevCommit import javax.inject.Inject class BranchesViewModel @Inject constructor( @@ -29,7 +28,7 @@ class BranchesViewModel @Inject constructor( // set selected branch as the first one always val selectedBranch = branchesList.find { it.name == _currentBranch.value } - if(selectedBranch != null) { + if (selectedBranch != null) { branchesList.remove(selectedBranch) branchesList.add(0, selectedBranch) } @@ -51,7 +50,7 @@ class BranchesViewModel @Inject constructor( return@safeProcessing RefreshType.ALL_DATA } - fun deleteBranch(branch: Ref) =tabState.safeProcessing { git -> + fun deleteBranch(branch: Ref) = tabState.safeProcessing { git -> branchesManager.deleteBranch(git, branch) return@safeProcessing RefreshType.ALL_DATA diff --git a/src/main/kotlin/app/viewmodels/DiffViewModel.kt b/src/main/kotlin/app/viewmodels/DiffViewModel.kt index 4399088..53ffb02 100644 --- a/src/main/kotlin/app/viewmodels/DiffViewModel.kt +++ b/src/main/kotlin/app/viewmodels/DiffViewModel.kt @@ -20,8 +20,8 @@ class DiffViewModel @Inject constructor( val lazyListState = MutableStateFlow( LazyListState( - 0, - 0 + 0, + 0 ) ) @@ -31,10 +31,10 @@ class DiffViewModel @Inject constructor( _diffResult.value = null // If it's a different file or different state (index or workdir), reset the scroll state - if(oldDiffEntryType != null && + if (oldDiffEntryType != null && (oldDiffEntryType.diffEntry.oldPath != diffEntryType.diffEntry.oldPath || - oldDiffEntryType.diffEntry.newPath != diffEntryType.diffEntry.newPath || - oldDiffEntryType::class != diffEntryType::class) + oldDiffEntryType.diffEntry.newPath != diffEntryType.diffEntry.newPath || + oldDiffEntryType::class != diffEntryType::class) ) { lazyListState.value = LazyListState( 0, diff --git a/src/main/kotlin/app/viewmodels/LogViewModel.kt b/src/main/kotlin/app/viewmodels/LogViewModel.kt index 6a2d41f..0411b11 100644 --- a/src/main/kotlin/app/viewmodels/LogViewModel.kt +++ b/src/main/kotlin/app/viewmodels/LogViewModel.kt @@ -75,7 +75,7 @@ class LogViewModel @Inject constructor( return@safeProcessing RefreshType.ALL_DATA } - fun deleteBranch(branch: Ref) =tabState.safeProcessing { git -> + fun deleteBranch(branch: Ref) = tabState.safeProcessing { git -> branchesManager.deleteBranch(git, branch) return@safeProcessing RefreshType.ALL_DATA @@ -100,5 +100,6 @@ class LogViewModel @Inject constructor( sealed class LogStatus { object Loading : LogStatus() - class Loaded(val hasUncommitedChanges: Boolean, val plotCommitList: GraphCommitList, val currentBranch: Ref?) : LogStatus() + class Loaded(val hasUncommitedChanges: Boolean, val plotCommitList: GraphCommitList, val currentBranch: Ref?) : + LogStatus() } \ No newline at end of file diff --git a/src/main/kotlin/app/viewmodels/MenuViewModel.kt b/src/main/kotlin/app/viewmodels/MenuViewModel.kt index 70db874..c6d883b 100644 --- a/src/main/kotlin/app/viewmodels/MenuViewModel.kt +++ b/src/main/kotlin/app/viewmodels/MenuViewModel.kt @@ -36,7 +36,7 @@ class MenuViewModel @Inject constructor( return@safeProcessing RefreshType.UNCOMMITED_CHANGES } - fun openFolderInFileExplorer() = tabState.runOperation (showError = true) { git -> + fun openFolderInFileExplorer() = tabState.runOperation(showError = true) { git -> Desktop.getDesktop().open(git.repository.directory.parentFile) return@runOperation RefreshType.NONE diff --git a/src/main/kotlin/app/viewmodels/RemotesViewModel.kt b/src/main/kotlin/app/viewmodels/RemotesViewModel.kt index eabaa21..5c86ca8 100644 --- a/src/main/kotlin/app/viewmodels/RemotesViewModel.kt +++ b/src/main/kotlin/app/viewmodels/RemotesViewModel.kt @@ -3,14 +3,11 @@ package app.viewmodels import app.git.BranchesManager import app.git.RemoteInfo import app.git.RemotesManager -import app.git.TabState import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.withContext import org.eclipse.jgit.api.Git -import org.eclipse.jgit.lib.Ref -import org.eclipse.jgit.transport.RemoteConfig import javax.inject.Inject class RemotesViewModel @Inject constructor( diff --git a/src/main/kotlin/app/viewmodels/StatusViewModel.kt b/src/main/kotlin/app/viewmodels/StatusViewModel.kt index 07e6d3d..6311ea0 100644 --- a/src/main/kotlin/app/viewmodels/StatusViewModel.kt +++ b/src/main/kotlin/app/viewmodels/StatusViewModel.kt @@ -135,7 +135,7 @@ class StatusViewModel @Inject constructor( } fun abortMerge() = tabState.safeProcessing { git -> - mergeManager.abortBranch(git) + mergeManager.abortMerge(git) return@safeProcessing RefreshType.ALL_DATA } diff --git a/src/main/kotlin/app/viewmodels/TabViewModel.kt b/src/main/kotlin/app/viewmodels/TabViewModel.kt index 32d6647..2cdc43e 100644 --- a/src/main/kotlin/app/viewmodels/TabViewModel.kt +++ b/src/main/kotlin/app/viewmodels/TabViewModel.kt @@ -2,10 +2,10 @@ package app.viewmodels import app.AppStateManager import app.ErrorsManager -import app.newErrorNow import app.credentials.CredentialsState import app.credentials.CredentialsStateManager import app.git.* +import app.newErrorNow import app.ui.SelectedItem import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel @@ -215,7 +215,7 @@ class TabViewModel @Inject constructor( } fun newSelectedRef(objectId: ObjectId?) = tabState.runOperation { git -> - if(objectId == null) { + if (objectId == null) { newSelectedItem(SelectedItem.None) return@runOperation RefreshType.NONE } @@ -233,7 +233,7 @@ class TabViewModel @Inject constructor( fun newSelectedItem(selectedItem: SelectedItem) { _selectedItem.value = selectedItem - if(selectedItem is SelectedItem.CommitBasedItem) { + if (selectedItem is SelectedItem.CommitBasedItem) { commitChangesViewModel.loadChanges(selectedItem.revCommit) } } diff --git a/src/main/resources/binary.svg b/src/main/resources/binary.svg index 669d4ff..89f8f02 100644 --- a/src/main/resources/binary.svg +++ b/src/main/resources/binary.svg @@ -1,3 +1,5 @@ - + diff --git a/src/main/resources/close.svg b/src/main/resources/close.svg index 5f1267d..6f80393 100644 --- a/src/main/resources/close.svg +++ b/src/main/resources/close.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + + \ No newline at end of file diff --git a/src/main/resources/source.svg b/src/main/resources/source.svg index 160eae0..0abe3fd 100644 --- a/src/main/resources/source.svg +++ b/src/main/resources/source.svg @@ -1 +1,7 @@ - \ No newline at end of file + + + + + + \ No newline at end of file