Skip to content

Commit afb64a8

Browse files
authored
Create ReleasesScreen.kt
1 parent 1a20017 commit afb64a8

1 file changed

Lines changed: 201 additions & 0 deletions

File tree

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package com.hackeros.app.ui.screens
2+
3+
import androidx.compose.animation.*
4+
import androidx.compose.animation.core.tween
5+
import androidx.compose.foundation.layout.*
6+
import androidx.compose.foundation.lazy.LazyColumn
7+
import androidx.compose.foundation.lazy.itemsIndexed
8+
import androidx.compose.material.icons.Icons
9+
import androidx.compose.material.icons.filled.Terminal
10+
import androidx.compose.material.icons.filled.WifiOff
11+
import androidx.compose.material3.*
12+
import androidx.compose.runtime.*
13+
import androidx.compose.ui.Alignment
14+
import androidx.compose.ui.Modifier
15+
import androidx.compose.ui.graphics.Color
16+
import androidx.compose.ui.text.font.FontFamily
17+
import androidx.compose.ui.text.font.FontWeight
18+
import androidx.compose.ui.unit.dp
19+
import androidx.compose.ui.unit.sp
20+
import com.hackeros.app.data.model.ReleaseInfo
21+
import com.hackeros.app.ui.components.VersionCard
22+
import com.hackeros.app.ui.theme.LocalAppTheme
23+
import com.hackeros.app.ui.theme.mutedColor
24+
import com.hackeros.app.ui.theme.primaryColor
25+
import com.hackeros.app.ui.theme.textColor
26+
import com.hackeros.app.utils.Translations
27+
28+
@Composable
29+
fun ReleasesScreen(
30+
releases: List<ReleaseInfo>,
31+
loading: Boolean,
32+
error: String?,
33+
translations: Translations,
34+
onRetry: () -> Unit
35+
) {
36+
val theme = LocalAppTheme.current
37+
val t = translations
38+
39+
LazyColumn(
40+
contentPadding = PaddingValues(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 100.dp),
41+
verticalArrangement = Arrangement.spacedBy(16.dp)
42+
) {
43+
item {
44+
// Header
45+
Row(
46+
verticalAlignment = Alignment.CenterVertically,
47+
modifier = Modifier.padding(horizontal = 4.dp, vertical = 8.dp)
48+
) {
49+
Text(
50+
text = "HackerOS",
51+
fontFamily = FontFamily.Monospace,
52+
fontWeight = FontWeight.Bold,
53+
fontSize = 28.sp,
54+
color = Color.White
55+
)
56+
Spacer(Modifier.width(12.dp))
57+
Surface(
58+
shape = androidx.compose.foundation.shape.RoundedCornerShape(6.dp),
59+
color = theme.primaryColor().copy(alpha = 0.15f),
60+
border = androidx.compose.foundation.BorderStroke(
61+
1.dp, theme.primaryColor().copy(alpha = 0.5f)
62+
)
63+
) {
64+
Text(
65+
text = t.sub_releases,
66+
fontSize = 9.sp,
67+
fontFamily = FontFamily.Monospace,
68+
fontWeight = FontWeight.Bold,
69+
color = theme.primaryColor(),
70+
letterSpacing = 0.5.sp,
71+
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
72+
)
73+
}
74+
}
75+
}
76+
77+
when {
78+
loading -> item {
79+
LoadingState(theme.primaryColor(), t.decrypting)
80+
}
81+
error != null -> item {
82+
ErrorState(
83+
errorSignal = t.error_signal,
84+
errorNetwork = t.error_network,
85+
retry = t.retry,
86+
onRetry = onRetry
87+
)
88+
}
89+
else -> {
90+
itemsIndexed(releases) { index, release ->
91+
AnimatedVisibility(
92+
visible = true,
93+
enter = fadeIn(tween(300 + index * 80)) +
94+
slideInVertically(tween(300 + index * 80)) { it / 2 }
95+
) {
96+
VersionCard(
97+
release = release,
98+
isLatest = index == 0,
99+
translations = t
100+
)
101+
}
102+
}
103+
item {
104+
Column(
105+
horizontalAlignment = Alignment.CenterHorizontally,
106+
modifier = Modifier
107+
.fillMaxWidth()
108+
.padding(vertical = 24.dp)
109+
) {
110+
Icon(
111+
Icons.Default.Terminal,
112+
contentDescription = null,
113+
tint = theme.mutedColor().copy(alpha = 0.4f),
114+
modifier = Modifier.size(24.dp)
115+
)
116+
Spacer(Modifier.height(8.dp))
117+
Text(
118+
text = t.end_of_log.uppercase(),
119+
fontSize = 9.sp,
120+
fontFamily = FontFamily.Monospace,
121+
color = theme.mutedColor().copy(alpha = 0.4f),
122+
letterSpacing = 2.sp
123+
)
124+
}
125+
}
126+
}
127+
}
128+
}
129+
}
130+
131+
@Composable
132+
private fun LoadingState(primaryColor: Color, label: String) {
133+
Column(
134+
horizontalAlignment = Alignment.CenterHorizontally,
135+
modifier = Modifier
136+
.fillMaxWidth()
137+
.height(300.dp),
138+
verticalArrangement = Arrangement.Center
139+
) {
140+
CircularProgressIndicator(color = primaryColor, modifier = Modifier.size(48.dp))
141+
Spacer(Modifier.height(16.dp))
142+
val infiniteTransition = rememberInfiniteTransition(label = "pulse")
143+
val alpha by infiniteTransition.animateFloat(
144+
initialValue = 0.3f, targetValue = 1f,
145+
animationSpec = infiniteRepeatable(tween(800), RepeatMode.Reverse),
146+
label = "alpha"
147+
)
148+
Text(
149+
text = label,
150+
fontSize = 11.sp,
151+
fontFamily = FontFamily.Monospace,
152+
color = primaryColor.copy(alpha = alpha)
153+
)
154+
}
155+
}
156+
157+
@Composable
158+
private fun ErrorState(
159+
errorSignal: String,
160+
errorNetwork: String,
161+
retry: String,
162+
onRetry: () -> Unit
163+
) {
164+
Column(
165+
horizontalAlignment = Alignment.CenterHorizontally,
166+
modifier = Modifier
167+
.fillMaxWidth()
168+
.height(300.dp)
169+
.padding(horizontal = 32.dp),
170+
verticalArrangement = Arrangement.Center
171+
) {
172+
Surface(
173+
shape = androidx.compose.foundation.shape.CircleShape,
174+
color = Color(0xFFEF4444).copy(alpha = 0.1f),
175+
border = androidx.compose.foundation.BorderStroke(
176+
1.dp, Color(0xFFEF4444).copy(alpha = 0.2f)
177+
),
178+
modifier = Modifier.size(72.dp)
179+
) {
180+
Box(contentAlignment = Alignment.Center) {
181+
Icon(
182+
Icons.Default.WifiOff,
183+
contentDescription = null,
184+
tint = Color(0xFFEF4444),
185+
modifier = Modifier.size(36.dp)
186+
)
187+
}
188+
}
189+
Spacer(Modifier.height(16.dp))
190+
Text(errorSignal, color = Color(0xFFEF4444), fontWeight = FontWeight.Bold, fontSize = 14.sp)
191+
Spacer(Modifier.height(6.dp))
192+
Text(errorNetwork, color = Color(0xFF94A3B8), fontSize = 12.sp)
193+
Spacer(Modifier.height(20.dp))
194+
Button(
195+
onClick = onRetry,
196+
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFEF4444))
197+
) {
198+
Text(retry, fontWeight = FontWeight.Bold, fontSize = 12.sp)
199+
}
200+
}
201+
}

0 commit comments

Comments
 (0)