Skip to content

Commit 0357227

Browse files
committed
Fixes loading states for mod installations
1 parent d8c70bf commit 0357227

File tree

4 files changed

+28
-11
lines changed

4 files changed

+28
-11
lines changed

apps/desktop/packages/mainWindow/src/components/ModDownloadButton/components/InstanceDropdown.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ export const InstanceDropdown = (props: InstanceDropdownProps) => {
5353
// This prevents the gap between "Installing" and "Installed"
5454
createEffect(() => {
5555
if (isDropdownOpen() && props.addon) {
56+
// Skip installation detection for worlds since they don't appear in mods list
57+
// and would cause infinite refetching
58+
if (props.addon.type === "world") {
59+
return
60+
}
61+
5662
props.filteredInstances().forEach((instance) => {
5763
const instanceQuery = getInstanceModsQuery(instance.id)
5864
const isLoading = props.instanceLoadingStates().get(instance.id)

apps/desktop/packages/mainWindow/src/components/ModDownloadButton/hooks/useTaskProgress.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { rspc } from "@/utils/rspcClient"
22
import { createSignal, createEffect, Accessor } from "solid-js"
3+
import { toast } from "@gd/ui"
34

45
export const useTaskProgress = (
56
instanceTaskIds: Accessor<Map<number, number>>,
6-
_clearInstanceLoadingState: (instanceId: number) => void
7+
clearInstanceLoadingState: (instanceId: number) => void,
8+
addon?: { title?: string; type?: string }
79
) => {
810
const [loading, setLoading] = createSignal(false)
911
const [progress, setProgress] = createSignal<number | null>(null)
@@ -18,11 +20,19 @@ export const useTaskProgress = (
1820
const allTasks = allTasksQuery.data || []
1921
const activeTaskIds = new Set(allTasks.map((task) => task.id))
2022

21-
taskIds.forEach((taskId, _instanceId) => {
23+
taskIds.forEach((taskId, instanceId) => {
2224
if (!activeTaskIds.has(taskId)) {
23-
// Don't clear loading state immediately - let the InstanceDropdown handle it
24-
// when it detects the mod is actually installed via the reactive effect
25-
// This prevents the gap between "Installing" and "Installed"
25+
// Clear loading state when task completes
26+
// For regular mods, InstanceDropdown will also handle this via installation detection
27+
// For worlds, this is the only way to clear loading state since they don't appear in mods list
28+
clearInstanceLoadingState(instanceId)
29+
30+
// Show success toast for dropdown installations
31+
if (addon) {
32+
toast.success(`${addon.title || "Addon"} installed successfully`, {
33+
duration: 2000
34+
})
35+
}
2636
}
2737
})
2838
})

apps/desktop/packages/mainWindow/src/components/ModDownloadButton/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ const ModDownloadButton = (props: ModDownloadButtonProps) => {
4242

4343
const { loading, setLoading, progress, setProgress } = useTaskProgress(
4444
instanceTaskIds,
45-
clearInstanceLoadingState
45+
clearInstanceLoadingState,
46+
props.addon
4647
)
4748

4849
createEffect(() => {
@@ -179,7 +180,7 @@ const ModDownloadButton = (props: ModDownloadButtonProps) => {
179180
// Track loading state changes
180181
setWasLoading(isCurrentlyLoading)
181182

182-
if (installed) {
183+
if (installed || (isWorld && taskId() === null)) {
183184
setLoading(false)
184185
setTaskId(null)
185186
setProgress(null)

packages/core_module/bindings.d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ export type FERequestNewVerificationTokenStatus = { status: "success" } | { stat
140140

141141
export type InstanceFolder = "Root" | "Data" | "Mods" | "Configs" | "Screenshots" | "Saves" | "Logs" | "CrashReports" | "ResourcePacks" | "TexturePacks" | "ShaderPacks"
142142

143+
export type FEUnifiedSearchResultWithDescription = ({ title: string; slug: string; description: string; imageUrl: string | null; highResImageUrl: string | null; downloadsCount: number; id: string; releaseDate: string; lastUpdated: string; platform: FEUnifiedPlatform; type: FEUnifiedSearchType; authors: FEUnifiedAuthor[]; websiteUrl: string | null; categories: FEUnifiedCategoryId[]; screenshotUrls: string[]; minecraftVersions: string[]; versions: string[] | null; mainFileId: string | null }) & { fullDescriptionBody: string }
144+
143145
export type CFFEModSearchParameters = { query: CFFEModSearchParametersQuery }
144146

145147
export type FEMetricsEvent = { event_name: "page_view"; data: string } | { event_name: "featured_modpack_installed"; data: { campaign_id: string; item_id: string } } | { event_name: "changelog_viewed" }
@@ -349,6 +351,8 @@ export type EnrollmentStatus = "refreshingMSAuth" | "requestingCode" | { polling
349351

350352
export type FESubtask = { name: Translation; progress: FESubtaskProgress }
351353

354+
export type FEUnifiedProjectID = { type: "curseforge"; value: number } | { type: "modrinth"; value: string }
355+
352356
export type FELauncherActionOnGameLaunch = "quitApp" | "closeWindow" | "minimizeWindow" | "hideWindow" | "none"
353357

354358
export type CFFEFileHash = { value: string; algo: CFFEHashAlgo }
@@ -401,8 +405,6 @@ export type MRFEVersionID = string
401405

402406
export type And<T> = T[]
403407

404-
export type FEUnifiedProjectID = { type: "curseforge"; value: number } | { type: "modrinth"; value: string }
405-
406408
export type LatestModSource = { Curseforge: number } | { Modrinth: string }
407409

408410
export type FEModdedManifestLoaderVersion = { id: string }
@@ -451,8 +453,6 @@ export type ExportEntry = { entries: { [key: string]: ExportEntry | null } }
451453

452454
export type ModrinthMod = { project_id: string; version_id: string }
453455

454-
export type FEUnifiedSearchResultWithDescription = ({ title: string; slug: string; description: string; imageUrl: string | null; highResImageUrl: string | null; downloadsCount: number; id: string; releaseDate: string; lastUpdated: string; platform: FEUnifiedPlatform; type: FEUnifiedSearchType; authors: FEUnifiedAuthor[]; websiteUrl: string | null; categories: FEUnifiedCategoryId[]; screenshotUrls: string[]; minecraftVersions: string[]; versions: string[] | null; mainFileId: string | null }) & { fullDescriptionBody: string }
455-
456456
export type AccountType = { type: "microsoft"; value: { email: string | null } } | { type: "offline" }
457457

458458
export type FEUnifiedCategory = { platform: FEUnifiedPlatform; id: FEUnifiedCategoryId; name: string | null; icon: FEUnifiedCategoryIcon | null; projectType: FEUnifiedSearchType; parentId: string | null }

0 commit comments

Comments
 (0)