v2.0.0-beta - Убрана тяжелая зависимость iconify, изменён дизайн.
Publish Release / publish-tauri (--bundles deb, src-tauri/target/release/bundle/deb/**.pkg.tar.zst, arch-latest) (push) Has been cancelled
Publish Release / publish-tauri (src-tauri/target/release/bundle/appimage/**.AppImage, src-tauri/target/release/bundle/deb/**.deb, ubuntu-latest) (push) Has been cancelled
Publish Release / publish-tauri (src-tauri/target/release/bundle/msi/**.msi, src-tauri/target/release/bundle/nsis/**.exe, window-latest) (push) Has been cancelled
Publish Release / publish-tauri (--bundles deb, src-tauri/target/release/bundle/deb/**.pkg.tar.zst, arch-latest) (push) Has been cancelled
Publish Release / publish-tauri (src-tauri/target/release/bundle/appimage/**.AppImage, src-tauri/target/release/bundle/deb/**.deb, ubuntu-latest) (push) Has been cancelled
Publish Release / publish-tauri (src-tauri/target/release/bundle/msi/**.msi, src-tauri/target/release/bundle/nsis/**.exe, window-latest) (push) Has been cancelled
В процессе: синхронизация между устройствами
This commit is contained in:
Generated
+4654
-4136
File diff suppressed because it is too large
Load Diff
+14
-8
@@ -1,17 +1,17 @@
|
||||
[package]
|
||||
name = "to-do-app"
|
||||
version = "0.0.0"
|
||||
description = "A Tauri App"
|
||||
version = "1.8.0"
|
||||
description = "A ToDo App"
|
||||
authors = ["you"]
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "1", features = [] }
|
||||
tauri-build = { version = "2.0.1", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "1", features = [ "window-show", "window-unminimize", "window-minimize", "window-maximize", "window-start-dragging", "window-hide", "window-close", "window-unmaximize", "shell-open"] }
|
||||
tauri = { version = "2.0.1", features = [] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
magic-crypt = "3.1.13"
|
||||
@@ -23,13 +23,19 @@ aes = "0.7.5"
|
||||
block-modes = "0.8.1"
|
||||
block-padding = "0.3.3"
|
||||
chrono = "0.4.38"
|
||||
tauri-plugin-shell = "2.0.1"
|
||||
|
||||
[features]
|
||||
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
|
||||
[profile.release]
|
||||
lto = true # Enables link to optimizations
|
||||
opt-level = "s" # Optimize for binary size
|
||||
strip = true # Remove debug symbols
|
||||
[lib]
|
||||
name = "app_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1 # Allows LLVM to perform better optimization.
|
||||
lto = true # Enables link-time-optimizations.
|
||||
opt-level = "s" # Prioritizes small binary size. Use `3` if you prefer speed.
|
||||
panic = "abort" # Higher performance by disabling panic handlers.
|
||||
strip = true # Ensures debug symbols are removed.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"identifier": "migrated",
|
||||
"description": "permissions that were migrated from v1",
|
||||
"local": true,
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"core:app:default",
|
||||
"core:window:allow-maximize",
|
||||
"core:window:allow-unmaximize",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-unminimize",
|
||||
"core:window:allow-toggle-maximize",
|
||||
"core:window:allow-show",
|
||||
"core:window:allow-hide",
|
||||
"core:window:allow-close",
|
||||
"core:window:allow-start-dragging",
|
||||
"core:event:allow-listen",
|
||||
"shell:allow-open",
|
||||
"shell:default"
|
||||
]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"migrated":{"identifier":"migrated","description":"permissions that were migrated from v1","local":true,"windows":["main"],"permissions":["core:app:default","core:window:allow-maximize","core:window:allow-unmaximize","core:window:allow-minimize","core:window:allow-unminimize","core:window:allow-toggle-maximize","core:window:allow-show","core:window:allow-hide","core:window:allow-close","core:window:allow-start-dragging","core:event:allow-listen","shell:allow-open","shell:default"]}}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,32 +1,32 @@
|
||||
use aes::Aes256;
|
||||
use block_modes::{BlockMode, Cbc};
|
||||
use block_modes::block_padding::Pkcs7;
|
||||
use rand::Rng;
|
||||
|
||||
type Aes256Cbc = Cbc<Aes256, Pkcs7>;
|
||||
|
||||
pub fn encrypt(key: &[u8], data: &str) -> Vec<u8> {
|
||||
let iv = rand::thread_rng().gen::<[u8; 16]>(); // Генерация соли
|
||||
let cipher = Aes256Cbc::new_from_slices(key, &iv).unwrap(); // Создание шифратора
|
||||
let ciphertext = cipher.encrypt_vec(data.as_bytes()); // Шифрование строки
|
||||
let res: &[u8] = &ciphertext[..];
|
||||
[&iv, res].concat() // Вывод данных в виде 256-битного массива
|
||||
}
|
||||
|
||||
pub fn decrypt(key: &[u8], encrypted_data: &[u8]) -> String {
|
||||
let iv = &encrypted_data[0..16]; // Получение соли из данных
|
||||
let ciphertext = &encrypted_data[16..]; // Получение текста из данных
|
||||
|
||||
let cipher = Aes256Cbc::new_from_slices(key, iv).unwrap(); // Создание дешифратора
|
||||
let decrypted_ciphertext = cipher.decrypt_vec(ciphertext).unwrap(); // Дешифрование данных
|
||||
String::from_utf8(decrypted_ciphertext).unwrap() // Вывод результата в виде строки
|
||||
}
|
||||
|
||||
// Примеры
|
||||
//println!("TEST ENC: {:?}", crate::aes_enc_dec::encrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), "{\"command\": \"status1\"}"));
|
||||
//println!("TEST DEC: {:?}\n", crate::aes_enc_dec::decrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), &crate::aes_enc_dec::encrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), "{\"command\": \"status1\"}")));
|
||||
|
||||
//println!("REQ HEX: {:?}", req.trim());
|
||||
//println!("REQ u8: {:?}\n", hex::decode(req.trim()).unwrap());
|
||||
|
||||
//println!("DEC AES: {:?}", crate::aes_enc_dec::decrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), &hex::decode(req.trim()).unwrap()))
|
||||
use aes::Aes256;
|
||||
use block_modes::block_padding::Pkcs7;
|
||||
use block_modes::{BlockMode, Cbc};
|
||||
use rand::Rng;
|
||||
|
||||
type Aes256Cbc = Cbc<Aes256, Pkcs7>;
|
||||
|
||||
pub fn encrypt(key: &[u8], data: &str) -> Vec<u8> {
|
||||
let iv = rand::thread_rng().gen::<[u8; 16]>(); // Генерация соли
|
||||
let cipher = Aes256Cbc::new_from_slices(key, &iv).unwrap(); // Создание шифратора
|
||||
let ciphertext = cipher.encrypt_vec(data.as_bytes()); // Шифрование строки
|
||||
let res: &[u8] = &ciphertext[..];
|
||||
[&iv, res].concat() // Вывод данных в виде 256-битного массива
|
||||
}
|
||||
|
||||
pub fn decrypt(key: &[u8], encrypted_data: &[u8]) -> String {
|
||||
let iv = &encrypted_data[0..16]; // Получение соли из данных
|
||||
let ciphertext = &encrypted_data[16..]; // Получение текста из данных
|
||||
|
||||
let cipher = Aes256Cbc::new_from_slices(key, iv).unwrap(); // Создание дешифратора
|
||||
let decrypted_ciphertext = cipher.decrypt_vec(ciphertext).unwrap(); // Дешифрование данных
|
||||
String::from_utf8(decrypted_ciphertext).unwrap() // Вывод результата в виде строки
|
||||
}
|
||||
|
||||
// Примеры
|
||||
//println!("TEST ENC: {:?}", crate::aes_enc_dec::encrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), "{\"command\": \"status1\"}"));
|
||||
//println!("TEST DEC: {:?}\n", crate::aes_enc_dec::decrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), &crate::aes_enc_dec::encrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), "{\"command\": \"status1\"}")));
|
||||
|
||||
//println!("REQ HEX: {:?}", req.trim());
|
||||
//println!("REQ u8: {:?}\n", hex::decode(req.trim()).unwrap());
|
||||
|
||||
//println!("DEC AES: {:?}", crate::aes_enc_dec::decrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), &hex::decode(req.trim()).unwrap()))
|
||||
|
||||
+123
-131
@@ -1,131 +1,123 @@
|
||||
use std::fs::{File, read_to_string};
|
||||
use std::path::Path;
|
||||
use serde_json::{json, Value};
|
||||
use crate::enc_dec_file::{encrypt_n_save_file, decrypt_file};
|
||||
|
||||
use rand::Rng;
|
||||
use rand::distributions::Uniform;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn check_or_create_config_file(app_handle: tauri::AppHandle) {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("config_api");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let exist: bool = Path::new(&path).exists();
|
||||
if exist{
|
||||
let content = read_to_string(path);
|
||||
return match content {
|
||||
Ok(_) => {},
|
||||
Err(_) => {
|
||||
println!("Не удалось открыть конфигурационный файл!");
|
||||
}
|
||||
}
|
||||
} else{
|
||||
let path = Path::new(&path);
|
||||
let prefix = path.parent().unwrap();
|
||||
let file = std::fs::create_dir_all(prefix);
|
||||
match file{
|
||||
Ok(_) => {},
|
||||
Err(err) => println!("Не удалось создать директории! \n{}", err)
|
||||
}
|
||||
let file = File::create(path);
|
||||
match file{
|
||||
Ok(_) => {
|
||||
let rand_s: String = rand::thread_rng()
|
||||
.sample_iter(Uniform::new(char::from(32), char::from(126)))
|
||||
.take(64)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
let token: String = rand_s.replace("'", "").replace('"', "")
|
||||
.replace("{", "").replace("}", "").replace("[", "")
|
||||
.replace("}", "").replace("\\", "").replace("'", "");
|
||||
|
||||
|
||||
let data = String::from(format!("{}\
|
||||
\"port\": 49494,\
|
||||
\"autostart\": false,\
|
||||
\"token\": \"{}\"\
|
||||
{}", "{", token, "}"));
|
||||
encrypt_n_save_file(path.into(), data);
|
||||
},
|
||||
Err(err) => println!("Не удалось создать файл! \n{}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_port(app_handle: tauri::AppHandle) -> i64 {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("config_api");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let content = decrypt_file(path.clone());
|
||||
let data = serde_json::from_str::<Value>(content.as_str());
|
||||
match data {
|
||||
Ok(data) => {
|
||||
return data["port"].as_i64().unwrap();
|
||||
},
|
||||
Err(_) => {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
check_or_create_config_file(app_handle.clone());
|
||||
return get_port(app_handle.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_autostart(app_handle: tauri::AppHandle) -> bool {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("config_api");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let content = decrypt_file(path);
|
||||
let data = serde_json::from_str::<Value>(content.as_str());
|
||||
match data {
|
||||
Ok(d) => return d["autostart"].as_bool().unwrap(),
|
||||
Err(err) => {println!("{}", err); return false;}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn edit_settings(app_handle: tauri::AppHandle, port: i32, autostart: bool) {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("config_api");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let content = decrypt_file(path.clone());
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
data["port"] = json!(port);
|
||||
data["autostart"] = json!(autostart);
|
||||
|
||||
encrypt_n_save_file(path.into(), data.to_string());
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn reset_token(app_handle: tauri::AppHandle) -> String {
|
||||
let mut path = app_handle.path_resolver().app_local_data_dir().unwrap();
|
||||
path.push("ToDo");
|
||||
path.push("config_api");
|
||||
|
||||
path.set_extension("enc");
|
||||
|
||||
let key = rand::thread_rng().gen::<[u8; 32]>(); // 256-битный ключ
|
||||
|
||||
let content = decrypt_file(path.clone());
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
data["token"] = json!(hex::encode(&key.clone()));
|
||||
|
||||
encrypt_n_save_file(path.into(), data.to_string());
|
||||
|
||||
return hex::encode(&key.clone());
|
||||
}
|
||||
use crate::enc_dec_file::{decrypt_file, encrypt_n_save_file};
|
||||
use serde_json::{json, Value};
|
||||
use std::fs::{read_to_string, File};
|
||||
use std::path::Path;
|
||||
use tauri::path::BaseDirectory;
|
||||
|
||||
use rand::distributions::Uniform;
|
||||
use rand::Rng;
|
||||
use tauri::Manager;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn check_or_create_config_file(app_handle: tauri::AppHandle) {
|
||||
let path = app_handle.path().resolve("ToDo/config_api.enc", BaseDirectory::AppLocalData).unwrap();
|
||||
|
||||
let exist: bool = Path::new(&path).exists();
|
||||
if exist {
|
||||
let content = read_to_string(path);
|
||||
return match content {
|
||||
Ok(_) => {}
|
||||
Err(_) => {
|
||||
println!("Не удалось открыть конфигурационный файл!");
|
||||
}
|
||||
};
|
||||
} else {
|
||||
let path = Path::new(&path);
|
||||
let prefix = path.parent().unwrap();
|
||||
let file = std::fs::create_dir_all(prefix);
|
||||
match file {
|
||||
Ok(_) => {}
|
||||
Err(err) => println!("Не удалось создать директории! \n{}", err),
|
||||
}
|
||||
let file = File::create(path);
|
||||
match file {
|
||||
Ok(_) => {
|
||||
let rand_s: String = rand::thread_rng()
|
||||
.sample_iter(Uniform::new(char::from(32), char::from(126)))
|
||||
.take(64)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
let token: String = rand_s
|
||||
.replace("'", "")
|
||||
.replace('"', "")
|
||||
.replace("{", "")
|
||||
.replace("}", "")
|
||||
.replace("[", "")
|
||||
.replace("}", "")
|
||||
.replace("\\", "")
|
||||
.replace("'", "");
|
||||
|
||||
let data = String::from(format!(
|
||||
"{}\
|
||||
\"port\": 49494,\
|
||||
\"autostart\": false,\
|
||||
\"token\": \"{}\"\
|
||||
{}",
|
||||
"{", token, "}"
|
||||
));
|
||||
encrypt_n_save_file(path.into(), data);
|
||||
}
|
||||
Err(err) => println!("Не удалось создать файл! \n{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_port(app_handle: tauri::AppHandle) -> i64 {
|
||||
let path = app_handle.path().resolve("ToDo/config_api.enc", BaseDirectory::AppLocalData).unwrap();
|
||||
|
||||
let content = decrypt_file(path.clone());
|
||||
let data = serde_json::from_str::<Value>(content.as_str());
|
||||
match data {
|
||||
Ok(data) => {
|
||||
return data["port"].as_i64().unwrap();
|
||||
}
|
||||
Err(_) => {
|
||||
std::fs::remove_file(path).unwrap();
|
||||
check_or_create_config_file(app_handle.clone());
|
||||
return get_port(app_handle.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_autostart(app_handle: tauri::AppHandle) -> bool {
|
||||
let path = app_handle.path().resolve("ToDo/config_api.enc", BaseDirectory::AppLocalData).unwrap();
|
||||
|
||||
let content = decrypt_file(path);
|
||||
let data = serde_json::from_str::<Value>(content.as_str());
|
||||
match data {
|
||||
Ok(d) => return d["autostart"].as_bool().unwrap(),
|
||||
Err(err) => {
|
||||
println!("{}", err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn edit_settings(app_handle: tauri::AppHandle, port: i32, autostart: bool) {
|
||||
let path = app_handle.path().resolve("ToDo/config_api.enc", BaseDirectory::AppLocalData).unwrap();
|
||||
|
||||
let content = decrypt_file(path.clone());
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
data["port"] = json!(port);
|
||||
data["autostart"] = json!(autostart);
|
||||
|
||||
encrypt_n_save_file(path.into(), data.to_string());
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn reset_token(app_handle: tauri::AppHandle) -> String {
|
||||
let path = app_handle.path().resolve("ToDo/config_api.enc", BaseDirectory::AppLocalData).unwrap();
|
||||
|
||||
let key = rand::thread_rng().gen::<[u8; 32]>(); // 256-битный ключ
|
||||
|
||||
let content = decrypt_file(path.clone());
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
data["token"] = json!(hex::encode(&key.clone()));
|
||||
|
||||
encrypt_n_save_file(path.into(), data.to_string());
|
||||
|
||||
return hex::encode(&key.clone());
|
||||
}
|
||||
|
||||
@@ -1,75 +1,92 @@
|
||||
use serde_json::Value;
|
||||
use chrono::{DateTime, Local};
|
||||
|
||||
use crate::aes_enc_dec::encrypt;
|
||||
use crate::tasks;
|
||||
|
||||
pub fn get_tasks_tcp(token: String) -> Vec<u8>{
|
||||
encrypt(&hex::decode(token).unwrap(), tasks::get_tasks().to_string().as_str())
|
||||
}
|
||||
|
||||
pub fn get_task_by_id_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
let tasks: Value = tasks::get_tasks();
|
||||
let res;
|
||||
if !json.get("id").is_none(){
|
||||
res = encrypt(&hex::decode(token).unwrap(), tasks[json["id"].as_str().unwrap_or("")].to_string().as_str());
|
||||
} else{
|
||||
res = encrypt(&hex::decode(token).unwrap(), "400");
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
pub fn create_task_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
if json["task"].is_object(){
|
||||
if json["task"]["name"].is_string(){
|
||||
let current_datetime: DateTime<Local> = Local::now();
|
||||
let date: String = current_datetime.format("%Y.%m.%d").to_string();
|
||||
let time: String = current_datetime.format("%H:%M").to_string();
|
||||
|
||||
let name = json["task"]["name"].as_str().unwrap().to_string();
|
||||
let description = json["task"]["description"].as_str().unwrap_or("").to_string();
|
||||
let priority = json["task"]["priority"].as_str().unwrap_or("0").to_string();
|
||||
|
||||
encrypt(&hex::decode(token).unwrap(), tasks::add_task(date, time, name, description, priority).as_str())
|
||||
} else{
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
} else{
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edit_task_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
if json["task"].is_object(){
|
||||
if json["task"]["id"].is_number(){
|
||||
let id_task = json["task"]["id"].as_number().unwrap().to_string();
|
||||
let name = json["task"]["name"].as_str().unwrap().to_string();
|
||||
let description = json["task"]["description"].as_str().unwrap_or("").to_string();
|
||||
let priority = json["task"]["priority"].as_str().unwrap_or("0").to_string();
|
||||
|
||||
if tasks::edit_task(id_task, name, description, priority) {
|
||||
encrypt(&hex::decode(token).unwrap(), "200")
|
||||
} else{
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
} else{
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
} else{
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_task_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
let res;
|
||||
if !json.get("id").is_none(){
|
||||
if tasks::delete_task(json["id"].to_string()){
|
||||
res = encrypt(&hex::decode(token).unwrap(), "200");
|
||||
} else{
|
||||
res = encrypt(&hex::decode(token).unwrap(), "400");
|
||||
}
|
||||
} else{
|
||||
res = encrypt(&hex::decode(token).unwrap(), "400");
|
||||
}
|
||||
res
|
||||
}
|
||||
use chrono::{DateTime, Local};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::aes_enc_dec::encrypt;
|
||||
use crate::tasks;
|
||||
|
||||
pub fn get_tasks_tcp(token: String) -> Vec<u8> {
|
||||
encrypt(
|
||||
&hex::decode(token).unwrap(),
|
||||
tasks::get_tasks().to_string().as_str(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_task_by_id_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
let tasks: Value = tasks::get_tasks();
|
||||
let res;
|
||||
if !json.get("id").is_none() {
|
||||
res = encrypt(
|
||||
&hex::decode(token).unwrap(),
|
||||
tasks[json["id"].as_str().unwrap_or("")]
|
||||
.to_string()
|
||||
.as_str(),
|
||||
);
|
||||
} else {
|
||||
res = encrypt(&hex::decode(token).unwrap(), "400");
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
pub fn create_task_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
if json["task"].is_object() {
|
||||
if json["task"]["name"].is_string() {
|
||||
let current_datetime: DateTime<Local> = Local::now();
|
||||
let date: String = current_datetime.format("%Y.%m.%d").to_string();
|
||||
let time: String = current_datetime.format("%H:%M").to_string();
|
||||
|
||||
let name = json["task"]["name"].as_str().unwrap().to_string();
|
||||
let description = json["task"]["description"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
let priority = json["task"]["priority"].as_str().unwrap_or("0").to_string();
|
||||
|
||||
encrypt(
|
||||
&hex::decode(token).unwrap(),
|
||||
tasks::add_task(date, time, name, description, priority).as_str(),
|
||||
)
|
||||
} else {
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
} else {
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edit_task_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
if json["task"].is_object() {
|
||||
if json["task"]["id"].is_number() {
|
||||
let id_task = json["task"]["id"].as_number().unwrap().to_string();
|
||||
let name = json["task"]["name"].as_str().unwrap().to_string();
|
||||
let description = json["task"]["description"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
let priority = json["task"]["priority"].as_str().unwrap_or("0").to_string();
|
||||
|
||||
if tasks::edit_task(id_task, name, description, priority) {
|
||||
encrypt(&hex::decode(token).unwrap(), "200")
|
||||
} else {
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
} else {
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
} else {
|
||||
encrypt(&hex::decode(token).unwrap(), "400")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_task_tcp(token: String, json: Value) -> Vec<u8> {
|
||||
let res;
|
||||
if !json.get("id").is_none() {
|
||||
if tasks::delete_task(json["id"].to_string()) {
|
||||
res = encrypt(&hex::decode(token).unwrap(), "200");
|
||||
} else {
|
||||
res = encrypt(&hex::decode(token).unwrap(), "400");
|
||||
}
|
||||
} else {
|
||||
res = encrypt(&hex::decode(token).unwrap(), "400");
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
@@ -1,171 +1,196 @@
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
use std::net::{TcpListener, TcpStream};
|
||||
use std::path::PathBuf;
|
||||
use std::thread;
|
||||
use std::string::String;
|
||||
use serde_json::Value;
|
||||
use tauri::{AppHandle, Manager};
|
||||
|
||||
use crate::{config_tcp, handler_commands};
|
||||
use crate::enc_dec_file::decrypt_file;
|
||||
use crate::aes_enc_dec::{encrypt, decrypt};
|
||||
|
||||
static mut TCP_COMMAND: &str = "";
|
||||
static mut PATH_CONFIG: Option<&'static str> = None;
|
||||
|
||||
fn get_token() -> String{
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
return data["token"].as_str().unwrap().to_string();
|
||||
}
|
||||
} // Получение токена доступа
|
||||
|
||||
fn data_to_enc_hex(data: &str) -> String{
|
||||
hex::encode(encrypt(&hex::decode(get_token()).unwrap(), data))
|
||||
} // Шифрование строки до данных обёрнутых в HEX
|
||||
|
||||
fn enc_hex_to_data(data: &str) -> String{
|
||||
decrypt(&hex::decode(get_token()).unwrap(), &hex::decode(data).unwrap())
|
||||
} // Расшифровка обёрнутых в HEX данных до строки
|
||||
|
||||
|
||||
fn create_tcp_listener(app_handle: AppHandle) -> TcpListener{
|
||||
let path: PathBuf = [
|
||||
app_handle.path_resolver().app_local_data_dir().unwrap(),
|
||||
"ToDo".into(),
|
||||
"config_api.enc".into(),
|
||||
].iter().collect(); // Путь к конфиг файлу
|
||||
|
||||
let path_str = Box::leak(Box::new(path.to_string_lossy().into_owned()));
|
||||
|
||||
unsafe {
|
||||
PATH_CONFIG = Some(path_str);
|
||||
}
|
||||
|
||||
return match TcpListener::bind(format!("127.0.0.1:{}", config_tcp::get_port(app_handle.clone()))){ // Создание TCP слушателя на локальном порту
|
||||
Ok(tcp) => {
|
||||
for stream in tcp.incoming() {
|
||||
unsafe {
|
||||
TCP_COMMAND = "";
|
||||
}
|
||||
|
||||
let stream = stream.unwrap(); // Получение запроса
|
||||
|
||||
let thread = thread::spawn(move || { // Создание отдельного потока
|
||||
handle_connection(stream); // Обработка запроса
|
||||
});
|
||||
|
||||
thread.join().unwrap(); // Ожидание пока завершится поток
|
||||
|
||||
unsafe {
|
||||
match TCP_COMMAND { // Сравнивание команд
|
||||
"stop" => {
|
||||
app_handle.emit_all("update_api", "").unwrap();
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tcp
|
||||
},
|
||||
Err(err) => {
|
||||
println!("{}", err);
|
||||
TcpListener::bind("").unwrap()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn handle_connection(mut stream: TcpStream) {
|
||||
let mut buf_reader = BufReader::new(&mut stream);
|
||||
let mut req = String::new(); // Получение body запроса
|
||||
match buf_reader.read_line(&mut req) {
|
||||
Ok(_) => {
|
||||
if req.len() > 0 {
|
||||
let res = enc_hex_to_data(req.trim()); // Дешифрование
|
||||
let json: Value = serde_json::from_str(res.as_str()).unwrap_or(serde_json::json!("")); // Попытка преобразования запроса в JSON
|
||||
if json != serde_json::json!(""){
|
||||
println!("JSON: {:?}", json);
|
||||
println!("JSON command: {:?}", json["command"]);
|
||||
match json["command"].as_str().unwrap() { // Сравнивание команд
|
||||
"stop" => {
|
||||
unsafe {
|
||||
TCP_COMMAND = "stop";
|
||||
}
|
||||
let res = encrypt(&hex::decode(get_token()).unwrap(), "200");
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"status" => {
|
||||
let res = encrypt(&hex::decode(get_token()).unwrap(), "200");
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"get_tasks" => {
|
||||
let res = handler_commands::get_tasks_tcp(get_token());
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"get_task_by_id" => {
|
||||
let res = handler_commands::get_task_by_id_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"create_task" => {
|
||||
let res = handler_commands::create_task_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"edit_task" => {
|
||||
let res = handler_commands::edit_task_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
"delete_task" => {
|
||||
let res = handler_commands::delete_task_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
} else{
|
||||
stream.write(hex::encode(encrypt(&hex::decode(get_token()).unwrap(), "400")).as_bytes()).unwrap();
|
||||
}
|
||||
}
|
||||
},
|
||||
what => {
|
||||
println!("{:?}", what);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn start_tcp_server(app_handle: AppHandle){
|
||||
let handle = app_handle.clone();
|
||||
thread::spawn(move || { // Создание потока
|
||||
create_tcp_listener(handle); // Создание слушателя
|
||||
});
|
||||
app_handle.emit_all("update_api", "").unwrap(); // Глобальное сообщение для фронтенда для обновления API страницы
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_status(app_handle: AppHandle) -> bool{
|
||||
match TcpListener::bind(format!("127.0.0.1:{}", config_tcp::get_port(app_handle))) { // Получения статуса слушателя, с помощью нового слушателя
|
||||
Ok(_) => {
|
||||
false // Если удалось создать возвращаем false, т.к. слушателя не было
|
||||
},
|
||||
Err(_) => {
|
||||
true // Иначе true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn send_command_to_server(app_handle: AppHandle, command: String) -> bool{
|
||||
match TcpStream::connect(format!("127.0.0.1:{}", config_tcp::get_port(app_handle))) { // Подключение к слушателю
|
||||
Ok(mut tcp) => {
|
||||
tcp.write_all(data_to_enc_hex(format!("{}: \"{}\" {}", "{\"command\"", command, "}\n").as_str()).as_bytes()).unwrap(); // Отправление команды
|
||||
true
|
||||
},
|
||||
Err(err) => {
|
||||
println!("{}", err);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
use serde_json::Value;
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
use std::net::{TcpListener, TcpStream};
|
||||
use std::path::PathBuf;
|
||||
use std::string::String;
|
||||
use std::thread;
|
||||
use tauri::{AppHandle, Emitter, Manager};
|
||||
use tauri::path::BaseDirectory;
|
||||
|
||||
use crate::aes_enc_dec::{decrypt, encrypt};
|
||||
use crate::enc_dec_file::decrypt_file;
|
||||
use crate::{config_tcp, handler_commands};
|
||||
|
||||
static mut TCP_COMMAND: &str = "";
|
||||
static mut PATH_CONFIG: Option<&'static str> = None;
|
||||
|
||||
fn get_token() -> String {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
return data["token"].as_str().unwrap().to_string();
|
||||
}
|
||||
} // Получение токена доступа
|
||||
|
||||
fn data_to_enc_hex(data: &str) -> String {
|
||||
hex::encode(encrypt(&hex::decode(get_token()).unwrap(), data))
|
||||
} // Шифрование строки до данных обёрнутых в HEX
|
||||
|
||||
fn enc_hex_to_data(data: &str) -> String {
|
||||
decrypt(
|
||||
&hex::decode(get_token()).unwrap(),
|
||||
&hex::decode(data).unwrap(),
|
||||
)
|
||||
} // Расшифровка обёрнутых в HEX данных до строки
|
||||
|
||||
fn create_tcp_listener(app_handle: AppHandle) -> TcpListener {
|
||||
let path: PathBuf = [
|
||||
app_handle.path().resolve("ToDo/config_api.enc", BaseDirectory::AppLocalData).unwrap(),
|
||||
"ToDo".into(),
|
||||
"config_api.enc".into(),
|
||||
]
|
||||
.iter()
|
||||
.collect(); // Путь к конфиг файлу
|
||||
|
||||
let path_str = Box::leak(Box::new(path.to_string_lossy().into_owned()));
|
||||
|
||||
unsafe {
|
||||
PATH_CONFIG = Some(path_str);
|
||||
}
|
||||
|
||||
return match TcpListener::bind(format!(
|
||||
"127.0.0.1:{}",
|
||||
config_tcp::get_port(app_handle.clone())
|
||||
)) {
|
||||
// Создание TCP слушателя на локальном порту
|
||||
Ok(tcp) => {
|
||||
for stream in tcp.incoming() {
|
||||
unsafe {
|
||||
TCP_COMMAND = "";
|
||||
}
|
||||
|
||||
let stream = stream.unwrap(); // Получение запроса
|
||||
|
||||
let thread = thread::spawn(move || {
|
||||
// Создание отдельного потока
|
||||
handle_connection(stream); // Обработка запроса
|
||||
});
|
||||
|
||||
thread.join().unwrap(); // Ожидание пока завершится поток
|
||||
|
||||
unsafe {
|
||||
match TCP_COMMAND {
|
||||
// Сравнивание команд
|
||||
"stop" => {
|
||||
app_handle.emit("update_api", "").unwrap();
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tcp
|
||||
}
|
||||
Err(err) => {
|
||||
println!("{}", err);
|
||||
TcpListener::bind("").unwrap()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn handle_connection(mut stream: TcpStream) {
|
||||
let mut buf_reader = BufReader::new(&mut stream);
|
||||
let mut req = String::new(); // Получение body запроса
|
||||
match buf_reader.read_line(&mut req) {
|
||||
Ok(_) => {
|
||||
if req.len() > 0 {
|
||||
let res = enc_hex_to_data(req.trim()); // Дешифрование
|
||||
let json: Value =
|
||||
serde_json::from_str(res.as_str()).unwrap_or(serde_json::json!("")); // Попытка преобразования запроса в JSON
|
||||
if json != serde_json::json!("") {
|
||||
println!("JSON: {:?}", json);
|
||||
println!("JSON command: {:?}", json["command"]);
|
||||
match json["command"].as_str().unwrap() {
|
||||
// Сравнивание команд
|
||||
"stop" => {
|
||||
unsafe {
|
||||
TCP_COMMAND = "stop";
|
||||
}
|
||||
let res = encrypt(&hex::decode(get_token()).unwrap(), "200");
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
}
|
||||
"status" => {
|
||||
let res = encrypt(&hex::decode(get_token()).unwrap(), "200");
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
}
|
||||
"get_tasks" => {
|
||||
let res = handler_commands::get_tasks_tcp(get_token());
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
}
|
||||
"get_task_by_id" => {
|
||||
let res = handler_commands::get_task_by_id_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
}
|
||||
"create_task" => {
|
||||
let res = handler_commands::create_task_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
}
|
||||
"edit_task" => {
|
||||
let res = handler_commands::edit_task_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
}
|
||||
"delete_task" => {
|
||||
let res = handler_commands::delete_task_tcp(get_token(), json);
|
||||
stream.write(hex::encode(res).as_bytes()).unwrap();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
stream
|
||||
.write(
|
||||
hex::encode(encrypt(&hex::decode(get_token()).unwrap(), "400"))
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
what => {
|
||||
println!("{:?}", what);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn start_tcp_server(app_handle: AppHandle) {
|
||||
let handle = app_handle.clone();
|
||||
thread::spawn(move || {
|
||||
// Создание потока
|
||||
create_tcp_listener(handle); // Создание слушателя
|
||||
});
|
||||
app_handle.emit("update_api", "").unwrap(); // Глобальное сообщение для фронтенда для обновления API страницы
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_status(app_handle: AppHandle) -> bool {
|
||||
match TcpListener::bind(format!("127.0.0.1:{}", config_tcp::get_port(app_handle))) {
|
||||
// Получения статуса слушателя, с помощью нового слушателя
|
||||
Ok(_) => {
|
||||
false // Если удалось создать возвращаем false, т.к. слушателя не было
|
||||
}
|
||||
Err(_) => {
|
||||
true // Иначе true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn send_command_to_server(app_handle: AppHandle, command: String) -> bool {
|
||||
match TcpStream::connect(format!("127.0.0.1:{}", config_tcp::get_port(app_handle))) {
|
||||
// Подключение к слушателю
|
||||
Ok(mut tcp) => {
|
||||
tcp.write_all(
|
||||
data_to_enc_hex(format!("{}: \"{}\" {}", "{\"command\"", command, "}\n").as_str())
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap(); // Отправление команды
|
||||
true
|
||||
}
|
||||
Err(err) => {
|
||||
println!("{}", err);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
use std::fs::{read_to_string, write};
|
||||
use std::path::PathBuf;
|
||||
use magic_crypt::{MagicCryptTrait, new_magic_crypt};
|
||||
|
||||
use crate::config;
|
||||
|
||||
pub fn encrypt_n_save_file(path: PathBuf, content: String){
|
||||
let key = config::ENC_KEY;
|
||||
let mc = new_magic_crypt!(key, 256);
|
||||
let mut encrypted: String = String::new();
|
||||
|
||||
for line in content.lines() {
|
||||
encrypted = encrypted.to_owned() + mc.encrypt_str_to_base64(line).as_str() + "\n";
|
||||
}
|
||||
let res = write(path, encrypted);
|
||||
match res {
|
||||
Ok(_) => {},
|
||||
Err(_) => println!("File save error!")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrypt_file(path: PathBuf) -> String {
|
||||
let key = config::ENC_KEY;
|
||||
let mc = new_magic_crypt!(key, 256);
|
||||
let mut decrypted: String = String::new();
|
||||
|
||||
let lines = read_to_string(path);
|
||||
match lines {
|
||||
Ok(lines) => {
|
||||
for line in lines.lines() {
|
||||
let dec_line = mc.decrypt_base64_to_string(&line);
|
||||
match dec_line {
|
||||
Ok(line) => {
|
||||
decrypted = decrypted.to_owned() + line.as_str() + "\n";
|
||||
return decrypted;
|
||||
},
|
||||
Err(_) => {
|
||||
println!("Что-то пошло не так!");
|
||||
}
|
||||
}
|
||||
}
|
||||
return String::new();
|
||||
},
|
||||
Err(_) => {
|
||||
println!("Что-то не так...");
|
||||
return String::new();
|
||||
}
|
||||
}
|
||||
}
|
||||
use magic_crypt::{new_magic_crypt, MagicCryptTrait};
|
||||
use std::fs::{read_to_string, write};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::config;
|
||||
|
||||
pub fn encrypt_n_save_file(path: PathBuf, content: String) {
|
||||
let key = config::ENC_KEY;
|
||||
let mc = new_magic_crypt!(key, 256);
|
||||
let mut encrypted: String = String::new();
|
||||
|
||||
for line in content.lines() {
|
||||
encrypted = encrypted.to_owned() + mc.encrypt_str_to_base64(line).as_str() + "\n";
|
||||
}
|
||||
let res = write(path, encrypted);
|
||||
match res {
|
||||
Ok(_) => {}
|
||||
Err(_) => println!("File save error!"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decrypt_file(path: PathBuf) -> String {
|
||||
let key = config::ENC_KEY;
|
||||
let mc = new_magic_crypt!(key, 256);
|
||||
let mut decrypted: String = String::new();
|
||||
|
||||
let lines = read_to_string(path);
|
||||
match lines {
|
||||
Ok(lines) => {
|
||||
for line in lines.lines() {
|
||||
let dec_line = mc.decrypt_base64_to_string(&line);
|
||||
match dec_line {
|
||||
Ok(line) => {
|
||||
decrypted = decrypted.to_owned() + line.as_str() + "\n";
|
||||
return decrypted;
|
||||
}
|
||||
Err(_) => {
|
||||
println!("Что-то пошло не так!");
|
||||
}
|
||||
}
|
||||
}
|
||||
return String::new();
|
||||
}
|
||||
Err(_) => {
|
||||
println!("Что-то не так...");
|
||||
return String::new();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
#[path = "api/aes_enc_dec.rs"] mod aes_enc_dec;
|
||||
#[path = "api/config_tcp.rs"] mod config_tcp;
|
||||
#[path = "api/handler_commands.rs"] mod handler_commands;
|
||||
#[path = "api/multithread_tcp_listener.rs"] mod multi_tcp_listener;
|
||||
|
||||
#[path = "config.rs"] mod config;
|
||||
#[path = "enc_dec_file.rs"] mod enc_dec_file;
|
||||
#[path = "subtasks_functions.rs"] mod subtasks;
|
||||
#[path = "tasks_functions.rs"] mod tasks;
|
||||
|
||||
pub fn run() {
|
||||
unsafe {
|
||||
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||
}
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.setup(|app| {
|
||||
let app_handle = app.handle();
|
||||
|
||||
config_tcp::check_or_create_config_file(app_handle.clone());
|
||||
if config_tcp::get_autostart(app_handle.clone()) {
|
||||
multi_tcp_listener::start_tcp_server(app_handle.clone());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
tasks::check_or_create_tasks_file,
|
||||
// Tasks
|
||||
tasks::get_tasks,
|
||||
tasks::search_tasks,
|
||||
tasks::add_task,
|
||||
tasks::edit_task,
|
||||
tasks::delete_task,
|
||||
tasks::set_task_field,
|
||||
// Subtasks
|
||||
subtasks::get_subtasks,
|
||||
subtasks::add_subtask,
|
||||
subtasks::edit_subtask,
|
||||
subtasks::delete_subtask,
|
||||
subtasks::set_subtask_field,
|
||||
multi_tcp_listener::start_tcp_server,
|
||||
multi_tcp_listener::get_status,
|
||||
multi_tcp_listener::send_command_to_server,
|
||||
config_tcp::check_or_create_config_file,
|
||||
config_tcp::get_port,
|
||||
config_tcp::get_autostart,
|
||||
config_tcp::edit_settings,
|
||||
config_tcp::reset_token
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
+5
-56
@@ -1,56 +1,5 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
#[path="api/multithread_tcp_listener.rs"] mod multi_tcp_listener;
|
||||
#[path= "api/handler_commands.rs"] mod handler_commands;
|
||||
#[path= "api/config_tcp.rs"] mod config_tcp;
|
||||
#[path= "api/aes_enc_dec.rs"] mod aes_enc_dec;
|
||||
|
||||
#[path="tasks_functions.rs"] mod tasks;
|
||||
#[path="subtasks_functions.rs"] mod subtasks;
|
||||
#[path="config.rs"] mod config;
|
||||
#[path="enc_dec_file.rs"] mod enc_dec_file;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
|
||||
}
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let app_handle = app.handle();
|
||||
|
||||
config_tcp::check_or_create_config_file(app_handle.clone());
|
||||
if config_tcp::get_autostart(app_handle.clone()) {
|
||||
multi_tcp_listener::start_tcp_server(app_handle);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
tasks::check_or_create_tasks_file,
|
||||
// Tasks
|
||||
tasks::get_tasks,
|
||||
tasks::search_tasks,
|
||||
tasks::add_task,
|
||||
tasks::edit_task,
|
||||
tasks::delete_task,
|
||||
tasks::set_task_field,
|
||||
// Subtasks
|
||||
subtasks::get_subtasks,
|
||||
subtasks::add_subtask,
|
||||
subtasks::edit_subtask,
|
||||
subtasks::delete_subtask,
|
||||
subtasks::set_subtask_field,
|
||||
multi_tcp_listener::start_tcp_server,
|
||||
multi_tcp_listener::get_status,
|
||||
multi_tcp_listener::send_command_to_server,
|
||||
config_tcp::check_or_create_config_file,
|
||||
config_tcp::get_port,
|
||||
config_tcp::get_autostart,
|
||||
config_tcp::edit_settings,
|
||||
config_tcp::reset_token
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
fn main() {
|
||||
app_lib::run();
|
||||
}
|
||||
|
||||
+134
-103
@@ -1,103 +1,134 @@
|
||||
use std::path::PathBuf;
|
||||
use serde_json::{json, Value};
|
||||
use crate::enc_dec_file::{decrypt_file, encrypt_n_save_file};
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_subtasks(id_task: String) -> Value {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()));
|
||||
let data = serde_json::from_str::<Value>(content.as_str());
|
||||
return match data {
|
||||
Ok(data) => {
|
||||
let res: &Value = &data["tasks"][id_task.clone()]["subtasks"];
|
||||
res.clone()
|
||||
},
|
||||
Err(_) => {
|
||||
std::fs::remove_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap())).unwrap();
|
||||
let data = String::from("{\
|
||||
\"id\": 0,\
|
||||
\"tasks\": {}\
|
||||
}");
|
||||
encrypt_n_save_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()), data);
|
||||
|
||||
return get_subtasks(id_task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn add_subtask(id_task: String, date: String, time: String, name: String, description: String) -> String {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let pending = data.clone();
|
||||
let id = &pending["id"];
|
||||
|
||||
let subtask = json!({
|
||||
"id": id.to_string(),
|
||||
"date": date,
|
||||
"time": time,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"completed": false
|
||||
});
|
||||
|
||||
data["id"] = (id.as_i64().unwrap() + 1).into();
|
||||
|
||||
data["tasks"][id_task]["subtasks"][id.to_string()] = subtask;
|
||||
encrypt_n_save_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()), data.to_string());
|
||||
|
||||
return id.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn edit_subtask(id_task: String, id_subtask: String, name: String, description: String) -> bool{
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
return if !data["tasks"][id_task.clone()]["subtasks"][id_subtask.clone()].get("id").is_none(){
|
||||
data["tasks"][id_task.clone()]["subtasks"][id_subtask.clone()]["name"] = json!(name);
|
||||
data["tasks"][id_task.clone()]["subtasks"][id_subtask.clone()]["description"] = json!(description);
|
||||
|
||||
encrypt_n_save_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()), data.to_string());
|
||||
true
|
||||
} else{
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_subtask(id_task: String, id_subtask: String) -> bool{
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let subtasks = data["tasks"][id_task.clone()]["subtasks"].as_object_mut().unwrap();
|
||||
let binding = subtasks.clone();
|
||||
for (key, value) in binding {
|
||||
if id_subtask == value["id"] {
|
||||
subtasks.remove(&key);
|
||||
data["tasks"][id_task]["subtasks"] = json!(subtasks);
|
||||
encrypt_n_save_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()), data.to_string());
|
||||
return true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn set_subtask_field(id_task: String, id_subtask: String, field: String, value: String) {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
data["tasks"][id_task]["subtasks"][id_subtask][field] = json!(value);
|
||||
|
||||
encrypt_n_save_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()), data.to_string());
|
||||
}
|
||||
}
|
||||
use crate::enc_dec_file::{decrypt_file, encrypt_n_save_file};
|
||||
use serde_json::{json, Value};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_subtasks(id_task: String) -> Value {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()));
|
||||
let data = serde_json::from_str::<Value>(content.as_str());
|
||||
return match data {
|
||||
Ok(data) => {
|
||||
let res: &Value = &data["tasks"][id_task.clone()]["subtasks"];
|
||||
res.clone()
|
||||
}
|
||||
Err(_) => {
|
||||
std::fs::remove_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap())).unwrap();
|
||||
let data = String::from(
|
||||
"{\
|
||||
\"id\": 0,\
|
||||
\"tasks\": {}\
|
||||
}",
|
||||
);
|
||||
encrypt_n_save_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()), data);
|
||||
|
||||
return get_subtasks(id_task);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn add_subtask(
|
||||
id_task: String,
|
||||
date: String,
|
||||
time: String,
|
||||
name: String,
|
||||
description: String,
|
||||
) -> String {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let pending = data.clone();
|
||||
let id = &pending["id"];
|
||||
|
||||
let subtask = json!({
|
||||
"id": id.to_string(),
|
||||
"date": date,
|
||||
"time": time,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"completed": false
|
||||
});
|
||||
|
||||
data["id"] = (id.as_i64().unwrap() + 1).into();
|
||||
|
||||
data["tasks"][id_task]["subtasks"][id.to_string()] = subtask;
|
||||
encrypt_n_save_file(
|
||||
PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()),
|
||||
data.to_string(),
|
||||
);
|
||||
|
||||
return id.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn edit_subtask(
|
||||
id_task: String,
|
||||
id_subtask: String,
|
||||
name: String,
|
||||
description: String,
|
||||
) -> bool {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
return if !data["tasks"][id_task.clone()]["subtasks"][id_subtask.clone()]
|
||||
.get("id")
|
||||
.is_none()
|
||||
{
|
||||
data["tasks"][id_task.clone()]["subtasks"][id_subtask.clone()]["name"] = json!(name);
|
||||
data["tasks"][id_task.clone()]["subtasks"][id_subtask.clone()]["description"] =
|
||||
json!(description);
|
||||
|
||||
encrypt_n_save_file(
|
||||
PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()),
|
||||
data.to_string(),
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_subtask(id_task: String, id_subtask: String) -> bool {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let subtasks = data["tasks"][id_task.clone()]["subtasks"]
|
||||
.as_object_mut()
|
||||
.unwrap();
|
||||
let binding = subtasks.clone();
|
||||
for (key, value) in binding {
|
||||
if id_subtask == value["id"] {
|
||||
subtasks.remove(&key);
|
||||
data["tasks"][id_task]["subtasks"] = json!(subtasks);
|
||||
encrypt_n_save_file(
|
||||
PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()),
|
||||
data.to_string(),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn set_subtask_field(id_task: String, id_subtask: String, field: String, value: String) {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
data["tasks"][id_task]["subtasks"][id_subtask][field] = json!(value);
|
||||
|
||||
encrypt_n_save_file(
|
||||
PathBuf::from(crate::tasks::PATH_CONFIG.unwrap()),
|
||||
data.to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+214
-198
@@ -1,198 +1,214 @@
|
||||
use std::fs::{read_to_string};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::fs::File;
|
||||
use serde_json::{Value, json};
|
||||
use rust_fuzzy_search::fuzzy_search_best_n;
|
||||
|
||||
use crate::enc_dec_file::{encrypt_n_save_file, decrypt_file};
|
||||
|
||||
pub static mut PATH_CONFIG: Option<&'static str> = None;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn check_or_create_tasks_file(app_handle: tauri::AppHandle) {
|
||||
let path: PathBuf = [
|
||||
app_handle.path_resolver().app_local_data_dir().unwrap(),
|
||||
"ToDo".into(),
|
||||
"tasks.enc".into(),
|
||||
].iter().collect(); // Путь к конфиг файлу
|
||||
|
||||
let path_str = Box::leak(Box::new(path.to_string_lossy().into_owned()));
|
||||
|
||||
unsafe {
|
||||
PATH_CONFIG = Some(path_str);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let exist: bool = Path::new(PATH_CONFIG.unwrap()).exists();
|
||||
if exist{
|
||||
let content = read_to_string(path);
|
||||
return match content {
|
||||
Ok(_) => {},
|
||||
Err(_) => {
|
||||
println!("Не удалось открыть конфигурационный файл!");
|
||||
}
|
||||
}
|
||||
} else{
|
||||
let path = Path::new(&path);
|
||||
let prefix = path.parent().unwrap();
|
||||
let file = std::fs::create_dir_all(prefix);
|
||||
match file{
|
||||
Ok(_) => {},
|
||||
Err(err) => println!("Не удалось создать директории! \n{}", err)
|
||||
}
|
||||
let file = File::create(path);
|
||||
match file{
|
||||
Ok(_) => {
|
||||
let data = String::from("{\
|
||||
\"id\": 0,\
|
||||
\"tasks\": {}\
|
||||
}");
|
||||
encrypt_n_save_file(path.into(), data);
|
||||
},
|
||||
Err(err) => println!("Не удалось создать файл! \n{}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_tasks() -> Value {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let data = serde_json::from_str::<Value>(content.as_str());
|
||||
return match data {
|
||||
Ok(data) => {
|
||||
let res: &Value = &data["tasks"];
|
||||
|
||||
res.clone()
|
||||
},
|
||||
Err(_) => {
|
||||
std::fs::remove_file(PathBuf::from(PATH_CONFIG.unwrap())).unwrap();
|
||||
let data = String::from("{\
|
||||
\"id\": 0,\
|
||||
\"tasks\": {}\
|
||||
}");
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data);
|
||||
|
||||
return get_tasks();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn search_tasks(value: String) -> Value {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let mut tasks = vec![];
|
||||
|
||||
let binding = data.clone();
|
||||
for (_key, value) in binding["tasks"].as_object().unwrap() {
|
||||
tasks.push(value["name"].as_str().unwrap().to_lowercase());
|
||||
}
|
||||
|
||||
let tasks_str: Vec<&str> = tasks.iter().map(|s| &**s).collect();
|
||||
|
||||
let n: usize = 5;
|
||||
let binding = value.to_lowercase();
|
||||
let res: Vec<(&str, f32)> = fuzzy_search_best_n(&binding, &tasks_str, n);
|
||||
|
||||
let mut result = json!({});
|
||||
|
||||
let res1 = res.clone();
|
||||
let binding1 = data.clone();
|
||||
for (name, score) in res1 {
|
||||
if score > 0.6 {
|
||||
for (key, value) in binding1["tasks"].as_object().unwrap() {
|
||||
if value.get("name").unwrap().as_str().unwrap().to_lowercase().as_str() == name {
|
||||
result[key] = binding1["tasks"].get(key).unwrap().clone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn add_task(date: String, time: String, name: String, description: String, priority: String) -> String {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let pending = data.clone();
|
||||
let id = &pending["id"];
|
||||
|
||||
let task = json!({
|
||||
"id": id.to_string(),
|
||||
"date": date,
|
||||
"time": time,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"priority": priority,
|
||||
"subtasks": {},
|
||||
"completed": false
|
||||
});
|
||||
|
||||
data["id"] = (id.as_i64().unwrap() + 1).into();
|
||||
|
||||
data["tasks"][id.to_string()] = task;
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
|
||||
return id.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn edit_task(id_task: String, name: String, description: String, priority: String) -> bool{
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
return if !data["tasks"][id_task.clone()].get("id").is_none(){
|
||||
data["tasks"][id_task.clone()]["name"] = json!(name);
|
||||
data["tasks"][id_task.clone()]["description"] = json!(description);
|
||||
data["tasks"][id_task]["priority"] = json!(priority);
|
||||
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
true
|
||||
} else{
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_task(id_task: String) -> bool{
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let tasks = data["tasks"].as_object_mut().unwrap();
|
||||
let binding = tasks.clone();
|
||||
for (key, value) in binding {
|
||||
if id_task == value["id"] {
|
||||
tasks.remove(&key);
|
||||
data["tasks"] = json!(tasks);
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
return true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn set_task_field(id_task: String, field: String, value: String) {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
data["tasks"][id_task][field] = json!(value);
|
||||
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
}
|
||||
}
|
||||
use rust_fuzzy_search::fuzzy_search_best_n;
|
||||
use serde_json::{json, Value};
|
||||
use std::fs::read_to_string;
|
||||
use std::fs::File;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tauri::Manager;
|
||||
use tauri::path::BaseDirectory;
|
||||
|
||||
use crate::enc_dec_file::{decrypt_file, encrypt_n_save_file};
|
||||
|
||||
pub static mut PATH_CONFIG: Option<&'static str> = None;
|
||||
|
||||
#[tauri::command]
|
||||
pub fn check_or_create_tasks_file(app_handle: tauri::AppHandle) {
|
||||
let path = app_handle.path().resolve("ToDo/tasks.enc", BaseDirectory::AppLocalData).unwrap();
|
||||
|
||||
let path_str = Box::leak(Box::new(path.to_string_lossy().into_owned()));
|
||||
|
||||
unsafe {
|
||||
PATH_CONFIG = Some(path_str);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let exist: bool = Path::new(PATH_CONFIG.unwrap()).exists();
|
||||
if exist {
|
||||
let content = read_to_string(path);
|
||||
return match content {
|
||||
Ok(_) => {}
|
||||
Err(_) => {
|
||||
println!("Не удалось открыть конфигурационный файл!");
|
||||
}
|
||||
};
|
||||
} else {
|
||||
let path = Path::new(&path);
|
||||
let prefix = path.parent().unwrap();
|
||||
let file = std::fs::create_dir_all(prefix);
|
||||
match file {
|
||||
Ok(_) => {}
|
||||
Err(err) => println!("Не удалось создать директории! \n{}", err),
|
||||
}
|
||||
let file = File::create(path);
|
||||
match file {
|
||||
Ok(_) => {
|
||||
let data = String::from(
|
||||
"{\
|
||||
\"id\": 0,\
|
||||
\"tasks\": {}\
|
||||
}",
|
||||
);
|
||||
encrypt_n_save_file(path.into(), data);
|
||||
}
|
||||
Err(err) => println!("Не удалось создать файл! \n{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_tasks() -> Value {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let data = serde_json::from_str::<Value>(content.as_str());
|
||||
return match data {
|
||||
Ok(data) => {
|
||||
let res: &Value = &data["tasks"];
|
||||
|
||||
res.clone()
|
||||
}
|
||||
Err(_) => {
|
||||
std::fs::remove_file(PathBuf::from(PATH_CONFIG.unwrap())).unwrap();
|
||||
let data = String::from(
|
||||
"{\
|
||||
\"id\": 0,\
|
||||
\"tasks\": {}\
|
||||
}",
|
||||
);
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data);
|
||||
|
||||
return get_tasks();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn search_tasks(value: String) -> Value {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let mut tasks = vec![];
|
||||
|
||||
let binding = data.clone();
|
||||
for (_key, value) in binding["tasks"].as_object().unwrap() {
|
||||
tasks.push(value["name"].as_str().unwrap().to_lowercase());
|
||||
}
|
||||
|
||||
let tasks_str: Vec<&str> = tasks.iter().map(|s| &**s).collect();
|
||||
|
||||
let n: usize = 5;
|
||||
let binding = value.to_lowercase();
|
||||
let res: Vec<(&str, f32)> = fuzzy_search_best_n(&binding, &tasks_str, n);
|
||||
|
||||
let mut result = json!({});
|
||||
|
||||
let res1 = res.clone();
|
||||
let binding1 = data.clone();
|
||||
for (name, score) in res1 {
|
||||
if score > 0.6 {
|
||||
for (key, value) in binding1["tasks"].as_object().unwrap() {
|
||||
if value
|
||||
.get("name")
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_lowercase()
|
||||
.as_str()
|
||||
== name
|
||||
{
|
||||
result[key] = binding1["tasks"].get(key).unwrap().clone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn add_task(
|
||||
date: String,
|
||||
time: String,
|
||||
name: String,
|
||||
description: String,
|
||||
priority: String,
|
||||
) -> String {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let pending = data.clone();
|
||||
let id = &pending["id"];
|
||||
|
||||
let task = json!({
|
||||
"id": id.to_string(),
|
||||
"date": date,
|
||||
"time": time,
|
||||
"name": name,
|
||||
"description": description,
|
||||
"priority": priority,
|
||||
"subtasks": {},
|
||||
"completed": false
|
||||
});
|
||||
|
||||
data["id"] = (id.as_i64().unwrap() + 1).into();
|
||||
|
||||
data["tasks"][id.to_string()] = task;
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
|
||||
return id.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn edit_task(id_task: String, name: String, description: String, priority: String) -> bool {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
return if !data["tasks"][id_task.clone()].get("id").is_none() {
|
||||
data["tasks"][id_task.clone()]["name"] = json!(name);
|
||||
data["tasks"][id_task.clone()]["description"] = json!(description);
|
||||
data["tasks"][id_task]["priority"] = json!(priority);
|
||||
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_task(id_task: String) -> bool {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
|
||||
let tasks = data["tasks"].as_object_mut().unwrap();
|
||||
let binding = tasks.clone();
|
||||
for (key, value) in binding {
|
||||
if id_task == value["id"] {
|
||||
tasks.remove(&key);
|
||||
data["tasks"] = json!(tasks);
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn set_task_field(id_task: String, field: String, value: String) {
|
||||
unsafe {
|
||||
let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap()));
|
||||
let mut data: Value = serde_json::from_str(content.as_str()).unwrap();
|
||||
data["tasks"][id_task][field] = json!(value);
|
||||
|
||||
encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
+37
-55
@@ -1,55 +1,37 @@
|
||||
{
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
"beforeBuildCommand": "npm run build",
|
||||
"devPath": "http://localhost:1420",
|
||||
"distDir": "../dist"
|
||||
},
|
||||
"package": {
|
||||
"productName": "to-do-app",
|
||||
"version": "1.7.0"
|
||||
},
|
||||
"tauri": {
|
||||
"allowlist": {
|
||||
"all": false,
|
||||
"shell": {
|
||||
"all": false,
|
||||
"open": true
|
||||
},
|
||||
"window": {
|
||||
"all": false,
|
||||
"close": true,
|
||||
"hide": true,
|
||||
"show": true,
|
||||
"maximize": true,
|
||||
"minimize": true,
|
||||
"unmaximize": true,
|
||||
"unminimize": true,
|
||||
"startDragging": true
|
||||
}
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"decorations": false,
|
||||
"title": "To Do List"
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"identifier": "com.a-dot.dev",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"build": {
|
||||
"beforeDevCommand": "npm run dev",
|
||||
"beforeBuildCommand": "npm run build",
|
||||
"frontendDist": "../dist",
|
||||
"devUrl": "http://localhost:1420"
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/128x128@2x.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
},
|
||||
"productName": "to-do-app",
|
||||
"mainBinaryName": "to-do-app",
|
||||
"version": "1.7.0",
|
||||
"identifier": "com.a-dot.dev",
|
||||
"plugins": {},
|
||||
"app": {
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"windows": [
|
||||
{
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"decorations": false,
|
||||
"title": "To Do List"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user