support events
This commit is contained in:
135
src-tauri/src/db.rs
Normal file
135
src-tauri/src/db.rs
Normal file
@@ -0,0 +1,135 @@
|
||||
use rusqlite::{params, Connection};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct Tag {
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
pub parent_id: Option<i64>,
|
||||
pub color: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct Event {
|
||||
pub id: i64,
|
||||
pub date: String,
|
||||
pub start_minute: i32,
|
||||
pub end_minute: i32,
|
||||
pub main_tag_id: i64,
|
||||
pub sub_tag_id: Option<i64>,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
pub fn init_db(path: &str) -> anyhow::Result<()> {
|
||||
let conn = Connection::open(path)?;
|
||||
|
||||
conn.execute(
|
||||
"CREATE TABLE IF NOT EXISTS tags (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
parent_id INTEGER,
|
||||
color TEXT NOT NULL,
|
||||
FOREIGN KEY(parent_id) REFERENCES tags(id)
|
||||
)",
|
||||
[],
|
||||
)?;
|
||||
|
||||
conn.execute(
|
||||
"CREATE TABLE IF NOT EXISTS events (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
date TEXT NOT NULL,
|
||||
start_minute INTEGER NOT NULL,
|
||||
end_minute INTEGER NOT NULL,
|
||||
main_tag_id INTEGER NOT NULL,
|
||||
sub_tag_id INTEGER,
|
||||
content TEXT,
|
||||
FOREIGN KEY(main_tag_id) REFERENCES tags(id),
|
||||
FOREIGN KEY(sub_tag_id) REFERENCES tags(id)
|
||||
)",
|
||||
[],
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_tags(path: &str) -> anyhow::Result<Vec<Tag>> {
|
||||
let conn = Connection::open(path)?;
|
||||
let mut stmt = conn.prepare("SELECT id, name, parent_id, color FROM tags")?;
|
||||
let tag_iter = stmt.query_map([], |row| {
|
||||
Ok(Tag {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
parent_id: row.get(2)?,
|
||||
color: row.get(3)?,
|
||||
})
|
||||
})?;
|
||||
|
||||
let mut results = Vec::new();
|
||||
for tag in tag_iter {
|
||||
results.push(tag?);
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
pub fn add_tag(path: &str, name: &str, parent_id: Option<i64>, color: &str) -> anyhow::Result<i64> {
|
||||
let conn = Connection::open(path)?;
|
||||
conn.execute(
|
||||
"INSERT INTO tags (name, parent_id, color) VALUES (?1, ?2, ?3)",
|
||||
params![name, parent_id, color],
|
||||
)?;
|
||||
Ok(conn.last_insert_rowid())
|
||||
}
|
||||
|
||||
pub fn delete_tag(path: &str, id: i64) -> anyhow::Result<()> {
|
||||
let conn = Connection::open(path)?;
|
||||
// Also delete child tags
|
||||
conn.execute("DELETE FROM tags WHERE parent_id = ?1", params![id])?;
|
||||
conn.execute("DELETE FROM tags WHERE id = ?1", params![id])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_events(path: &str, date: &str) -> anyhow::Result<Vec<Event>> {
|
||||
let conn = Connection::open(path)?;
|
||||
let mut stmt = conn.prepare("SELECT id, date, start_minute, end_minute, main_tag_id, sub_tag_id, content FROM events WHERE date = ?1")?;
|
||||
let event_iter = stmt.query_map(params![date], |row| {
|
||||
Ok(Event {
|
||||
id: row.get(0)?,
|
||||
date: row.get(1)?,
|
||||
start_minute: row.get(2)?,
|
||||
end_minute: row.get(3)?,
|
||||
main_tag_id: row.get(4)?,
|
||||
sub_tag_id: row.get(5)?,
|
||||
content: row.get(6)?,
|
||||
})
|
||||
})?;
|
||||
|
||||
let mut results = Vec::new();
|
||||
for event in event_iter {
|
||||
results.push(event?);
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
pub fn save_event(path: &str, event: Event) -> anyhow::Result<i64> {
|
||||
let conn = Connection::open(path)?;
|
||||
if event.id > 0 {
|
||||
conn.execute(
|
||||
"UPDATE events SET date=?1, start_minute=?2, end_minute=?3, main_tag_id=?4, sub_tag_id=?5, content=?6 WHERE id=?7",
|
||||
params![event.date, event.start_minute, event.end_minute, event.main_tag_id, event.sub_tag_id, event.content, event.id],
|
||||
)?;
|
||||
Ok(event.id)
|
||||
} else {
|
||||
conn.execute(
|
||||
"INSERT INTO events (date, start_minute, end_minute, main_tag_id, sub_tag_id, content) VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
|
||||
params![event.date, event.start_minute, event.end_minute, event.main_tag_id, event.sub_tag_id, event.content],
|
||||
)?;
|
||||
Ok(conn.last_insert_rowid())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_event(path: &str, id: i64) -> anyhow::Result<()> {
|
||||
let conn = Connection::open(path)?;
|
||||
conn.execute("DELETE FROM events WHERE id = ?1", params![id])?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -11,9 +11,60 @@ use tauri_plugin_store::StoreExt;
|
||||
pub struct AppState {
|
||||
pub is_paused: Arc<AtomicBool>,
|
||||
pub capture_interval_secs: std::sync::atomic::AtomicU64,
|
||||
pub db_path: std::sync::Mutex<Option<String>>,
|
||||
pub toggle_menu_item: std::sync::Mutex<Option<tauri::menu::MenuItem<tauri::Wry>>>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn update_db_path(state: tauri::State<'_, AppState>, path: String) -> Result<(), String> {
|
||||
crate::db::init_db(&path).map_err(|e| e.to_string())?;
|
||||
let mut db_path = state.db_path.lock().unwrap();
|
||||
*db_path = Some(path);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_tags(state: tauri::State<'_, AppState>) -> Result<Vec<crate::db::Tag>, String> {
|
||||
let path = state.db_path.lock().unwrap();
|
||||
let path = path.as_ref().ok_or("Database path not set")?;
|
||||
crate::db::get_tags(path).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn add_tag(state: tauri::State<'_, AppState>, name: String, parent_id: Option<i64>, color: String) -> Result<i64, String> {
|
||||
let path = state.db_path.lock().unwrap();
|
||||
let path = path.as_ref().ok_or("Database path not set")?;
|
||||
crate::db::add_tag(path, &name, parent_id, &color).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_tag(state: tauri::State<'_, AppState>, id: i64) -> Result<(), String> {
|
||||
let path = state.db_path.lock().unwrap();
|
||||
let path = path.as_ref().ok_or("Database path not set")?;
|
||||
crate::db::delete_tag(path, id).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_events(state: tauri::State<'_, AppState>, date: String) -> Result<Vec<crate::db::Event>, String> {
|
||||
let path = state.db_path.lock().unwrap();
|
||||
let path = path.as_ref().ok_or("Database path not set")?;
|
||||
crate::db::get_events(path, &date).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn save_event(state: tauri::State<'_, AppState>, event: crate::db::Event) -> Result<i64, String> {
|
||||
let path = state.db_path.lock().unwrap();
|
||||
let path = path.as_ref().ok_or("Database path not set")?;
|
||||
crate::db::save_event(path, event).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_event(state: tauri::State<'_, AppState>, id: i64) -> Result<(), String> {
|
||||
let path = state.db_path.lock().unwrap();
|
||||
let path = path.as_ref().ok_or("Database path not set")?;
|
||||
crate::db::delete_event(path, id).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn update_interval(state: tauri::State<'_, AppState>, seconds: u64) {
|
||||
state.capture_interval_secs.store(seconds, Ordering::SeqCst);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
mod db;
|
||||
mod engine;
|
||||
mod tray;
|
||||
|
||||
@@ -21,12 +22,20 @@ pub fn run() {
|
||||
engine::get_pause_state,
|
||||
engine::get_timeline,
|
||||
engine::get_image_base64,
|
||||
engine::update_interval
|
||||
engine::update_interval,
|
||||
engine::update_db_path,
|
||||
engine::get_tags,
|
||||
engine::add_tag,
|
||||
engine::delete_tag,
|
||||
engine::get_events,
|
||||
engine::save_event,
|
||||
engine::delete_event
|
||||
])
|
||||
.setup(|app| {
|
||||
app.manage(engine::AppState {
|
||||
is_paused: Arc::new(AtomicBool::new(false)),
|
||||
capture_interval_secs: std::sync::atomic::AtomicU64::new(30),
|
||||
db_path: std::sync::Mutex::new(None),
|
||||
toggle_menu_item: std::sync::Mutex::new(None),
|
||||
});
|
||||
tray::create_tray(app.handle())?;
|
||||
|
||||
Reference in New Issue
Block a user