Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions app_cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ use crate::eth::send_payload;

pub mod eth;

pub const USED_ITEM_SUBDIR_NAME: &str = "used";

#[derive(Clone, Debug)]
pub struct Config {
// The URL for the Beacon API
Expand Down Expand Up @@ -405,3 +407,16 @@ pub async fn commit_item(params: &Params, cfg: &Config, input: &Path) -> anyhow:

Ok(())
}

pub async fn destroy_item(_params: &Params, _cfg: &Config, item: &PathBuf) -> anyhow::Result<()> {
// TODO: Nullify
let (file_name, parent_dir) = item
.file_name()
.and_then(|name| Some((name.display(), item.parent()?.display())))
.ok_or(anyhow!("Item at {} is not a file.", item.display()))?;
let used_item = PathBuf::from(format!("{parent_dir}/{USED_ITEM_SUBDIR_NAME}/{file_name}"));
std::fs::rename(item, used_item)?;
info!("Destroyed item at {}", item.display());

Ok(())
}
14 changes: 10 additions & 4 deletions app_gui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ use std::{
};

use anyhow::{Result, anyhow};
use app_cli::{Config, CraftedItem, Recipe, commit_item, craft_item, load_item, log_init};
use app_cli::{
Config, CraftedItem, Recipe, USED_ITEM_SUBDIR_NAME, commit_item, craft_item, load_item,
log_init,
};
use common::load_dotenv;
use egui::{Color32, Frame, Label, RichText, Ui};
use itertools::Itertools;
Expand All @@ -27,7 +30,8 @@ use tokio::runtime::Runtime;
use tracing::{error, info};

use crate::{
Committing, Crafting, ItemView, Request, Response, TaskStatus, task_system::handle_req,
Committing, Crafting, Destruction, ItemView, Request, Response, TaskStatus,
task_system::handle_req,
};

#[derive(Clone)]
Expand All @@ -47,6 +51,7 @@ pub struct App {
pub item_view: ItemView,
pub crafting: Crafting,
pub committing: Committing,
pub destruction: Destruction,
pub task_req_tx: mpsc::Sender<Request>,
pub task_res_rx: mpsc::Receiver<Response>,
pub _task_handler: JoinHandle<()>,
Expand Down Expand Up @@ -104,6 +109,7 @@ IsTinPremium(item, private: ingredients, inputs, key, work) = AND(
item_view: Default::default(),
crafting: Default::default(),
committing: Default::default(),
destruction: Default::default(),
task_req_tx: req_tx,
task_res_rx: res_rx,
_task_handler: task_handler,
Expand Down Expand Up @@ -149,7 +155,7 @@ IsTinPremium(item, private: ingredients, inputs, key, work) = AND(

pub fn refresh_items(&mut self) -> Result<()> {
// create 'pods_path' & 'pods_path/used' dir in case they do not exist
fs::create_dir_all(format!("{}/used", &self.cfg.pods_path))?;
fs::create_dir_all(format!("{}/{}", &self.cfg.pods_path, USED_ITEM_SUBDIR_NAME))?;

self.items = Vec::new();
self.used_items = Vec::new();
Expand All @@ -163,7 +169,7 @@ IsTinPremium(item, private: ingredients, inputs, key, work) = AND(
}

log::info!("Loading used items...");
for entry in fs::read_dir(format!("{}/used", &self.cfg.pods_path))? {
for entry in fs::read_dir(format!("{}/{}", &self.cfg.pods_path, USED_ITEM_SUBDIR_NAME))? {
let entry = entry?;
// skip dirs
if !entry.file_type()?.is_dir() {
Expand Down
51 changes: 8 additions & 43 deletions app_gui/src/crafting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,56 +96,21 @@ IsBronze(item, private: ingredients, inputs, key, work) = AND(

impl App {
// Crafting panel
pub fn update_crafting_ui(&mut self, ctx: &egui::Context, ui: &mut Ui) {
egui::Grid::new("production title").show(ui, |ui| {
ui.set_min_height(32.0);
ui.vertical(|ui| {
ui.horizontal(|ui| {
if ui
.selectable_label(self.selected_tab == 0, "Mine")
.clicked()
{
self.crafting.selected_recipe = None;
self.selected_tab = 0;
}
if ui
.selectable_label(self.selected_tab == 1, "Craft")
.clicked()
{
self.crafting.selected_recipe = None;
self.selected_tab = 1;
}
if ui
.selectable_label(self.selected_tab == 2, "+ New Predicate")
.clicked()
{
self.modal_new_predicates = true;
self.crafting.selected_recipe = None;
self.selected_tab = 2;
}
});
ui.separator();
match self.selected_tab {
0 => self.ui_produce(ctx, ui, ProductionType::Mine),
1 => self.ui_produce(ctx, ui, ProductionType::Craft),
2 => self.ui_new_predicate(ctx, ui),
_ => {}
}
});
ui.end_row();
});
}

// UI for producing new items through Mine & Craft
fn ui_produce(&mut self, ctx: &egui::Context, ui: &mut Ui, production_type: ProductionType) {
pub(crate) fn ui_produce(
&mut self,
ctx: &egui::Context,
ui: &mut Ui,
production_type: ProductionType,
) {
let mut selected_recipe = self.crafting.selected_recipe;
egui::Grid::new("mine title").show(ui, |ui| {
ui.set_min_height(32.0);
ui.heading(production_type.to_string());
ui.end_row();
});
ui.separator();
egui::ComboBox::from_label("")
egui::ComboBox::from_id_salt("items to mine/craft")
.selected_text(selected_recipe.map(|r| r.to_string()).unwrap_or_default())
.show_ui(ui, |ui| {
for recipe in &self.recipes {
Expand Down Expand Up @@ -268,7 +233,7 @@ impl App {
}
}

fn ui_new_predicate(&mut self, ctx: &egui::Context, ui: &mut Ui) {
pub(crate) fn ui_new_predicate(&mut self, ctx: &egui::Context, ui: &mut Ui) {
let language: String = "js".to_string();

if self.modal_new_predicates {
Expand Down
94 changes: 94 additions & 0 deletions app_gui/src/destruction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::{
collections::HashMap,
fmt::{self, Write},
fs::{self},
mem,
path::{Path, PathBuf},
sync::{
Arc, RwLock,
mpsc::{self, channel},
},
thread::{self, JoinHandle},
time,
};

use anyhow::{Result, anyhow};
use app_cli::{
Config, CraftedItem, ProductionType, Recipe, commit_item, craft_item, load_item, log_init,
};
use common::load_dotenv;
use egui::{Color32, Frame, Label, RichText, Ui};
use itertools::Itertools;
use pod2::{
backends::plonky2::primitives::merkletree::MerkleProof,
middleware::{
Hash, Params, RawValue, Statement, StatementArg, TypedValue, Value, containers::Set,
},
};
use tokio::runtime::Runtime;
use tracing::{error, info};

use crate::{App, Committing, ItemView, Request, Response, TaskStatus, utils::result2text};

#[derive(Default)]
pub struct Destruction {
pub item_index: Option<usize>,
pub result: Option<Result<PathBuf>>,
}

impl App {
// UI for the destruction of items.
pub(crate) fn ui_destroy(&mut self, ctx: &egui::Context, ui: &mut Ui) {
let all_items = self.all_items();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently in the dropdown menu of items to be destructed, the ones in the used_items list appear too; but those items have been already been nullified.
Maybe here we can just list the non-used items?

Suggested change
let all_items = self.all_items();
let all_items = self.items.clone();

egui::Grid::new("destruction").show(ui, |ui| {
ui.set_min_height(32.0);
ui.heading("Destroy");
ui.end_row();
});
ui.separator();
let frame = Frame::default().inner_margin(4.0);
let (_, dropped_payload) =
ui.dnd_drop_zone::<usize, ()>(frame, |ui| match &self.destruction.item_index {
Some(i) => {
if let Some(name) = self.items.get(*i).map(|item| item.name.to_string()) {
self.destruction.result = None;
ui.label(name);
} else {
self.destruction.result = Some(Err(anyhow!(
"Item '{}' has already been used or destroyed!",
all_items[*i].name
)));
ui.label("...");
}
}
_ => {
ui.label("...");
}
});
ui.end_row();
if let Some(i) = dropped_payload {
self.destruction.item_index = Some(*i);
}

let mut button_destroy_clicked = false;

egui::Grid::new("destruction buttons").show(ui, |ui| {
if let (Some(i), None) = (self.destruction.item_index, &self.destruction.result) {
button_destroy_clicked = ui.button("Destroy").clicked();

if button_destroy_clicked {
let item = all_items[i].path.clone();
self.task_req_tx
.send(Request::Destroy {
params: self.params.clone(),
cfg: self.cfg.clone(),
item,
})
.unwrap();
}
}
ui.label(result2text(&self.destruction.result));
ui.end_row();
});
}
}
95 changes: 71 additions & 24 deletions app_gui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ use std::{
};

use anyhow::{Result, anyhow};
use app_cli::{Config, CraftedItem, Recipe, commit_item, craft_item, load_item, log_init};
use app_cli::{
Config, CraftedItem, ProductionType, Recipe, commit_item, craft_item, load_item, log_init,
};
use common::load_dotenv;
use egui::{Color32, Frame, Label, RichText, Ui};
use itertools::Itertools;
Expand All @@ -34,12 +36,14 @@ use tracing::{error, info};

mod app;
mod crafting;
mod destruction;
mod item_view;
mod task_system;
mod utils;

use app::*;
use crafting::*;
use destruction::*;
use item_view::*;
use task_system::*;

Expand All @@ -66,9 +70,7 @@ fn main() -> Result<()> {
}),
)
.map_err(|e| anyhow::anyhow!("{e}"))?;
// app.task_handler
// .join()
// .map_err(|e| anyhow::anyhow!("{e:?}"))?;

Ok(())
}

Expand All @@ -92,22 +94,15 @@ impl eframe::App for App {
self.crafting.craft_result = Some(r)
}
Response::Commit(r) => self.crafting.commit_result = Some(r),
Response::Destroy(r) => {
self.refresh_items().unwrap();
self.destruction.item_index = None;
self.destruction.result = Some(r)
}
Response::Null => {}
}
}

// If the task is busy, display a spinner and the task name
let task_status = self.task_status.read().unwrap().clone();
if let Some(task) = task_status.busy {
egui::CentralPanel::default().show(ctx, |ui| {
ui.vertical_centered(|ui| {
ui.spinner();
ui.heading(task);
});
});
return;
}

// Left side panel "Item list"
egui::SidePanel::left("item list").show(ctx, |ui| {
ui.horizontal(|ui| {
Expand Down Expand Up @@ -142,16 +137,24 @@ impl eframe::App for App {
});
});

egui::CentralPanel::default().show(ctx, |ui| {
ui.columns_const(|[item_view_ui, crafting_ui]| {
item_view_ui.vertical(|ui| {
self.update_item_view_ui(ui);
});
egui::CentralPanel::default().show(ctx, |ui| self.update_item_view_ui(ui));

crafting_ui.vertical(|ui| {
self.update_crafting_ui(ctx, ui);
// If the task is busy, display a spinner and the task name,
// else display the action UI.
let task_status = self.task_status.read().unwrap().clone();
egui::SidePanel::right("actions").show(ctx, |ui| {
if let Some(task) = task_status.busy {
ui.horizontal_centered(|ui| {
ui.spinner();
ui.heading(task);
});
});
} else {
self.update_action_ui(ctx, ui);
}
// Display window(s).
if self.modal_new_predicates {
self.ui_new_predicate(ctx, ui);
}
});
}

Expand All @@ -161,3 +164,47 @@ impl eframe::App for App {
thread::sleep(time::Duration::from_millis(100));
}
}

impl App {
pub fn update_action_ui(&mut self, ctx: &egui::Context, ui: &mut Ui) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to request a minimum width of this right panel so that the predicates don't wrap (too much).

I tried to implement it and wasn't able to get it working reliably so instead I want to request the removal of the Grid which allows the panel to be resizable (so that we can resize it to avoid the wrapping of predicates):

diff --git a/app_gui/src/main.rs b/app_gui/src/main.rs
index bf47292..da9cf02 100644
--- a/app_gui/src/main.rs
+++ b/app_gui/src/main.rs
@@ -167,47 +167,43 @@ impl eframe::App for App {
 
 impl App {
     pub fn update_action_ui(&mut self, ctx: &egui::Context, ui: &mut Ui) {
-        egui::Grid::new("action UI").show(ui, |ui| {
-            ui.set_min_height(32.0);
-            ui.vertical(|ui| {
-                ui.horizontal(|ui| {
-                    if ui
-                        .selectable_label(self.selected_tab == 0, "Mine")
-                        .clicked()
-                    {
-                        self.crafting.selected_recipe = None;
-                        self.selected_tab = 0;
-                    }
-                    if ui
-                        .selectable_label(self.selected_tab == 1, "Craft")
-                        .clicked()
-                    {
-                        self.crafting.selected_recipe = None;
-                        self.selected_tab = 1;
-                    }
-                    if ui
-                        .selectable_label(self.selected_tab == 2, "Destroy")
-                        .clicked()
-                    {
-                        self.destruction.item_index = None;
-                        self.selected_tab = 2;
-                    }
-                    if ui
-                        .selectable_label(self.modal_new_predicates, "+ New Predicate")
-                        .clicked()
-                    {
-                        self.modal_new_predicates = true;
-                    }
-                });
-                ui.separator();
-                match self.selected_tab {
-                    0 => self.ui_produce(ctx, ui, ProductionType::Mine),
-                    1 => self.ui_produce(ctx, ui, ProductionType::Craft),
-                    2 => self.ui_destroy(ctx, ui),
-                    _ => {}
+        ui.vertical(|ui| {
+            ui.horizontal(|ui| {
+                if ui
+                    .selectable_label(self.selected_tab == 0, "Mine")
+                    .clicked()
+                {
+                    self.crafting.selected_recipe = None;
+                    self.selected_tab = 0;
+                }
+                if ui
+                    .selectable_label(self.selected_tab == 1, "Craft")
+                    .clicked()
+                {
+                    self.crafting.selected_recipe = None;
+                    self.selected_tab = 1;
+                }
+                if ui
+                    .selectable_label(self.selected_tab == 2, "Destroy")
+                    .clicked()
+                {
+                    self.destruction.item_index = None;
+                    self.selected_tab = 2;
+                }
+                if ui
+                    .selectable_label(self.modal_new_predicates, "+ New Predicate")
+                    .clicked()
+                {
+                    self.modal_new_predicates = true;
                 }
             });
-            ui.end_row();
+            ui.separator();
+            match self.selected_tab {
+                0 => self.ui_produce(ctx, ui, ProductionType::Mine),
+                1 => self.ui_produce(ctx, ui, ProductionType::Craft),
+                2 => self.ui_destroy(ctx, ui),
+                _ => {}
+            }
         });
     }
 }

ui.vertical(|ui| {
ui.horizontal(|ui| {
if ui
.selectable_label(self.selected_tab == 0, "Mine")
.clicked()
{
self.crafting.selected_recipe = None;
self.selected_tab = 0;
}
if ui
.selectable_label(self.selected_tab == 1, "Craft")
.clicked()
{
self.crafting.selected_recipe = None;
self.selected_tab = 1;
}
if ui
.selectable_label(self.selected_tab == 2, "Destroy")
.clicked()
{
self.destruction.item_index = None;
self.selected_tab = 2;
}
if ui
.selectable_label(self.modal_new_predicates, "+ New Predicate")
.clicked()
{
self.modal_new_predicates = true;
}
});
ui.separator();
match self.selected_tab {
0 => self.ui_produce(ctx, ui, ProductionType::Mine),
1 => self.ui_produce(ctx, ui, ProductionType::Craft),
2 => self.ui_destroy(ctx, ui),
_ => {}
}
});
ui.end_row();
}
}
Loading