Skip to content

Commit d973634

Browse files
committed
fix initial loading and select
1 parent 3f82927 commit d973634

File tree

11 files changed

+129
-74
lines changed

11 files changed

+129
-74
lines changed

apps/desktop/packages/main/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ const RUNTIME_PATH_DEFAULT_NAME = "data"
8888
export let CURRENT_RUNTIME_PATH: string | null = null
8989

9090
let win: BrowserWindow | null = null
91+
let lastCoreModuleProgress: number | null = null
9192

9293
const getWin = () => {
9394
return win
@@ -439,6 +440,7 @@ const loadCoreModule: CoreModule = () =>
439440
break
440441
}
441442

443+
lastCoreModuleProgress = progress
442444
getWin()?.webContents.send("coreModuleProgress", progress)
443445
}
444446
} else if (row.startsWith("_INSTANCE_STATE_:")) {
@@ -978,6 +980,10 @@ ipcMain.handle("getCoreModule", async () => {
978980
}
979981
})
980982

983+
ipcMain.handle("getCurrentProgress", () => {
984+
return lastCoreModuleProgress
985+
})
986+
981987
app.whenReady().then(async () => {
982988
console.log("App is ready")
983989
const accessibility = validateArgument("--enable-accessibility")

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

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,13 @@ const ExploreVersionsNavbar = (props: Props) => {
5252

5353
const infiniteQuery = useInfiniteVersionsQuery()
5454

55-
// Helper to determine if modloader filter should be shown
56-
// Currently only hides for resourcePack, easily extensible to other types
55+
// Addon types that don't need modloader filtering
56+
const NO_MODLOADER_TYPES = ["resourcePack", "shader", "world", "datapack"]
57+
5758
const shouldShowModloaderFilter = () => {
58-
return props.addonType !== "resourcePack"
59+
return props.addonType
60+
? !NO_MODLOADER_TYPES.includes(props.addonType)
61+
: true
5962
}
6063

6164
const [overrideEnabled, setOverrideEnabled] = createSignal(
@@ -72,9 +75,13 @@ const ExploreVersionsNavbar = (props: Props) => {
7275
queryKey: ["instance.getInstanceDetails", instanceId()]
7376
}))
7477

78+
// Supported modloaders in GDLauncher
79+
const SUPPORTED_MODLOADERS = ["forge", "fabric", "quilt", "neoforge"]
80+
7581
const modloaders = () => {
76-
const results = globalStore.modloaders.data
77-
return ["", ...(results?.map((v) => v.toString()) || [])]
82+
// Always show all supported modloaders
83+
// The default selection is set in InfiniteScrollVersionsQueryWrapper based on instance
84+
return ["", ...SUPPORTED_MODLOADERS]
7885
}
7986

8087
const getModloaderLabel = (value: string | null | undefined) => {
@@ -158,6 +165,11 @@ const ExploreVersionsNavbar = (props: Props) => {
158165
value={infiniteQuery.query.gameVersion || ""}
159166
options={filteredMappedGameVersions()}
160167
disabled={!overrideEnabled()}
168+
gutter={4}
169+
sameWidth={true}
170+
placement="bottom"
171+
modal={false}
172+
preventScroll={false}
161173
placeholder={
162174
<div class="flex items-center gap-2">
163175
<div class="i-hugeicons:tag-01" />
@@ -194,6 +206,11 @@ const ExploreVersionsNavbar = (props: Props) => {
194206
value={infiniteQuery.query.modLoaderType || ""}
195207
options={modloaders()}
196208
disabled={!overrideEnabled()}
209+
gutter={4}
210+
sameWidth={true}
211+
placement="bottom"
212+
modal={false}
213+
preventScroll={false}
197214
placeholder={
198215
<div class="flex items-center gap-2">
199216
<div class="i-hugeicons:tag-01" />

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ import { useSearchParams } from "@solidjs/router"
88
import useVersionsQuery from "@/pages/Mods/useVersionsQuery"
99
import useSearchContext from "../SearchInputContext"
1010
import { VirtualizerHandle } from "virtua/lib/solid"
11+
import { FEUnifiedSearchType } from "@gd/core_module/bindings"
12+
13+
// Addon types that don't support modloader filtering
14+
const supportsModloader = (type?: FEUnifiedSearchType) => {
15+
const noModloaderTypes = ["resourcePack", "shader", "world", "datapack"]
16+
return type ? !noModloaderTypes.includes(type) : true
17+
}
1118

1219
export interface VersionRowType {
1320
data: VersionRowTypeData[]
@@ -47,6 +54,7 @@ interface Props {
4754
modplatform: "curseforge" | "modrinth"
4855
modId: string
4956
initialQuery?: Partial<typeof versionsQuery>
57+
addonType?: FEUnifiedSearchType
5058
}
5159

5260
const InfiniteQueryContext = createContext<InfiniteQueryType>()
@@ -185,6 +193,7 @@ const InfiniteScrollVersionsQueryWrapper = (props: Props) => {
185193
createEffect(() => {
186194
const _instanceId = parseInt(searchParams.instanceId, 10)
187195
const instanceId = isNaN(_instanceId) ? undefined : _instanceId
196+
const addonType = props.addonType
188197

189198
searchContext?.setSelectedInstanceId(instanceId)
190199

@@ -193,7 +202,9 @@ const InfiniteScrollVersionsQueryWrapper = (props: Props) => {
193202
.query(["instance.getInstanceDetails", instanceId])
194203
.then((details) => {
195204
setQueryWrapper({
196-
modLoaderType: details?.modloaders[0].type_,
205+
modLoaderType: supportsModloader(addonType)
206+
? details?.modloaders[0].type_
207+
: undefined,
197208
gameVersion: details?.version
198209
})
199210
})

apps/desktop/packages/mainWindow/src/global.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ declare global {
8989
listenToCoreModuleProgress: (
9090
cb: (event: Electron.IpcRendererEvent, progress: number) => void
9191
) => void
92+
getCurrentProgress: () => Promise<number | null>
9293
onProtocolUrl: (cb: (url: string) => void) => void
9394
}
9495
}

apps/desktop/packages/mainWindow/src/main.tsx

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -100,32 +100,14 @@ render(() => {
100100
})
101101

102102
window.listenToCoreModuleProgress((_, progress) => {
103-
const startProgress = coreModuleProgress() ?? 0
104-
const endProgress = progress
105-
const duration = 300
106-
const startTime = Date.now()
107-
108-
const easeOutCubic = (x: number): number => {
109-
return 1 - Math.pow(1 - x, 3)
110-
}
103+
setCoreModuleProgress(progress)
104+
})
111105

112-
const animate = () => {
113-
const currentTime = Date.now()
114-
const elapsed = currentTime - startTime
115-
const progress = Math.min(elapsed / duration, 1)
116-
117-
if (progress < 1) {
118-
const easedProgress = easeOutCubic(progress)
119-
const currentValue =
120-
startProgress + (endProgress - startProgress) * easedProgress
121-
setCoreModuleProgress(currentValue)
122-
requestAnimationFrame(animate)
123-
} else {
124-
setCoreModuleProgress(endProgress)
125-
}
106+
// Request any buffered progress that was sent before listener was ready
107+
window.getCurrentProgress().then((progress) => {
108+
if (progress !== null && progress > (coreModuleProgress() ?? 0)) {
109+
setCoreModuleProgress(progress)
126110
}
127-
128-
requestAnimationFrame(animate)
129111
})
130112

131113
const startTime = Date.now()

apps/desktop/packages/mainWindow/src/pages/AddonViewPage/Changelog.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ import {
2121
} from "@gd/ui"
2222
import { rspc } from "@/utils/rspcClient"
2323
import fetchData from "./changelog.data"
24-
import { CFFEFile, CFFEFileIndex } from "@gd/core_module/bindings"
25-
import { sortArrayByGameVersion } from "@/utils/mods"
24+
import { CFFEFile } from "@gd/core_module/bindings"
2625
import { format, formatDistanceToNowStrict } from "date-fns"
2726

2827
const ChangelogCard = (props: {
@@ -211,22 +210,22 @@ const Changelog = () => {
211210
setOptionLabels(labels)
212211
}
213212
} else {
214-
const sortedVersions = sortArrayByGameVersion(
215-
routeData.modpackDetails.data?.data.latestFilesIndexes
216-
)
213+
// Use latestFiles for actual distinct file versions (not latestFilesIndexes which is per-game-version)
214+
const files = routeData.modpackDetails.data?.data.latestFiles || []
217215
setChangelog(undefined)
218216
setReleaseDate(undefined)
219217
setIsLoadingChangelog(false)
220218

221-
const opts = (sortedVersions as CFFEFileIndex[]).map((file) =>
222-
file.fileId.toString()
223-
)
219+
const opts = files.map((file) => file.id.toString())
224220
const labels = Object.fromEntries(
225-
(sortedVersions as CFFEFileIndex[]).map((file) => [
226-
file.fileId.toString(),
227-
file.filename
228-
])
221+
files.map((file) => [file.id.toString(), file.displayName])
229222
)
223+
224+
// Set default value to first option for CurseForge
225+
if (opts.length > 0) {
226+
setFileId(opts[0])
227+
}
228+
230229
setOptions(opts)
231230
setOptionLabels(labels)
232231
}

apps/desktop/packages/mainWindow/src/pages/AddonViewPage/index.tsx

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ import {
2828
createSignal,
2929
createMemo,
3030
onMount,
31-
onCleanup
31+
onCleanup,
32+
useContext
3233
} from "solid-js"
3334
import { format } from "date-fns"
3435
import ExploreVersionsNavbar from "@/components/ExploreVersionsNavbar"
@@ -66,14 +67,33 @@ const ModsInfiniteScrollQueryWrapper = () => {
6667
const params = useParams()
6768
const platform = () => params.platform as FEUnifiedPlatform
6869

70+
// Hoisted project query to pass addonType to InfiniteScrollVersionsQueryWrapper
71+
const project = rspc.createQuery(() => ({
72+
queryKey: [
73+
"modplatforms.unifiedGetProject",
74+
platform() === "curseforge"
75+
? {
76+
type: "curseforge",
77+
value: parseInt(params.id, 10)
78+
}
79+
: {
80+
type: "modrinth",
81+
value: params.id
82+
}
83+
]
84+
}))
85+
6986
return (
7087
<InfiniteScrollVersionsQueryWrapper
7188
modId={params.id}
7289
modplatform={platform()}
90+
addonType={project.data?.type}
7391
>
74-
<ContentWrapper zeroPadding>
75-
<AddonExplore />
76-
</ContentWrapper>
92+
<AddonContext.Provider value={project}>
93+
<ContentWrapper zeroPadding>
94+
<AddonExplore />
95+
</ContentWrapper>
96+
</AddonContext.Provider>
7797
</InfiniteScrollVersionsQueryWrapper>
7898
)
7999
}
@@ -116,20 +136,8 @@ const AddonExplore = () => {
116136
enabled: selectedInstanceId() !== undefined
117137
}))
118138

119-
const project = rspc.createQuery(() => ({
120-
queryKey: [
121-
"modplatforms.unifiedGetProject",
122-
platform() === "curseforge"
123-
? {
124-
type: "curseforge",
125-
value: parseInt(params.id, 10)
126-
}
127-
: {
128-
type: "modrinth",
129-
value: params.id
130-
}
131-
]
132-
}))
139+
// Use the hoisted project query from context
140+
const project = useContext(AddonContext)!
133141

134142
const isFetching = () => project.isLoading
135143

@@ -236,11 +244,26 @@ const AddonExplore = () => {
236244

237245
// Measure sticky header height for versions table positioning
238246
if (refStickyTabs) {
247+
let rafId: number | null = null
248+
239249
const resizeObserver = new ResizeObserver(() => {
240-
setStickyHeaderHeight(refStickyTabs.getBoundingClientRect().height)
250+
// Debounce with requestAnimationFrame to avoid layout thrashing
251+
// when Select dropdowns open (prevents page shift)
252+
if (rafId !== null) {
253+
cancelAnimationFrame(rafId)
254+
}
255+
rafId = requestAnimationFrame(() => {
256+
setStickyHeaderHeight(refStickyTabs.getBoundingClientRect().height)
257+
rafId = null
258+
})
241259
})
242260
resizeObserver.observe(refStickyTabs)
243-
onCleanup(() => resizeObserver.disconnect())
261+
onCleanup(() => {
262+
if (rafId !== null) {
263+
cancelAnimationFrame(rafId)
264+
}
265+
resizeObserver.disconnect()
266+
})
244267
}
245268
})
246269

apps/desktop/packages/preload/loading.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,3 +513,7 @@ contextBridge.exposeInMainWorld(
513513
(cb: (event: Electron.IpcRendererEvent, progress: number) => void) =>
514514
ipcRenderer.on("coreModuleProgress", cb)
515515
)
516+
517+
contextBridge.exposeInMainWorld("getCurrentProgress", () =>
518+
ipcRenderer.invoke("getCurrentProgress")
519+
)

packages/i18n/locale/english/onboarding.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
"_trn_search_syntax_description": "You can search addons in multiple ways:",
55
"_trn_search_syntax_text": "Search by addon name",
66
"_trn_search_syntax_urls": "Paste CurseForge or Modrinth links directly",
7-
"_trn_search_syntax_ids": "Use project IDs (e.g., #12345)",
7+
"_trn_search_syntax_ids": "Use project IDs or slugs (e.g., #12345, #sodium)",
88
"_trn_search_syntax_urls_label": "URLs",
9-
"_trn_search_syntax_id_label": "#id",
9+
"_trn_search_syntax_id_label": "#id/slug",
1010
"_trn_search_syntax_addon_type": "Select addon type (mods, modpacks, etc.) on the left",
1111
"_trn_search_syntax_filters": "Filter by categories and more on the right",
1212
"_trn_welcome_gdlauncher_title": "Welcome to GDLauncher! 🎉",

packages/ui/src/Progress/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export const Progress = (props: Props) => {
4848
}
4949

5050
const barClasses = () => {
51-
const baseClasses = `h-full transition-all duration-300 ease-out ${mergedProps.color}`
51+
const baseClasses = `h-full transition-all duration-400 ease-spring ${mergedProps.color}`
5252
const animationClasses = isIndeterminate()
5353
? "w-full origin-[0%_50%] animate-loadingbar"
5454
: ""

0 commit comments

Comments
 (0)