2025-12-21 17:58:04 -07:00
|
|
|
mod interface;
|
2025-12-17 16:40:34 -07:00
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
|
path::PathBuf,
|
|
|
|
|
sync::{Arc, Mutex},
|
|
|
|
|
};
|
|
|
|
|
|
2025-12-21 17:58:04 -07:00
|
|
|
use egui_async::Bind;
|
|
|
|
|
use log::debug;
|
2025-12-21 00:35:28 -07:00
|
|
|
use unshell_lib::config::TreeMessage;
|
2025-12-21 17:58:04 -07:00
|
|
|
use unshell_lib::{ModuleError, Result};
|
2025-12-21 00:35:28 -07:00
|
|
|
|
|
|
|
|
use crate::auth::Auth;
|
2025-12-17 16:40:34 -07:00
|
|
|
|
|
|
|
|
#[derive(serde::Deserialize, serde::Serialize)]
|
|
|
|
|
pub struct InterfaceWindow {
|
|
|
|
|
path: PathBuf,
|
2025-12-21 17:58:04 -07:00
|
|
|
// #[serde(skip)]
|
|
|
|
|
// data_bind: Bind<String, ModuleError>,
|
2025-12-17 16:40:34 -07:00
|
|
|
#[serde(skip)]
|
|
|
|
|
state: Arc<Mutex<InterfaceWindowState>>,
|
2025-12-21 17:58:04 -07:00
|
|
|
// #[serde(skip)]
|
|
|
|
|
// promise: Option<PromiseWrapper<Result<TreeMessage>>>,
|
2025-12-17 16:40:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct InterfaceWindowState {
|
|
|
|
|
is_request: bool,
|
|
|
|
|
is_error: bool,
|
2025-12-21 00:35:28 -07:00
|
|
|
branch: Option<TreeMessage>,
|
2025-12-17 16:40:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl InterfaceWindow {
|
|
|
|
|
pub fn update(&mut self, auth: &mut Auth, ui: &mut egui::Ui) {
|
2025-12-21 17:58:04 -07:00
|
|
|
// let data_bind = Bind::<InterfaceWindowState, ModuleError>::new(false);
|
|
|
|
|
|
2025-12-17 16:40:34 -07:00
|
|
|
ui.heading("Interface");
|
|
|
|
|
ui.label(self.path.to_string_lossy());
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
if !self.path.eq("/") && ui.button("Go up").clicked() {
|
|
|
|
|
self.go_up();
|
|
|
|
|
self.state.lock().unwrap().branch = None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let state_lock = self.state.lock().unwrap();
|
|
|
|
|
|
|
|
|
|
let (is_request, is_error, is_some) = (
|
|
|
|
|
state_lock.is_request,
|
|
|
|
|
state_lock.is_error,
|
|
|
|
|
state_lock.branch.is_some(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
drop(state_lock);
|
|
|
|
|
|
|
|
|
|
if is_request {
|
|
|
|
|
ui.spinner();
|
|
|
|
|
} else if is_error {
|
|
|
|
|
self.reset_path();
|
|
|
|
|
let mut state_lock = self.state.lock().unwrap();
|
|
|
|
|
|
|
|
|
|
state_lock.is_error = false;
|
|
|
|
|
state_lock.is_request = false;
|
|
|
|
|
state_lock.branch = None;
|
|
|
|
|
|
|
|
|
|
drop(state_lock)
|
|
|
|
|
} else if !is_some {
|
|
|
|
|
{
|
|
|
|
|
let mut state_lock = self.state.lock().unwrap();
|
|
|
|
|
|
|
|
|
|
state_lock.is_request = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let state_clone = self.state.clone();
|
|
|
|
|
auth.get(
|
|
|
|
|
&format!("/api/interface{}", self.path.display()),
|
2025-12-21 00:35:28 -07:00
|
|
|
move |response: Result<TreeMessage>| {
|
2025-12-17 16:40:34 -07:00
|
|
|
let mut state_lock = state_clone.lock().unwrap();
|
|
|
|
|
|
|
|
|
|
match response {
|
|
|
|
|
Ok(item) => {
|
|
|
|
|
state_lock.branch = Some(item);
|
|
|
|
|
}
|
2025-12-21 17:58:04 -07:00
|
|
|
Err(err) => {
|
|
|
|
|
crate::log(&format!("Got error {err:?}"));
|
2025-12-17 16:40:34 -07:00
|
|
|
state_lock.is_error = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
state_lock.is_request = false;
|
|
|
|
|
|
|
|
|
|
drop(state_lock);
|
|
|
|
|
},
|
2025-12-21 00:35:28 -07:00
|
|
|
)
|
|
|
|
|
.unwrap();
|
2025-12-17 16:40:34 -07:00
|
|
|
} else {
|
|
|
|
|
let state_clone = self.state.clone();
|
|
|
|
|
|
|
|
|
|
let mut state_lock = state_clone.lock().unwrap();
|
|
|
|
|
|
2025-12-21 12:04:53 -07:00
|
|
|
let branch = (state_lock.branch).as_mut().unwrap();
|
2025-12-17 16:40:34 -07:00
|
|
|
|
|
|
|
|
let clear = match branch {
|
2025-12-21 00:35:28 -07:00
|
|
|
TreeMessage::InterfaceAndValue(interface_struct, interface_data) => {
|
2025-12-21 17:58:04 -07:00
|
|
|
interface::render(ui, interface_struct, interface_data);
|
2025-12-21 12:04:53 -07:00
|
|
|
|
|
|
|
|
if ui.button("Save").clicked() {
|
|
|
|
|
auth.post(
|
|
|
|
|
&format!("/api/interface{}", self.path.display()),
|
|
|
|
|
&TreeMessage::State(interface_data.clone()),
|
|
|
|
|
move |response: Result<TreeMessage>| {
|
2025-12-21 17:58:04 -07:00
|
|
|
debug!("{response:?}");
|
2025-12-21 12:04:53 -07:00
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-17 16:40:34 -07:00
|
|
|
false
|
|
|
|
|
}
|
2025-12-21 00:35:28 -07:00
|
|
|
TreeMessage::Folder(items) => {
|
2025-12-17 16:40:34 -07:00
|
|
|
let mut clear = false;
|
|
|
|
|
for item in items {
|
|
|
|
|
if ui.button(&format!("Item {}", item)).clicked() {
|
|
|
|
|
self.go_down(item.clone());
|
|
|
|
|
clear = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
clear
|
|
|
|
|
}
|
|
|
|
|
_ => false,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if clear {
|
|
|
|
|
state_lock.branch = None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
drop(state_lock)
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-12-21 17:58:04 -07:00
|
|
|
|
|
|
|
|
// if ui.button("Go Up").clicked() {
|
|
|
|
|
// self.go_up();
|
|
|
|
|
// // self.data_bind.clear();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// match self.promise.as_mut() {
|
|
|
|
|
// Some(promise) => {
|
|
|
|
|
// if let Some(result) = promise.poll() {
|
|
|
|
|
// crate::log(&format!("{result:?}"));
|
|
|
|
|
// } else {
|
|
|
|
|
// crate::log("Poll failed");
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// None => {
|
|
|
|
|
// self.promise =
|
|
|
|
|
// Some(auth.get_async(&format!("/api/interface{}", self.path.to_str().unwrap())));
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// let future = Auth::get_async::<String>("/api/test").await;
|
|
|
|
|
// future.;
|
|
|
|
|
|
|
|
|
|
// if let Some(res) = self.data_bind.read_or_request(async || {
|
|
|
|
|
// // self.go_up();
|
|
|
|
|
// // auth.get("", |e: String| {});
|
|
|
|
|
|
|
|
|
|
// reqwest::get("https://icanhazip.com/")
|
|
|
|
|
// .await
|
|
|
|
|
// .map_err(|e| ModuleError::Error(e.to_string()))?
|
|
|
|
|
// .text()
|
|
|
|
|
// .await
|
|
|
|
|
// .map_err(|e| ModuleError::Error(e.to_string()))
|
|
|
|
|
// }) {
|
|
|
|
|
// match res {
|
|
|
|
|
// Ok(ip) => {
|
|
|
|
|
// ui.label(format!("OK {ip}"));
|
|
|
|
|
// }
|
|
|
|
|
// Err(err) => {
|
|
|
|
|
// ui.label(format!("ERR {err}"));
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// } else {
|
|
|
|
|
// ui.spinner();
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// if ui.button("Refresh").clicked() {
|
|
|
|
|
// Auth::get_async_callback::<String>("/api/interface");
|
|
|
|
|
// // self.data_bind.clear();
|
|
|
|
|
// }
|
2025-12-17 16:40:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn reset_path(&mut self) {
|
|
|
|
|
self.path = PathBuf::from("/");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn go_up(&mut self) {
|
2025-12-21 17:58:04 -07:00
|
|
|
if let Some(parent) = self.path.parent() {
|
|
|
|
|
self.path = PathBuf::from(parent);
|
|
|
|
|
}
|
2025-12-17 16:40:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn go_down(&mut self, path: String) {
|
|
|
|
|
self.path = self.path.join(path);
|
|
|
|
|
}
|
2025-12-21 17:58:04 -07:00
|
|
|
|
|
|
|
|
async fn get() {}
|
2025-12-17 16:40:34 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for InterfaceWindow {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
path: "/".into(),
|
2025-12-21 17:58:04 -07:00
|
|
|
// promise: None,
|
2025-12-17 16:40:34 -07:00
|
|
|
state: Arc::new(Mutex::new(InterfaceWindowState::default())),
|
2025-12-21 17:58:04 -07:00
|
|
|
// data_bind: Bind::new(false),
|
2025-12-17 16:40:34 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Default for InterfaceWindowState {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
is_request: false,
|
|
|
|
|
branch: None,
|
|
|
|
|
is_error: false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|