auto update text files in archive after editing

This commit is contained in:
Radek Davidek 2026-04-29 19:35:17 +02:00
parent 07434a9fd6
commit 39aa6daa35
2 changed files with 125 additions and 2 deletions

View File

@ -127,6 +127,10 @@ public class FileEditor extends JFrame {
this.onSaveSuccess = onSaveSuccess; this.onSaveSuccess = onSaveSuccess;
} }
public void setOnSaveSuccess(Runnable onSaveSuccess) {
this.onSaveSuccess = onSaveSuccess;
}
private void initSearchPanel() { private void initSearchPanel() {
searchPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 2)); searchPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 2));
searchPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.GRAY)); searchPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.GRAY));
@ -1286,12 +1290,16 @@ public class FileEditor extends JFrame {
return; // message handled in SwingWorker return; // message handled in SwingWorker
} }
if (onSaveSuccess != null) {
onSaveSuccess.run();
}
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this,
"File saved", "File saved",
"Success", "Success",
JOptionPane.INFORMATION_MESSAGE); JOptionPane.INFORMATION_MESSAGE);
updateStatus(); updateStatus();
} catch (IOException e) { } catch (Exception e) {
JOptionPane.showMessageDialog(this, JOptionPane.showMessageDialog(this,
"Error during saving:\n" + e.getMessage(), "Error during saving:\n" + e.getMessage(),
"Error", "Error",

View File

@ -2514,7 +2514,7 @@ public class MainWindow extends JFrame {
java.util.List<String> cmd = new java.util.ArrayList<>(); java.util.List<String> cmd = new java.util.ArrayList<>();
cmd.add(ext); cmd.add(ext);
cmd.add(tempFile.getAbsolutePath()); cmd.add(tempFile.getAbsolutePath());
Process p = new ProcessBuilder(cmd).start(); new ProcessBuilder(cmd).start();
// Optional: Monitor process to upload back on exit? // Optional: Monitor process to upload back on exit?
// For now internal editor is safer for auto-upload. // For now internal editor is safer for auto-upload.
} catch (Exception ex) { } catch (Exception ex) {
@ -2543,6 +2543,22 @@ public class MainWindow extends JFrame {
} }
File file = item.getFile(); File file = item.getFile();
FilePanelTab activeTab = activePanel != null ? activePanel.getCurrentTab() : null;
boolean fileInsideOpenedArchive = activeTab != null && activeTab.isDirectoryInsideOpenedArchive(file.getParentFile());
boolean forceInternalEditor = fileInsideOpenedArchive && isLikelyTextFile(file);
if (forceInternalEditor) {
FileEditor editor = new FileEditor(this, file, config, false);
editor.setOnSaveSuccess(() -> syncArchiveAfterInternalEdit(file));
editor.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosed(java.awt.event.WindowEvent e) {
requestFocusInActivePanel();
}
});
editor.setVisible(true);
return;
}
// If an external editor is configured, try launching it with the file path // If an external editor is configured, try launching it with the file path
String ext = config.getExternalEditorPath(); String ext = config.getExternalEditorPath();
@ -2572,6 +2588,105 @@ public class MainWindow extends JFrame {
editor.setVisible(true); editor.setVisible(true);
} }
private boolean isLikelyTextFile(File file) {
if (file == null || !file.isFile()) {
return false;
}
int probeSize = 4096;
byte[] probe;
try {
long size = Files.size(file.toPath());
int toRead = (int) Math.min(probeSize, size);
probe = new byte[toRead];
try (java.io.InputStream in = Files.newInputStream(file.toPath())) {
int read = in.read(probe);
if (read < 0) {
return true;
}
if (read < toRead) {
byte[] trimmed = new byte[read];
System.arraycopy(probe, 0, trimmed, 0, read);
probe = trimmed;
}
}
} catch (Exception e) {
return false;
}
if (probe.length == 0) {
return true;
}
int nonPrintable = 0;
for (byte b : probe) {
int value = b & 0xFF;
if (value == 0) {
return false;
}
boolean printable = value == 9 || value == 10 || value == 13 || (value >= 32 && value <= 126);
if (!printable) {
nonPrintable++;
}
}
return nonPrintable <= Math.max(1, probe.length / 6);
}
private void syncArchiveAfterInternalEdit(File editedFile) {
try {
if (activePanel == null) {
return;
}
FilePanelTab activeTab = activePanel.getCurrentTab();
if (activeTab == null) {
return;
}
File parentDir = editedFile != null ? editedFile.getParentFile() : null;
if (parentDir == null || !activeTab.isDirectoryInsideOpenedArchive(parentDir)) {
return;
}
if (!activeTab.canSyncOpenedArchive()) {
throw new IOException("Updating this archive format is not supported");
}
activeTab.syncOpenedArchiveChanges(new FileOperations.ProgressCallback() {
@Override
public void onProgress(long current, long total, String fileName) {}
@Override
public void onFileProgress(long current, long total) {}
@Override
public boolean isCancelled() {
return false;
}
@Override
public FileOperations.OverwriteResponse confirmOverwrite(File source, File target) {
return FileOperations.OverwriteResponse.YES;
}
@Override
public FileOperations.ErrorResponse onError(File file, Exception e) {
return FileOperations.ErrorResponse.ABORT;
}
@Override
public FileOperations.SymlinkResponse confirmSymlink(File file) {
return FileOperations.SymlinkResponse.FOLLOW;
}
@Override
public String requestPassword(String archiveName) {
return null;
}
});
activePanel.refresh(false);
} catch (Exception ex) {
throw new RuntimeException("File saved, but archive sync failed: " + ex.getMessage(), ex);
}
}
/** /**
* Compare files from both panels * Compare files from both panels
*/ */