Skip to content

Commit 6dfbbf2

Browse files
RedxAxRedxAx
authored andcommitted
Improved UX And Tabs Saving For Explorer.
And Some Small Changes.
1 parent 188747c commit 6dfbbf2

12 files changed

Lines changed: 223 additions & 99 deletions

src/main/java/redxax/oxy/remotely/RemotelyClient.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.google.gson.reflect.TypeToken;
55
import net.minecraft.client.gui.screen.Screen;
66
import redxax.oxy.remotely.config.Config;
7+
import redxax.oxy.remotely.explorer.FileExplorerScreen;
78
import redxax.oxy.remotely.servers.RemoteHostInfo;
89
import redxax.oxy.remotely.servers.ServerInfo;
910
import redxax.oxy.remotely.config.SettingsScreen;
@@ -35,6 +36,7 @@ public class RemotelyClient {
3536
private static final Path SNIPPETS_FILE = Paths.get(String.valueOf(remotelyDir), "data", "snippets.json");
3637
private static final Path FILE_EDITOR_TABS_FILE = Paths.get(String.valueOf(remotelyDir), "data", "file_editor_tabs.json");
3738
public static List<MultiTerminalScreen.Theme> themes = new ArrayList<>();
39+
public static FileExplorerScreen fileExplorer;
3840

3941

4042
private static final Gson GSON = new Gson();
@@ -52,6 +54,7 @@ public class RemotelyClient {
5254
private final Map<String, SSHManager> hostSSHManagers = new HashMap<>();
5355
public static String os;
5456
public static Screen mcScreen = null;
57+
public static MinecraftClient mc = MinecraftClient.getInstance();
5558

5659
public void initialize() {
5760
INSTANCE = this;
@@ -135,7 +138,7 @@ private void loadSavedTerminals() {
135138
for (Path entry : stream) {
136139
String fileName = entry.getFileName().toString();
137140
String tabName = fileName.substring(0, fileName.length() - 4);
138-
TerminalInstance terminal = new TerminalInstance(MinecraftClient.getInstance(), multiTerminalScreen, UUID.randomUUID());
141+
TerminalInstance terminal = new TerminalInstance(mc, multiTerminalScreen, UUID.randomUUID());
139142
terminal.loadTerminalOutput(entry);
140143
terminals.add(terminal);
141144
tabNames.add(tabName);
@@ -144,8 +147,8 @@ private void loadSavedTerminals() {
144147
multiTerminalScreen.activeTerminalIndex = activeTerminalIndex;
145148
}
146149
} catch (IOException e) {
147-
if (MinecraftClient.getInstance().player != null) {
148-
MinecraftClient.getInstance().player.sendMessage(Text.literal("Failed to load saved terminals."), false);
150+
if (mc.player != null) {
151+
mc.player.sendMessage(Text.literal("Failed to load saved terminals."), false);
149152
}
150153
}
151154
}

src/main/java/redxax/oxy/remotely/explorer/FileExplorerScreen.java

Lines changed: 128 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package redxax.oxy.remotely.explorer;
22

3-
import net.minecraft.client.MinecraftClient;
3+
import com.google.common.reflect.TypeToken;
4+
import com.google.gson.Gson;
45
import net.minecraft.client.gui.screen.Screen;
56
import net.minecraft.text.Text;
67
import org.lwjgl.glfw.GLFW;
@@ -16,6 +17,8 @@
1617
import redxax.oxy.remotely.util.Sound;
1718

1819
import java.awt.image.BufferedImage;
20+
import java.io.IOException;
21+
import java.nio.file.Files;
1922
import java.nio.file.Path;
2023
import java.nio.file.Paths;
2124
import java.util.*;
@@ -27,7 +30,6 @@
2730
import static redxax.oxy.remotely.util.searchUtils.isFuzzyMatch;
2831

2932
public class FileExplorerScreen extends ReScreen {
30-
private final MinecraftClient minecraftClient;
3133
private final Screen parent;
3234
private final ServerInfo serverInfo;
3335
private final RemotelyCoreAPI fileAPI;
@@ -37,7 +39,7 @@ public class FileExplorerScreen extends ReScreen {
3739
private final List<FileEntryWidget> allWidgets = new CopyOnWriteArrayList<>();
3840
private final boolean importMode;
3941
private ContextMenuWidget itemsContextMenu;
40-
42+
private Map<Container, Path> containerPaths = new HashMap<>();
4143
public static BufferedImage fileIcon;
4244
public static BufferedImage folderIcon;
4345
public static BufferedImage pinIcon;
@@ -50,13 +52,12 @@ public class FileExplorerScreen extends ReScreen {
5052
".bash", ".fish", ".toml", ".mcfunction", ".nbt"
5153
);
5254

53-
public FileExplorerScreen(MinecraftClient mc, Screen parent, ServerInfo info) {
54-
this(mc, parent, info, false);
55+
public FileExplorerScreen(Screen parent, ServerInfo info) {
56+
this(parent, info, false);
5557
}
5658

57-
public FileExplorerScreen(MinecraftClient mc, Screen parent, ServerInfo info, boolean importMode) {
59+
public FileExplorerScreen(Screen parent, ServerInfo info, boolean importMode) {
5860
super(Text.literal("File Explorer"));
59-
this.minecraftClient = mc;
6061
this.parent = parent;
6162
this.serverInfo = info;
6263
this.importMode = importMode;
@@ -94,13 +95,13 @@ protected void init() {
9495
.addLeft("/assets/remotely/icons/goforward.png", this::navigateBack, "Go Up")
9596
.addLeft("/assets/remotely/icons/newFile.png", this::createNewFile, "Create New")
9697
.addLeft("/assets/remotely/icons/external.png", this::openExternally, "Open Externally")
97-
.addRight("/assets/remotely/icons/close.png", () -> minecraftClient.setScreen(parent), "Close")
98+
.addRight("/assets/remotely/icons/close.png", () -> client.setScreen(parent), "Close")
9899
.addRight("/assets/remotely/icons/paste.png", this::paste, "Paste")
99100
.addRight("/assets/remotely/icons/copy.png", this::copy, "Copy")
100101
.addRight("/assets/remotely/icons/favorite.png", this::toggleFavorites, "Toggle Favorites")
101102
.setSearchMode(searchMode, true)
102103
.build();
103-
tabs().builder().allowReorder(true).allowAdd(true).position(5, 36).size(width - 5, 18).onTabClosed(this::onTabClosed).onPlusButtonClicked(this::onNewTab).build();
104+
tabs().builder().allowReorder(true).allowAdd(true).position(5, 36).size(width - 5, 18).onTabClosed(this::onTabClosed).onPlusButtonClicked(this::onNewTab).onTabsReordered(this::onTabReordered).onTabSelected(this::onTabSelected).build();
104105

105106
TabsManager.Tab initialTab = tabs().addTab(getTabName(currentPath), explorerContainer);
106107
tabs().setActiveTab(0);
@@ -149,14 +150,15 @@ protected void init() {
149150
}, "")
150151
.addIconItem("Copy Path", "snippets.png", () -> {
151152
FileEntryWidget firstWidget = (FileEntryWidget) currentSelectedWidgets.getFirst();
152-
minecraftClient.keyboard.setClipboard(firstWidget.getFileEntry().path.toString());
153+
client.keyboard.setClipboard(firstWidget.getFileEntry().path.toString());
153154
}, "")
154155
.addIconItem("Undo", "goback.png", this::undo, "")
155156
.addIconItem("Refresh", "reload.png", () -> {
156157
playSound(Sound.CLICK);
157158
loadDirectory(currentPath);
158159
}, "").build();
159160
addDrawableChild(itemsContextMenu);
161+
loadExplorerTabs();
160162
}
161163

162164
private void loadIcons() {
@@ -188,23 +190,19 @@ private void loadIcons() {
188190
private void loadDirectory(Path path) {
189191
loading = true;
190192
currentPath = path;
193+
containerPaths.put(activeContainer, currentPath);
191194
activeContainer.clearWidgets();
192195
allWidgets.clear();
193196
currentSelectedWidgets.clear();
194-
195-
fileAPI.listDirectory(path).thenAccept(entries -> {
196-
minecraftClient.execute(() -> {
197-
for (RemotelyCoreAPI.FileEntry entry : entries) {
198-
FileEntryWidget widget = new FileEntryWidget.Builder(entry, fileAPI, serverInfo.isRemote, favoritePaths, favoritePathsLock).size(0, 20)
199-
.onClick(this::onFileDoubleClick).onRightClick(this::onFileRightClick).build();
200-
201-
activeContainer.addWidget(widget);
202-
allWidgets.add(widget);
203-
}
204-
loading = false;
205-
});
206-
}).exceptionally(e -> {
207-
minecraftClient.execute(() -> {
197+
fileAPI.listDirectory(path).thenAccept(entries -> client.execute(() -> {
198+
for (RemotelyCoreAPI.FileEntry entry : entries) {
199+
FileEntryWidget widget = new FileEntryWidget.Builder(entry, fileAPI, serverInfo.isRemote, favoritePaths, favoritePathsLock).size(0, 20).onClick(this::onFileDoubleClick).onRightClick(this::onFileRightClick).build();
200+
activeContainer.addWidget(widget);
201+
allWidgets.add(widget);
202+
}
203+
loading = false;
204+
})).exceptionally(e -> {
205+
client.execute(() -> {
208206
loading = false;
209207
new Notification("Failed to load directory: ", e.getMessage(), Notification.Type.ERROR);
210208
});
@@ -219,15 +217,14 @@ private void onFileDoubleClick(FileEntryWidget widget) {
219217
navigateTo(entry.path);
220218
} else {
221219
if (importMode && entry.path.getFileName().toString().equalsIgnoreCase("server.jar")) {
222-
minecraftClient.setScreen(parent);
220+
client.setScreen(parent);
223221
return;
224222
}
225223
if (isSupportedFile(entry.path)) {
226-
minecraftClient.setScreen(new FileEditorScreen(minecraftClient, this, entry.path, serverInfo));
224+
client.setScreen(new FileEditorScreen(client, this, entry.path, serverInfo));
227225
} else {
228226
openExternally(entry.path);
229227
}
230-
231228
}
232229
}
233230

@@ -238,16 +235,37 @@ private void onFileRightClick(FileEntryWidget widget) {
238235

239236
private void onTabClosed(TabsManager.Tab tab) {
240237
if (tabs().getTabs().isEmpty()) {
241-
minecraftClient.setScreen(parent);
238+
client.setScreen(parent);
239+
}
240+
saveExplorerTabs();
241+
}
242+
243+
private void onTabReordered(List<TabsManager.Tab> tabs) {
244+
saveExplorerTabs();
245+
}
246+
247+
private void onTabSelected(TabsManager.Tab tab) {
248+
if (tab.getContainer().getWidgets().isEmpty()) {
249+
Path path = containerPaths.get(tab.getContainer());
250+
if (path != null) {
251+
loadDirectory(path);
252+
}
242253
}
243254
}
244255

245256
public void onNewTab() {
246257
Path homePath = serverInfo.isRemote ? Paths.get("/") : Paths.get(System.getProperty("user.home")).toAbsolutePath().normalize();
247-
createTab(homePath);
258+
createTab(homePath, false);
248259
}
249260

250-
public void createTab(Path newPath) {
261+
public void createTab(Path newPath, boolean allowDuplicate) {
262+
for (TabsManager.Tab tab : tabs().getTabs()) {
263+
if (containerPaths.get(tab.getContainer()).equals(newPath) && !allowDuplicate) {
264+
tabs().setActiveTab(tabs().getTabs().indexOf(tab));
265+
return;
266+
}
267+
}
268+
playSound(Sound.CREATE);
251269
Container newContainer = createContainer(5, 60, width - 10, height - 5);
252270
newContainer.columns(1).padding(2).enableSelecting(true).layoutStyle(Container.LayoutStyle.RESTRICTED);
253271
TabsManager.Tab newTab = tabs().addTab(getTabName(newPath), newContainer);
@@ -288,15 +306,17 @@ private void navigateTo(Path path) {
288306
if (activeTab != null) {
289307
activeTab.setName(getTabName(path));
290308
}
309+
saveExplorerTabs();
291310
}
292311

293312
private void navigateUp() {
294313
Path parentPath = currentPath.getParent();
295314
if (parentPath != null) {
296315
navigateTo(parentPath);
297316
} else {
298-
minecraftClient.setScreen(parent);
317+
client.setScreen(parent);
299318
}
319+
saveExplorerTabs();
300320
}
301321

302322
private void navigateBack() {
@@ -356,15 +376,66 @@ private void toggleFavorites() {
356376
}
357377
}
358378

359-
private void updateButtonStates() {
360-
boolean hasSelection = !currentSelectedWidgets.isEmpty();
361-
// Update button visibility based on selection
362-
}
363-
364379
private String getTabName(Path path) {
365380
return path.getFileName() != null ? path.getFileName().toString() : path.toString();
366381
}
367382

383+
public void saveExplorerTabs() {
384+
try {
385+
Path tabsFile = Paths.get(String.valueOf(remotelyDir), "data", "file_explorer_tabs.json");
386+
if (!Files.exists(tabsFile.getParent())) {
387+
Files.createDirectories(tabsFile.getParent());
388+
}
389+
Map<String, Object> data = new HashMap<>();
390+
List<Map<String, Object>> tabList = new ArrayList<>();
391+
List<TabsManager.Tab> tabs = tabs().getTabs();
392+
for (TabsManager.Tab tab : tabs) {
393+
Map<String, Object> tabMap = new HashMap<>();
394+
Path tabPath = containerPaths.get(tab.getContainer());
395+
tabMap.put("path", tabPath.toString());
396+
tabMap.put("isRemote", serverInfo.isRemote);
397+
tabMap.put("scrollOffset", 0);
398+
if (serverInfo.isRemote && serverInfo.remoteHost != null) {
399+
Map<String, Object> hostMap = new HashMap<>();
400+
hostMap.put("user", serverInfo.remoteHost.getUser());
401+
hostMap.put("ip", serverInfo.remoteHost.getIp());
402+
hostMap.put("port", serverInfo.remoteHost.getPort());
403+
hostMap.put("password", serverInfo.remoteHost.getPassword());
404+
tabMap.put("remoteHostInfo", hostMap);
405+
}
406+
tabList.add(tabMap);
407+
}
408+
data.put("tabs", tabList);
409+
data.put("currentTabIndex", tabs().getActiveTabIndex());
410+
String json = new Gson().toJson(data);
411+
Files.write(tabsFile, json.getBytes());
412+
} catch (IOException e) {
413+
throw new RuntimeException(e);
414+
}
415+
}
416+
417+
public void loadExplorerTabs() {
418+
try {
419+
Path tabsFile = Paths.get(String.valueOf(remotelyDir), "data", "file_explorer_tabs.json");
420+
if (Files.exists(tabsFile)) {
421+
String json = new String(Files.readAllBytes(tabsFile));
422+
Map<String, Object> data = new Gson().fromJson(json, new TypeToken<Map<String, Object>>() {}.getType());
423+
List<Map<String, Object>> tabList = (List<Map<String, Object>>) data.get("tabs");
424+
int activeTabIndex = ((Number) data.getOrDefault("currentTabIndex", 0)).intValue();
425+
for (Map<String, Object> tabMap : tabList) {
426+
String pathStr = (String) tabMap.get("path");
427+
Path path = Paths.get(pathStr);
428+
createTab(path, false);
429+
loadDirectory(path);
430+
System.out.println("Loaded tab for path: " + path);
431+
}
432+
tabs().setActiveTab(activeTabIndex);
433+
}
434+
} catch (IOException e) {
435+
throw new RuntimeException(e);
436+
}
437+
}
438+
368439
public static BufferedImage getIconForFile(Path file) {
369440
String fileName = file.getFileName().toString().toLowerCase();
370441
if (fileName.endsWith(".exe")) return appsIcon;
@@ -401,6 +472,13 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) {
401472
}
402473
if (button == 1) {
403474
itemsContextMenu.show((int) mouseX, (int) mouseY);
475+
if (currentSelectedWidgets.isEmpty()) {
476+
for (AnimatedWidget widget : activeContainer.getWidgets()) {
477+
if (widget.isMouseOver(mouseX, mouseY)) {
478+
activeContainer.addSelectedWidget(widget);
479+
}
480+
}
481+
}
404482
return true;
405483
}
406484
return super.mouseClicked(mouseX, mouseY, button);
@@ -434,7 +512,10 @@ public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
434512
}
435513
}
436514
if (keyCode == GLFW.GLFW_KEY_ENTER) {
437-
515+
for (FileEntryWidget widget : allWidgets) {
516+
if (widget.isFocused()) onFileDoubleClick(widget);
517+
}
518+
return true;
438519
}
439520
if (keyCode == GLFW.GLFW_KEY_DELETE) {
440521
deleteSelected();
@@ -478,6 +559,16 @@ private void undo() {
478559
}
479560
}
480561

562+
@Override
563+
public void setActiveContainer(Container container) {
564+
super.setActiveContainer(container);
565+
if (containerPaths.containsKey(container)) {
566+
currentPath = containerPaths.get(container);
567+
} else {
568+
containerPaths.put(container, currentPath);
569+
}
570+
}
571+
481572
@Override
482573
public void onDisplayed() {
483574
playSound(Sound.FILEEXPLORER);

src/main/java/redxax/oxy/remotely/mixin/GameMenuScreenMixin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ private void openMultiTerminalScreen() {
187187
private void openFileExplorerScreen() {
188188
MinecraftClient client = MinecraftClient.getInstance();
189189
if (client != null) {
190-
client.setScreen(new FileExplorerScreen(client, this, new ServerInfo(remotelyDir.toString())));
190+
client.setScreen(new FileExplorerScreen(this, new ServerInfo(remotelyDir.toString())));
191191
}
192192
}
193193
}

src/main/java/redxax/oxy/remotely/mixin/TitleScreenMixin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,6 @@ private void openMultiTerminalScreen() {
186186
@Unique
187187
private void openFileExplorerScreen() {
188188
MinecraftClient client = MinecraftClient.getInstance();
189-
client.setScreen(new FileExplorerScreen(client, this, new ServerInfo(remotelyDir.toString())));
189+
client.setScreen(new FileExplorerScreen(this, new ServerInfo(remotelyDir.toString())));
190190
}
191191
}

0 commit comments

Comments
 (0)