friends list CRD
This commit is contained in:
Generated
+752
-4
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,7 @@ ed25519-dalek = "3.0.0"
|
||||
getrandom = "0.4.3"
|
||||
device_query = "4.0.1"
|
||||
tokio = "1.53.1"
|
||||
sqlx = { version = "0.8.6", features = ["runtime-tokio-rustls", "sqlite", "migrate"] }
|
||||
tauri-specta = { version = "2.0.0-rc.21", features = ["derive", "typescript"] }
|
||||
specta = "2.0.0-rc.21"
|
||||
specta-typescript = { version = "0.0.9" }
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
CREATE TABLE friends (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
display_name TEXT NOT NULL
|
||||
);
|
||||
@@ -0,0 +1,48 @@
|
||||
use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions};
|
||||
use sqlx::{Pool, Sqlite};
|
||||
use std::error::Error;
|
||||
use tauri::{AppHandle, Manager};
|
||||
|
||||
const DATABASE_FILE: &str = "wyd.sqlite";
|
||||
|
||||
pub struct AppDatabase {
|
||||
pool: Pool<Sqlite>,
|
||||
}
|
||||
|
||||
impl AppDatabase {
|
||||
pub fn new(pool: Pool<Sqlite>) -> Self {
|
||||
Self { pool }
|
||||
}
|
||||
|
||||
pub fn pool(&self) -> &Pool<Sqlite> {
|
||||
&self.pool
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn init(app: &AppHandle) -> Result<(), Box<dyn Error>> {
|
||||
let app_data_dir = app.path().app_data_dir()?;
|
||||
std::fs::create_dir_all(&app_data_dir)?;
|
||||
|
||||
let db_path = app_data_dir.join(DATABASE_FILE);
|
||||
let options = SqliteConnectOptions::new()
|
||||
.filename(db_path)
|
||||
.create_if_missing(true)
|
||||
.journal_mode(SqliteJournalMode::Wal)
|
||||
.foreign_keys(true);
|
||||
|
||||
let pool = SqlitePoolOptions::new()
|
||||
.max_connections(5)
|
||||
.connect_with(options)
|
||||
.await?;
|
||||
|
||||
sqlx::migrate!("./migrations").run(&pool).await?;
|
||||
|
||||
app.manage(AppDatabase::new(pool));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn command_error(error: impl std::fmt::Display) -> String {
|
||||
error.to_string()
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
use crate::db::{self, AppDatabase};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
use tauri::State;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type, sqlx::FromRow)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Friend {
|
||||
pub id: String,
|
||||
pub display_name: String,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn create_friend(
|
||||
database: State<'_, AppDatabase>,
|
||||
friend: Friend,
|
||||
) -> Result<Friend, String> {
|
||||
sqlx::query("INSERT INTO friends (id, display_name) VALUES (?1, ?2)")
|
||||
.bind(&friend.id)
|
||||
.bind(&friend.display_name)
|
||||
.execute(database.pool())
|
||||
.await
|
||||
.map_err(db::command_error)?;
|
||||
|
||||
Ok(friend)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn list_friends(database: State<'_, AppDatabase>) -> Result<Vec<Friend>, String> {
|
||||
sqlx::query_as::<_, Friend>(
|
||||
"SELECT id, display_name FROM friends ORDER BY display_name COLLATE NOCASE, id",
|
||||
)
|
||||
.fetch_all(database.pool())
|
||||
.await
|
||||
.map_err(db::command_error)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn get_friend(
|
||||
database: State<'_, AppDatabase>,
|
||||
id: String,
|
||||
) -> Result<Option<Friend>, String> {
|
||||
sqlx::query_as::<_, Friend>("SELECT id, display_name FROM friends WHERE id = ?1")
|
||||
.bind(id)
|
||||
.fetch_optional(database.pool())
|
||||
.await
|
||||
.map_err(db::command_error)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn delete_friend(database: State<'_, AppDatabase>, id: String) -> Result<bool, String> {
|
||||
let result = sqlx::query("DELETE FROM friends WHERE id = ?1")
|
||||
.bind(id)
|
||||
.execute(database.pool())
|
||||
.await
|
||||
.map_err(db::command_error)?;
|
||||
|
||||
Ok(result.rows_affected() > 0)
|
||||
}
|
||||
+14
-3
@@ -1,17 +1,28 @@
|
||||
mod cursor;
|
||||
mod db;
|
||||
mod friends;
|
||||
mod ufa;
|
||||
mod windowing;
|
||||
|
||||
fn launch_app(app: &tauri::App) {
|
||||
async fn launch_app(app: &tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let handle = app.handle();
|
||||
crate::db::init(handle).await?;
|
||||
crate::ufa::init();
|
||||
crate::cursor::init(handle);
|
||||
crate::windowing::init(handle);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
let specta_builder = tauri_specta::Builder::<tauri::Wry>::new()
|
||||
.error_handling(tauri_specta::ErrorHandlingMode::Throw)
|
||||
.commands(tauri_specta::collect_commands![])
|
||||
.commands(tauri_specta::collect_commands![
|
||||
crate::friends::create_friend,
|
||||
crate::friends::list_friends,
|
||||
crate::friends::get_friend,
|
||||
crate::friends::delete_friend
|
||||
])
|
||||
.events(tauri_specta::collect_events![]);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
@@ -26,7 +37,7 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.invoke_handler(specta_builder.invoke_handler())
|
||||
.setup(|app| {
|
||||
launch_app(app);
|
||||
tauri::async_runtime::block_on(launch_app(app))?;
|
||||
Ok(())
|
||||
})
|
||||
.build(tauri::generate_context!())
|
||||
|
||||
+13
-2
@@ -5,7 +5,18 @@
|
||||
|
||||
|
||||
export const commands = {
|
||||
|
||||
async createFriend(friend: Friend) : Promise<Friend> {
|
||||
return await TAURI_INVOKE("create_friend", { friend });
|
||||
},
|
||||
async listFriends() : Promise<Friend[]> {
|
||||
return await TAURI_INVOKE("list_friends");
|
||||
},
|
||||
async getFriend(id: string) : Promise<Friend | null> {
|
||||
return await TAURI_INVOKE("get_friend", { id });
|
||||
},
|
||||
async deleteFriend(id: string) : Promise<boolean> {
|
||||
return await TAURI_INVOKE("delete_friend", { id });
|
||||
}
|
||||
}
|
||||
|
||||
/** user-defined events **/
|
||||
@@ -18,7 +29,7 @@ export const commands = {
|
||||
|
||||
/** user-defined types **/
|
||||
|
||||
|
||||
export type Friend = { id: string; displayName: string }
|
||||
|
||||
/** tauri-specta globals **/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user