优化投影管理文件夹已存在提示 (#6664)

Co-authored-by: Glavo <[email protected]>
This commit is contained in:
辞庐andGlavo authored and GitHub committed 2026-08-13 21:52:53 +08:00
1 parent a03c11be42
commit 770c58c2e7
2 files changed
+112 -1

No files matched your search

@@ -41,6 +41,7 @@ import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.ui.*;
import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.util.FileNameSet;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.i18n.I18n;
@@ -161,10 +162,20 @@ public final class SchematicsPage extends ListPageBase<SchematicsPage.Item> impl
return;
Path parent = currentDirectory.path;
FileNameSet existingPaths;
try {
existingPaths = FileNameSet.list(parent, null);
} catch (Exception e) {
LOG.warning("Failed to list folders in " + parent, e);
existingPaths = new FileNameSet(false);
}
Controllers.prompt(
i18n("schematics.create_directory.prompt"),
(result, handler) -> {
Path targetDir = parent.resolve(result);
if (Files.exists(targetDir)) {
handler.reject(i18n("schematics.create_directory.failed.already_exists"));
return;
@@ -178,7 +189,11 @@ public final class SchematicsPage extends ListPageBase<SchematicsPage.Item> impl
LOG.warning("Failed to create directory: " + targetDir, e);
handler.reject(i18n("schematics.create_directory.failed", targetDir));
}
}, "", new RequiredValidator(), new Validator(i18n("schematics.create_directory.failed.invalid_name"), FileUtils::isNameValid));
},
"",
new RequiredValidator(),
new Validator(i18n("schematics.create_directory.failed.invalid_name"), FileUtils::isNameValid),
new Validator(i18n("schematics.create_directory.failed.already_exists"), existingPaths::notContains));
}
private DirItem loadAll(Path dir, @Nullable DirItem parent) {
@@ -0,0 +1,96 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2026 huangyuhui <[email protected]> and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jackhuang.hmcl.util;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jetbrains.annotations.NotNullByDefault;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashSet;
import java.util.Locale;
import java.util.function.Predicate;
/// @author Glavo
@NotNullByDefault
public final class FileNameSet {
public static FileNameSet list(Path directory, @Nullable Predicate<? super Path> predicate) throws IOException {
try (var list = Files.list(directory)) {
boolean caseSensitive = OperatingSystem.CURRENT_OS != OperatingSystem.WINDOWS
|| directory.getFileSystem() != FileSystems.getDefault();
var set = new FileNameSet(caseSensitive);
list.forEachOrdered(path -> {
if (predicate == null || predicate.test(path)) {
set.add(path.getFileName().toString());
}
});
return set;
}
}
private final boolean caseSensitive;
private final HashSet<String> set = new HashSet<>();
public FileNameSet(boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}
public boolean add(String name) {
if (caseSensitive) {
return set.add(name);
} else {
return set.add(name.toLowerCase(Locale.ROOT));
}
}
public boolean contains(String name) {
if (set.isEmpty())
return false;
if (caseSensitive) {
return set.contains(name);
} else {
return set.contains(name.toLowerCase(Locale.ROOT));
}
}
public boolean notContains(String name) {
return !contains(name);
}
@Override
public int hashCode() {
return Boolean.hashCode(caseSensitive) ^ set.hashCode();
}
@Override
public boolean equals(Object obj) {
return this == obj || obj instanceof FileNameSet that && this.caseSensitive == that.caseSensitive && this.set.equals(that.set);
}
@Override
public String toString() {
return set.toString();
}
}