From 88e9134306027c8690197abf9a3b7c7cd469249e Mon Sep 17 00:00:00 2001 From: Prospector <6166773+Prospector@users.noreply.github.com> Date: Fri, 14 Aug 2026 10:46:06 -0700 Subject: [PATCH] Revert "feat: sync individual content installation states on panel (#6909)" This reverts commit 9628b4c26962dc861b3befad3dda57ed1c6fb7d3. --- .../providers/setup/server-install-content.ts | 92 +++- .../composables/use-server-install-content.ts | 91 +++- .../api-client/src/core/abstract-websocket.ts | 27 +- .../api-client/src/modules/archon/types.ts | 136 ----- .../src/platform/websocket-generic.ts | 38 +- .../components/servers/InstallingBanner.vue | 303 ++++++----- .../components/servers/ServerSetupModal.vue | 19 - .../admonitions/ServerPanelAdmonitions.vue | 69 ++- .../server-header/use-server-power-action.ts | 14 +- packages/ui/src/composables/index.ts | 2 - .../src/composables/server-context-runtime.ts | 350 ------------ .../server-installation-tracker.ts | 342 ------------ .../composables/server-manage-core-runtime.ts | 114 ++-- .../ui/src/composables/server-panel-sync.ts | 133 +---- .../browse-tab/composables/install-logic.ts | 8 + .../components/ContentCardItem.vue | 22 +- .../components/ContentCardTable.vue | 20 +- .../src/layouts/shared/content-tab/layout.vue | 1 - .../src/layouts/shared/content-tab/types.ts | 2 - .../composables/use-installation-form.ts | 14 +- .../providers/installation-settings.ts | 1 - .../server-settings/pages/installation.vue | 277 +++------- .../wrapped/hosting/manage/content.vue | 416 +++++++++++---- .../layouts/wrapped/hosting/manage/root.vue | 505 +++++++++++++----- packages/ui/src/locales/cs-CZ/index.json | 27 + packages/ui/src/locales/da-DK/index.json | 3 + packages/ui/src/locales/de-CH/index.json | 42 ++ packages/ui/src/locales/de-DE/index.json | 42 ++ packages/ui/src/locales/en-US/index.json | 70 +-- packages/ui/src/locales/es-419/index.json | 42 ++ packages/ui/src/locales/es-ES/index.json | 42 ++ packages/ui/src/locales/fr-FR/index.json | 42 ++ packages/ui/src/locales/hu-HU/index.json | 30 ++ packages/ui/src/locales/it-IT/index.json | 42 ++ packages/ui/src/locales/ja-JP/index.json | 42 ++ packages/ui/src/locales/ko-KR/index.json | 42 ++ packages/ui/src/locales/ms-MY/index.json | 39 ++ packages/ui/src/locales/nl-NL/index.json | 42 ++ packages/ui/src/locales/pl-PL/index.json | 42 ++ packages/ui/src/locales/pt-BR/index.json | 42 ++ packages/ui/src/locales/ru-RU/index.json | 42 ++ packages/ui/src/locales/sr-CS/index.json | 42 ++ packages/ui/src/locales/sv-SE/index.json | 30 ++ packages/ui/src/locales/tr-TR/index.json | 42 ++ packages/ui/src/locales/uk-UA/index.json | 42 ++ packages/ui/src/locales/vi-VN/index.json | 42 ++ packages/ui/src/locales/zh-CN/index.json | 42 ++ packages/ui/src/locales/zh-TW/index.json | 42 ++ packages/ui/src/providers/server-context.ts | 12 +- .../stories/servers/EditServerIcon.stories.ts | 6 +- .../servers/InstallingBanner.stories.ts | 250 +++------ .../servers/ServerPanelAdmonitions.stories.ts | 6 +- packages/ui/src/utils/index.ts | 1 + .../ui/src/utils/server-content-installing.ts | 203 +++++++ 54 files changed, 2426 insertions(+), 2003 deletions(-) delete mode 100644 packages/ui/src/composables/server-context-runtime.ts delete mode 100644 packages/ui/src/composables/server-installation-tracker.ts create mode 100644 packages/ui/src/utils/server-content-installing.ts diff --git a/apps/app-frontend/src/providers/setup/server-install-content.ts b/apps/app-frontend/src/providers/setup/server-install-content.ts index 225ff1f986..c0a8ccf427 100644 --- a/apps/app-frontend/src/providers/setup/server-install-content.ts +++ b/apps/app-frontend/src/providers/setup/server-install-content.ts @@ -1,5 +1,6 @@ import type { Archon, Labrinth } from '@modrinth/api-client' import { + addPendingServerContentInstalls, type BrowseInstallPlan, type BrowseSelectedProject, createContext, @@ -11,11 +12,12 @@ import { injectModrinthClient, injectNotificationManager, type ModpackSearchResult, + type PendingServerContentInstall, + type PendingServerContentInstallType, readStoredServerInstallQueue, + removePendingServerContentInstall, resolveServerAddonInstallPlans, - useServerContextRuntime, - useServerPanelSync, - waitForServerContextRuntimeReady, + writePendingServerContentInstallBaseline, writeStoredServerInstallQueue, } from '@modrinth/ui' import { useQueryClient } from '@tanstack/vue-query' @@ -28,6 +30,7 @@ type InstallableSearchResult = Labrinth.Search.v3.ResultSearchProject & { installing?: boolean installed?: boolean } +type PendingServerContentInstallInput = Omit export interface ServerModpackSelectionRequest { projectId: string @@ -93,6 +96,61 @@ function readQueryString(value: unknown): string | null { return typeof value === 'string' && value.length > 0 ? value : null } +function getQueuedInstallOwnerFallback(project: InstallableSearchResult) { + if (project.organization) { + const ownerId = project.organization_id ?? project.organization + return { + id: ownerId, + name: project.organization, + type: 'organization' as const, + link: `https://modrinth.com/organization/${ownerId}`, + } + } + + if (!project.author) return null + + const ownerId = project.author_id ?? project.author + return { + id: ownerId, + name: project.author, + type: 'user' as const, + link: `/user/${encodeURIComponent(ownerId)}`, + } +} + +function getQueuedAddonInstallPlans( + plans: Map>, +) { + return Array.from(plans.values()).filter((plan) => plan.contentType !== 'modpack') +} + +function getQueuedInstallPlaceholder( + plan: BrowseInstallPlan, + owner: PendingServerContentInstallInput['owner'], +): PendingServerContentInstallInput { + const project = plan.project as InstallableSearchResult & { slug?: string | null } + return { + projectId: plan.projectId, + versionId: plan.versionId, + contentType: plan.contentType as PendingServerContentInstallType, + title: project.name ?? 'Project', + versionName: plan.versionName ?? null, + versionNumber: plan.versionNumber ?? null, + fileName: plan.fileName ?? null, + owner, + slug: project.slug ?? plan.projectId, + iconUrl: project.icon_url ?? null, + } +} + +function getQueuedInstallPlaceholderFallbacks( + plans: Map>, +) { + return getQueuedAddonInstallPlans(plans).map((plan) => + getQueuedInstallPlaceholder(plan, getQueuedInstallOwnerFallback(plan.project)), + ) +} + export function createServerInstallContent(opts: { serverSetupModalRef: Ref }) { @@ -115,7 +173,6 @@ export function createServerInstallContent(opts: { const isFromWorlds = computed(() => browseFrom.value === 'worlds') const isServerContext = computed(() => !!serverIdQuery.value) const isSetupServerContext = computed(() => !!serverIdQuery.value && !!serverFlowFrom.value) - useServerContextRuntime(serverIdQuery) const serverContextWorldId = ref(worldIdQuery.value) @@ -142,6 +199,7 @@ export function createServerInstallContent(opts: { initialServerId ? getCachedServer(initialServerId) : null, ) const serverContentProjectIds = ref>(new Set()) + const serverContentInstallKeys = ref>(new Set()) const queuedServerInstalls = ref>>( new Map(), ) @@ -162,10 +220,6 @@ export function createServerInstallContent(opts: { const isInstallingQueuedServerInstalls = ref(false) const queuedInstallProgress = ref({ completed: 0, total: 0 }) const effectiveServerWorldId = computed(() => worldIdQuery.value ?? serverContextWorldId.value) - useServerPanelSync({ - serverId: serverIdQuery, - worldId: effectiveServerWorldId, - }) const serverBackUrl = computed(() => { const sid = serverIdQuery.value if (!sid) return '/hosting/manage' @@ -211,7 +265,11 @@ export function createServerInstallContent(opts: { .map((addon) => addon.project_id) .filter((projectId): projectId is string => !!projectId), ) + const keys = new Set( + (content.addons ?? []).map((addon) => addon.project_id ?? addon.filename), + ) serverContentProjectIds.value = ids + serverContentInstallKeys.value = keys } catch (err) { handleError(err as Error) } @@ -253,12 +311,14 @@ export function createServerInstallContent(opts: { serverContextWorldId.value = null serverContextServerData.value = null serverContentProjectIds.value = new Set() + serverContentInstallKeys.value = new Set() setQueuedServerInstallPlans(new Map()) return } if (sid !== prevSid) { serverContentProjectIds.value = new Set() + serverContentInstallKeys.value = new Set() queuedServerInstalls.value = readStoredServerInstallQueue(sid, wid) serverContextServerData.value = getCachedServer(sid) try { @@ -427,13 +487,6 @@ export function createServerInstallContent(opts: { const queuedPlans = getStoredServerAddonInstallQueue(serverId, worldId) if (queuedPlans.size === 0) return true - try { - await waitForServerContextRuntimeReady(client, serverId) - } catch (error) { - handleError(error as Error) - return false - } - isInstallingQueuedServerInstalls.value = true queuedInstallProgress.value = { completed: 0, @@ -454,6 +507,9 @@ export function createServerInstallContent(opts: { }) if (!result.ok) { + for (const plan of result.attemptedPlans) { + removePendingServerContentInstall(serverId, worldId, plan.projectId) + } handleError(result.error as Error) return false } @@ -466,6 +522,10 @@ export function createServerInstallContent(opts: { ...serverContentProjectIds.value, ...result.flushedPlans.map((plan) => plan.projectId), ]) + serverContentInstallKeys.value = new Set([ + ...serverContentInstallKeys.value, + ...result.flushedPlans.map((plan) => plan.projectId), + ]) if (result.flushedPlans.length > 0) { await queryClient.invalidateQueries({ queryKey: ['content', 'list', 'v1', serverId] }) } @@ -490,6 +550,8 @@ export function createServerInstallContent(opts: { if (sid && wid) { writeStoredServerInstallQueue(sid, wid, plans) + writePendingServerContentInstallBaseline(sid, wid, serverContentInstallKeys.value) + addPendingServerContentInstalls(sid, wid, getQueuedInstallPlaceholderFallbacks(plans)) } const installed = await flushQueuedServerInstalls(sid, wid) if (!installed) return false diff --git a/apps/frontend/src/composables/use-server-install-content.ts b/apps/frontend/src/composables/use-server-install-content.ts index c60cc6929c..ca08cc7221 100644 --- a/apps/frontend/src/composables/use-server-install-content.ts +++ b/apps/frontend/src/composables/use-server-install-content.ts @@ -6,8 +6,11 @@ import type { CreationFlowContextValue, EnvironmentSearchOverride, FilterValue, + PendingServerContentInstall, + PendingServerContentInstallType, } from '@modrinth/ui' import { + addPendingServerContentInstalls, commonMessages, defineMessages, flushStoredServerAddonInstallQueue, @@ -17,14 +20,13 @@ import { injectModrinthClient, injectNotificationManager, readStoredServerInstallQueue, + removePendingServerContentInstall, requestInstall, resolveServerAddonInstallPlans, stripServerRuntimeInstallFilters, stripServerRuntimeInstallOverrides, - useServerContextRuntime, - useServerPanelSync, useVIntl, - waitForServerContextRuntimeReady, + writePendingServerContentInstallBaseline, writeStoredServerInstallQueue, } from '@modrinth/ui' import { useQuery, useQueryClient } from '@tanstack/vue-query' @@ -34,6 +36,7 @@ import { computed, nextTick, ref, watch } from 'vue' import { navigateTo, useRoute } from '#app' import { queryAsString } from '~/utils/router' +type PendingServerContentInstallInput = Omit type ServerInstallBrowseSearchState = Pick< BrowseSearchState, 'currentFilters' | 'overriddenProvidedFilterTypes' @@ -86,6 +89,34 @@ const messages = defineMessages({ }, }) +function getQueuedInstallOwnerFallback(project: ServerInstallSearchResult) { + if (project.organization) { + const ownerId = project.organization_id ?? project.organization + return { + id: ownerId, + name: project.organization, + type: 'organization' as const, + link: `/organization/${ownerId}`, + } + } + + if (!project.author) return null + + const ownerId = project.author_id ?? project.author + return { + id: ownerId, + name: project.author, + type: 'user' as const, + link: `/user/${ownerId}`, + } +} + +function getQueuedAddonInstallPlans( + plans: Map>, +) { + return Array.from(plans.values()).filter((plan) => plan.contentType !== 'modpack') +} + export function useServerInstallContent({ projectType, onboardingModalRef, @@ -106,11 +137,6 @@ export function useServerInstallContent({ const currentServerId = computed(() => queryAsString(route.query.sid) || null) const fromContext = computed(() => queryAsString(route.query.from) || null) const currentWorldId = computed(() => queryAsString(route.query.wid) || null) - useServerContextRuntime(currentServerId) - useServerPanelSync({ - serverId: currentServerId, - worldId: currentWorldId, - }) const { data: serverData, @@ -199,6 +225,32 @@ export function useServerInstallContent({ writeStoredServerInstallQueue(serverId, worldId, plans) } + function getQueuedInstallPlaceholder( + plan: BrowseInstallPlan, + owner: PendingServerContentInstallInput['owner'], + ): PendingServerContentInstallInput { + return { + projectId: plan.projectId, + versionId: plan.versionId, + contentType: plan.contentType as PendingServerContentInstallType, + title: getInstallProjectName(plan.project), + versionName: plan.versionName ?? null, + versionNumber: plan.versionNumber ?? null, + fileName: plan.fileName ?? null, + owner, + slug: plan.project.slug ?? plan.projectId, + iconUrl: plan.project.icon_url ?? null, + } + } + + function getQueuedInstallPlaceholderFallbacks( + plans: Map>, + ) { + return getQueuedAddonInstallPlans(plans).map((plan) => + getQueuedInstallPlaceholder(plan, getQueuedInstallOwnerFallback(plan.project)), + ) + } + function setProjectInstalling(projectId: string, installing: boolean) { const next = new Set(installingProjectIds.value) if (installing) { @@ -224,6 +276,10 @@ export function useServerInstallContent({ ) } + function getServerInstalledContentKeys(data = serverContentData.value) { + return new Set((data?.addons ?? []).map((addon) => addon.project_id ?? addon.filename)) + } + function syncHiddenInstalledProjectIds() { hiddenInstalledProjectIds.value = new Set([ ...getServerInstalledProjectIds(), @@ -410,13 +466,6 @@ export function useServerInstallContent({ ) if (queuedPlans.size === 0) return true - try { - await waitForServerContextRuntimeReady(client, serverId) - } catch (error) { - handleError(error as Error) - return false - } - isInstallingQueuedServerInstalls.value = true queuedInstallProgress.value = { completed: 0, @@ -437,6 +486,9 @@ export function useServerInstallContent({ }) if (!result.ok) { + for (const plan of result.attemptedPlans) { + removePendingServerContentInstall(serverId, worldId, plan.projectId) + } handleError(result.error as Error) return false } @@ -449,7 +501,9 @@ export function useServerInstallContent({ total: result.flushedPlans.length, } if (result.flushedPlans.length > 0) { - await queryClient.invalidateQueries({ queryKey: ['content', 'list'] }) + await queryClient.invalidateQueries({ + queryKey: ['content', 'list', 'v1', serverId], + }) } return true @@ -472,6 +526,11 @@ export function useServerInstallContent({ if (sid && wid) { writeStoredServerInstallQueue(sid, wid, plans) + writePendingServerContentInstallBaseline(sid, wid, [ + ...getServerInstalledContentKeys(), + ...optimisticallyInstalledProjectIds.value, + ]) + addPendingServerContentInstalls(sid, wid, getQueuedInstallPlaceholderFallbacks(plans)) } const installed = await flushQueuedServerInstalls(sid, wid) if (!installed) return false diff --git a/packages/api-client/src/core/abstract-websocket.ts b/packages/api-client/src/core/abstract-websocket.ts index 784bf50a40..8d3e54ee29 100644 --- a/packages/api-client/src/core/abstract-websocket.ts +++ b/packages/api-client/src/core/abstract-websocket.ts @@ -9,7 +9,6 @@ export type WebSocketEventHandler< export interface WebSocketConnection { serverId: string socket: WebSocket - authenticated: boolean reconnectAttempts: number reconnectTimer?: ReturnType isReconnecting: boolean @@ -32,7 +31,6 @@ export abstract class AbstractWebSocketClient { protected readonly MAX_RECONNECT_ATTEMPTS = 10 protected readonly RECONNECT_BASE_DELAY = 1000 protected readonly RECONNECT_MAX_DELAY = 30000 - protected readonly AUTHENTICATION_TIMEOUT = 30000 constructor( protected client: { @@ -60,7 +58,6 @@ export abstract class AbstractWebSocketClient { } if (status && !status.connected && !options?.force) { - await this.waitForAuthentication(serverId) return } @@ -72,28 +69,6 @@ export abstract class AbstractWebSocketClient { await this.connect(serverId, auth) } - protected async waitForAuthentication(serverId: string): Promise { - await new Promise((resolve, reject) => { - let unsubscribe = () => {} - const timeout = setTimeout(() => { - unsubscribe() - reject(new Error(`WebSocket authentication timed out for server ${serverId}`)) - }, this.AUTHENTICATION_TIMEOUT) - - unsubscribe = this.on(serverId, 'auth-ok', () => { - clearTimeout(timeout) - unsubscribe() - resolve() - }) - - if (this.getStatus(serverId)?.connected) { - clearTimeout(timeout) - unsubscribe() - resolve() - } - }) - } - on( serverId: string, eventType: E, @@ -113,7 +88,7 @@ export abstract class AbstractWebSocketClient { if (!connection) return null return { - connected: connection.socket.readyState === WebSocket.OPEN && connection.authenticated, + connected: connection.socket.readyState === WebSocket.OPEN, reconnecting: connection.isReconnecting, reconnectAttempts: connection.reconnectAttempts, } diff --git a/packages/api-client/src/modules/archon/types.ts b/packages/api-client/src/modules/archon/types.ts index 56df291622..7add0d5a84 100644 --- a/packages/api-client/src/modules/archon/types.ts +++ b/packages/api-client/src/modules/archon/types.ts @@ -301,24 +301,13 @@ export namespace Archon { environment?: Labrinth.Projects.v3.Environment | null } - export type AddonStatus = - | 'pending' - | 'installed' - | { - failed: { - error: string - } - } - export type Addon = { id: string filename: string filesize: number - btime?: string disabled: boolean kind: AddonKind from_modpack: boolean - status: AddonStatus pack_client_retained: boolean pack_client_depends: boolean has_update: string | null @@ -334,10 +323,6 @@ export namespace Archon { modloader_version: string | null game_version: string | null modpack: ModpackFields | null - installing?: 'loader' | 'modpack' - error?: { - message: string - } addons: Addon[] | null } @@ -1004,78 +989,6 @@ export namespace Archon { world_id: string spec: Archon.Content.v1.Addons } - export type WorldContentPlatform = - | 'forge' - | 'neoforge' - | 'fabric' - | 'quilt' - | 'paper' - | 'purpur' - | 'vanilla' - export type WorldContentPlatformData = { - platform: WorldContentPlatform - game_version: string - platform_version: string | null - } - export type WorldContentModpackSource = - | 'CurseForge' - | { - Modrinth: { - version_id: string - project_id: string - mrpack_sha1: string | null - } - } - | { - LocalMrPackFile: { - path: string - name: string - description: string | null - version_name: string | null - } - } - export type WorldContentModpack = { - spec: WorldContentModpackSource - downloads: number | null - followers: number | null - icon_url: string | null - owner: Archon.Content.v1.ContentOwner | null - title: string | null - description: string | null - version_number: string | null - date_published: string | null - environment: Labrinth.Projects.v3.Environment | null - has_update: string | null - } - export type WorldContentItem = { - parent_directory: string - file_sha1: string | null - filename: string - btime?: string - from_modpack: boolean - version_id: string | null - project_id: string | null - pack_client_retained: boolean - pack_client_depends: boolean - status: Archon.Content.v1.AddonStatus - filesize: number | null - name: string | null - version: Archon.Content.v1.AddonVersion | null - owner: Archon.Content.v1.ContentOwner | null - has_update: string | null - icon_url: string | null - } - export type WorldContentUpdateEvent = { - type: 'world.content.update' - world_id: string - platform_data: WorldContentPlatformData | null - linked_modpack: WorldContentModpack | null - installing?: 'loader' | 'modpack' - error?: { - message: string - } - content: WorldContentItem[] - } export type SyncEvent = | ProtocolResetEvent @@ -1094,7 +1007,6 @@ export namespace Archon { | WorldStartupPatchEvent | WorldContentAddonPatchEvent | WorldContentBaseUpdateEvent - | WorldContentUpdateEvent } } @@ -1199,53 +1111,6 @@ export namespace Archon { version_id: string } - export type InstallProgressFileKey = { - type: 'file' - install_type: 'install' | 'update' - project_id: string - version_id: string - parent_directory: string - source_filename: string | null - target_filename?: string | null - } - - export type InstallProgressModrinthModpackKey = { - type: 'modrinth_modpack' - project_id: string - version_id: string - } - - export type InstallProgressLocalModpackKey = { - type: 'local_modpack' - filename: string - } - - export type InstallProgressPlatformKey = { - type: 'platform' - platform: 'forge' | 'neoforge' | 'fabric' | 'quilt' | 'paper' | 'purpur' | 'vanilla' - platform_version: string - game_version: string - } - - export type InstallProgressKey = - | InstallProgressFileKey - | InstallProgressModrinthModpackKey - | InstallProgressLocalModpackKey - | InstallProgressPlatformKey - - export type InstallProgressItem = { - world_id: string - key: InstallProgressKey - id: string - progress: number | null - error: string | null - } - - export type WSInstallProgressEvent = { - event: 'install-progress' - items: InstallProgressItem[] - } - export type FilesystemOpKind = 'unarchive' export type FilesystemOpState = @@ -1343,7 +1208,6 @@ export namespace Archon { | WSInstallationResultEvent | WSUptimeEvent | WSNewModEvent - | WSInstallProgressEvent | WSFilesystemOpsEvent export type WSEventType = WSEvent['event'] diff --git a/packages/api-client/src/platform/websocket-generic.ts b/packages/api-client/src/platform/websocket-generic.ts index 16c7f4ef4a..19aa098f45 100644 --- a/packages/api-client/src/platform/websocket-generic.ts +++ b/packages/api-client/src/platform/websocket-generic.ts @@ -19,60 +19,36 @@ export class GenericWebSocketClient extends AbstractWebSocketClient { } return new Promise((resolve, reject) => { - let settled = false - let authenticationTimeout: ReturnType | null = null - const resolveConnection = () => { - if (settled) return - settled = true - if (authenticationTimeout) clearTimeout(authenticationTimeout) - resolve() - } - const rejectConnection = (error: unknown) => { - if (settled) return - settled = true - if (authenticationTimeout) clearTimeout(authenticationTimeout) - reject(error) - } try { const ws = new WebSocket(getNodeWebSocketUrl(auth.url)) const connection: WebSocketConnection = { serverId, socket: ws, - authenticated: false, reconnectAttempts: 0, reconnectTimer: undefined, isReconnecting: false, } this.connections.set(serverId, connection) - authenticationTimeout = setTimeout(() => { - rejectConnection(new Error(`WebSocket authentication timed out for server ${serverId}`)) - if (this.connections.get(serverId) === connection) this.closeConnection(serverId) - }, this.AUTHENTICATION_TIMEOUT) ws.onopen = () => { ws.send(JSON.stringify({ event: 'auth', jwt: auth.token })) connection.reconnectAttempts = 0 connection.isReconnecting = false + + resolve() } ws.onmessage = (messageEvent) => { try { const data = JSON.parse(messageEvent.data) as Archon.Websocket.v0.WSEvent - if (data.event === 'auth-ok') { - connection.authenticated = true - } else if (data.event === 'auth-incorrect') { - connection.authenticated = false - } const eventKey = `${serverId}:${data.event}` as keyof WSEventMap // eslint-disable-next-line @typescript-eslint/no-explicit-any this.emitter.emit(eventKey, data as any) - if (data.event === 'auth-ok') resolveConnection() - if (data.event === 'auth-expiring' || data.event === 'auth-incorrect') { this.handleAuthExpiring(serverId).catch(console.error) } @@ -82,17 +58,11 @@ export class GenericWebSocketClient extends AbstractWebSocketClient { } ws.onclose = (event) => { - connection.authenticated = false console.debug(`[WebSocket] Closed for server ${serverId}:`, { code: event.code, reason: event.reason, wasClean: event.wasClean, }) - rejectConnection( - new Error( - `WebSocket closed before authentication for server ${serverId} (code: ${event.code})`, - ), - ) if (event.code !== NORMAL_CLOSURE) { this.scheduleReconnect(serverId, auth) } @@ -107,14 +77,14 @@ export class GenericWebSocketClient extends AbstractWebSocketClient { readyStateLabel: ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'][readyState], type: (event as Event).type, }) - rejectConnection( + reject( new Error( `WebSocket connection failed for server ${serverId} (readyState: ${readyState})`, ), ) } } catch (error) { - rejectConnection(error) + reject(error) } }) } diff --git a/packages/ui/src/components/servers/InstallingBanner.vue b/packages/ui/src/components/servers/InstallingBanner.vue index b857f63d16..60eb456b61 100644 --- a/packages/ui/src/components/servers/InstallingBanner.vue +++ b/packages/ui/src/components/servers/InstallingBanner.vue @@ -1,8 +1,7 @@ - {{ installation.status === 'failed' ? errorLabel : descriptionLabel }} -