auto update text files in archive after editing
This commit is contained in:
parent
07434a9fd6
commit
39aa6daa35
@ -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",
|
||||||
|
|||||||
@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user