diff --git a/Makefile b/Makefile
index e9c1cd8..d4f2a7d 100644
--- a/Makefile
+++ b/Makefile
@@ -6,11 +6,16 @@ dev:
build:
cargo build --release
-# Install the release build with its icon and launcher entry under ~/.local
+# Install the release build with its icon, launcher entry and hourly backup timer under ~/.local
install-local: build
install -Dm755 target/release/chelete $(HOME)/.local/bin/chelete
install -Dm644 assets/icons/128x128@2x.png $(HOME)/.local/share/icons/hicolor/256x256/apps/chelete.png
install -Dm644 assets/chelete.desktop $(HOME)/.local/share/applications/chelete.desktop
+ install -Dm755 scripts/chelete-backup $(HOME)/.local/bin/chelete-backup
+ install -Dm644 assets/systemd/chelete-backup.service $(HOME)/.config/systemd/user/chelete-backup.service
+ install -Dm644 assets/systemd/chelete-backup.timer $(HOME)/.config/systemd/user/chelete-backup.timer
+ -systemctl --user daemon-reload
+ -systemctl --user enable --now chelete-backup.timer
-gtk-update-icon-cache -q $(HOME)/.local/share/icons/hicolor
-update-desktop-database $(HOME)/.local/share/applications
diff --git a/README.md b/README.md
index 4f85018..109462e 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,10 @@ The UI tests run the real screens headlessly with simulated keystrokes, so they
make build # cargo build --release
```
+## Backups
+
+`make install-local` also installs a systemd user timer that dumps the database to `~/Documents/chelete/backup.json` every hour (needs `sqlite3` and `jq`). Check it with `systemctl --user list-timers chelete-backup`.
+
## Usage
```bash
diff --git a/assets/icon.svg b/assets/icon.svg
index 5773aea..cc37b7f 100644
--- a/assets/icon.svg
+++ b/assets/icon.svg
@@ -1,13 +1,9 @@
diff --git a/assets/icons/128x128.png b/assets/icons/128x128.png
index cc80f9f..dac03fb 100644
Binary files a/assets/icons/128x128.png and b/assets/icons/128x128.png differ
diff --git a/assets/icons/128x128@2x.png b/assets/icons/128x128@2x.png
index 9cac92b..26e68fa 100644
Binary files a/assets/icons/128x128@2x.png and b/assets/icons/128x128@2x.png differ
diff --git a/assets/icons/32x32.png b/assets/icons/32x32.png
index b9b1503..46b4fb0 100644
Binary files a/assets/icons/32x32.png and b/assets/icons/32x32.png differ
diff --git a/assets/icons/icon.icns b/assets/icons/icon.icns
index 0dbb20c..20483ff 100644
Binary files a/assets/icons/icon.icns and b/assets/icons/icon.icns differ
diff --git a/assets/icons/icon.ico b/assets/icons/icon.ico
index 7e09b05..79ff081 100644
Binary files a/assets/icons/icon.ico and b/assets/icons/icon.ico differ
diff --git a/assets/systemd/chelete-backup.service b/assets/systemd/chelete-backup.service
new file mode 100644
index 0000000..6938618
--- /dev/null
+++ b/assets/systemd/chelete-backup.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=Back up Chelete to ~/Documents/chelete/backup.json
+
+[Service]
+Type=oneshot
+ExecStart=%h/.local/bin/chelete-backup
diff --git a/assets/systemd/chelete-backup.timer b/assets/systemd/chelete-backup.timer
new file mode 100644
index 0000000..d5abda6
--- /dev/null
+++ b/assets/systemd/chelete-backup.timer
@@ -0,0 +1,9 @@
+[Unit]
+Description=Back up Chelete every hour
+
+[Timer]
+OnCalendar=hourly
+Persistent=true
+
+[Install]
+WantedBy=timers.target
diff --git a/scripts/chelete-backup b/scripts/chelete-backup
new file mode 100755
index 0000000..63479b3
--- /dev/null
+++ b/scripts/chelete-backup
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Dump the Chelete database to ~/Documents/chelete/backup.json.
+set -euo pipefail
+db="$HOME/.local/share/com.chelete.app/chelete.db"
+out="$HOME/Documents/chelete/backup.json"
+mkdir -p "$(dirname "$out")"
+tmp="$out.tmp"
+dump() { sqlite3 -readonly -json "$db" "SELECT * FROM $1" | jq -c '. // []' ; }
+jq -n --argjson accounts "$(dump accounts)" \
+ --argjson categories "$(dump categories)" \
+ --argjson transactions "$(dump transactions)" \
+ --argjson subscriptions "$(dump subscriptions)" \
+ '{accounts: $accounts, categories: $categories, transactions: $transactions, subscriptions: $subscriptions}' > "$tmp"
+mv "$tmp" "$out"
diff --git a/src/ui/widgets.rs b/src/ui/widgets.rs
index 6df3a3b..df2df40 100644
--- a/src/ui/widgets.rs
+++ b/src/ui/widgets.rs
@@ -388,7 +388,7 @@ pub fn submit_on_enter(
pub const ELEMENT_NUMBER: &str = "17";
pub const ELEMENT_SYMBOL: &str = "Ch";
-pub const ELEMENT_NAME: &str = "Chlorine";
+pub const ELEMENT_NAME: &str = "Chelete";
pub const ELEMENT_MASS: &str = "35.45";
/// How much of the element tile to draw.
@@ -465,10 +465,10 @@ mod logo_tests {
use super::*;
#[test]
- fn the_tile_reads_17_ch_chlorine() {
+ fn the_tile_reads_17_ch_chelete() {
assert_eq!(ELEMENT_NUMBER, "17");
assert_eq!(ELEMENT_SYMBOL, "Ch");
- assert_eq!(ELEMENT_NAME, "Chlorine");
+ assert_eq!(ELEMENT_NAME, "Chelete");
assert_eq!(ELEMENT_MASS, "35.45");
}
}