mirror of
https://github.com/patarapolw/cjdic2.git
synced 2026-11-08 17:35:18 +00:00
consume core in Tauri
This commit is contained in:
1 parent
876b879a65
commit
59968e0d6c
14 files changed
+157
-75
No files matched your search
Generated
+1
-3
@@ -446,9 +446,6 @@ name = "cjdic2"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cjdic2-core",
|
||||
"rusqlite",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-plugin-opener",
|
||||
@@ -461,6 +458,7 @@ dependencies = [
|
||||
"rusqlite",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -10,3 +10,4 @@ crate-type = ["cdylib", "rlib"]
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
rusqlite = { version = "0.38.0", features = ["bundled", "unlock_notify"] }
|
||||
thiserror = "2.0.18"
|
||||
@@ -0,0 +1,6 @@
|
||||
use crate::{error::CJDicError, service::AppService};
|
||||
|
||||
pub fn list_entries_json(service: &AppService) -> Result<String, CJDicError> {
|
||||
let entries = service.list_entries()?;
|
||||
Ok(serde_json::to_string(&entries)?)
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
use std::{path::Path, sync::Mutex};
|
||||
|
||||
use rusqlite::{Connection, Result};
|
||||
|
||||
use crate::models::Entry;
|
||||
|
||||
pub struct Database {
|
||||
conn: Mutex<Connection>,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub fn new<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||
let conn = Connection::open(path)?;
|
||||
Ok(Self {
|
||||
conn: Mutex::new(conn),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn init(&self) -> Result<()> {
|
||||
let conn = self.conn.lock().unwrap();
|
||||
|
||||
conn.execute_batch(
|
||||
"
|
||||
CREATE TABLE IF NOT EXISTS entries (
|
||||
id INTEGER PRIMARY KEY,
|
||||
word TEXT NOT NULL,
|
||||
definition TEXT NOT NULL
|
||||
)",
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn insert_entry(&self, word: &str, definition: &str) -> Result<()> {
|
||||
let conn = self.conn.lock().unwrap();
|
||||
|
||||
conn.execute(
|
||||
"INSERT INTO entries (word, definition) VALUES (?, ?)",
|
||||
[word, definition],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn fetch_all_entries(&self) -> Result<Vec<Entry>> {
|
||||
let conn = self.conn.lock().unwrap();
|
||||
|
||||
let mut stmt = conn.prepare("SELECT id, word, definition FROM entries")?;
|
||||
|
||||
let rows = stmt.query_map([], |row| {
|
||||
Ok(Entry {
|
||||
id: row.get(0)?,
|
||||
word: row.get(1)?,
|
||||
definition: row.get(2)?,
|
||||
})
|
||||
})?;
|
||||
|
||||
let mut entries = Vec::new();
|
||||
for entry in rows {
|
||||
entries.push(entry?);
|
||||
}
|
||||
|
||||
Ok(entries)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CJDicError {
|
||||
#[error("Database error: {0}")]
|
||||
Database(#[from] rusqlite::Error),
|
||||
|
||||
#[error("Serialization error: {0}")]
|
||||
Serialization(#[from] serde_json::Error),
|
||||
|
||||
#[error("Not found")]
|
||||
NotFound,
|
||||
}
|
||||
@@ -1,4 +1,12 @@
|
||||
pub mod api;
|
||||
pub mod db;
|
||||
pub mod error;
|
||||
pub mod models;
|
||||
pub mod service;
|
||||
|
||||
pub use error::CJDicError;
|
||||
pub use models::*;
|
||||
pub use service::AppService;
|
||||
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
left + right
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
use std::path::Path;
|
||||
|
||||
use crate::{db::Database, error::CJDicError, models::Entry};
|
||||
|
||||
pub struct AppService {
|
||||
db: Database,
|
||||
}
|
||||
|
||||
impl AppService {
|
||||
pub fn new<P: AsRef<Path>>(db_path: P) -> Result<Self, CJDicError> {
|
||||
let db = Database::new(db_path)?;
|
||||
db.init()?;
|
||||
Ok(Self { db })
|
||||
}
|
||||
|
||||
pub fn add_entry(&self, word: &str, definition: &str) -> Result<(), CJDicError> {
|
||||
self.db.insert_entry(word, definition)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn list_entries(&self) -> Result<Vec<Entry>, CJDicError> {
|
||||
Ok(self.db.fetch_all_entries()?)
|
||||
}
|
||||
}
|
||||
Vendored
+3
@@ -15,5 +15,8 @@
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.formatOnSave": true
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.formatOnSave": true
|
||||
}
|
||||
}
|
||||
+15
-5
@@ -1,15 +1,24 @@
|
||||
import { useState } from "react";
|
||||
import reactLogo from "./assets/react.svg";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import "./App.css";
|
||||
import './App.css';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
|
||||
import reactLogo from './assets/react.svg';
|
||||
|
||||
function App() {
|
||||
const [greetMsg, setGreetMsg] = useState("");
|
||||
const [name, setName] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
invoke("list_entries").then((r) => {
|
||||
setGreetMsg(JSON.stringify(r));
|
||||
});
|
||||
}, [name]);
|
||||
|
||||
async function greet() {
|
||||
invoke("add_entry", { name });
|
||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||
setGreetMsg(await invoke("greet", { name }));
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -39,6 +48,7 @@ function App() {
|
||||
<input
|
||||
id="greet-input"
|
||||
onChange={(e) => setName(e.currentTarget.value)}
|
||||
autoComplete="off"
|
||||
placeholder="Enter a name..."
|
||||
/>
|
||||
<button type="submit">Greet</button>
|
||||
|
||||
@@ -20,7 +20,4 @@ tauri-build = { version = "2", features = [] }
|
||||
[dependencies]
|
||||
tauri = { version = "2", features = [] }
|
||||
tauri-plugin-opener = "2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
rusqlite = { version = "0.38.0", features = ["bundled", "unlock_notify"] }
|
||||
cjdic2-core = { path = "../src-core" }
|
||||
@@ -0,0 +1,14 @@
|
||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||
use cjdic2_core::{AppService, Entry};
|
||||
|
||||
#[tauri::command]
|
||||
pub fn add_entry(name: &str, state: tauri::State<AppService>) -> Result<(), String> {
|
||||
state
|
||||
.add_entry(name, "definition")
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn list_entries(state: tauri::State<AppService>) -> Result<Vec<Entry>, String> {
|
||||
state.list_entries().map_err(|e| e.to_string())
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::state;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct SearchRow {
|
||||
a: i32,
|
||||
b: i32,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_db(state: tauri::State<state::AppState>) -> Result<Vec<SearchRow>, String> {
|
||||
let conn = state.conn.lock().map_err(|e| e.to_string())?;
|
||||
let mut stmt = conn.prepare("SELECT a, b FROM test").map_err(|e| e.to_string())?;
|
||||
|
||||
let rows = stmt.query_map([], |r| {
|
||||
Ok(SearchRow {
|
||||
a: r.get(0)?,
|
||||
b: r.get(1)?,
|
||||
})
|
||||
}).map_err(|e| e.to_string())?;
|
||||
|
||||
let mut out = Vec::new();
|
||||
for r in rows {
|
||||
out.push(r.map_err(|e| e.to_string())?);
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
+9
-29
@@ -1,15 +1,8 @@
|
||||
use crate::command::*;
|
||||
use cjdic2_core::*;
|
||||
use tauri::Manager;
|
||||
use rusqlite::Connection;
|
||||
use std::sync::Mutex;
|
||||
|
||||
mod db;
|
||||
mod state;
|
||||
|
||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||
#[tauri::command]
|
||||
fn greet(name: &str) -> String {
|
||||
format!("Hello, {}! You've been greeted from Rust!", name)
|
||||
}
|
||||
mod command;
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
@@ -17,31 +10,18 @@ pub fn run() {
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.setup(|app| {
|
||||
let cfg_dir = app.path().app_config_dir();
|
||||
let app_dir = cfg_dir
|
||||
.unwrap_or_else(|_| std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from(".")));
|
||||
|
||||
let app_dir = cfg_dir.unwrap_or_else(|_| {
|
||||
std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from("."))
|
||||
});
|
||||
std::fs::create_dir_all(&app_dir)?;
|
||||
|
||||
let db_path = app_dir.join("cjdic.db");
|
||||
let is_new = !db_path.exists();
|
||||
let service = AppService::new(&db_path)?;
|
||||
app.manage(service);
|
||||
|
||||
println!("{}", cjdic2_core::add(1, 2));
|
||||
|
||||
let conn = Connection::open(&db_path)?;
|
||||
|
||||
if is_new {
|
||||
conn.execute_batch("CREATE TABLE test (a, b);")?;
|
||||
let mut stmt = conn.prepare("INSERT INTO test VALUES (?1, ?2)")?;
|
||||
stmt.insert([1, 2])?;
|
||||
stmt.insert([3, 4])?;
|
||||
}
|
||||
|
||||
app.manage(state::AppState{
|
||||
conn: Mutex::new(conn),
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![greet, db::get_db])
|
||||
.invoke_handler(tauri::generate_handler![add_entry, list_entries])
|
||||
.build(tauri::generate_context!())
|
||||
.expect("error while running tauri application")
|
||||
.run(|_app_handle, event| match event {
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
use rusqlite::Connection;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct AppState {
|
||||
pub conn: Mutex<Connection>
|
||||
}
|
||||
Reference in new issue
Block a user