base tree creation
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
use client_network::{filename_to_string, node_hash_to_hex_string, MerkleNode, MerkleTree, NetworkCommand, NetworkEvent, NodeHash};
|
||||
use client_network::{
|
||||
MerkleNode, MerkleTree, NetworkCommand, NetworkEvent, NodeHash, filename_to_string,
|
||||
node_hash_to_hex_string,
|
||||
};
|
||||
use crossbeam_channel::{Receiver, Sender};
|
||||
use egui::{Align, Button, CentralPanel, CollapsingHeader, Context, Layout, ScrollArea, SidePanel, TopBottomPanel, Ui, ViewportCommand};
|
||||
use egui::{
|
||||
Align, Button, CentralPanel, CollapsingHeader, Context, Layout, ScrollArea, SidePanel,
|
||||
TopBottomPanel, Ui, ViewportCommand,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
// --- Main Application Struct ---
|
||||
@@ -23,22 +29,17 @@ pub struct P2PClientApp {
|
||||
|
||||
impl P2PClientApp {
|
||||
pub fn new(cmd_tx: Sender<NetworkCommand>, event_rx: Receiver<NetworkEvent>) -> Self {
|
||||
let (root_hash, tree_content) = MerkleNode::generate_random_tree(5).expect("Couldn't generate tree");
|
||||
let mut peer_root_hash = HashMap::new();
|
||||
peer_root_hash.insert("bob".to_string(), "yoyoyoyo".to_string());
|
||||
let (root_hash, tree_content) = MerkleNode::generate_base_tree();
|
||||
|
||||
let mut loaded_fs = HashMap::new();
|
||||
let tree = MerkleTree::new(tree_content, root_hash);
|
||||
loaded_fs.insert("bob".to_string(), tree);
|
||||
|
||||
|
||||
Self {
|
||||
network_cmd_tx: cmd_tx,
|
||||
network_event_rx: event_rx,
|
||||
status_message: "Client Initialized. Awaiting network status...".to_string(),
|
||||
known_peers: vec![
|
||||
"bob".to_string()
|
||||
],
|
||||
known_peers: vec!["bob".to_string()],
|
||||
connect_address_input: "127.0.0.1:8080".to_string(),
|
||||
loaded_fs,
|
||||
active_peer: None,
|
||||
@@ -50,7 +51,6 @@ impl P2PClientApp {
|
||||
|
||||
impl eframe::App for P2PClientApp {
|
||||
fn update(&mut self, ctx: &Context, _frame: &mut eframe::Frame) {
|
||||
|
||||
// 1. Process incoming Network Events
|
||||
// We poll the channel and update the GUI state for every event received.
|
||||
while let Ok(event) = self.network_event_rx.try_recv() {
|
||||
@@ -119,33 +119,43 @@ impl eframe::App for P2PClientApp {
|
||||
});
|
||||
|
||||
// 3. Right-sided Panel (Known Peers)
|
||||
SidePanel::right("right_panel").resizable(true).min_width(180.0).show(ctx, |ui| {
|
||||
ui.heading("🌐 Known Peers");
|
||||
ui.separator();
|
||||
ScrollArea::vertical().show(ui, |ui| {
|
||||
if self.known_peers.is_empty() {
|
||||
ui.add_space(10.0);
|
||||
ui.label("No active peers.");
|
||||
} else {
|
||||
for peer in &self.known_peers {
|
||||
let is_active = self.active_peer.as_ref().map_or(false, |id| id == peer); // if peer.id == self.active_peer_id
|
||||
SidePanel::right("right_panel")
|
||||
.resizable(true)
|
||||
.min_width(180.0)
|
||||
.show(ctx, |ui| {
|
||||
ui.heading("🌐 Known Peers");
|
||||
ui.separator();
|
||||
ScrollArea::vertical().show(ui, |ui| {
|
||||
if self.known_peers.is_empty() {
|
||||
ui.add_space(10.0);
|
||||
ui.label("No active peers.");
|
||||
} else {
|
||||
for peer in &self.known_peers {
|
||||
let is_active =
|
||||
self.active_peer.as_ref().map_or(false, |id| id == peer); // if peer.id == self.active_peer_id
|
||||
|
||||
if ui.selectable_label(is_active, format!("{}", peer)).clicked() {
|
||||
// switch to displaying this peer's tree
|
||||
self.active_peer = Some(peer.clone());
|
||||
// Request root content if not loaded
|
||||
if !self.loaded_fs.contains_key(self.active_peer.as_ref().unwrap()) {
|
||||
todo!();
|
||||
// let _ = self.network_cmd_tx.send(NetworkCommand::RequestDirectoryContent(
|
||||
// peer.clone(),
|
||||
// peer.clone(),
|
||||
// ));
|
||||
if ui
|
||||
.selectable_label(is_active, format!("{}", peer))
|
||||
.clicked()
|
||||
{
|
||||
// switch to displaying this peer's tree
|
||||
self.active_peer = Some(peer.clone());
|
||||
// Request root content if not loaded
|
||||
if !self
|
||||
.loaded_fs
|
||||
.contains_key(self.active_peer.as_ref().unwrap())
|
||||
{
|
||||
todo!();
|
||||
// let _ = self.network_cmd_tx.send(NetworkCommand::RequestDirectoryContent(
|
||||
// peer.clone(),
|
||||
// peer.clone(),
|
||||
// ));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 4. Central Panel (Filesystem Tree)
|
||||
let heading = {
|
||||
@@ -185,72 +195,30 @@ impl eframe::App for P2PClientApp {
|
||||
// --- Helper for Drawing the Recursive File Tree ---
|
||||
|
||||
impl P2PClientApp {
|
||||
// fn draw_file_tree(&self, ui: &mut Ui, node: &FileNode, depth: usize) {
|
||||
// let indent_space = 15.0 * depth as f32;
|
||||
// let active_peer_id = self.active_peer_id.clone();
|
||||
//
|
||||
// let entry_hash = &node.hash_id;
|
||||
// let filename = &node.name;
|
||||
// let is_dir = node.is_dir;
|
||||
//
|
||||
// if is_dir {
|
||||
// // --- Directory Node: Check if content (children) is already loaded (stored in the map) ---
|
||||
//
|
||||
// if let Some(children) = node.children.as_ref() {
|
||||
// // Content is already loaded: draw the collapsing header and recurse
|
||||
// CollapsingHeader::new(format!("📁 {}", filename))
|
||||
// .default_open(false)
|
||||
// .enabled(true)
|
||||
// .show(ui, |ui| {
|
||||
// // Recursive call: iterate over children and call draw_file_tree for each
|
||||
// for child_node in children {
|
||||
// self.draw_file_tree(ui, child_node, depth + 1);
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// // Content is NOT loaded: show a clickable button to request loading
|
||||
// let response = ui.with_layout(Layout::left_to_right(Align::Min), |ui| {
|
||||
// ui.add_space(indent_space);
|
||||
// ui.add(Button::new(format!("▶️ {} (Load)", filename)).small()).on_hover_text(format!("Hash: {}...", &entry_hash[..8]));
|
||||
// }).response;
|
||||
//
|
||||
// if response.clicked() {
|
||||
// if let Some(peer_id) = active_peer_id.clone() {
|
||||
// let _ = self.network_cmd_tx.send(NetworkCommand::RequestDirectoryContent(
|
||||
// peer_id,
|
||||
// entry_hash.clone(),
|
||||
// ));
|
||||
// // self.status_message = format!("Requested directory content for: {}...", &entry_hash[..8]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// // --- File Node (Chunk or Big) ---
|
||||
// ui.with_layout(Layout::left_to_right(Align::Center), |ui| {
|
||||
// ui.add_space(indent_space);
|
||||
// if ui.selectable_label(false, format!("📄 {} (Hash: {}...)", filename, &entry_hash[..8])).on_hover_text("Click to request file chunks...").clicked() {
|
||||
// if let Some(peer_id) = active_peer_id.clone() {
|
||||
// let _ = self.network_cmd_tx.send(NetworkCommand::RequestChunk(peer_id, entry_hash.clone()));
|
||||
// // self.status_message = format!("Requested file chunks for: {}...", &entry_hash[..8]);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
fn draw_file_tree(&self, ui: &mut Ui, tree: &MerkleTree) {
|
||||
assert!(self.active_peer.is_some());
|
||||
assert!(self.loaded_fs.get(&self.active_peer.clone().unwrap()).is_some());
|
||||
assert!(
|
||||
self.loaded_fs
|
||||
.get(&self.active_peer.clone().unwrap())
|
||||
.is_some()
|
||||
);
|
||||
let root = tree.root;
|
||||
CollapsingHeader::new(format!("📁 root"))
|
||||
.default_open(true)
|
||||
.enabled(true)
|
||||
.show(ui, |ui| {
|
||||
self.draw_file_node(ui, root, tree,0, None);
|
||||
self.draw_file_node(ui, root, tree, 0, None);
|
||||
});
|
||||
}
|
||||
|
||||
fn draw_file_node(&self, ui: &mut Ui, to_draw: NodeHash, tree: &MerkleTree, depth: usize, filename: Option<[u8; 32]>) {
|
||||
fn draw_file_node(
|
||||
&self,
|
||||
ui: &mut Ui,
|
||||
to_draw: NodeHash,
|
||||
tree: &MerkleTree,
|
||||
depth: usize,
|
||||
filename: Option<[u8; 32]>,
|
||||
) {
|
||||
if depth >= 32 {
|
||||
return;
|
||||
}
|
||||
@@ -264,7 +232,11 @@ impl P2PClientApp {
|
||||
};
|
||||
match current {
|
||||
MerkleNode::Chunk(node) => {
|
||||
if ui.selectable_label(false, format!("📄 (C) {}...", name)).on_hover_text("Click to request file chunks...").clicked() {
|
||||
if ui
|
||||
.selectable_label(false, format!("📄 (C) {}...", name))
|
||||
.on_hover_text("Click to request file chunks...")
|
||||
.clicked()
|
||||
{
|
||||
todo!();
|
||||
// if let Some(peer_id) = active_peer_id.clone() {
|
||||
// let _ = self.network_cmd_tx.send(NetworkCommand::RequestChunk(peer_id, entry_hash.clone()));
|
||||
@@ -278,12 +250,17 @@ impl P2PClientApp {
|
||||
.enabled(true)
|
||||
.show(ui, |ui| {
|
||||
for entry in &node.entries {
|
||||
self.draw_file_node(ui, entry.content_hash, tree, depth + 1, Some(entry.filename));
|
||||
self.draw_file_node(
|
||||
ui,
|
||||
entry.content_hash,
|
||||
tree,
|
||||
depth + 1,
|
||||
Some(entry.filename),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
MerkleNode::Big(node) => {
|
||||
|
||||
CollapsingHeader::new(format!("📄 (B) {}", name))
|
||||
.default_open(false)
|
||||
.enabled(true)
|
||||
@@ -306,4 +283,5 @@ impl P2PClientApp {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user