In progress transfer

This commit is contained in:
2026-03-17 14:34:07 -05:00
parent b53d67acb7
commit b99015fc1b
3 changed files with 147 additions and 48 deletions

View File

@@ -1,8 +1,9 @@
use std::fs::DirEntry; use std::sync::mpsc;
use std::ops::DerefMut; use std::collections::HashMap;
use std::sync::Arc;
use egui::mutex::Mutex; use crate::templates::{self, Template};
use egui::{Align, Layout};
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_bindgen_futures; use wasm_bindgen_futures;
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@@ -11,7 +12,7 @@ use web_sys;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use smol; use smol;
use tinytemplate; use tinytemplate::TinyTemplate;
/// We derive Deserialize/Serialize so we can persist app state on shutdown. /// We derive Deserialize/Serialize so we can persist app state on shutdown.
#[derive(serde::Deserialize, serde::Serialize)] #[derive(serde::Deserialize, serde::Serialize)]
@@ -25,12 +26,20 @@ pub struct TemplateApp {
#[serde(skip)] // This how you opt-out of serialization of a field #[serde(skip)] // This how you opt-out of serialization of a field
value: f32, value: f32,
#[serde(skip)]
templates: Vec<DirEntry>, templates: HashMap<String, Template>,
active_template: String,
#[serde(skip)] #[serde(skip)]
cont_mux: Arc<Mutex<String>>, preview_text: String,
content: String,
#[serde(skip)]
messaging: (mpsc::Sender<Message>, mpsc::Receiver<Message>),
}
pub enum Message {
AddTemplate(Template),
} }
impl Default for TemplateApp { impl Default for TemplateApp {
@@ -40,9 +49,10 @@ impl Default for TemplateApp {
init: false, init: false,
label: "Hello World!".to_owned(), label: "Hello World!".to_owned(),
value: 2.7, value: 2.7,
templates: Vec::new(), templates: HashMap::new(),
cont_mux: Arc::new(Mutex::new(String::new())), active_template: "Select a template".to_string(),
content: "No File selected".to_string(), preview_text: "No File Selected".to_string(),
messaging: mpsc::channel(),
} }
} }
} }
@@ -61,6 +71,7 @@ impl TemplateApp {
Default::default() Default::default()
} }
} }
} }
impl eframe::App for TemplateApp { impl eframe::App for TemplateApp {
@@ -74,12 +85,19 @@ impl eframe::App for TemplateApp {
// Put your widgets into a `SidePanel`, `TopBottomPanel`, `CentralPanel`, `Window` or `Area`. // Put your widgets into a `SidePanel`, `TopBottomPanel`, `CentralPanel`, `Window` or `Area`.
// For inspiration and more examples, go to https://emilk.github.io/egui // For inspiration and more examples, go to https://emilk.github.io/egui
let is_web = cfg!(target_arch = "wasm32");
for i in self.messaging.1.try_iter() {
match i {
Message::AddTemplate(t) => add_template(&mut self.templates, t.name.clone(), t),
}
}
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| { egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
// The top panel is often a good place for a menu bar: // The top panel is often a good place for a menu bar:
egui::MenuBar::new().ui(ui, |ui| { egui::MenuBar::new().ui(ui, |ui| {
// NOTE: no File->Quit on web pages! // NOTE: no File->Quit on web pages!
let is_web = cfg!(target_arch = "wasm32");
if !is_web { if !is_web {
ui.menu_button("File", |ui| { ui.menu_button("File", |ui| {
if ui.button("Quit").clicked() { if ui.button("Quit").clicked() {
@@ -92,8 +110,17 @@ impl eframe::App for TemplateApp {
}); });
}); });
egui::TopBottomPanel::bottom("bottom_panel").show(ctx, |ui| {
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
powered_by_egui_and_eframe(ui);
egui::warn_if_debug_build(ui);
});
});
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
// The central panel the region left after adding TopPanel's and SidePanel's // The central panel the region left after adding TopPanel's and SidePanel's
egui::containers::Sides::new().show(ui, |ui|{
ui.with_layout(Layout::top_down(Align::LEFT), |ui| {
ui.heading("eframe template"); ui.heading("eframe template");
ui.horizontal(|ui| { ui.horizontal(|ui| {
@@ -101,17 +128,27 @@ impl eframe::App for TemplateApp {
ui.text_edit_singleline(&mut self.label); ui.text_edit_singleline(&mut self.label);
}); });
ui.add(egui::Slider::new(&mut self.value, 0.0..=10.0).text("value"));
if ui.button("test").clicked() { if ui.button("test").clicked() {
self.value += 1.0; self.value += 1.0;
} }
if ui.button("rfd").clicked() { if ui.button("rfd").clicked() {
let file = test_async(self.cont_mux.clone()); test_async(self.messaging.0.clone());
} }
self.content = self.cont_mux.lock().clone();
ui.text_edit_multiline(&mut self.content); ui.separator();
if self.templates.is_empty() {
}
egui::containers::ComboBox::from_label("Select a template")
.selected_text(self.active_template.clone())
.show_ui(ui, |x| {
for (name, _) in self.templates.iter() {
x.selectable_value(&mut self.active_template, name.clone(), name.clone());
}
});
ui.separator(); ui.separator();
@@ -119,11 +156,19 @@ impl eframe::App for TemplateApp {
"https://github.com/emilk/eframe_template/blob/main/", "https://github.com/emilk/eframe_template/blob/main/",
"Source code." "Source code."
)); ));
});
}, |ui| {
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| { let selected = match self.templates.get(&self.active_template.clone()) {
powered_by_egui_and_eframe(ui); Some(t) => {
egui::warn_if_debug_build(ui); let text = t.text_files.iter().next();
match text {
Some(t) => t.1.clone(),
None => "No File Selected".to_string(),
}
},
None => "No File Selected".to_string()
};
ui.label(selected);
}); });
}); });
} }
@@ -143,7 +188,7 @@ fn powered_by_egui_and_eframe(ui: &mut egui::Ui) {
}); });
} }
fn test_async(test: Arc<Mutex<String>>) { fn test_async(test: mpsc::Sender<Message>) {
// Spawn dialog on main thread // Spawn dialog on main thread
let task = rfd::AsyncFileDialog::new().pick_file(); let task = rfd::AsyncFileDialog::new().pick_file();
@@ -154,6 +199,7 @@ fn test_async(test: Arc<Mutex<String>>) {
if let Some(file) = file { if let Some(file) = file {
// If you care about wasm support you just read() the file // If you care about wasm support you just read() the file
let name = file.file_name();
let output = file.read().await; let output = file.read().await;
let string_data = match String::from_utf8(output) { let string_data = match String::from_utf8(output) {
@@ -164,9 +210,7 @@ fn test_async(test: Arc<Mutex<String>>) {
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
web_sys::console::log_1(&string_data.clone().into()); web_sys::console::log_1(&string_data.clone().into());
let mut t = test.lock(); let _ = test.send(Message::AddTemplate(Template::new(string_data)));
let a = t.deref_mut();
*a = string_data;
} }
}); });
} }
@@ -183,6 +227,7 @@ fn execute<F: Future<Output = ()> + 'static>(f: F) {
web_sys::console::log_1(&"Async End".into()); web_sys::console::log_1(&"Async End".into());
} }
enum FileError {
Unknown, fn add_template(map: &mut HashMap<String, Template>, label: String, template: Template) {
map.insert(label, template);
} }

View File

@@ -1,4 +1,6 @@
#![warn(clippy::all, rust_2018_idioms)] #![warn(clippy::all, rust_2018_idioms)]
mod app; mod app;
mod templates;
pub use app::TemplateApp; pub use app::TemplateApp;

52
src/templates.rs Normal file
View File

@@ -0,0 +1,52 @@
use std::hash::Hash;
#[derive(serde::Serialize, serde::Deserialize, Eq)]
#[serde(default)]
pub struct Template {
pub name: String,
pub text_files: Vec<(String, String)>,
pub images: Vec<(String, Vec<u8>)>,
pub config: String,
}
impl Template {
pub fn new(name: String) -> Self {
Self {
name,
text_files: Vec::new(),
images: Vec::new(),
config: String::new(),
}
}
}
impl Default for Template {
fn default() -> Self {
Self {
name: "New_Template".to_string(),
text_files: Vec::new(),
images: Vec::new(),
config: String::new() }
}
}
impl PartialEq for Template {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl PartialEq<String> for Template {
fn eq(&self, other: &String) -> bool {
&self.name == other
}
}
impl Hash for Template {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}