Skip to content

feat(mods): 实现模组列表导出功能#6233

Open
zkitefly wants to merge 35 commits into
HMCL-dev:mainfrom
zkitefly:modlist-output
Open

feat(mods): 实现模组列表导出功能#6233
zkitefly wants to merge 35 commits into
HMCL-dev:mainfrom
zkitefly:modlist-output

Conversation

@zkitefly

@zkitefly zkitefly commented Jun 26, 2026

Copy link
Copy Markdown
Member

支持CSV和JSON格式,可自定义导出字段

要在模组列表选择要导出的项,然后就有导出清单按钮

close #6158

实现模组列表导出功能,支持CSV和JSON格式,可自定义导出字段

@3gf8jv4dv 3gf8jv4dv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

默认窗口大小下,对话框高度几乎撑满窗口了。要不限制一下?

Comment thread HMCL/src/main/resources/assets/lang/I18N_zh.properties Outdated
Comment thread HMCL/src/main/resources/assets/lang/I18N_zh.properties Outdated
Comment thread HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties Outdated
zkitefly and others added 3 commits June 27, 2026 09:56
Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com>
Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com>
Co-authored-by: 3gf8jv4dv <3gf8jv4dv@gmail.com>
@Minecraft269

Copy link
Copy Markdown

解决一下CheckStyle?

@Minecraft269

Copy link
Copy Markdown

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a feature to export the mod list to CSV or JSON format, including a UI dialog for selecting export formats and fields, and backend logic for generating the files and computing SHA1/SHA512 hashes. The review feedback highlights three critical improvements: offloading the export and hash computation to a background thread to prevent blocking the JavaFX UI thread, adding defensive null checks when retrieving mod field values to avoid potential NullPointerExceptions, and localizing the hardcoded English labels in the export dialog to support proper internationalization.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java Outdated
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java Outdated
@ChouChiu

Copy link
Copy Markdown

会不会考虑做成 Prsim 那样,导出的格式更多一点,还能自定义

@Minecraft269

Copy link
Copy Markdown

话说支不支持mcmod的格式? (方便整合包作者)

@zkitefly

Copy link
Copy Markdown
Member Author

话说支不支持mcmod的格式? (方便整合包作者)

具体是什么格式

@Minecraft269

Copy link
Copy Markdown

话说支不支持mcmod的格式? (方便整合包作者)

具体是什么格式

https://www.mcmod.cn/class/2995.html https://bbs.mcmod.cn/thread-21260-1-1.html 应该是这种格式吧

@zkitefly

Copy link
Copy Markdown
Member Author

会不会考虑做成 Prsim 那样,导出的格式更多一点,还能自定义

已支持

@Minecraft269

Copy link
Copy Markdown

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a feature to export the mod list to CSV, JSON, or custom text formats asynchronously, complete with a configuration dialog in the UI and corresponding localization updates. The review feedback highlights several key areas for improvement: addressing thread-safety issues by replacing the remoteModInfoCache's HashMap with a ConcurrentHashMap, preventing potential NullPointerExceptions by adding null checks for fetched remote addons, improving error dialogs when exception.getMessage() is null, refactoring duplicated emoji-filtering logic, and resolving performance bottlenecks caused by sequential network requests during bulk exports.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java Outdated
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java Outdated
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java Outdated
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java
@zkitefly

Copy link
Copy Markdown
Member Author

话说支不支持mcmod的格式? (方便整合包作者)

具体是什么格式

https://www.mcmod.cn/class/2995.html https://bbs.mcmod.cn/thread-21260-1-1.html 应该是这种格式吧

这里的网盘连接过期了,找不到源文件,也没有讲是啥格式(

@3gf8jv4dv

Copy link
Copy Markdown
Contributor

这里的网盘连接过期了,找不到源文件,也没有讲是啥格式(

我看了下,bbs.mcmod.cn 链接里说是用 https://www.mcmod.cn/class/2995.html 这个模组。

用这个模组导出的结构,和这个 PR JSON 格式的一致。

@zkitefly

Copy link
Copy Markdown
Member Author

CC?

@Minecraft269

Minecraft269 commented Jul 16, 2026

Copy link
Copy Markdown

CC?

自行 /gemini review即可(在7.16之前(诶不对 击退就是7.16 所以今天是最后一天了)) 修正 是7.17

@Minecraft269

Copy link
Copy Markdown

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a feature to export the mod list to CSV, JSON, or custom text formats asynchronously, complete with a configuration dialog, parallel prefetching of metadata, and localization support. The review feedback identifies a thread-safety issue where a plain integer is incremented concurrently, which should be refactored to an AtomicInteger. Additionally, it is recommended to remove the manual System.gc() call to prevent potential UI stuttering during garbage collection.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java Outdated
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java Outdated
zkitefly and others added 2 commits July 16, 2026 14:19
…java

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@zkitefly

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a feature to export the mod list to CSV, JSON, or a custom template format asynchronously, along with UI dialogs and internationalization support. The review feedback highlights several critical areas for improvement: resolving potential thread starvation deadlocks and performance bottlenecks caused by nested blocking joins in parallel prefetching tasks, simplifying remote mod info retrieval by fetching sources sequentially, handling custom template placeholder prefetching, clearing caches between exports to prevent stale data, and improving the user experience by removing redundant progress updates during the final export phase.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java
@zkitefly

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a feature to export the mod list to CSV, JSON, or custom text formats asynchronously. It adds an export dialog to the UI, supports fetching remote mod metadata from CurseForge and Modrinth, caches file hashes, and extracts emoji-filtering logic into a reusable utility method. The review comments identify two important issues: first, a concurrency risk where shared cache maps on the page instance are cleared and accessed by concurrent export tasks; second, a thread-blocking issue where acquiring semaphores inside thread pool tasks can lead to thread starvation. Both comments provide highly actionable suggestions to improve thread safety and resource utilization.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java
Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPage.java
@zkitefly

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an asynchronous mod list export feature supporting CSV, JSON, and custom text formats, complete with a configuration dialog, localization keys, and caching for file hashes and remote metadata. The review feedback highlights opportunities to improve efficiency and maintainability: first, by avoiding clearing caches at the start of every export to preserve data across consecutive runs; second, by merging switch cases in getFieldValue to prevent redundant getRemoteModInfo calls; and third, by refactoring the checkbox creation in showExportDialog to eliminate repetitive code and adhere to DRY principles.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +315 to +317
remoteModInfoCache.clear();
sha1Cache.clear();
sha512Cache.clear();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

exportMods 方法的开头,每次导出都会清空 remoteModInfoCachesha1Cachesha512Cache。这会导致在连续导出(例如,用户第一次导出后发现缺少字段,然后立即进行第二次导出)或重试失败的导出时,所有缓存数据都被清除,即使是已经成功获取的数据也需要重新获取,降低了效率。

考虑到重试逻辑中已经有了针对性地移除失败缓存的逻辑 (task.getFailedModPaths().forEach(remoteModInfoCache::remove)),建议移除此处的全局清空缓存操作,以提升用户体验和性能。例如,可以提供一个手动刷新缓存的按钮,而不是在每次导出时自动清空。

Comment on lines +658 to +677
case "curseForgeUrl" -> {
RemoteModInfo remoteInfo = getRemoteModInfo(mod);
yield remoteInfo.curseForgeUrl;
}
case "curseForgeFileUrl" -> {
RemoteModInfo remoteInfo = getRemoteModInfo(mod);
yield remoteInfo.curseForgeFileUrl;
}
case "curseForgeDownloadPage" -> {
RemoteModInfo remoteInfo = getRemoteModInfo(mod);
yield remoteInfo.curseForgeDownloadPage;
}
case "modrinthUrl" -> {
RemoteModInfo remoteInfo = getRemoteModInfo(mod);
yield remoteInfo.modrinthUrl;
}
case "modrinthFileUrl" -> {
RemoteModInfo remoteInfo = getRemoteModInfo(mod);
yield remoteInfo.modrinthFileUrl;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

getFieldValue 方法中,获取 curseForgeUrlcurseForgeFileUrl 等多个远程信息字段时,每个 case 分支都重复调用了 getRemoteModInfo(mod)。这使得代码显得冗余,不易维护。

建议将这些 case 合并,一次性获取 RemoteModInfo 对象,然后根据 field 返回对应的属性值。这样可以使代码更简洁,也为后续优化(如在 getFieldValues 中缓存 RemoteModInfo)打下基础。

            case "curseForgeUrl", "curseForgeFileUrl", "curseForgeDownloadPage", "modrinthUrl", "modrinthFileUrl" -> {
                RemoteModInfo remoteInfo = getRemoteModInfo(mod);
                yield switch (field) {
                    case "curseForgeUrl" -> remoteInfo.curseForgeUrl;
                    case "curseForgeFileUrl" -> remoteInfo.curseForgeFileUrl;
                    case "curseForgeDownloadPage" -> remoteInfo.curseForgeDownloadPage;
                    case "modrinthUrl" -> remoteInfo.modrinthUrl;
                    case "modrinthFileUrl" -> remoteInfo.modrinthFileUrl;
                    default -> ""; // Should not happen
                };
            }

Comment thread HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/ModListPageSkin.java Outdated
@zkitefly

Copy link
Copy Markdown
Member Author

@Glavo CC?

Comment thread HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties Outdated
@github-actions github-actions Bot added the 500+ label Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 在实例管理的模组列表中提供导出模组列表功能

4 participants