OXYGENHUB
# 0b152017dee3 oxygenhub-android / app / src / main / java / io / oxygenhub / android / ui / repos / CloneDialog.kt
3.0 KiB · last changed Clone from the phone: the repository screen's Clone action shows the oxy clone command with a copy button (refs #3) 8 days ago source blame history raw
1
package io.oxygenhub.android.ui.repos
2
3
import android.content.ClipData
4
import androidx.compose.foundation.layout.Column
5
import androidx.compose.foundation.layout.Arrangement
6
import androidx.compose.foundation.text.selection.SelectionContainer
7
import androidx.compose.material3.AlertDialog
8
import androidx.compose.material3.MaterialTheme
9
import androidx.compose.material3.Text
10
import androidx.compose.material3.TextButton
11
import androidx.compose.runtime.Composable
12
import androidx.compose.runtime.getValue
13
import androidx.compose.runtime.mutableStateOf
14
import androidx.compose.runtime.produceState
15
import androidx.compose.runtime.remember
16
import androidx.compose.runtime.rememberCoroutineScope
17
import androidx.compose.runtime.setValue
18
import androidx.compose.ui.platform.ClipEntry
19
import androidx.compose.ui.platform.LocalClipboard
20
import androidx.compose.ui.text.font.FontFamily
21
import androidx.compose.ui.unit.dp
22
import io.oxygenhub.android.api.userMessage
23
import kotlinx.coroutines.launch
24
25
/** The command that clones a repository at [url] with oxy. */
26
fun cloneCommand(url: String): String = "oxy clone $url"
27
28
/**
29
 * How to clone the repository (#3): its `oxy clone` command, selectable,
30
 * and a button that copies it. [cloneUrl] fetches the address.
31
 */
32
@Composable
33
fun CloneDialog(cloneUrl: suspend () -> String, onDismiss: () -> Unit) {
34
    val url by produceState<Result<String>?>(null) { value = runCatching { cloneUrl() } }
35
    val clipboard = LocalClipboard.current
36
    val scope = rememberCoroutineScope()
37
    var copied by remember { mutableStateOf(false) }
38
    val command = url?.getOrNull()?.takeIf { it.isNotEmpty() }?.let(::cloneCommand)
39
    AlertDialog(
40
        onDismissRequest = onDismiss,
41
        title = { Text("Clone") },
42
        text = {
43
            Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
44
                when {
45
                    url == null -> Text("Finding its address…")
46
                    command == null -> Text(url?.exceptionOrNull()?.userMessage() ?: "The hub gave no clone address.")
47
                    else -> {
48
                        SelectionContainer { Text(command, fontFamily = FontFamily.Monospace) }
49
                        Text(
50
                            "In a terminal with oxy installed. A private repository asks for your sign-in.",
51
                            style = MaterialTheme.typography.bodySmall,
52
                            color = MaterialTheme.colorScheme.onSurfaceVariant,
53
                        )
54
                    }
55
                }
56
            }
57
        },
58
        confirmButton = {
59
            TextButton(
60
                enabled = command != null,
61
                onClick = {
62
                    val text = command ?: return@TextButton
63
                    scope.launch {
64
                        clipboard.setClipEntry(ClipEntry(ClipData.newPlainText("oxy clone", text)))
65
                        copied = true
66
                    }
67
                },
68
            ) { Text(if (copied) "Copied" else "Copy") }
69
        },
70
        dismissButton = { TextButton(onClick = onDismiss) { Text("Close") } },
71
    )
72
}