git.iko.soy/opencode-android
on f9ed438 help sign in
79 lines 3.3 kB history raw
1package soy.iko.opencode.ui.file
3import androidx.compose.foundation.horizontalScroll
4import androidx.compose.foundation.layout.Box
5import androidx.compose.foundation.layout.fillMaxSize
6import androidx.compose.foundation.layout.padding
7import androidx.compose.foundation.rememberScrollState
8import androidx.compose.foundation.verticalScroll
9import androidx.compose.material.icons.Icons
10import androidx.compose.material.icons.automirrored.filled.ArrowBack
11import androidx.compose.material3.CircularProgressIndicator
12import androidx.compose.material3.ExperimentalMaterial3Api
13import androidx.compose.material3.Icon
14import androidx.compose.material3.IconButton
15import androidx.compose.material3.MaterialTheme
16import androidx.compose.material3.Scaffold
17import androidx.compose.material3.Text
18import androidx.compose.material3.TopAppBar
19import androidx.compose.runtime.Composable
20import androidx.compose.runtime.getValue
21import androidx.compose.ui.Alignment
22import androidx.compose.ui.Modifier
23import androidx.compose.ui.text.font.FontFamily
24import androidx.compose.ui.text.style.TextOverflow
25import androidx.compose.ui.unit.dp
26import androidx.lifecycle.compose.collectAsStateWithLifecycle
27import androidx.lifecycle.viewmodel.compose.viewModel
28import soy.iko.opencode.di.AppContainer
29import soy.iko.opencode.ui.vmFactory
31@OptIn(ExperimentalMaterial3Api::class)
32@Composable
33fun FileViewScreen(
34 container: AppContainer,
35 path: String,
36 onBack: () -> Unit,
37) {
38 val vm: FileViewModel = viewModel(factory = vmFactory { FileViewModel(container, path) })
39 val state by vm.state.collectAsStateWithLifecycle()
41 Scaffold(
42 topBar = {
43 TopAppBar(
44 title = { Text(path.substringAfterLast('/'), maxLines = 1, overflow = TextOverflow.Ellipsis) },
45 navigationIcon = {
46 IconButton(onClick = onBack) {
47 Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
48 }
49 },
50 )
51 },
52 ) { padding ->
53 Box(modifier = Modifier.fillMaxSize().padding(padding)) {
54 when {
55 state.loading -> CircularProgressIndicator(Modifier.align(Alignment.Center))
56 state.error != null -> Text(
57 state.error!!,
58 modifier = Modifier.align(Alignment.Center).padding(24.dp),
59 color = MaterialTheme.colorScheme.error,
60 )
61 state.content?.isBinary == true -> Text(
62 "Binary file — preview not supported.",
63 modifier = Modifier.align(Alignment.Center).padding(24.dp),
64 color = MaterialTheme.colorScheme.onSurfaceVariant,
65 )
66 else -> Text(
67 text = state.content?.content.orEmpty(),
68 modifier = Modifier
69 .fillMaxSize()
70 .verticalScroll(rememberScrollState())
71 .horizontalScroll(rememberScrollState())
72 .padding(12.dp),
73 style = MaterialTheme.typography.bodySmall,
74 fontFamily = FontFamily.Monospace,
75 )
76 }
77 }
78 }