diff --git a/pom.xml b/pom.xml
index e6533e9..fcadf3a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,7 +30,7 @@
com.andrewlalis
javafx-scene-router
- 1.5.1
+ 1.6.0
diff --git a/src/main/java/com/andrewlalis/perfin/control/AccountViewController.java b/src/main/java/com/andrewlalis/perfin/control/AccountViewController.java
index b41dc4a..2727486 100644
--- a/src/main/java/com/andrewlalis/perfin/control/AccountViewController.java
+++ b/src/main/java/com/andrewlalis/perfin/control/AccountViewController.java
@@ -94,8 +94,7 @@ public class AccountViewController implements RouteSelectionListener {
);
if (confirmResult) {
Profile.getCurrent().getDataSource().useAccountRepository(repo -> repo.archive(account.id));
- router.getHistory().clear();
- router.navigate("accounts");
+ router.replace("accounts");
}
}
@@ -106,8 +105,7 @@ public class AccountViewController implements RouteSelectionListener {
);
if (confirm) {
Profile.getCurrent().getDataSource().useAccountRepository(repo -> repo.unarchive(account.id));
- router.getHistory().clear();
- router.navigate("accounts");
+ router.replace("accounts");
}
}
@@ -122,8 +120,7 @@ public class AccountViewController implements RouteSelectionListener {
);
if (confirm) {
Profile.getCurrent().getDataSource().useAccountRepository(repo -> repo.delete(account));
- router.getHistory().clear();
- router.navigate("accounts");
+ router.replace("accounts");
}
}
diff --git a/src/main/java/com/andrewlalis/perfin/control/EditAccountController.java b/src/main/java/com/andrewlalis/perfin/control/EditAccountController.java
index 89c915d..3074aa9 100644
--- a/src/main/java/com/andrewlalis/perfin/control/EditAccountController.java
+++ b/src/main/java/com/andrewlalis/perfin/control/EditAccountController.java
@@ -124,8 +124,7 @@ public class EditAccountController implements RouteSelectionListener {
// Once we create the new account, go to the account.
Account newAccount = accountRepo.findById(id).orElseThrow();
- router.getHistory().clear();
- router.navigate("account", newAccount);
+ router.replace("account", newAccount);
}
} else {
log.debug("Updating account {}", account.id);
@@ -135,8 +134,7 @@ public class EditAccountController implements RouteSelectionListener {
account.setCurrency(accountCurrencyComboBox.getValue());
accountRepo.update(account);
Account updatedAccount = accountRepo.findById(account.id).orElseThrow();
- router.getHistory().clear();
- router.navigate("account", updatedAccount);
+ router.replace("account", updatedAccount);
}
} catch (Exception e) {
log.error("Failed to save (or update) account " + account.id, e);
diff --git a/src/main/java/com/andrewlalis/perfin/control/MainViewController.java b/src/main/java/com/andrewlalis/perfin/control/MainViewController.java
index 1a55118..9e8e2fc 100644
--- a/src/main/java/com/andrewlalis/perfin/control/MainViewController.java
+++ b/src/main/java/com/andrewlalis/perfin/control/MainViewController.java
@@ -25,7 +25,7 @@ public class MainViewController {
@FXML public void initialize() {
AnchorPaneRouterView routerView = (AnchorPaneRouterView) router.getView();
- mainContainer.setCenter(routerView.getAnchorPane());
+ mainContainer.setCenter(routerView.getPane());
// Set up a simple breadcrumb display in the top bar.
BindingUtil.mapContent(
@@ -76,13 +76,11 @@ public class MainViewController {
}
@FXML public void goToAccounts() {
- router.getHistory().clear();
- router.navigate("accounts");
+ router.replace("accounts");
}
@FXML public void goToTransactions() {
- router.getHistory().clear();
- router.navigate("transactions");
+ router.replace("transactions");
}
@FXML public void viewProfiles() {
@@ -98,17 +96,14 @@ public class MainViewController {
}
@FXML public void helpViewHome() {
- helpRouter.getHistory().clear();
- helpRouter.navigate("home");
+ helpRouter.replace("home");
}
@FXML public void helpViewAccounts() {
- helpRouter.getHistory().clear();
- helpRouter.navigate("accounts");
+ helpRouter.replace("accounts");
}
@FXML public void helpViewTransactions() {
- helpRouter.getHistory().clear();
- helpRouter.navigate("transactions");
+ helpRouter.replace("transactions");
}
}
diff --git a/src/main/java/com/andrewlalis/perfin/control/ProfilesViewController.java b/src/main/java/com/andrewlalis/perfin/control/ProfilesViewController.java
index edeb452..89d7aca 100644
--- a/src/main/java/com/andrewlalis/perfin/control/ProfilesViewController.java
+++ b/src/main/java/com/andrewlalis/perfin/control/ProfilesViewController.java
@@ -106,8 +106,7 @@ public class ProfilesViewController {
try {
Profile.load(name);
ProfilesStage.closeView();
- router.getHistory().clear();
- router.navigate("accounts");
+ router.replace("accounts");
if (showPopup) Popups.message("The profile \"" + name + "\" has been loaded.");
return true;
} catch (ProfileLoadException e) {
diff --git a/src/main/java/com/andrewlalis/perfin/control/TransactionViewController.java b/src/main/java/com/andrewlalis/perfin/control/TransactionViewController.java
index 4b56611..1c6155e 100644
--- a/src/main/java/com/andrewlalis/perfin/control/TransactionViewController.java
+++ b/src/main/java/com/andrewlalis/perfin/control/TransactionViewController.java
@@ -95,8 +95,7 @@ public class TransactionViewController {
Profile.getCurrent().getDataSource().useTransactionRepository(repo -> {
// TODO: Delete attachments first!
repo.delete(transaction.id);
- router.getHistory().clear();
- router.navigate("transactions");
+ router.replace("transactions");
});
}
}
diff --git a/src/main/java/com/andrewlalis/perfin/data/AttachmentRepository.java b/src/main/java/com/andrewlalis/perfin/data/AttachmentRepository.java
index 69cc2b4..34e4dd3 100644
--- a/src/main/java/com/andrewlalis/perfin/data/AttachmentRepository.java
+++ b/src/main/java/com/andrewlalis/perfin/data/AttachmentRepository.java
@@ -10,4 +10,5 @@ public interface AttachmentRepository extends AutoCloseable {
Optional findById(long attachmentId);
Optional findByIdentifier(String identifier);
void deleteById(long attachmentId);
+ void deleteAllOrphans();
}
diff --git a/src/main/java/com/andrewlalis/perfin/data/impl/JdbcAttachmentRepository.java b/src/main/java/com/andrewlalis/perfin/data/impl/JdbcAttachmentRepository.java
index 2acdbc3..fec310a 100644
--- a/src/main/java/com/andrewlalis/perfin/data/impl/JdbcAttachmentRepository.java
+++ b/src/main/java/com/andrewlalis/perfin/data/impl/JdbcAttachmentRepository.java
@@ -5,6 +5,8 @@ import com.andrewlalis.perfin.data.ulid.UlidCreator;
import com.andrewlalis.perfin.data.util.DbUtil;
import com.andrewlalis.perfin.data.util.FileUtil;
import com.andrewlalis.perfin.model.Attachment;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.UncheckedIOException;
@@ -18,6 +20,8 @@ import java.util.List;
import java.util.Optional;
public record JdbcAttachmentRepository(Connection conn, Path contentDir) implements AttachmentRepository {
+ private static final Logger log = LoggerFactory.getLogger(JdbcAttachmentRepository.class);
+
@Override
public Attachment insert(Path sourcePath) {
String filename = sourcePath.getFileName().toString();
@@ -67,6 +71,41 @@ public record JdbcAttachmentRepository(Connection conn, Path contentDir) impleme
}
}
+ @Override
+ public void deleteAllOrphans() {
+ DbUtil.doTransaction(conn, () -> {
+ List orphans = DbUtil.findAll(
+ conn,
+ """
+ SELECT * FROM attachment
+ WHERE
+ id NOT IN (SELECT attachment_id FROM transaction_attachment) AND
+ id NOT IN (SELECT attachment_id FROM balance_record_attachment)""",
+ JdbcAttachmentRepository::parseAttachment
+ );
+ for (Attachment orphan : orphans) {
+ DbUtil.updateOne(
+ conn,
+ "DELETE FROM attachment WHERE id = ?",
+ List.of(orphan.id)
+ );
+ Path filePath = orphan.getPath(contentDir);
+ try {
+ Files.deleteIfExists(filePath);
+ Path parentDir = filePath.getParent();
+ try (var filesRemaining = Files.list(parentDir)) {
+ if (filesRemaining.findAny().isEmpty()) {
+ Files.delete(parentDir);
+ }
+ }
+ } catch (IOException e) {
+ log.warn("Failed to delete attachment at " + filePath + ".", e);
+ }
+ log.debug("Deleted orphan attachment with id {} at {}.", orphan.id, filePath);
+ }
+ });
+ }
+
@Override
public void close() throws Exception {
conn.close();
diff --git a/src/main/java/com/andrewlalis/perfin/data/impl/JdbcTransactionRepository.java b/src/main/java/com/andrewlalis/perfin/data/impl/JdbcTransactionRepository.java
index 9668aa0..fefa1e3 100644
--- a/src/main/java/com/andrewlalis/perfin/data/impl/JdbcTransactionRepository.java
+++ b/src/main/java/com/andrewlalis/perfin/data/impl/JdbcTransactionRepository.java
@@ -151,6 +151,7 @@ public record JdbcTransactionRepository(Connection conn, Path contentDir) implem
@Override
public void delete(long transactionId) {
DbUtil.updateOne(conn, "DELETE FROM transaction WHERE id = ?", List.of(transactionId));
+ new JdbcAttachmentRepository(conn, contentDir).deleteAllOrphans();
}
@Override