358 lines
15 KiB
Kotlin
358 lines
15 KiB
Kotlin
package app.ui.dialogs
|
|
|
|
import androidx.compose.foundation.background
|
|
import androidx.compose.foundation.border
|
|
import androidx.compose.foundation.clickable
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.foundation.lazy.LazyColumn
|
|
import androidx.compose.foundation.lazy.items
|
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
import androidx.compose.material.*
|
|
import androidx.compose.material.icons.Icons
|
|
import androidx.compose.material.icons.filled.Clear
|
|
import androidx.compose.runtime.*
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.ExperimentalComposeUiApi
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.res.painterResource
|
|
import androidx.compose.ui.text.TextStyle
|
|
import androidx.compose.ui.unit.dp
|
|
import app.theme.borderColor
|
|
import app.theme.primaryTextColor
|
|
import app.theme.secondaryTextColor
|
|
import app.viewmodels.RemotesViewModel
|
|
import org.eclipse.jgit.transport.RemoteConfig
|
|
|
|
@OptIn(ExperimentalComposeUiApi::class)
|
|
@Composable
|
|
fun EditRemotesDialog(
|
|
remotesViewModel: RemotesViewModel,
|
|
onDismiss: () -> Unit,
|
|
) {
|
|
var remotesEditorData by remember {
|
|
mutableStateOf(
|
|
RemotesEditorData(
|
|
emptyList(),
|
|
null,
|
|
)
|
|
)
|
|
}
|
|
|
|
val remotes by remotesViewModel.remotes.collectAsState()
|
|
var remoteChanged by remember { mutableStateOf(false) }
|
|
val selectedRemote = remotesEditorData.selectedRemote
|
|
|
|
|
|
LaunchedEffect(remotes) {
|
|
val newRemotesWrappers = remotes.map {
|
|
val remoteConfig = it.remoteInfo.remoteConfig
|
|
remoteConfig.toRemoteWrapper()
|
|
}
|
|
|
|
val safeSelectedRemote = remotesEditorData.selectedRemote
|
|
var newSelectedRemote: RemoteWrapper? = null
|
|
|
|
if (safeSelectedRemote != null) {
|
|
newSelectedRemote = newRemotesWrappers.firstOrNull { it.remoteName == safeSelectedRemote.remoteName }
|
|
}
|
|
|
|
remoteChanged = newSelectedRemote?.haveUrisChanged ?: false
|
|
|
|
remotesEditorData = remotesEditorData.copy(
|
|
listRemotes = newRemotesWrappers,
|
|
selectedRemote = newSelectedRemote,
|
|
)
|
|
}
|
|
|
|
MaterialDialog(
|
|
paddingVertical = 8.dp,
|
|
paddingHorizontal = 16.dp,
|
|
) {
|
|
Column(
|
|
modifier = Modifier
|
|
.size(width = 900.dp, height = 600.dp),
|
|
horizontalAlignment = Alignment.CenterHorizontally,
|
|
verticalArrangement = Arrangement.Center,
|
|
) {
|
|
Row(
|
|
modifier = Modifier,
|
|
verticalAlignment = Alignment.CenterVertically,
|
|
) {
|
|
Text(
|
|
text = "Remotes",
|
|
color = MaterialTheme.colors.primaryTextColor,
|
|
modifier = Modifier.padding(vertical = 8.dp),
|
|
)
|
|
|
|
Spacer(modifier = Modifier.weight(1f))
|
|
|
|
IconButton(
|
|
onClick = onDismiss,
|
|
) {
|
|
Icon(
|
|
imageVector = Icons.Default.Clear,
|
|
contentDescription = null,
|
|
tint = MaterialTheme.colors.primaryTextColor,
|
|
)
|
|
}
|
|
}
|
|
Row(
|
|
modifier = Modifier
|
|
.padding(bottom = 8.dp)
|
|
.border(
|
|
width = 1.dp,
|
|
shape = RoundedCornerShape(5.dp),
|
|
color = MaterialTheme.colors.borderColor,
|
|
)
|
|
.background(MaterialTheme.colors.surface)
|
|
) {
|
|
Column(
|
|
modifier = Modifier
|
|
.width(200.dp)
|
|
.fillMaxHeight(),
|
|
) {
|
|
LazyColumn(
|
|
modifier = Modifier.weight(1f)
|
|
) {
|
|
items(remotesEditorData.listRemotes) { remote ->
|
|
val background = if (remote == selectedRemote) {
|
|
MaterialTheme.colors.background
|
|
} else
|
|
MaterialTheme.colors.surface
|
|
|
|
Text(
|
|
text = remote.remoteName,
|
|
color = MaterialTheme.colors.primaryTextColor,
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.clickable {
|
|
remotesEditorData = remotesEditorData.copy(selectedRemote = remote)
|
|
}
|
|
.background(background)
|
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
|
)
|
|
}
|
|
}
|
|
|
|
Row(
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.background(MaterialTheme.colors.background)
|
|
) {
|
|
IconButton(
|
|
modifier = Modifier.size(36.dp),
|
|
onClick = {
|
|
val remotesWithNew = remotesEditorData.listRemotes.toMutableList()
|
|
val newRemote = RemoteWrapper(
|
|
remoteName = "new_remote",
|
|
fetchUri = "",
|
|
originalFetchUri = "",
|
|
pushUri = "",
|
|
originalPushUri = "",
|
|
isNew = true
|
|
)
|
|
|
|
remotesWithNew.add(newRemote)
|
|
|
|
remotesEditorData = remotesEditorData.copy(
|
|
listRemotes = remotesWithNew,
|
|
selectedRemote = newRemote
|
|
)
|
|
}
|
|
) {
|
|
Icon(
|
|
painter = painterResource("add.svg"),
|
|
contentDescription = null,
|
|
tint = MaterialTheme.colors.primaryTextColor,
|
|
)
|
|
}
|
|
IconButton(
|
|
modifier = Modifier.size(36.dp),
|
|
enabled = selectedRemote != null,
|
|
onClick = {
|
|
if (selectedRemote != null)
|
|
remotesViewModel.deleteRemote(selectedRemote.remoteName, selectedRemote.isNew)
|
|
}
|
|
) {
|
|
Icon(
|
|
painter = painterResource("remove.svg"),
|
|
contentDescription = null,
|
|
tint = if (selectedRemote != null)
|
|
MaterialTheme.colors.primaryTextColor
|
|
else
|
|
MaterialTheme.colors.secondaryTextColor,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
Box(
|
|
modifier = Modifier
|
|
.fillMaxHeight()
|
|
.width(1.dp)
|
|
.background(MaterialTheme.colors.borderColor)
|
|
)
|
|
|
|
Column(
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.background(MaterialTheme.colors.surface)
|
|
.padding(horizontal = 8.dp)
|
|
) {
|
|
if (selectedRemote != null) {
|
|
Column {
|
|
if (selectedRemote.isNew) {
|
|
Text(
|
|
text = "New remote name",
|
|
color = MaterialTheme.colors.primaryTextColor,
|
|
modifier = Modifier.padding(vertical = 8.dp),
|
|
)
|
|
|
|
OutlinedTextField(
|
|
value = selectedRemote.remoteName,
|
|
onValueChange = { newValue ->
|
|
val newSelectedRemoteConfig = selectedRemote.copy(remoteName = newValue)
|
|
val listRemotes = remotesEditorData.listRemotes.toMutableList()
|
|
val newRemoteToBeReplacedIndex = listRemotes.indexOfFirst { it.isNew }
|
|
listRemotes[newRemoteToBeReplacedIndex] = newSelectedRemoteConfig
|
|
|
|
remotesEditorData = remotesEditorData.copy(
|
|
listRemotes = listRemotes,
|
|
selectedRemote = newSelectedRemoteConfig
|
|
)
|
|
},
|
|
textStyle = TextStyle.Default.copy(color = MaterialTheme.colors.primaryTextColor),
|
|
maxLines = 1,
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.padding(vertical = 8.dp)
|
|
)
|
|
}
|
|
|
|
Text(
|
|
text = "Fetch URL",
|
|
color = MaterialTheme.colors.primaryTextColor,
|
|
modifier = Modifier.padding(vertical = 8.dp),
|
|
)
|
|
|
|
OutlinedTextField(
|
|
value = selectedRemote.fetchUri,
|
|
onValueChange = { newValue ->
|
|
val newSelectedRemoteConfig = selectedRemote.copy(fetchUri = newValue)
|
|
remotesEditorData = remotesEditorData.copy(selectedRemote = newSelectedRemoteConfig)
|
|
remoteChanged = newSelectedRemoteConfig.haveUrisChanged
|
|
},
|
|
textStyle = TextStyle.Default.copy(color = MaterialTheme.colors.primaryTextColor),
|
|
maxLines = 1,
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.padding(vertical = 8.dp)
|
|
)
|
|
|
|
Text(
|
|
text = "Push URL",
|
|
color = MaterialTheme.colors.primaryTextColor,
|
|
modifier = Modifier.padding(vertical = 8.dp),
|
|
)
|
|
|
|
OutlinedTextField(
|
|
value = selectedRemote.pushUri,
|
|
onValueChange = { newValue ->
|
|
val newSelectedRemoteConfig = selectedRemote.copy(pushUri = newValue)
|
|
remotesEditorData = remotesEditorData.copy(selectedRemote = newSelectedRemoteConfig)
|
|
remoteChanged = newSelectedRemoteConfig.haveUrisChanged
|
|
},
|
|
textStyle = TextStyle.Default.copy(color = MaterialTheme.colors.primaryTextColor),
|
|
maxLines = 1,
|
|
modifier = Modifier
|
|
.fillMaxWidth()
|
|
.padding(vertical = 8.dp)
|
|
)
|
|
|
|
Spacer(modifier = Modifier.weight(1f))
|
|
|
|
Row(
|
|
modifier = Modifier
|
|
.padding(top = 16.dp)
|
|
.align(Alignment.End)
|
|
) {
|
|
Spacer(modifier = Modifier.weight(1f))
|
|
|
|
if (!selectedRemote.isNew) {
|
|
TextButton(
|
|
modifier = Modifier.padding(end = 8.dp),
|
|
enabled = remoteChanged,
|
|
onClick = {
|
|
remotesEditorData = remotesEditorData.copy(
|
|
selectedRemote = selectedRemote.copy(
|
|
fetchUri = selectedRemote.originalFetchUri,
|
|
pushUri = selectedRemote.originalPushUri,
|
|
)
|
|
)
|
|
|
|
remoteChanged = false
|
|
}
|
|
) {
|
|
Text("Discard changes")
|
|
}
|
|
}
|
|
|
|
Button(
|
|
modifier = Modifier,
|
|
enabled = remoteChanged,
|
|
onClick = {
|
|
if (selectedRemote.isNew)
|
|
remotesViewModel.addRemote(selectedRemote)
|
|
else
|
|
remotesViewModel.updateRemote(selectedRemote)
|
|
},
|
|
) {
|
|
val text = if (selectedRemote.isNew)
|
|
"Add new remote"
|
|
else
|
|
"Save ${selectedRemote.remoteName} changes"
|
|
|
|
Text(text)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
data class RemoteWrapper(
|
|
val remoteName: String,
|
|
val fetchUri: String,
|
|
val originalFetchUri: String,
|
|
val pushUri: String,
|
|
val originalPushUri: String,
|
|
val isNew: Boolean = false,
|
|
) {
|
|
val haveUrisChanged: Boolean = isNew ||
|
|
fetchUri != originalFetchUri ||
|
|
pushUri.toString() != originalPushUri
|
|
}
|
|
|
|
|
|
data class RemotesEditorData(
|
|
val listRemotes: List<RemoteWrapper>,
|
|
val selectedRemote: RemoteWrapper?,
|
|
)
|
|
|
|
fun RemoteConfig.toRemoteWrapper(): RemoteWrapper {
|
|
val fetchUri = this.urIs.firstOrNull()
|
|
val pushUri = this.pushURIs.firstOrNull()
|
|
?: this.urIs.firstOrNull() // If push URI == null, take fetch URI
|
|
|
|
return RemoteWrapper(
|
|
remoteName = this.name,
|
|
fetchUri = fetchUri?.toString().orEmpty(),
|
|
originalFetchUri = fetchUri?.toString().orEmpty(),
|
|
pushUri = pushUri?.toString().orEmpty(),
|
|
originalPushUri = pushUri?.toString().orEmpty(),
|
|
)
|
|
} |