summaryrefslogtreecommitdiff
path: root/Source/Android/app/src
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2026-10-22 13:12:33 -0400
committerGitHub <noreply@github.com>2026-10-22 13:12:33 -0400
commit2c805fee8f232d090c454381bb1b8422242345e1 (patch)
treeb564d1524b09695f3fda8730d3595f1f66a29beb /Source/Android/app/src
parentcf5cb7ef81c3e8e7af5c9d566334219ffda9f68b (diff)
parent66657167e357597b99b0957a4ee27a0da8b36571 (diff)
Merge pull request #14734 from tom-pratt/trigger-game-digest-check
Android: Trigger netplay game digest check
Diffstat (limited to 'Source/Android/app/src')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt26
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/GameDigestProgress.kt8
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt6
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayActivity.kt3
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt56
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt4
-rw-r--r--Source/Android/app/src/main/res/values/strings.xml3
7 files changed, 91 insertions, 15 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt
index d44e70ba09..8e6ac314ff 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt
@@ -186,6 +186,12 @@ class NetplaySession(
fun startGame() = nativeStartGame()
+ fun computeGameDigest() = nativeComputeGameDigest()
+
+ fun computeSDCardDigest() = nativeComputeSDCardDigest()
+
+ fun abortGameDigest() = nativeAbortGameDigest()
+
fun getPort(): Int = nativeGetPort()
fun getExternalIpAddress(): String? = nativeGetExternalIpAddress()
@@ -284,6 +290,12 @@ class NetplaySession(
private external fun nativeStartGame()
+ private external fun nativeComputeGameDigest()
+
+ private external fun nativeComputeSDCardDigest()
+
+ private external fun nativeAbortGameDigest()
+
private external fun nativeGetPort(): Int
private external fun nativeGetExternalIpAddress(): String?
@@ -410,7 +422,7 @@ class NetplaySession(
result = null,
)
} ?: emptyList(),
- matches = null,
+ finished = false,
)
}
@@ -427,18 +439,12 @@ class NetplaySession(
@Keep
fun onSetGameDigestResult(playerId: Int, result: String) {
val current = _gameDigestProgress.value ?: return
- val updated = current.copy(
+ _gameDigestProgress.value = current.copy(
playerProgresses = current.playerProgresses.map {
if (it.playerId == playerId) it.copy(result = result) else it
- }
+ },
+ finished = true,
)
- val finished = updated.playerProgresses.all { it.result != null }
- _gameDigestProgress.value = if (finished) {
- val results = updated.playerProgresses.map { it.result }
- updated.copy(matches = results.distinct().size == 1)
- } else {
- updated
- }
}
/**
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/GameDigestProgress.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/GameDigestProgress.kt
index 923f03068a..861a5b99d2 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/GameDigestProgress.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/GameDigestProgress.kt
@@ -5,8 +5,14 @@ package org.dolphinemu.dolphinemu.features.netplay.model
data class GameDigestProgress(
val title: String,
val playerProgresses: List<PlayerProgress>,
- val matches: Boolean?,
+ val finished: Boolean,
) {
+ val matches: Boolean?
+ get() {
+ val results = playerProgresses.mapNotNull { it.result }
+ return if (results.size >= 2) results.distinct().size == 1 else null
+ }
+
data class PlayerProgress(
val playerId: Int,
val name: String,
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt
index 1e3aea26a2..1dae14b6e2 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt
@@ -183,6 +183,12 @@ class NetplayViewModel(
controllerMapping.value.withWiiRemote(remoteNumber, player)
)
}
+
+ fun computeGameDigest() = netplaySession.computeGameDigest()
+
+ fun computeSDCardDigest() = netplaySession.computeSDCardDigest()
+
+ fun abortGameDigest() = netplaySession.abortGameDigest()
private fun getLocalIp(): JoinAddress {
val localIp = networkHelper.getLocalIpString()
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayActivity.kt
index ee1098956d..4916a6c7a1 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayActivity.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayActivity.kt
@@ -76,6 +76,9 @@ class NetplayActivity : AppCompatActivity(), ThemeProvider {
controllerMapping = viewModel.controllerMapping.collectAsState().value,
onGamecubePortChanged = viewModel::setGamecubePort,
onWiiRemoteChanged = viewModel::setWiiRemote,
+ onComputeGameDigest = viewModel::computeGameDigest,
+ onComputeSDCardDigest = viewModel::computeSDCardDigest,
+ onAbortGameDigest = viewModel::abortGameDigest,
)
}
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt
index aebac3f5bc..c3602facf4 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/ui/NetplayScreen.kt
@@ -42,11 +42,13 @@ import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Remove
+import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuAnchorType
@@ -153,6 +155,9 @@ fun NetplayScreen(
controllerMapping: ControllerMapping,
onGamecubePortChanged: (port: Int, player: Player?) -> Unit,
onWiiRemoteChanged: (port: Int, player: Player?) -> Unit,
+ onComputeGameDigest: () -> Unit,
+ onComputeSDCardDigest: () -> Unit,
+ onAbortGameDigest: () -> Unit,
) {
val scrollState = rememberScrollState()
@@ -168,6 +173,42 @@ fun NetplayScreen(
)
}
},
+ actions = {
+ if (isHosting) {
+ var menuExpanded by remember { mutableStateOf(false) }
+ IconButton(onClick = { menuExpanded = true }) {
+ Icon(
+ imageVector = Icons.Default.MoreVert,
+ contentDescription = "More options",
+ )
+ }
+ DropdownMenu(
+ expanded = menuExpanded,
+ onDismissRequest = { menuExpanded = false },
+ ) {
+ Text(
+ text = stringResource(R.string.netplay_checksum),
+ style = MaterialTheme.typography.labelSmall,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp),
+ )
+ DropdownMenuItem(
+ text = { Text(stringResource(R.string.netplay_checksum_current_game)) },
+ onClick = {
+ menuExpanded = false
+ onComputeGameDigest()
+ },
+ )
+ DropdownMenuItem(
+ text = { Text(stringResource(R.string.netplay_checksum_sd_card)) },
+ onClick = {
+ menuExpanded = false
+ onComputeSDCardDigest()
+ },
+ )
+ }
+ }
+ },
floatingActionButton = {
if (isHosting) {
ExtendedFloatingActionButton(onClick = onStartGame) {
@@ -327,7 +368,10 @@ fun NetplayScreen(
gameDigestProgress != null && !dismissGameDigestDialog -> {
GameDigestProgressDialog(
gameDigestProgress = gameDigestProgress,
- onDismiss = { dismissGameDigestDialog = true },
+ onDismiss = {
+ dismissGameDigestDialog = true
+ if (isHosting) onAbortGameDigest()
+ },
)
}
@@ -1472,11 +1516,12 @@ private fun GameDigestProgressDialog(
HorizontalDivider()
}
}
- if (gameDigestProgress.matches != null) {
+ val matches = gameDigestProgress.matches
+ if (matches != null) {
Spacer(modifier = Modifier.height(4.dp))
Text(
text = stringResource(
- if (gameDigestProgress.matches) {
+ if (matches) {
R.string.netplay_game_digest_match
} else {
R.string.netplay_game_digest_mismatch
@@ -1489,7 +1534,7 @@ private fun GameDigestProgressDialog(
}
},
confirmButton = {
- if (gameDigestProgress.matches != null) {
+ if (gameDigestProgress.finished) {
TextButton(onClick = onDismiss) {
Text(stringResource(R.string.netplay_game_digest_close))
}
@@ -1721,5 +1766,8 @@ private fun PreviewNetplayScreen() {
// ),
// ),
// ),
+ onAbortGameDigest = {},
+ onComputeGameDigest = {},
+ onComputeSDCardDigest = {},
)
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt
index e3ab05f3ab..f3d0ac1fce 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/theme/DolphinTheme.kt
@@ -13,6 +13,7 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -156,6 +157,7 @@ fun DolphinScaffold(
title: @Composable () -> Unit,
navigationIcon: @Composable () -> Unit,
modifier: Modifier = Modifier,
+ actions: @Composable RowScope.() -> Unit = {},
floatingActionButton: @Composable () -> Unit = {},
content: @Composable (PaddingValues) -> Unit,
) {
@@ -175,11 +177,13 @@ fun DolphinScaffold(
TopAppBar(
title = title,
navigationIcon = navigationIcon,
+ actions = actions,
)
} else {
MediumTopAppBar(
title = title,
navigationIcon = navigationIcon,
+ actions = actions,
scrollBehavior = topAppBarScrollBehavior,
)
}
diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml
index f8099fd652..69d8631e7e 100644
--- a/Source/Android/app/src/main/res/values/strings.xml
+++ b/Source/Android/app/src/main/res/values/strings.xml
@@ -1048,6 +1048,9 @@ It can efficiently compress both junk data and encrypted Wii data.
<string name="netplay_game_digest_match">The hashes match</string>
<string name="netplay_game_digest_mismatch">The hashes do not match</string>
<string name="netplay_game_digest_close">Close</string>
+ <string name="netplay_checksum">Checksum</string>
+ <string name="netplay_checksum_current_game">Current game</string>
+ <string name="netplay_checksum_sd_card">SD Card</string>
<string name="netplay_host_port_label">Port</string>
<string name="netplay_use_upnp">Forward port (UPnP)</string>
<string name="netplay_host_address_label">Join info</string>