diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/di/factories/SidePanelViewModelsFactory.kt b/src/main/kotlin/com/jetpackduba/gitnuro/di/factories/SidePanelViewModelsFactory.kt index 68be4c9..5fea5c4 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/di/factories/SidePanelViewModelsFactory.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/di/factories/SidePanelViewModelsFactory.kt @@ -1,9 +1,6 @@ package com.jetpackduba.gitnuro.di.factories -import com.jetpackduba.gitnuro.viewmodels.sidepanel.BranchesViewModel -import com.jetpackduba.gitnuro.viewmodels.sidepanel.RemotesViewModel -import com.jetpackduba.gitnuro.viewmodels.sidepanel.StashesViewModel -import com.jetpackduba.gitnuro.viewmodels.sidepanel.TagsViewModel +import com.jetpackduba.gitnuro.viewmodels.sidepanel.* import dagger.assisted.AssistedFactory import kotlinx.coroutines.flow.StateFlow @@ -25,4 +22,9 @@ interface TagsViewModelFactory { @AssistedFactory interface StashesViewModelFactory { fun create(filter: StateFlow): StashesViewModel +} + +@AssistedFactory +interface SubmodulesViewModelFactory { + fun create(filter: StateFlow): SubmodulesViewModel } \ 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 a61d002..80b11fd 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt @@ -21,6 +21,7 @@ import com.jetpackduba.gitnuro.ui.dialogs.EditRemotesDialog import com.jetpackduba.gitnuro.viewmodels.sidepanel.* import org.eclipse.jgit.lib.Ref import org.eclipse.jgit.revwalk.RevCommit +import org.eclipse.jgit.submodule.SubmoduleStatus @Composable fun SidePanel( @@ -29,6 +30,7 @@ fun SidePanel( remotesViewModel: RemotesViewModel = sidePanelViewModel.remotesViewModel, tagsViewModel: TagsViewModel = sidePanelViewModel.tagsViewModel, stashesViewModel: StashesViewModel = sidePanelViewModel.stashesViewModel, + submodulesViewModel: SubmodulesViewModel = sidePanelViewModel.submodulesViewModel, ) { var filter by remember(sidePanelViewModel) { mutableStateOf(sidePanelViewModel.filter.value) } @@ -36,6 +38,7 @@ fun SidePanel( val remotesState by remotesViewModel.remoteState.collectAsState() val tagsState by tagsViewModel.tagsState.collectAsState() val stashesState by stashesViewModel.stashesState.collectAsState() + val submodulesState by submodulesViewModel.submodules.collectAsState() var showEditRemotesDialog by remember { mutableStateOf(false) } @@ -74,6 +77,11 @@ fun SidePanel( stashesState = stashesState, stashesViewModel = stashesViewModel, ) + + submodules( + submodulesState = submodulesState, + submodulesViewModel = submodulesViewModel + ) } } @@ -285,6 +293,38 @@ fun LazyListScope.stashes( } } +fun LazyListScope.submodules( + submodulesState: SubmodulesState, + submodulesViewModel: SubmodulesViewModel, +) { + val isExpanded = submodulesState.isExpanded + val submodules = submodulesState.submodules + + item { + ContextMenu( + items = { emptyList() } + ) { + SideMenuHeader( + text = "Submodules", + icon = painterResource("topic.svg"), + itemsCount = submodules.count(), + hoverIcon = null, + isExpanded = isExpanded, + onExpand = { submodulesViewModel.onExpand() } + ) + } + } + + if (isExpanded) { + items(submodules, key = { it.first }) { submodule -> + Submodule( + submodule, + onInitializeModule = { submodulesViewModel.initializeSubmodule(submodule.first) } + ) + } + } +} + @Composable private fun Branch( branch: Ref, @@ -416,4 +456,34 @@ private fun Stash( onClick = onClick, ) } +} + +@Composable +private fun Submodule( + submodulePair: Pair, + onInitializeModule: () -> Unit, +) { + ContextMenu( + items = { + submoduleContextMenuItems( + submodulePair.second, + onInitializeModule = onInitializeModule + ) + } + ) { + SideMenuSubentry( + text = submodulePair.first, + iconResourcePath = "topic.svg", + ) { + val stateName = submodulePair.second.type.toString() + Tooltip(stateName) { + Text( + text = stateName.first().toString(), + color = MaterialTheme.colors.onBackgroundSecondary, + style = MaterialTheme.typography.body2, + modifier = Modifier.padding(horizontal = 16.dp), + ) + } + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/Submodules.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/Submodules.kt deleted file mode 100644 index 8043874..0000000 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/Submodules.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.jetpackduba.gitnuro.ui - -import androidx.compose.foundation.layout.padding -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.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp -import com.jetpackduba.gitnuro.theme.onBackgroundSecondary -import com.jetpackduba.gitnuro.ui.components.SideMenuPanel -import com.jetpackduba.gitnuro.ui.components.SideMenuSubentry -import com.jetpackduba.gitnuro.ui.components.Tooltip -import com.jetpackduba.gitnuro.ui.components.gitnuroViewModel -import com.jetpackduba.gitnuro.ui.context_menu.ContextMenu -import com.jetpackduba.gitnuro.ui.context_menu.submoduleContextMenuItems -import com.jetpackduba.gitnuro.viewmodels.sidepanel.SubmodulesViewModel -import org.eclipse.jgit.submodule.SubmoduleStatus - -@Composable -fun Submodules( - submodulesViewModel: SubmodulesViewModel = gitnuroViewModel(), -) { - val submodules by submodulesViewModel.submodules.collectAsState() - val isExpanded by submodulesViewModel.isExpanded.collectAsState() - - SideMenuPanel( - title = "Submodules", - icon = painterResource("topic.svg"), - items = submodules, - isExpanded = isExpanded, - onExpand = { submodulesViewModel.onExpand() }, - itemContent = { submodule -> - SubmoduleLineEntry( - submodulePair = submodule, - onInitializeModule = { submodulesViewModel.initializeSubmodule(submodule.first) } - ) - } - ) -} - -@Composable -private fun SubmoduleLineEntry( - submodulePair: Pair, - onInitializeModule: () -> Unit, -) { - ContextMenu( - items = { - submoduleContextMenuItems( - submodulePair.second, - onInitializeModule = onInitializeModule - ) - } - ) { - SideMenuSubentry( - text = submodulePair.first, - iconResourcePath = "topic.svg", - ) { - val stateName = submodulePair.second.type.toString() - Tooltip(stateName) { - Text( - text = stateName.first().toString(), - color = MaterialTheme.colors.onBackgroundSecondary, - style = MaterialTheme.typography.body2, - modifier = Modifier.padding(horizontal = 16.dp), - ) - } - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/SidePanelViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/SidePanelViewModel.kt index f2d9d10..9aa3dd3 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/SidePanelViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/SidePanelViewModel.kt @@ -1,9 +1,6 @@ package com.jetpackduba.gitnuro.viewmodels.sidepanel -import com.jetpackduba.gitnuro.di.factories.BranchesViewModelFactory -import com.jetpackduba.gitnuro.di.factories.RemotesViewModelFactory -import com.jetpackduba.gitnuro.di.factories.StashesViewModelFactory -import com.jetpackduba.gitnuro.di.factories.TagsViewModelFactory +import com.jetpackduba.gitnuro.di.factories.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import javax.inject.Inject @@ -13,6 +10,7 @@ class SidePanelViewModel @Inject constructor( remotesViewModelFactory: RemotesViewModelFactory, tagsViewModelFactory: TagsViewModelFactory, stashesViewModelFactory: StashesViewModelFactory, + submodulesViewModelFactory: SubmodulesViewModelFactory, ) { private val _filter = MutableStateFlow("") val filter: StateFlow = _filter @@ -21,6 +19,7 @@ class SidePanelViewModel @Inject constructor( val remotesViewModel: RemotesViewModel = remotesViewModelFactory.create(filter) val tagsViewModel: TagsViewModel = tagsViewModelFactory.create(filter) val stashesViewModel: StashesViewModel = stashesViewModelFactory.create(filter) + val submodulesViewModel: SubmodulesViewModel = submodulesViewModelFactory.create(filter) fun newFilter(newValue: String) { _filter.value = newValue diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/SubmodulesViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/SubmodulesViewModel.kt index 8e97da4..39c3828 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/SubmodulesViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/SubmodulesViewModel.kt @@ -1,28 +1,49 @@ package com.jetpackduba.gitnuro.viewmodels.sidepanel +import com.jetpackduba.gitnuro.extensions.lowercaseContains import com.jetpackduba.gitnuro.git.RefreshType import com.jetpackduba.gitnuro.git.TabState import com.jetpackduba.gitnuro.git.submodules.GetSubmodulesUseCase import com.jetpackduba.gitnuro.git.submodules.InitializeSubmoduleUseCase import com.jetpackduba.gitnuro.git.submodules.UpdateSubmoduleUseCase +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import org.eclipse.jgit.api.Git import org.eclipse.jgit.submodule.SubmoduleStatus -import javax.inject.Inject -class SubmodulesViewModel @Inject constructor( +class SubmodulesViewModel @AssistedInject constructor( private val tabState: TabState, private val getSubmodulesUseCase: GetSubmodulesUseCase, private val initializeSubmoduleUseCase: InitializeSubmoduleUseCase, private val updateSubmoduleUseCase: UpdateSubmoduleUseCase, private val tabScope: CoroutineScope, + @Assisted + private val filter: StateFlow, ) : SidePanelChildViewModel(true) { + private val _submodules = MutableStateFlow>>(listOf()) - val submodules: StateFlow>> - get() = _submodules + val submodules: StateFlow = _submodules.combine(isExpanded) { submodules, isExpanded -> + SubmodulesState(submodules, isExpanded) + }.stateIn( + scope = tabScope, + started = SharingStarted.Eagerly, + initialValue = SubmodulesState(emptyList(), isExpanded.value) + ) + + val submodulesState: StateFlow = + combine(_submodules, isExpanded, filter) { submodules, isExpanded, filter -> + SubmodulesState( + submodules = submodules.filter { it.first.lowercaseContains(filter) }, + isExpanded + ) + }.stateIn( + tabScope, + SharingStarted.Eagerly, + SubmodulesState(emptyList(), isExpanded.value) + ) init { tabScope.launch { @@ -48,4 +69,6 @@ class SubmodulesViewModel @Inject constructor( suspend fun refresh(git: Git) { loadSubmodules(git) } -} \ No newline at end of file +} + +data class SubmodulesState(val submodules: List>, val isExpanded: Boolean) \ No newline at end of file