Added author info request when doing a new commit if the info is not set previously
This commit is contained in:
parent
96599b045c
commit
4388ccb690
@ -30,6 +30,7 @@ object AppIcons {
|
||||
const val MERGE = "merge.svg"
|
||||
const val MORE_VERT = "more_vert.svg"
|
||||
const val OPEN = "open.svg"
|
||||
const val PERSON = "person.svg"
|
||||
const val REFRESH = "refresh.svg"
|
||||
const val REMOVE = "remove.svg"
|
||||
const val REVERT = "revert.svg"
|
||||
|
@ -3,15 +3,22 @@ package com.jetpackduba.gitnuro.git.workspace
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.PersonIdent
|
||||
import org.eclipse.jgit.revwalk.RevCommit
|
||||
import javax.inject.Inject
|
||||
|
||||
class DoCommitUseCase @Inject constructor() {
|
||||
suspend operator fun invoke(git: Git, message: String, amend: Boolean): RevCommit = withContext(Dispatchers.IO) {
|
||||
suspend operator fun invoke(
|
||||
git: Git,
|
||||
message: String,
|
||||
amend: Boolean,
|
||||
author: PersonIdent?,
|
||||
): RevCommit = withContext(Dispatchers.IO) {
|
||||
git.commit()
|
||||
.setMessage(message)
|
||||
.setAllowEmpty(amend) // Only allow empty commits when amending
|
||||
.setAmend(amend)
|
||||
.setAuthor(author)
|
||||
.call()
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@ import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
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.Density
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.jetpackduba.gitnuro.extensions.*
|
||||
import com.jetpackduba.gitnuro.git.DiffEntryType
|
||||
@ -44,6 +45,8 @@ import com.jetpackduba.gitnuro.ui.context_menu.ContextMenu
|
||||
import com.jetpackduba.gitnuro.ui.context_menu.ContextMenuElement
|
||||
import com.jetpackduba.gitnuro.ui.context_menu.EntryType
|
||||
import com.jetpackduba.gitnuro.ui.context_menu.statusEntriesContextMenuItems
|
||||
import com.jetpackduba.gitnuro.ui.dialogs.CommitAuthorDialog
|
||||
import com.jetpackduba.gitnuro.viewmodels.CommitterDataRequestState
|
||||
import com.jetpackduba.gitnuro.viewmodels.StageStatus
|
||||
import com.jetpackduba.gitnuro.viewmodels.StatusViewModel
|
||||
import org.eclipse.jgit.lib.RepositoryState
|
||||
@ -63,6 +66,8 @@ fun UncommitedChanges(
|
||||
val stagedListState by statusViewModel.stagedLazyListState.collectAsState()
|
||||
val unstagedListState by statusViewModel.unstagedLazyListState.collectAsState()
|
||||
val isAmend by statusViewModel.isAmend.collectAsState()
|
||||
val committerDataRequestState = statusViewModel.committerDataRequestState.collectAsState()
|
||||
val committerDataRequestStateValue = committerDataRequestState.value
|
||||
|
||||
val stageStatus = stageStatusState.value
|
||||
val staged: List<StatusEntry>
|
||||
@ -94,10 +99,20 @@ fun UncommitedChanges(
|
||||
}
|
||||
}
|
||||
|
||||
if (committerDataRequestStateValue is CommitterDataRequestState.WaitingInput) {
|
||||
CommitAuthorDialog(
|
||||
committerDataRequestStateValue.authorInfo,
|
||||
onClose = { statusViewModel.onRejectCommitterData() },
|
||||
onAccept = { newAuthorInfo, persist ->
|
||||
statusViewModel.onAcceptCommitterData(newAuthorInfo, persist)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(end = 8.dp, bottom = 8.dp)
|
||||
.fillMaxWidth()
|
||||
.fillMaxWidth(),
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = isLoading,
|
||||
@ -107,70 +122,74 @@ fun UncommitedChanges(
|
||||
LinearProgressIndicator(modifier = Modifier.fillMaxWidth(), color = MaterialTheme.colors.primaryVariant)
|
||||
}
|
||||
|
||||
EntriesList(
|
||||
modifier = Modifier
|
||||
.weight(5f)
|
||||
.padding(bottom = 4.dp)
|
||||
.fillMaxWidth(),
|
||||
title = "Staged",
|
||||
allActionTitle = "Unstage all",
|
||||
actionTitle = "Unstage",
|
||||
selectedEntryType = if (selectedEntryType is DiffEntryType.StagedDiff) selectedEntryType else null,
|
||||
actionColor = MaterialTheme.colors.error,
|
||||
actionTextColor = MaterialTheme.colors.onError,
|
||||
statusEntries = staged,
|
||||
lazyListState = stagedListState,
|
||||
onDiffEntrySelected = onStagedDiffEntrySelected,
|
||||
onDiffEntryOptionSelected = {
|
||||
statusViewModel.unstage(it)
|
||||
},
|
||||
onGenerateContextMenu = { statusEntry ->
|
||||
statusEntriesContextMenuItems(
|
||||
statusEntry = statusEntry,
|
||||
entryType = EntryType.STAGED,
|
||||
onBlame = { onBlameFile(statusEntry.filePath) },
|
||||
onReset = { statusViewModel.resetStaged(statusEntry) },
|
||||
onHistory = { onHistoryFile(statusEntry.filePath) },
|
||||
)
|
||||
},
|
||||
onAllAction = {
|
||||
statusViewModel.unstageAll()
|
||||
},
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
EntriesList(
|
||||
modifier = Modifier
|
||||
.weight(5f)
|
||||
.padding(bottom = 4.dp)
|
||||
.fillMaxWidth(),
|
||||
title = "Staged",
|
||||
allActionTitle = "Unstage all",
|
||||
actionTitle = "Unstage",
|
||||
selectedEntryType = if (selectedEntryType is DiffEntryType.StagedDiff) selectedEntryType else null,
|
||||
actionColor = MaterialTheme.colors.error,
|
||||
actionTextColor = MaterialTheme.colors.onError,
|
||||
statusEntries = staged,
|
||||
lazyListState = stagedListState,
|
||||
onDiffEntrySelected = onStagedDiffEntrySelected,
|
||||
onDiffEntryOptionSelected = {
|
||||
statusViewModel.unstage(it)
|
||||
},
|
||||
onGenerateContextMenu = { statusEntry ->
|
||||
statusEntriesContextMenuItems(
|
||||
statusEntry = statusEntry,
|
||||
entryType = EntryType.STAGED,
|
||||
onBlame = { onBlameFile(statusEntry.filePath) },
|
||||
onReset = { statusViewModel.resetStaged(statusEntry) },
|
||||
onHistory = { onHistoryFile(statusEntry.filePath) },
|
||||
)
|
||||
},
|
||||
onAllAction = {
|
||||
statusViewModel.unstageAll()
|
||||
},
|
||||
)
|
||||
|
||||
EntriesList(
|
||||
modifier = Modifier
|
||||
.weight(5f)
|
||||
.padding(bottom = 4.dp)
|
||||
.fillMaxWidth(),
|
||||
title = "Unstaged",
|
||||
actionTitle = "Stage",
|
||||
selectedEntryType = if (selectedEntryType is DiffEntryType.UnstagedDiff) selectedEntryType else null,
|
||||
actionColor = MaterialTheme.colors.primary,
|
||||
actionTextColor = MaterialTheme.colors.onPrimary,
|
||||
statusEntries = unstaged,
|
||||
lazyListState = unstagedListState,
|
||||
onDiffEntrySelected = onUnstagedDiffEntrySelected,
|
||||
onDiffEntryOptionSelected = {
|
||||
statusViewModel.stage(it)
|
||||
},
|
||||
onGenerateContextMenu = { statusEntry ->
|
||||
statusEntriesContextMenuItems(
|
||||
statusEntry = statusEntry,
|
||||
entryType = EntryType.UNSTAGED,
|
||||
onBlame = { onBlameFile(statusEntry.filePath) },
|
||||
onHistory = { onHistoryFile(statusEntry.filePath) },
|
||||
onReset = { statusViewModel.resetUnstaged(statusEntry) },
|
||||
onDelete = {
|
||||
statusViewModel.deleteFile(statusEntry)
|
||||
},
|
||||
)
|
||||
},
|
||||
onAllAction = {
|
||||
statusViewModel.stageAll()
|
||||
},
|
||||
allActionTitle = "Stage all",
|
||||
)
|
||||
EntriesList(
|
||||
modifier = Modifier
|
||||
.weight(5f)
|
||||
.padding(bottom = 4.dp)
|
||||
.fillMaxWidth(),
|
||||
title = "Unstaged",
|
||||
actionTitle = "Stage",
|
||||
selectedEntryType = if (selectedEntryType is DiffEntryType.UnstagedDiff) selectedEntryType else null,
|
||||
actionColor = MaterialTheme.colors.primary,
|
||||
actionTextColor = MaterialTheme.colors.onPrimary,
|
||||
statusEntries = unstaged,
|
||||
lazyListState = unstagedListState,
|
||||
onDiffEntrySelected = onUnstagedDiffEntrySelected,
|
||||
onDiffEntryOptionSelected = {
|
||||
statusViewModel.stage(it)
|
||||
},
|
||||
onGenerateContextMenu = { statusEntry ->
|
||||
statusEntriesContextMenuItems(
|
||||
statusEntry = statusEntry,
|
||||
entryType = EntryType.UNSTAGED,
|
||||
onBlame = { onBlameFile(statusEntry.filePath) },
|
||||
onHistory = { onHistoryFile(statusEntry.filePath) },
|
||||
onReset = { statusViewModel.resetUnstaged(statusEntry) },
|
||||
onDelete = {
|
||||
statusViewModel.deleteFile(statusEntry)
|
||||
},
|
||||
)
|
||||
},
|
||||
onAllAction = {
|
||||
statusViewModel.stageAll()
|
||||
},
|
||||
allActionTitle = "Stage all",
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@ -693,4 +712,40 @@ private fun FileEntry(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Stable
|
||||
val BottomReversed = object : Arrangement.Vertical {
|
||||
override fun Density.arrange(
|
||||
totalSize: Int,
|
||||
sizes: IntArray,
|
||||
outPositions: IntArray
|
||||
) = placeRightOrBottom(totalSize, sizes, outPositions, reverseInput = true)
|
||||
|
||||
override fun toString() = "Arrangement#BottomReversed"
|
||||
}
|
||||
|
||||
internal fun placeRightOrBottom(
|
||||
totalSize: Int,
|
||||
size: IntArray,
|
||||
outPosition: IntArray,
|
||||
reverseInput: Boolean
|
||||
) {
|
||||
val consumedSize = size.fold(0) { a, b -> a + b }
|
||||
var current = totalSize - consumedSize
|
||||
size.forEachIndexed(reverseInput) { index, it ->
|
||||
outPosition[index] = current
|
||||
current += it
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun IntArray.forEachIndexed(reversed: Boolean, action: (Int, Int) -> Unit) {
|
||||
if (!reversed) {
|
||||
forEachIndexed(action)
|
||||
} else {
|
||||
for (i in (size - 1) downTo 0) {
|
||||
action(i, get(i))
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
package com.jetpackduba.gitnuro.ui.dialogs
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Checkbox
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
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.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.jetpackduba.gitnuro.AppIcons
|
||||
import com.jetpackduba.gitnuro.extensions.handMouseClickable
|
||||
import com.jetpackduba.gitnuro.models.AuthorInfo
|
||||
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
|
||||
|
||||
@Composable
|
||||
fun CommitAuthorDialog(
|
||||
authorInfo: AuthorInfo,
|
||||
onClose: () -> Unit,
|
||||
onAccept: (newAuthorInfo: AuthorInfo, persist: Boolean) -> Unit,
|
||||
) {
|
||||
var globalName by remember(authorInfo) { mutableStateOf(authorInfo.globalName.orEmpty()) }
|
||||
var globalEmail by remember(authorInfo) { mutableStateOf(authorInfo.globalEmail.orEmpty()) }
|
||||
var persist by remember { mutableStateOf(false) }
|
||||
|
||||
MaterialDialog(
|
||||
onCloseRequested = onClose,
|
||||
background = MaterialTheme.colors.surface,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp)
|
||||
.width(IntrinsicSize.Min),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
|
||||
Icon(
|
||||
painterResource(AppIcons.PERSON),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(bottom = 16.dp)
|
||||
.size(64.dp),
|
||||
tint = MaterialTheme.colors.onBackground,
|
||||
)
|
||||
|
||||
|
||||
Text(
|
||||
text = "Author identity",
|
||||
modifier = Modifier
|
||||
.padding(bottom = 8.dp),
|
||||
color = MaterialTheme.colors.onBackground,
|
||||
style = MaterialTheme.typography.body1,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "Your Git configuration does not have a user identity set.",
|
||||
modifier = Modifier,
|
||||
color = MaterialTheme.colors.onBackground,
|
||||
style = MaterialTheme.typography.body2,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "What identity would you like to use for this commit?",
|
||||
modifier = Modifier
|
||||
.padding(bottom = 8.dp),
|
||||
color = MaterialTheme.colors.onBackground,
|
||||
style = MaterialTheme.typography.body2,
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.SemiBold
|
||||
)
|
||||
|
||||
|
||||
TextInput(
|
||||
title = "Name",
|
||||
value = globalName,
|
||||
onValueChange = { globalName = it },
|
||||
)
|
||||
|
||||
TextInput(
|
||||
title = "Email",
|
||||
value = globalEmail,
|
||||
onValueChange = { globalEmail = it },
|
||||
)
|
||||
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.handMouseClickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = null,
|
||||
) {
|
||||
persist = !persist
|
||||
}.fillMaxWidth()
|
||||
) {
|
||||
Checkbox(
|
||||
checked = persist,
|
||||
onCheckedChange = {
|
||||
persist = it
|
||||
},
|
||||
modifier = Modifier
|
||||
.padding(all = 8.dp)
|
||||
.size(12.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
"Save identity in the .gitconfig file",
|
||||
style = MaterialTheme.typography.body2,
|
||||
color = MaterialTheme.colors.onBackground,
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(top = 16.dp)
|
||||
.align(Alignment.End)
|
||||
) {
|
||||
PrimaryButton(
|
||||
text = "Cancel",
|
||||
modifier = Modifier.padding(end = 8.dp),
|
||||
onClick = onClose,
|
||||
backgroundColor = Color.Transparent,
|
||||
textColor = MaterialTheme.colors.onBackground,
|
||||
)
|
||||
PrimaryButton(
|
||||
onClick = {
|
||||
onAccept(
|
||||
AuthorInfo(
|
||||
globalName,
|
||||
globalEmail,
|
||||
authorInfo.name,
|
||||
authorInfo.email,
|
||||
),
|
||||
persist,
|
||||
)
|
||||
},
|
||||
text = "Continue"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TextInput(
|
||||
title: String,
|
||||
value: String,
|
||||
enabled: Boolean = true,
|
||||
onValueChange: (String) -> Unit,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.width(400.dp)
|
||||
.padding(vertical = 8.dp),
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.body1,
|
||||
modifier = Modifier
|
||||
.padding(bottom = 8.dp),
|
||||
)
|
||||
|
||||
AdjustableOutlinedTextField(
|
||||
value = value,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
enabled = enabled,
|
||||
onValueChange = onValueChange,
|
||||
colors = outlinedTextFieldColors(),
|
||||
singleLine = true,
|
||||
)
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@ import com.jetpackduba.gitnuro.extensions.isMerging
|
||||
import com.jetpackduba.gitnuro.extensions.isReverting
|
||||
import com.jetpackduba.gitnuro.git.RefreshType
|
||||
import com.jetpackduba.gitnuro.git.TabState
|
||||
import com.jetpackduba.gitnuro.git.author.LoadAuthorUseCase
|
||||
import com.jetpackduba.gitnuro.git.author.SaveAuthorUseCase
|
||||
import com.jetpackduba.gitnuro.git.log.CheckHasPreviousCommitsUseCase
|
||||
import com.jetpackduba.gitnuro.git.log.GetLastCommitMessageUseCase
|
||||
import com.jetpackduba.gitnuro.git.rebase.AbortRebaseUseCase
|
||||
@ -13,6 +15,7 @@ import com.jetpackduba.gitnuro.git.rebase.ContinueRebaseUseCase
|
||||
import com.jetpackduba.gitnuro.git.rebase.SkipRebaseUseCase
|
||||
import com.jetpackduba.gitnuro.git.repository.ResetRepositoryStateUseCase
|
||||
import com.jetpackduba.gitnuro.git.workspace.*
|
||||
import com.jetpackduba.gitnuro.models.AuthorInfo
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
@ -22,6 +25,7 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.lib.PersonIdent
|
||||
import org.eclipse.jgit.lib.RepositoryState
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
@ -46,6 +50,8 @@ class StatusViewModel @Inject constructor(
|
||||
private val getUnstagedUseCase: GetUnstagedUseCase,
|
||||
private val checkHasUncommitedChangedUseCase: CheckHasUncommitedChangedUseCase,
|
||||
private val doCommitUseCase: DoCommitUseCase,
|
||||
private val loadAuthorUseCase: LoadAuthorUseCase,
|
||||
private val saveAuthorUseCase: SaveAuthorUseCase,
|
||||
private val tabScope: CoroutineScope,
|
||||
) {
|
||||
private val _stageStatus = MutableStateFlow<StageStatus>(StageStatus.Loaded(listOf(), listOf(), false))
|
||||
@ -60,6 +66,9 @@ class StatusViewModel @Inject constructor(
|
||||
val stagedLazyListState = MutableStateFlow(LazyListState(0, 0))
|
||||
val unstagedLazyListState = MutableStateFlow(LazyListState(0, 0))
|
||||
|
||||
private val _committerDataRequestState = MutableStateFlow<CommitterDataRequestState>(CommitterDataRequestState.None)
|
||||
val committerDataRequestState: StateFlow<CommitterDataRequestState> = _committerDataRequestState
|
||||
|
||||
/**
|
||||
* Notify the UI that the commit message has been changed by the view model
|
||||
*/
|
||||
@ -213,7 +222,35 @@ class StatusViewModel @Inject constructor(
|
||||
} else
|
||||
message
|
||||
|
||||
doCommitUseCase(git, commitMessage, amend)
|
||||
val author = loadAuthorUseCase(git)
|
||||
|
||||
val personIdent = if (
|
||||
author.name.isNullOrEmpty() && author.globalName.isNullOrEmpty() ||
|
||||
author.email.isNullOrEmpty() && author.globalEmail.isNullOrEmpty()
|
||||
) {
|
||||
_committerDataRequestState.value = CommitterDataRequestState.WaitingInput(author)
|
||||
|
||||
var committerData = _committerDataRequestState.value
|
||||
|
||||
while (committerData is CommitterDataRequestState.WaitingInput) {
|
||||
committerData = _committerDataRequestState.value
|
||||
}
|
||||
|
||||
if (committerData is CommitterDataRequestState.Accepted) {
|
||||
val authorInfo = committerData.authorInfo
|
||||
|
||||
if (committerData.persist) {
|
||||
saveAuthorUseCase(git, authorInfo)
|
||||
}
|
||||
|
||||
PersonIdent(authorInfo.globalName, authorInfo.globalEmail)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} else
|
||||
null
|
||||
|
||||
doCommitUseCase(git, commitMessage, amend, personIdent)
|
||||
updateCommitMessage("")
|
||||
_isAmend.value = false
|
||||
}
|
||||
@ -285,6 +322,14 @@ class StatusViewModel @Inject constructor(
|
||||
persistMessage()
|
||||
_commitMessageChangesFlow.emit(savedCommitMessage.message)
|
||||
}
|
||||
|
||||
fun onRejectCommitterData() {
|
||||
this._committerDataRequestState.value = CommitterDataRequestState.Reject
|
||||
}
|
||||
|
||||
fun onAcceptCommitterData(newAuthorInfo: AuthorInfo, persist: Boolean) {
|
||||
this._committerDataRequestState.value = CommitterDataRequestState.Accepted(newAuthorInfo, persist)
|
||||
}
|
||||
}
|
||||
|
||||
sealed class StageStatus {
|
||||
@ -301,4 +346,11 @@ data class CommitMessage(val message: String, val messageType: MessageType)
|
||||
enum class MessageType {
|
||||
NORMAL,
|
||||
MERGE;
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface CommitterDataRequestState {
|
||||
object None : CommitterDataRequestState
|
||||
data class WaitingInput(val authorInfo: AuthorInfo) : CommitterDataRequestState
|
||||
data class Accepted(val authorInfo: AuthorInfo, val persist: Boolean) : CommitterDataRequestState
|
||||
object Reject : CommitterDataRequestState
|
||||
}
|
||||
|
1
src/main/resources/person.svg
Normal file
1
src/main/resources/person.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 6c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2m0 10c2.7 0 5.8 1.29 6 2H6c.23-.72 3.31-2 6-2m0-12C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 10c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></svg>
|
After Width: | Height: | Size: 360 B |
Loading…
Reference in New Issue
Block a user