diff --git a/Cargo.lock b/Cargo.lock index 506caad..211c288 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -291,6 +291,27 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "csv" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" +dependencies = [ + "memchr", +] + [[package]] name = "dashmap" version = "6.1.0" @@ -351,6 +372,27 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -384,6 +426,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "equivalent" version = "1.0.2" @@ -640,6 +688,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" + [[package]] name = "hex" version = "0.4.3" @@ -848,6 +902,17 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" +[[package]] +name = "is-terminal" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +dependencies = [ + "hermit-abi 0.5.1", + "libc", + "windows-sys", +] + [[package]] name = "istyles" version = "0.1.0" @@ -883,6 +948,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "leptos" version = "0.8.2" @@ -1015,6 +1086,16 @@ version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", +] + [[package]] name = "linear-map" version = "1.2.0" @@ -1141,7 +1222,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -1274,6 +1355,20 @@ dependencies = [ "syn", ] +[[package]] +name = "prettytable-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" +dependencies = [ + "csv", + "encode_unicode", + "is-terminal", + "lazy_static", + "term", + "unicode-width", +] + [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -1427,6 +1522,17 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", +] + [[package]] name = "regex" version = "1.11.1" @@ -1717,6 +1823,7 @@ dependencies = [ "log", "once_cell", "parking_lot", + "prettytable-rs", "reactive_stores", "serde", "serde-wasm-bindgen", @@ -1823,6 +1930,17 @@ dependencies = [ "web-sys", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -1958,6 +2076,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "unicode-xid" version = "0.2.6" @@ -2121,6 +2245,22 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -2130,6 +2270,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/Cargo.toml b/Cargo.toml index 512eafd..41109f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ reactive_stores = "0.2.2" thiserror = "2.0.12" serde = "1.0.219" serde_json = "1.0.140" -web-sys = { version = "0.3.77", features = ["Clipboard", "DedicatedWorkerGlobalScope", "File", "FileList", "HtmlSelectElement", "MediaQueryList", "Navigator", "Storage", "Worker", "WorkerOptions", "WorkerType"] } +web-sys = { version = "0.3.77", features = ["BlobPropertyBag", "Clipboard", "DedicatedWorkerGlobalScope", "File", "FileList", "HtmlSelectElement", "MediaQueryList", "Navigator", "Storage", "Worker", "WorkerOptions", "WorkerType"] } serde-wasm-bindgen = "0.6.5" parking_lot = "0.12.3" once_cell = "1.21.3" @@ -37,3 +37,4 @@ console_log = "1.0.0" log = "0.4.27" fragile = "2.0.1" hex = "0.4.3" +prettytable-rs = "0.10.0" diff --git a/src/app/header.rs b/src/app/header.rs index f968f7f..32db35b 100644 --- a/src/app/header.rs +++ b/src/app/header.rs @@ -1,12 +1,13 @@ use istyles::istyles; use leptos::{html::Input, prelude::*, tachys::html}; +use prettytable::{Cell, Row, Table}; use reactive_stores::Store; use wasm_bindgen::{JsCast, prelude::Closure}; use web_sys::{Blob, Event, FileReader, HtmlInputElement, Url, UrlSearchParams}; use crate::{ DownloadDbOptions, FragileComfirmed, LoadDbOptions, PrepareOptions, SQLightError, - WorkerRequest, + SQLiteStatementResult, WorkerRequest, app::{ ImportProgress, advanced_options_menu::AdvancedOptionsMenu, @@ -358,6 +359,44 @@ fn ShareButton() -> impl IntoView { return; }; + let mut offset_inserts = vec![]; + + for result in &*state.output().read() { + let mut table_s = Table::new(); + + match result { + SQLiteStatementResult::Finish => continue, + SQLiteStatementResult::Step(table) => { + let end = table.position[1]; + + if let Some(values) = &table.values { + table_s.add_row(Row::new( + values.columns.iter().map(|s| Cell::new(s)).collect(), + )); + for row in &values.rows { + table_s.add_row(Row::new(row.iter().map(|s| Cell::new(s)).collect())); + } + + let result = table_s + .to_string() + .lines() + .map(|x| format!("-- {x}")) + .collect::>() + .join("\n"); + + offset_inserts.push((end, format!("\n-- Output:\n{result}\n"))); + } + } + } + } + + let mut sql_with_result = code.clone(); + for (idx, result) in offset_inserts.into_iter().rev() { + sql_with_result.insert_str(idx, &result); + } + + state.share_sql_with_result().set(Some(sql_with_result)); + if let Ok(href) = window().location().href().and_then(|href| { let url = Url::new(&href)?; let params = UrlSearchParams::new()?; @@ -366,8 +405,9 @@ fn ShareButton() -> impl IntoView { Ok(url.href()) }) { state.share_href().set(Some(href)); - change_focus(state, Some(Focus::Share)); } + + change_focus(state, Some(Focus::Share)); }; view! { } diff --git a/src/app/output/share.rs b/src/app/output/share.rs index 04dcd42..959408f 100644 --- a/src/app/output/share.rs +++ b/src/app/output/share.rs @@ -3,27 +3,29 @@ use std::{sync::Arc, time::Duration}; use istyles::istyles; use leptos::prelude::*; use reactive_stores::Store; +use wasm_bindgen::JsValue; use wasm_bindgen_futures::{JsFuture, spawn_local}; +use web_sys::{Blob, BlobPropertyBag, Url}; use crate::app::{GlobalState, GlobalStateStoreFields, icon::clipboard_icon}; istyles!(styles, "assets/module.postcss/output/share.module.css.map"); #[component] -fn Copied(href: H, children: Children) -> impl IntoView +fn Copied(shared: S, href: H, children: Children) -> impl IntoView where + S: Fn() -> String + Send + Sync + 'static, H: Fn() -> String + Send + Sync + 'static, { let (copied, set_copied) = signal(false); - let href = Arc::new(href); - let href1 = Arc::clone(&href); + let shared = Arc::new(shared); let copy = move |_| { - let href = Arc::clone(&href1); + let shared = Arc::clone(&shared); spawn_local(async move { set_copied.set(true); if let Err(err) = - JsFuture::from(window().navigator().clipboard().write_text(&href())).await + JsFuture::from(window().navigator().clipboard().write_text(&shared())).await { log::error!("Failed to write href to clipboard: {err:?}"); } @@ -33,7 +35,9 @@ where view! {

- {children()} + + {children()} + @@ -43,13 +47,66 @@ where } #[component] -fn Links() -> impl IntoView { +fn EmbeddedLinks() -> impl IntoView { let state = expect_context::>(); - let code_url = move || state.share_href().get_untracked().unwrap_or_default(); - view! { Embedded code in link } + let shared = move || state.share_href().get_untracked().unwrap_or_default(); + let href = move || state.share_href().get_untracked().unwrap_or_default(); + view! { + + "Embedded code in link" + + } +} + +#[component] +fn SQLWithResultLinks() -> impl IntoView { + let state = expect_context::>(); + + let shared = move || { + state + .share_sql_with_result() + .get_untracked() + .unwrap_or_default() + }; + + let href = move || { + let text = state + .share_sql_with_result() + .get_untracked() + .unwrap_or_default(); + let string_array = js_sys::Array::new(); + string_array.push(&JsValue::from(text)); + + let blob_properties = BlobPropertyBag::new(); + blob_properties.set_type("text/plain"); + + let blob = + Blob::new_with_str_sequence_and_options(&string_array, &blob_properties).unwrap(); + + let url = Url::create_object_url_with_blob(&blob).unwrap(); + let url1 = url.clone(); + + set_timeout( + move || Url::revoke_object_url(&url1).unwrap(), + Duration::from_millis(5000), + ); + + url + }; + + view! { + + "[Need run first] Copy sql with result" + + } } #[component] pub fn Share() -> impl IntoView { - view! { } + view! { + <> + + + + } } diff --git a/src/app/state.rs b/src/app/state.rs index 0da95ad..0dc9857 100644 --- a/src/app/state.rs +++ b/src/app/state.rs @@ -48,6 +48,8 @@ pub struct GlobalState { #[serde(skip)] share_href: Option, #[serde(skip)] + share_sql_with_result: Option, + #[serde(skip)] show_something: bool, #[serde(skip)] output: Vec, @@ -75,6 +77,7 @@ impl Default for GlobalState { is_focused: false, opened_focus: HashSet::new(), share_href: None, + share_sql_with_result: None, show_something: false, output: Vec::new(), last_error: None,