From dac5a5dcad3e687aec30d9bdbe8e757caa24e58f Mon Sep 17 00:00:00 2001 From: Prospector <6166773+Prospector@users.noreply.github.com> Date: Wed, 29 Jul 2026 14:19:59 -0700 Subject: [PATCH 1/2] fix race condition with server ping lookup before protocol resolved --- apps/app-frontend/src/helpers/worlds.ts | 5 +++++ apps/app-frontend/src/pages/instance/Worlds.vue | 17 ++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/apps/app-frontend/src/helpers/worlds.ts b/apps/app-frontend/src/helpers/worlds.ts index 3b5285f51b..8455e59811 100644 --- a/apps/app-frontend/src/helpers/worlds.ts +++ b/apps/app-frontend/src/helpers/worlds.ts @@ -439,6 +439,7 @@ export function refreshServers( worlds: World[], serverData: Record, protocolVersion: ProtocolVersion | null, + ping = true, ) { const servers = worlds.filter(isServerWorld) servers.forEach((server) => { @@ -451,6 +452,10 @@ export function refreshServers( } }) + if (!ping) { + return + } + // noinspection ES6MissingAwait - handled by refreshServerData Object.keys(serverData).forEach((address) => refreshServerData(serverData[address], protocolVersion, address), diff --git a/apps/app-frontend/src/pages/instance/Worlds.vue b/apps/app-frontend/src/pages/instance/Worlds.vue index 1ddcb5e943..b6348083c6 100644 --- a/apps/app-frontend/src/pages/instance/Worlds.vue +++ b/apps/app-frontend/src/pages/instance/Worlds.vue @@ -328,7 +328,7 @@ const isLinux = platform() === 'linux' const linuxRefreshCount = ref(0) const protocolVersion = ref(null) - +const protocolVersionReady = ref(false) const gameVersions = ref([]) const supportsServerQuickPlay = computed(() => hasServerQuickPlaySupport(gameVersions.value, instance.value.game_version), @@ -342,8 +342,13 @@ watch( (data) => { if (data) { worlds.value = [...data] - refreshServers(worlds.value, serverData.value, protocolVersion.value) hadNoWorlds.value = worlds.value.length === 0 + refreshServers( + worlds.value, + serverData.value, + protocolVersion.value, + protocolVersionReady.value, + ) } }, { immediate: true }, @@ -443,9 +448,14 @@ async function initWorldsTab() { unlistenInstance = _unlistenInstance protocolVersion.value = resolvedProtocolVersion gameVersions.value = resolvedGameVersions + protocolVersionReady.value = true + + if (worlds.value.length > 0) { + refreshServers(worlds.value, serverData.value, protocolVersion.value) + } } -await initWorldsTab() +void initWorldsTab() async function refreshServer(address: string) { if (!serverData.value[address]) { @@ -453,6 +463,7 @@ async function refreshServer(address: string) { refreshing: true, } } + if (!protocolVersionReady.value) return await refreshServerData(serverData.value[address], protocolVersion.value, address) } From 5fbec7c0656e9b5c90aa2500b05c2bf81a8c4872 Mon Sep 17 00:00:00 2001 From: Prospector <6166773+Prospector@users.noreply.github.com> Date: Wed, 29 Jul 2026 14:24:22 -0700 Subject: [PATCH 2/2] fix refresh button on worlds page --- apps/app-frontend/src/helpers/worlds.ts | 11 +++-- .../app-frontend/src/locales/en-US/index.json | 3 ++ .../src/pages/instance/Worlds.vue | 49 +++++++++++++++---- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/apps/app-frontend/src/helpers/worlds.ts b/apps/app-frontend/src/helpers/worlds.ts index 8455e59811..5eb3385497 100644 --- a/apps/app-frontend/src/helpers/worlds.ts +++ b/apps/app-frontend/src/helpers/worlds.ts @@ -435,12 +435,12 @@ export async function refreshServerData( } } -export function refreshServers( +export async function refreshServers( worlds: World[], serverData: Record, protocolVersion: ProtocolVersion | null, ping = true, -) { +): Promise { const servers = worlds.filter(isServerWorld) servers.forEach((server) => { if (!serverData[server.address]) { @@ -456,9 +456,10 @@ export function refreshServers( return } - // noinspection ES6MissingAwait - handled by refreshServerData - Object.keys(serverData).forEach((address) => - refreshServerData(serverData[address], protocolVersion, address), + await Promise.all( + Object.keys(serverData).map((address) => + refreshServerData(serverData[address], protocolVersion, address), + ), ) } diff --git a/apps/app-frontend/src/locales/en-US/index.json b/apps/app-frontend/src/locales/en-US/index.json index 91ff2a64ff..475e1027ca 100644 --- a/apps/app-frontend/src/locales/en-US/index.json +++ b/apps/app-frontend/src/locales/en-US/index.json @@ -590,6 +590,9 @@ "app.instance.worlds.no-worlds-heading": { "message": "No servers or worlds added" }, + "app.instance.worlds.refreshing": { + "message": "Refreshing..." + }, "app.instance.worlds.remove-server-modal.remove-button": { "message": "Remove server" }, diff --git a/apps/app-frontend/src/pages/instance/Worlds.vue b/apps/app-frontend/src/pages/instance/Worlds.vue index b6348083c6..4a5bd6192d 100644 --- a/apps/app-frontend/src/pages/instance/Worlds.vue +++ b/apps/app-frontend/src/pages/instance/Worlds.vue @@ -75,7 +75,11 @@ @@ -242,6 +246,10 @@ const messages = defineMessages({ id: 'app.instance.worlds.filter-offline', defaultMessage: 'Offline', }, + refreshingButton: { + id: 'app.instance.worlds.refreshing', + defaultMessage: 'Refreshing...', + }, }) const { formatMessage } = useVIntl() @@ -343,12 +351,15 @@ watch( if (data) { worlds.value = [...data] hadNoWorlds.value = worlds.value.length === 0 - refreshServers( - worlds.value, - serverData.value, - protocolVersion.value, - protocolVersionReady.value, - ) + // Manual refresh handles its own server pings to avoid double-pinging + if (!refreshingAll.value) { + void refreshServers( + worlds.value, + serverData.value, + protocolVersion.value, + protocolVersionReady.value, + ) + } } }, { immediate: true }, @@ -474,8 +485,28 @@ async function refreshAllWorlds() { } refreshingAll.value = true - await queryClient.invalidateQueries({ queryKey: ['worlds', instance.value.id] }) - refreshingAll.value = false + try { + // Show loading on server rows immediately while the list refreshes + for (const world of worlds.value) { + if (world.type === 'server') { + if (!serverData.value[world.address]) { + serverData.value[world.address] = { refreshing: true } + } else { + serverData.value[world.address].refreshing = true + } + } + } + + await queryClient.invalidateQueries({ queryKey: ['worlds', instance.value.id] }) + await refreshServers( + worlds.value, + serverData.value, + protocolVersion.value, + protocolVersionReady.value, + ) + } finally { + refreshingAll.value = false + } } async function addServer(server: ServerWorld) {