mirror of
https://github.com/Astatin3/unshell.git
synced 2026-06-08 22:38:01 -06:00
Work on payload editor
This commit is contained in:
Generated
+16
@@ -153,6 +153,21 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
@@ -528,6 +543,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"chrono",
|
||||
"crossbeam-channel",
|
||||
"libc",
|
||||
"libloading",
|
||||
"rand",
|
||||
|
||||
Generated
+469
-837
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ name = "unshell-gui"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
|
||||
authors = ["ASTATIN3"]
|
||||
include = ["LICENSE-APACHE", "LICENSE-MIT", "**/*.rs", "Cargo.toml"]
|
||||
rust-version = "1.88"
|
||||
|
||||
@@ -12,9 +12,11 @@ all-features = true
|
||||
targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"]
|
||||
|
||||
[dependencies]
|
||||
unshell-lib = {path="../unshell-lib"}
|
||||
|
||||
egui = "0.33.0"
|
||||
eframe = { version = "0.33.0", default-features = false, features = [
|
||||
"accesskit", # Make egui compatible with screen readers. NOTE: adds a lot of dependencies.
|
||||
# "accesskit", # Make egui compatible with screen readers. NOTE: adds a lot of dependencies.
|
||||
"default_fonts", # Embed the default egui fonts.
|
||||
"glow", # Use the glow rendering backend. Alternative: "wgpu".
|
||||
"persistence", # Enable restoring app state when restarting the app.
|
||||
@@ -25,10 +27,11 @@ log = "0.4.27"
|
||||
|
||||
# You only need serde if you want app persistence:
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
egui_extras = "0.33.2"
|
||||
|
||||
# native:
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
env_logger = "0.11.8"
|
||||
pretty_env_logger = "0.5.0"
|
||||
|
||||
# web:
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
|
||||
+26
-71
@@ -1,4 +1,4 @@
|
||||
use crate::flowchart::FlowChart;
|
||||
use crate::{config::Config, flowchart::FlowChart};
|
||||
|
||||
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
@@ -6,11 +6,11 @@ use crate::flowchart::FlowChart;
|
||||
pub struct TemplateApp {
|
||||
tab: Tab,
|
||||
|
||||
#[serde(skip)]
|
||||
flowchart: FlowChart,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[derive(serde::Deserialize, serde::Serialize, PartialEq, Eq)]
|
||||
pub enum Tab {
|
||||
Flowchart,
|
||||
Test,
|
||||
@@ -24,6 +24,7 @@ impl Default for TemplateApp {
|
||||
// label: "Hello World!".to_owned(),
|
||||
// value: 2.7,
|
||||
flowchart: FlowChart::new(),
|
||||
config: Config::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,29 +59,25 @@ impl eframe::App for TemplateApp {
|
||||
egui::TopBottomPanel::top("tab_panel").show(ctx, |ui| {
|
||||
// The top panel is often a good place for a menu bar:
|
||||
|
||||
egui::MenuBar::new()
|
||||
// .style(StyleModifier::new(|s| s.visuals))
|
||||
.ui(ui, |ui| {
|
||||
if ui
|
||||
.menu_button("Network", |ui| if ui.button("Quit").clicked() {})
|
||||
.response
|
||||
.clicked()
|
||||
{
|
||||
self.tab = Tab::Flowchart;
|
||||
};
|
||||
egui::MenuBar::new().ui(ui, |ui| {
|
||||
if ui
|
||||
.selectable_label(self.tab == Tab::Flowchart, "Network")
|
||||
.clicked()
|
||||
{
|
||||
self.tab = Tab::Flowchart;
|
||||
}
|
||||
|
||||
if ui
|
||||
.menu_button("Test", |ui| if ui.button("Quit").clicked() {})
|
||||
.response
|
||||
.clicked()
|
||||
{
|
||||
self.tab = Tab::Test;
|
||||
};
|
||||
if ui
|
||||
.selectable_label(self.tab == Tab::Test, self.config.title())
|
||||
.clicked()
|
||||
{
|
||||
self.tab = Tab::Test;
|
||||
}
|
||||
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
egui::widgets::global_theme_preference_switch(ui);
|
||||
});
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
egui::widgets::global_theme_preference_switch(ui);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
egui::TopBottomPanel::bottom("tab_panel").show(ctx, |ui| {
|
||||
@@ -90,54 +87,12 @@ impl eframe::App for TemplateApp {
|
||||
});
|
||||
});
|
||||
|
||||
// egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||
// // The top panel is often a good place for a menu bar:
|
||||
|
||||
// egui::MenuBar::new().ui(ui, |ui| {
|
||||
// if ui
|
||||
// .menu_button("Network", |ui| if ui.button("Quit").clicked() {})
|
||||
// .response
|
||||
// .clicked()
|
||||
// {
|
||||
// self.tab = Tab::Flowchart;
|
||||
// };
|
||||
|
||||
// if ui
|
||||
// .menu_button("Test", |ui| if ui.button("Quit").clicked() {})
|
||||
// .response
|
||||
// .clicked()
|
||||
// {
|
||||
// self.tab = Tab::Test;
|
||||
// };
|
||||
// });
|
||||
// });
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
match self.tab {
|
||||
Tab::Flowchart => {
|
||||
self.flowchart.paint(ui);
|
||||
}
|
||||
Tab::Test => {
|
||||
// The central panel the region left after adding TopPanel's and SidePanel's
|
||||
ui.heading("eframe template");
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Write something: ");
|
||||
// ui.text_edit_singleline(&mut self.label);
|
||||
});
|
||||
|
||||
// ui.add(egui::Slider::new(&mut self.value, 0.0..=10.0).text("value"));
|
||||
// if ui.button("Increment").clicked() {
|
||||
// self.value += 1.0;
|
||||
// }
|
||||
|
||||
ui.separator();
|
||||
|
||||
ui.add(egui::github_link_file!(
|
||||
"https://github.com/emilk/eframe_template/blob/main/",
|
||||
"Source code."
|
||||
));
|
||||
}
|
||||
egui::CentralPanel::default().show(ctx, |ui| match self.tab {
|
||||
Tab::Flowchart => {
|
||||
self.flowchart.paint(ui);
|
||||
}
|
||||
Tab::Test => {
|
||||
self.config.update(ui);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
use egui::{TextStyle, Ui};
|
||||
use egui_extras::{Column, TableBuilder};
|
||||
use unshell_lib::config::RuntimeConfig;
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
pub struct Config {
|
||||
state: ConfigState,
|
||||
current_payloads: Vec<PayloadConfig>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
enum ConfigState {
|
||||
Base,
|
||||
NewConfig(PayloadConfig),
|
||||
EditConfig(usize, PayloadConfig),
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
state: ConfigState::Base,
|
||||
current_payloads: vec![PayloadConfig {
|
||||
name: "Test".to_string(),
|
||||
components: vec!["server".to_string()],
|
||||
runtimes: Vec::new(),
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn title(&self) -> &str {
|
||||
match self.state {
|
||||
ConfigState::Base => "Config",
|
||||
ConfigState::NewConfig(..) => "Config/New",
|
||||
ConfigState::EditConfig(..) => "Config/Edit",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, ui: &mut Ui) {
|
||||
match &mut self.state {
|
||||
ConfigState::Base => self.table_ui(ui),
|
||||
ConfigState::EditConfig(_, config) => {
|
||||
ui.heading("Edit Payload");
|
||||
match Self::edit_ui(ui, config) {
|
||||
Some(true) => {
|
||||
if let ConfigState::EditConfig(n, config) =
|
||||
std::mem::replace(&mut self.state, ConfigState::Base)
|
||||
{
|
||||
self.current_payloads[n] = config;
|
||||
}
|
||||
}
|
||||
Some(false) => {
|
||||
self.state = ConfigState::Base;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
ConfigState::NewConfig(config) => {
|
||||
ui.heading("Edit Payload");
|
||||
match Self::edit_ui(ui, config) {
|
||||
Some(true) => {
|
||||
if let ConfigState::NewConfig(config) =
|
||||
std::mem::replace(&mut self.state, ConfigState::Base)
|
||||
{
|
||||
self.current_payloads.push(config);
|
||||
}
|
||||
}
|
||||
Some(false) => {
|
||||
self.state = ConfigState::Base;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn table_ui(&mut self, ui: &mut Ui) {
|
||||
ui.horizontal(|ui| {
|
||||
ui.heading("Payloads");
|
||||
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
if ui.button("New").clicked() {
|
||||
self.state = ConfigState::NewConfig(PayloadConfig::new());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let body_text_size = TextStyle::Body.resolve(ui.style()).size;
|
||||
use egui_extras::{Size, StripBuilder};
|
||||
StripBuilder::new(ui)
|
||||
.size(Size::remainder().at_least(100.0)) // for the table
|
||||
.size(Size::exact(body_text_size)) // for the source code link
|
||||
.vertical(|mut strip| {
|
||||
strip.cell(|ui| {
|
||||
egui::ScrollArea::horizontal().show(ui, |ui| {
|
||||
let table = TableBuilder::new(ui)
|
||||
.striped(true)
|
||||
.resizable(true)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
|
||||
.column(Column::auto().resizable(false))
|
||||
.column(Column::remainder())
|
||||
.column(Column::remainder())
|
||||
.column(Column::remainder())
|
||||
.min_scrolled_height(0.0)
|
||||
.sense(egui::Sense::click());
|
||||
|
||||
table
|
||||
.header(20., |mut header| {
|
||||
header.col(|ui| {
|
||||
ui.strong("#");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.strong("Name");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.strong("Components");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.strong("Runtimes");
|
||||
});
|
||||
})
|
||||
.body(|mut body| {
|
||||
for i in 0..self.current_payloads.len() {
|
||||
// let runtime = self.current_runtimes
|
||||
|
||||
body.row(18., |mut row| {
|
||||
row.col(|ui| {
|
||||
ui.label(i.to_string());
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(self.current_payloads[i].name.clone());
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(format!(
|
||||
"{:?}",
|
||||
self.current_payloads[i].components.clone()
|
||||
));
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label("A");
|
||||
});
|
||||
|
||||
if row.response().clicked() {
|
||||
self.state = ConfigState::EditConfig(
|
||||
i,
|
||||
self.current_payloads[i].clone(),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn edit_ui(ui: &mut Ui, config: &mut PayloadConfig) -> Option<bool> {
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Name");
|
||||
ui.text_edit_singleline(&mut config.name);
|
||||
});
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Components: ");
|
||||
|
||||
for component in vec!["client", "server"] {
|
||||
let enabled = config
|
||||
.components
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|s| s.1.eq(component));
|
||||
if ui.selectable_label(enabled.is_some(), component).clicked() {
|
||||
if let Some((i, _)) = enabled {
|
||||
let _ = config.components.remove(i);
|
||||
} else {
|
||||
config.components.push(component.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mut ret = None;
|
||||
ui.horizontal(|ui| {
|
||||
ret = if ui.button("Back").clicked() {
|
||||
Some(false)
|
||||
} else if ui.button("Save").clicked() {
|
||||
Some(true)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
});
|
||||
|
||||
ret
|
||||
|
||||
// return None;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, serde::Deserialize, serde::Serialize)]
|
||||
struct PayloadConfig {
|
||||
name: String,
|
||||
components: Vec<String>,
|
||||
runtimes: Vec<RuntimeConfig>,
|
||||
}
|
||||
|
||||
impl PayloadConfig {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
name: "New Payload".to_string(),
|
||||
components: Vec::new(),
|
||||
runtimes: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ const BG_STROKE: Stroke = Stroke {
|
||||
color: Color32::GRAY,
|
||||
};
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
|
||||
pub struct FlowChart {
|
||||
// frame: Frame,
|
||||
container: DraggableContainer,
|
||||
@@ -46,14 +48,15 @@ impl FlowChart {
|
||||
0.,
|
||||
Color32::PURPLE,
|
||||
BG_STROKE,
|
||||
egui::StrokeKind::Middle,
|
||||
egui::StrokeKind::Outside,
|
||||
);
|
||||
ui.label("Tests");
|
||||
ui.button("Test");
|
||||
let _ = ui.button("Test");
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
pub struct DraggableContainer {
|
||||
pub pos: egui::Pos2,
|
||||
pub size: egui::Vec2,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#![warn(clippy::all, rust_2018_idioms)]
|
||||
#![macro_use]
|
||||
extern crate log;
|
||||
|
||||
mod app;
|
||||
pub use app::TemplateApp;
|
||||
|
||||
mod config;
|
||||
|
||||
mod flowchart;
|
||||
|
||||
@@ -6,17 +6,12 @@ use unshell_gui::TemplateApp;
|
||||
// When compiling natively:
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn main() -> eframe::Result {
|
||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||
pretty_env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||
|
||||
let native_options = eframe::NativeOptions {
|
||||
viewport: egui::ViewportBuilder::default()
|
||||
.with_inner_size([400.0, 300.0])
|
||||
.with_min_inner_size([300.0, 220.0]),
|
||||
// .with_icon(
|
||||
// // NOTE: Adding an icon is optional
|
||||
// eframe::icon_data::from_png_bytes(&include_bytes!("../assets/icon-256.png")[..])
|
||||
// .expect("Failed to load icon"),
|
||||
// ),
|
||||
..Default::default()
|
||||
};
|
||||
eframe::run_native(
|
||||
|
||||
@@ -21,7 +21,7 @@ bincode = "2.0.1"
|
||||
unshell-obfuscate = {path = "../unshell-obfuscate"}
|
||||
chrono = "0.4.42"
|
||||
|
||||
serde = {version = "1.0.228", features=["derive"]}
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.145"
|
||||
libc = "0.2.177"
|
||||
rand = "0.9.2"
|
||||
|
||||
@@ -21,7 +21,7 @@ pub struct PayloadConfig {
|
||||
pub runtime_config: Vec<RuntimeConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Encode, Decode)]
|
||||
#[derive(Debug, Clone, Encode, Decode, serde::Deserialize, serde::Serialize)]
|
||||
pub struct RuntimeConfig {
|
||||
pub parent_component: String,
|
||||
pub name: String,
|
||||
|
||||
Reference in New Issue
Block a user