Skip to content

Commit 3eed580

Browse files
authored
Update GamesStoreScreen.kt
1 parent cec7471 commit 3eed580

1 file changed

Lines changed: 115 additions & 3 deletions

File tree

source-code/app/src/main/java/com/hackeros/app/ui/screens/GamesStoreScreen.kt

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package com.hackeros.app.ui.screens
22

3+
import android.content.ClipData
4+
import android.content.ClipboardManager
5+
import android.content.Context
6+
import android.widget.Toast
37
import androidx.compose.foundation.background
48
import androidx.compose.foundation.border
59
import androidx.compose.foundation.clickable
@@ -164,6 +168,7 @@ fun GamesStoreScreen(
164168
}
165169

166170
selectedGame?.let { game ->
171+
val uriHandler = androidx.compose.ui.platform.LocalUriHandler.current
167172
GameDetailDialog(
168173
game = game,
169174
installState = installStates[game.id],
@@ -172,7 +177,12 @@ fun GamesStoreScreen(
172177
onDismiss = { selectedGame = null },
173178
onDownload = { onDownload(game) },
174179
onInstall = { onInstall(game.id) },
175-
onOpen = { onOpen(game.packageName) }
180+
onOpen = { onOpen(game.packageName) },
181+
onOpenRepo = {
182+
val url = game.sourceUrl
183+
?: game.repoOwner?.let { owner -> game.repoName?.let { repo -> "https://github.com/$owner/$repo" } }
184+
if (url != null) try { uriHandler.openUri(url) } catch (_: Exception) {}
185+
}
176186
)
177187
}
178188
}
@@ -240,12 +250,14 @@ private fun GameRow(
240250

241251
GameActionButton(
242252
small = true,
253+
game = game,
243254
installState = installState,
244255
installed = installed,
245256
translations = t,
246257
onDownload = { },
247258
onInstall = { },
248259
onOpen = { },
260+
onOpenRepo = { },
249261
disabled = true
250262
)
251263
}
@@ -254,19 +266,41 @@ private fun GameRow(
254266
@Composable
255267
private fun GameActionButton(
256268
small: Boolean,
269+
game: CommunityGame,
257270
installState: MainViewModel.ApkUpdateState?,
258271
installed: Boolean,
259272
translations: Translations,
260273
onDownload: () -> Unit,
261274
onInstall: () -> Unit,
262275
onOpen: () -> Unit,
276+
onOpenRepo: () -> Unit,
263277
disabled: Boolean = false
264278
) {
265279
val theme = LocalAppTheme.current
266280
val t = translations
267281
val height = if (small) 32.dp else 46.dp
268282
val fontSize = if (small) 10.sp else 12.sp
269283

284+
if (game.isSourceBuild) {
285+
// Source-only entries never claim to silently "compile" arbitrary code on the phone -
286+
// there's no Android toolchain for that on-device. Instead this opens the repository,
287+
// and the full build/clone commands are shown (copyable) in the detail dialog below.
288+
Button(
289+
onClick = onOpenRepo, enabled = !disabled,
290+
colors = ButtonDefaults.buttonColors(containerColor = Color.White.copy(alpha = 0.08f)),
291+
shape = RoundedCornerShape(10.dp),
292+
contentPadding = PaddingValues(horizontal = 12.dp),
293+
modifier = Modifier.height(height)
294+
) {
295+
Icon(Icons.Default.Code, null, tint = theme.textColor(), modifier = Modifier.size(if (small) 12.dp else 14.dp))
296+
if (!small) {
297+
Spacer(Modifier.width(6.dp))
298+
Text(t.games_source_build_title, fontWeight = FontWeight.Bold, fontSize = fontSize, color = theme.textColor())
299+
}
300+
}
301+
return
302+
}
303+
270304
when {
271305
installState is MainViewModel.ApkUpdateState.Downloading -> {
272306
Box(
@@ -330,7 +364,8 @@ private fun GameDetailDialog(
330364
onDismiss: () -> Unit,
331365
onDownload: () -> Unit,
332366
onInstall: () -> Unit,
333-
onOpen: () -> Unit
367+
onOpen: () -> Unit,
368+
onOpenRepo: () -> Unit
334369
) {
335370
val theme = LocalAppTheme.current
336371
val t = translations
@@ -405,14 +440,20 @@ private fun GameDetailDialog(
405440
Box(modifier = Modifier.fillMaxWidth()) {
406441
GameActionButton(
407442
small = false,
443+
game = game,
408444
installState = installState,
409445
installed = installed,
410446
translations = t,
411447
onDownload = onDownload,
412448
onInstall = onInstall,
413-
onOpen = onOpen
449+
onOpen = onOpen,
450+
onOpenRepo = onOpenRepo
414451
)
415452
}
453+
if (game.isSourceBuild) {
454+
Spacer(Modifier.height(14.dp))
455+
SourceBuildCard(game = game, translations = t)
456+
}
416457
if (installState is MainViewModel.ApkUpdateState.ReadyToInstall && !installState.verified) {
417458
Spacer(Modifier.height(8.dp))
418459
Text("" + t.update_unverified, fontSize = 9.sp, color = Color(0xFFF59E0B))
@@ -426,6 +467,77 @@ private fun GameDetailDialog(
426467
}
427468
}
428469

470+
@Composable
471+
private fun SourceBuildCard(game: CommunityGame, translations: Translations) {
472+
val theme = LocalAppTheme.current
473+
val t = translations
474+
val context = androidx.compose.ui.platform.LocalContext.current
475+
476+
Column(
477+
modifier = Modifier
478+
.fillMaxWidth()
479+
.clip(RoundedCornerShape(12.dp))
480+
.background(theme.backgroundColor())
481+
.border(1.dp, Color.White.copy(alpha = 0.06f), RoundedCornerShape(12.dp))
482+
.padding(14.dp)
483+
) {
484+
Row(verticalAlignment = Alignment.CenterVertically) {
485+
Icon(Icons.Default.Code, null, tint = theme.primaryColor(), modifier = Modifier.size(14.dp))
486+
Spacer(Modifier.width(6.dp))
487+
Text(t.games_source_build_title, fontWeight = FontWeight.Bold, fontSize = 12.sp, color = theme.textColor())
488+
}
489+
Spacer(Modifier.height(6.dp))
490+
Text(t.games_source_build_desc, fontSize = 11.sp, color = theme.mutedColor(), lineHeight = 15.sp)
491+
492+
if (game.repoOwner != null && game.repoName != null) {
493+
Spacer(Modifier.height(8.dp))
494+
Text(
495+
"${game.repoOwner}/${game.repoName} (${game.repoBranch})",
496+
fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = theme.primaryColor()
497+
)
498+
}
499+
500+
val commands = game.buildCommands.ifEmpty {
501+
if (game.repoOwner != null && game.repoName != null) listOf(
502+
"git clone --branch ${game.repoBranch} https://github.com/${game.repoOwner}/${game.repoName}.git",
503+
"cd ${game.repoName}"
504+
) else emptyList()
505+
}
506+
507+
if (commands.isNotEmpty()) {
508+
Spacer(Modifier.height(10.dp))
509+
Column(
510+
modifier = Modifier
511+
.fillMaxWidth()
512+
.clip(RoundedCornerShape(8.dp))
513+
.background(Color.Black.copy(alpha = 0.35f))
514+
.padding(10.dp)
515+
) {
516+
commands.forEach { cmd ->
517+
Text(cmd, fontFamily = FontFamily.Monospace, fontSize = 10.sp, color = theme.textColor(),
518+
modifier = Modifier.padding(vertical = 1.dp))
519+
}
520+
}
521+
Spacer(Modifier.height(8.dp))
522+
Row(
523+
modifier = Modifier
524+
.clip(RoundedCornerShape(8.dp))
525+
.clickable {
526+
val cm = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
527+
cm.setPrimaryClip(ClipData.newPlainText("build-commands", commands.joinToString("\n")))
528+
Toast.makeText(context, t.toast_copied, Toast.LENGTH_SHORT).show()
529+
}
530+
.padding(vertical = 4.dp, horizontal = 2.dp),
531+
verticalAlignment = Alignment.CenterVertically,
532+
horizontalArrangement = Arrangement.spacedBy(6.dp)
533+
) {
534+
Icon(Icons.Default.ContentCopy, null, tint = theme.primaryColor(), modifier = Modifier.size(12.dp))
535+
Text(t.games_source_copy_commands, fontSize = 11.sp, color = theme.primaryColor())
536+
}
537+
}
538+
}
539+
}
540+
429541
@Composable
430542
private fun MetaLabel(label: String, value: String, mutedColor: Color, textColor: Color) {
431543
Column {

0 commit comments

Comments
 (0)