feat: ZeroSend v2.5.1 - Revamped 3-Step Live Folder Auto-Sync, Dynamic Credits & UI Polish

This commit is contained in:
RarDog
2026-08-27 12:59:46 +03:00
parent 514f88ae33
commit dc72fe47e1
5 changed files with 212 additions and 145 deletions
Generated
+1 -1
View File
@@ -6372,7 +6372,7 @@ checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
[[package]]
name = "zerosend"
version = "2.5.0"
version = "2.5.1"
dependencies = [
"arboard",
"axum",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "zerosend"
version = "2.5.0"
version = "2.5.1"
edition = "2021"
description = "Fast, peer-to-peer file transfer designed for ZeroTier, Tailscale, Radmin VPN and LAN"
authors = ["RarDog"]
+1 -1
View File
@@ -298,7 +298,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
.with_inner_size([config.window_width, config.window_height])
.with_min_inner_size([780.0, 500.0])
.with_visible(!start_minimized)
.with_title("ZeroSend v2.5.0 - P2P Sharing for ZeroTier & VPN"),
.with_title(format!("ZeroSend v{} - P2P Sharing for ZeroTier & VPN", env!("CARGO_PKG_VERSION"))),
..Default::default()
};
+2 -1
View File
@@ -2330,7 +2330,7 @@ async fn handle_web_ui(State(state): State<Arc<ServerState>>) -> Html<String> {
<div class="toast" id="toast"></div>
<div class="footer">
ZeroSend v2.4.1 • Ultra-fast P2P File & Text Sharing • 🛡️ SHA-256 Verified
ZeroSend v{version} • Ultra-fast P2P File & Text Sharing • 🛡️ SHA-256 Verified
</div>
</div>
@@ -2766,6 +2766,7 @@ async fn handle_web_ui(State(state): State<Arc<ServerState>>) -> Html<String> {
</html>"###,
device_name = state.my_info.name,
net_type = state.my_info.net_type,
version = env!("CARGO_PKG_VERSION"),
);
Html(html)
+188 -122
View File
@@ -2023,62 +2023,6 @@ impl ZeroSendApp {
}
fn render_my_shares(&mut self, ui: &mut Ui, theme: ThemeColors) {
// WebDAV Windows Explorer Network Drive Card
Frame::none()
.fill(theme.bg_card)
.rounding(Rounding::same(8.0))
.stroke(theme.stroke_border)
.inner_margin(Margin::same(12.0))
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.label(RichText::new("🌐 WebDAV Windows Drive Mount").strong().color(theme.text_primary));
ui.label(
RichText::new(format!("(Local WebDAV: http://127.0.0.1:{}/webdav)", self.config.webdav_port))
.size(11.0)
.color(theme.text_muted),
);
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
if self.webdav_mounted {
if ui.button(RichText::new("✕ Unmount Z: Drive").color(Color32::from_rgb(239, 68, 68))).clicked() {
let _ = crate::transfer::unmount_webdav_drive(self.webdav_drive_letter);
self.webdav_mounted = false;
self.webdav_status_msg = Some("Unmounted drive".to_string());
}
ui.label(RichText::new(format!("● Mounted as Drive {}:", self.webdav_drive_letter)).color(Color32::from_rgb(34, 197, 94)).strong());
} else {
let mount_btn = Button::new(
RichText::new("🔗 Mount as Network Drive Z: in Windows Explorer")
.strong()
.color(Color32::WHITE),
)
.fill(Color32::from_rgb(37, 99, 235))
.rounding(Rounding::same(6.0));
if ui.add(mount_btn).clicked() {
match crate::transfer::mount_webdav_drive(self.webdav_drive_letter, self.config.webdav_port) {
Ok(msg) => {
self.webdav_mounted = true;
self.webdav_status_msg = Some(msg);
let _ = std::process::Command::new("explorer").arg(format!("{}:\\", self.webdav_drive_letter)).spawn();
}
Err(e) => {
self.webdav_status_msg = Some(format!("Error: {}", e));
}
}
}
}
});
});
if let Some(msg) = &self.webdav_status_msg {
ui.add_space(4.0);
ui.label(RichText::new(msg).size(11.0).color(theme.text_muted));
}
});
ui.add_space(8.0);
if self.shared_folders.is_empty() {
Frame::none()
.fill(theme.bg_card)
@@ -2089,7 +2033,7 @@ impl ZeroSendApp {
ui.vertical_centered(|ui| {
ui.label(RichText::new("📁").size(36.0));
ui.label(
RichText::new("You haven't shared any local folders yet.")
RichText::new("У вас пока нет локальных общих папок.")
.size(15.0)
.strong()
.color(theme.text_primary),
@@ -2097,15 +2041,15 @@ impl ZeroSendApp {
ui.add_space(4.0);
ui.label(
RichText::new(
"Share movies, music, or code folders so your friends on ZeroTier/LAN can stream and download them.",
"Откройте доступ к папкам с фильмами, музыкой или кодом, чтобы ваши друзья в ZeroTier/LAN могли смотреть и скачивать их.",
)
.size(12.0)
.color(theme.text_muted),
);
ui.add_space(12.0);
let choose_btn = Button::new(RichText::new("➕ Choose Folder to Share").strong().color(Color32::WHITE))
let choose_btn = Button::new(RichText::new("➕ Выбрать папку для общего доступа").strong().color(Color32::WHITE))
.fill(Color32::from_rgb(34, 197, 94))
.min_size(Vec2::new(180.0, 34.0));
.min_size(Vec2::new(220.0, 36.0));
if ui.add(choose_btn).clicked() {
if let Some(folder) = FileDialog::new().pick_folder() {
@@ -2147,9 +2091,9 @@ impl ZeroSendApp {
ui.label(RichText::new(&share.name).strong().size(14.0).color(theme.text_primary));
let (ro_label, ro_color) = if share.read_only {
("Read-Only (Streaming/Download)", Color32::from_rgb(59, 130, 246))
("Только чтение (Стриминг/Скачивание)", Color32::from_rgb(59, 130, 246))
} else {
("Read & Write (Uploads Allowed)", Color32::from_rgb(34, 197, 94))
("Чтение и запись (Загрузка разрешена)", Color32::from_rgb(34, 197, 94))
};
Frame::none()
@@ -2169,7 +2113,7 @@ impl ZeroSendApp {
.inner_margin(Margin::symmetric(6.0, 2.0))
.show(ui, |ui| {
ui.label(
RichText::new("🔒 PIN Protected")
RichText::new("🔒 PIN-защита")
.size(10.5)
.color(Color32::from_rgb(245, 158, 11)),
);
@@ -2186,15 +2130,15 @@ impl ZeroSendApp {
});
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
if ui.button(RichText::new("🗑 Remove").color(Color32::from_rgb(239, 68, 68))).clicked() {
if ui.button(RichText::new("🗑 Удалить").color(Color32::from_rgb(239, 68, 68))).clicked() {
remove_index = Some(idx);
}
if ui.button("📂 Open Folder").clicked() {
if ui.button("📂 Открыть папку").clicked() {
let _ = std::process::Command::new("explorer").arg(&share.path).spawn();
}
if ui.checkbox(&mut share.read_only, "Read-Only").changed() {
if ui.checkbox(&mut share.read_only, "Только чтение").changed() {
config_changed = true;
}
});
@@ -2215,68 +2159,170 @@ impl ZeroSendApp {
}
fn render_auto_sync_subtab(&mut self, ui: &mut Ui, theme: ThemeColors) {
// Explanatory Banner
Frame::none()
.fill(if theme.is_dark { Color32::from_rgb(15, 23, 42) } else { Color32::from_rgb(238, 242, 255) })
.rounding(Rounding::same(8.0))
.stroke(Stroke::new(1.0_f32, Color32::from_rgb(99, 102, 241)))
.inner_margin(Margin::symmetric(14.0, 10.0))
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.label(RichText::new("🔄").size(22.0));
ui.vertical(|ui| {
ui.label(
RichText::new("Двусторонняя авто-синхронизация (Two-Way Live Sync)")
.strong()
.size(14.0)
.color(theme.text_primary),
);
ui.label(
RichText::new(
"Автоматически зеркалирует локальную папку на вашем ПК с общей папкой друга в фоновом режиме каждые 8 секунд без лишних действий.",
)
.size(11.5)
.color(theme.text_secondary),
);
});
});
});
ui.add_space(10.0);
// Collect all online friends with shared folders
let mut online_shares: Vec<(String, String, String, String)> = Vec::new();
for peer in &self.peers {
if peer.is_online && !peer.shared_folders.is_empty() {
let (pname, _) = self.get_peer_display_name(peer);
for folder in &peer.shared_folders {
online_shares.push((peer.peer_id.clone(), pname.clone(), folder.id.clone(), folder.name.clone()));
}
}
}
// STEP-BY-STEP PAIRING WIZARD
Frame::none()
.fill(theme.bg_card)
.rounding(Rounding::same(8.0))
.stroke(theme.stroke_border)
.inner_margin(Margin::same(14.0))
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.label(RichText::new("🔄 Two-Way Live Folder Synchronization").strong().size(14.0).color(theme.text_primary));
ui.label(
RichText::new("(Automatic real-time background sync with friend's shared folder)")
.size(11.0)
.color(theme.text_muted),
);
});
ui.label(RichText::new("➕ Настройка новой авто-синхронизации (3 простых шага)").strong().size(13.5).color(theme.text_accent));
ui.add_space(8.0);
ui.separator();
ui.add_space(8.0);
// Add New Sync Pairing form
ui.label(RichText::new("➕ Create New Sync Pairing").strong().color(theme.text_secondary));
// --- ШАГ 1: Выбор папки друга ---
ui.label(RichText::new("Шаг 1: Выберите общую папку друга из сети").strong().color(theme.text_primary));
ui.add_space(4.0);
if online_shares.is_empty() {
Frame::none()
.fill(theme.bg_card_secondary)
.rounding(Rounding::same(6.0))
.inner_margin(Margin::same(8.0))
.show(ui, |ui| {
ui.label(
RichText::new("ℹ️ В сети пока не обнаружено общих папок у друзей. Подключитесь к ZeroTier/LAN, чтобы друзья появились онлайн.")
.size(11.5)
.color(theme.text_muted),
);
});
} else {
ui.horizontal_wrapped(|ui| {
for (pid, pname, fid, fname) in &online_shares {
let is_chosen = self.new_sync_peer_id == *pid && self.new_sync_folder_id == *fid;
let btn_text = format!("📁 {} (от {})", fname, pname);
let share_btn = Button::new(
RichText::new(btn_text)
.size(12.0)
.strong()
.color(if is_chosen { Color32::WHITE } else { theme.text_primary }),
)
.fill(if is_chosen {
Color32::from_rgb(37, 99, 235)
} else {
theme.bg_card_secondary
})
.stroke(if is_chosen {
Stroke::new(1.5_f32, Color32::from_rgb(96, 165, 250))
} else {
Stroke::NONE
})
.rounding(Rounding::same(6.0))
.min_size(Vec2::new(180.0, 32.0));
if ui.add(share_btn).clicked() {
self.new_sync_peer_id = pid.clone();
self.new_sync_folder_id = fid.clone();
if self.new_sync_name.trim().is_empty() {
self.new_sync_name = format!("Синхронизация {} ({})", fname, pname);
}
}
}
});
}
ui.add_space(10.0);
// --- ШАГ 2: Выбор локальной папки на диске ---
ui.label(RichText::new("Шаг 2: Выберите локальную папку на вашем компьютере").strong().color(theme.text_primary));
ui.add_space(4.0);
ui.horizontal(|ui| {
ui.label("Name:");
ui.add(egui::TextEdit::singleline(&mut self.new_sync_name).hint_text("My Project Sync").desired_width(130.0));
let browse_btn = Button::new(RichText::new("📁 Выбрать папку на диске...").strong().color(Color32::WHITE))
.fill(Color32::from_rgb(59, 130, 246))
.rounding(Rounding::same(4.0));
ui.label("Local Path:");
ui.add(egui::TextEdit::singleline(&mut self.new_sync_local_path).hint_text("C:\\Projects\\...").desired_width(180.0));
if ui.button("📁 Browse").clicked() {
if ui.add(browse_btn).clicked() {
if let Some(folder) = FileDialog::new().pick_folder() {
self.new_sync_local_path = folder.to_string_lossy().into_owned();
}
}
if self.new_sync_local_path.is_empty() {
ui.label(RichText::new("Папка не выбрана").color(Color32::from_rgb(239, 68, 68)).size(11.5));
} else {
ui.label(RichText::new(&self.new_sync_local_path).strong().color(Color32::from_rgb(34, 197, 94)).monospace().size(11.5));
}
});
ui.add_space(10.0);
// --- ШАГ 3: Запуск синхронизации ---
ui.label(RichText::new("Шаг 3: Назовите и запустите синхронизацию").strong().color(theme.text_primary));
ui.add_space(4.0);
ui.horizontal(|ui| {
ui.label("Friend (Peer ID):");
ui.add(egui::TextEdit::singleline(&mut self.new_sync_peer_id).hint_text("Select or paste peer ID...").desired_width(180.0));
ui.label("Имя пары:");
ui.add(egui::TextEdit::singleline(&mut self.new_sync_name).hint_text("Мой проект").desired_width(180.0));
ui.label("Remote Folder ID:");
ui.add(egui::TextEdit::singleline(&mut self.new_sync_folder_id).hint_text("Shared folder ID...").desired_width(160.0));
let is_ready = !self.new_sync_local_path.trim().is_empty()
&& !self.new_sync_peer_id.trim().is_empty()
&& !self.new_sync_folder_id.trim().is_empty();
let add_pair_btn = Button::new(RichText::new("➕ Add Pairing").strong().color(Color32::WHITE))
.fill(Color32::from_rgb(34, 197, 94))
.rounding(Rounding::same(4.0));
let start_btn = Button::new(RichText::new("🚀 Запустить авто-синхронизацию").strong().color(Color32::WHITE))
.fill(if is_ready { Color32::from_rgb(34, 197, 94) } else { Color32::from_rgb(100, 116, 139) })
.rounding(Rounding::same(4.0))
.min_size(Vec2::new(200.0, 30.0));
if ui.add(add_pair_btn).clicked() {
if !self.new_sync_local_path.trim().is_empty() && !self.new_sync_peer_id.trim().is_empty() {
if ui.add_enabled(is_ready, start_btn).clicked() {
let name = if self.new_sync_name.trim().is_empty() {
"Folder Sync".to_string()
} else {
self.new_sync_name.trim().to_string()
};
let peer_name = self.peers.iter()
.find(|p| p.peer_id == self.new_sync_peer_id)
.map(|p| self.get_peer_display_name(p).0)
.unwrap_or_else(|| "Friend".to_string());
let pair = crate::transfer::FolderSyncPairConfig {
id: uuid::Uuid::new_v4().to_string(),
name,
local_path: PathBuf::from(self.new_sync_local_path.trim()),
remote_peer_id: self.new_sync_peer_id.trim().to_string(),
remote_peer_name: "Friend".to_string(),
remote_peer_name: peer_name,
remote_folder_id: self.new_sync_folder_id.trim().to_string(),
is_active: true,
last_sync: None,
@@ -2286,9 +2332,11 @@ impl ZeroSendApp {
self.config.folder_sync_pairs = self.folder_sync_pairs.clone();
self.persist_config();
self.logs.push(format!("🔄 Создана новая авто-синхронизация: {}", self.new_sync_name));
self.new_sync_local_path.clear();
self.new_sync_name.clear();
}
self.new_sync_peer_id.clear();
self.new_sync_folder_id.clear();
}
});
});
@@ -2296,6 +2344,9 @@ impl ZeroSendApp {
ui.add_space(10.0);
// List of Active Sync Pairs
ui.label(RichText::new(format!("Активные пары синхронизации ({})", self.folder_sync_pairs.len())).strong().size(13.0).color(theme.text_primary));
ui.add_space(4.0);
if self.folder_sync_pairs.is_empty() {
Frame::none()
.fill(theme.bg_card)
@@ -2304,8 +2355,8 @@ impl ZeroSendApp {
.inner_margin(Margin::same(24.0))
.show(ui, |ui| {
ui.vertical_centered(|ui| {
ui.label(RichText::new("🔄 No active sync pairings configured.").color(theme.text_secondary));
ui.label(RichText::new("Configure a pairing above to automatically synchronize folders with friends.").size(11.5).color(theme.text_muted));
ui.label(RichText::new("🔄 Нет активных настроенных пар синхронизации.").color(theme.text_secondary));
ui.label(RichText::new("Выберите общую папку друга в мастере выше и укажите локальную папку для старта.").size(11.5).color(theme.text_muted));
});
});
} else {
@@ -2320,35 +2371,35 @@ impl ZeroSendApp {
.inner_margin(Margin::same(12.0))
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.label(RichText::new("🔄").size(20.0));
ui.label(RichText::new("🔄").size(22.0));
ui.vertical(|ui| {
ui.horizontal(|ui| {
ui.label(RichText::new(&pair.name).strong().color(theme.text_primary));
ui.label(RichText::new(&pair.name).strong().size(13.5).color(theme.text_primary));
if pair.is_active {
ui.label(RichText::new("● Active (Auto-Syncing)").color(Color32::from_rgb(34, 197, 94)).size(11.0));
ui.label(RichText::new("● Авто-синхронизация активна (каждые 8с)").color(Color32::from_rgb(34, 197, 94)).size(11.0).strong());
} else {
ui.label(RichText::new("⏸ Paused").color(theme.text_muted).size(11.0));
ui.label(RichText::new("⏸ На паузе").color(theme.text_muted).size(11.0));
}
});
ui.label(
RichText::new(format!("Local: {:?} ➔ Remote Folder ID: {}", pair.local_path, pair.remote_folder_id))
.monospace()
.size(11.0)
.color(theme.text_muted),
);
ui.horizontal(|ui| {
ui.label(RichText::new("💻 Локально:").strong().size(11.0).color(theme.text_secondary));
ui.label(RichText::new(format!("{:?}", pair.local_path)).monospace().size(11.0).color(theme.text_muted));
ui.label(RichText::new("➔ 🌐 Удаленно (Друг):").strong().size(11.0).color(theme.text_secondary));
ui.label(RichText::new(&pair.remote_peer_name).size(11.0).color(theme.text_accent));
});
});
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
if ui.button(RichText::new("🗑 Delete").color(Color32::from_rgb(239, 68, 68))).clicked() {
if ui.button(RichText::new("🗑 Удалить").color(Color32::from_rgb(239, 68, 68))).clicked() {
remove_sync_idx = Some(idx);
}
if ui.checkbox(&mut pair.is_active, "Enabled").changed() {
if ui.checkbox(&mut pair.is_active, "Включено").changed() {
sync_changed = true;
}
if ui.button("📂 Open Local").clicked() {
if ui.button("📂 Открыть локально").clicked() {
let _ = std::process::Command::new("explorer").arg(&pair.local_path).spawn();
}
});
@@ -2377,12 +2428,12 @@ impl ZeroSendApp {
.stroke(theme.stroke_border)
.inner_margin(Margin::same(10.0))
.show(ui, |ui| {
ui.label(RichText::new("📜 Live Sync Activity Log").strong().size(12.0).color(Color32::from_rgb(148, 163, 184)));
ui.label(RichText::new("📜 Журнал работы авто-синхронизации (Live Activity Log)").strong().size(12.0).color(Color32::from_rgb(148, 163, 184)));
ui.add_space(4.0);
ScrollArea::vertical().max_height(140.0).show(ui, |ui| {
if self.sync_log_messages.is_empty() {
ui.label(RichText::new("No sync activity yet. Files will be mirrored automatically.").size(11.0).color(Color32::from_rgb(100, 116, 139)));
ui.label(RichText::new("Синхронизация ожидает изменений. Новые и измененные файлы будут синхронизироваться автоматически.").size(11.0).color(Color32::from_rgb(100, 116, 139)));
} else {
for log in self.sync_log_messages.iter().rev() {
ui.label(RichText::new(log).monospace().size(11.0).color(Color32::from_rgb(203, 213, 225)));
@@ -2532,18 +2583,34 @@ impl ZeroSendApp {
ui.with_layout(Layout::right_to_left(Align::Center), |ui| {
// Grep search button
if ui.button(RichText::new("🔎 Search Text/Code").color(Color32::from_rgb(56, 189, 248))).clicked() {
if ui.button(RichText::new("🔎 Поиск текста/кода").color(Color32::from_rgb(56, 189, 248))).clicked() {
self.show_grep_modal = true;
self.grep_query.clear();
self.grep_results.clear();
self.grep_status_msg = None;
}
// Quick Auto-Sync pairing shortcut
let folder_id_clone = folder_id.clone();
let peer_id_clone = peer.peer_id.clone();
let peer_name_clone = peer_name.clone();
let f_name = peer.shared_folders.iter().find(|f| f.id == folder_id_clone).map(|f| f.name.clone()).unwrap_or_else(|| "Shared".to_string());
if ui.button(RichText::new("🔄 Авто-Синхронизация").color(Color32::from_rgb(168, 85, 247))).clicked() {
self.new_sync_peer_id = peer_id_clone;
self.new_sync_folder_id = folder_id_clone;
self.new_sync_name = format!("Синхронизация {} ({})", f_name, peer_name_clone);
self.selected_share_subtab = SharedSubTab::AutoSync;
if let Some(folder) = FileDialog::new().pick_folder() {
self.new_sync_local_path = folder.to_string_lossy().into_owned();
}
}
// Search filter box
ui.add(
egui::TextEdit::singleline(&mut self.share_search_query)
.hint_text("🔍 Filter files...")
.desired_width(140.0),
.hint_text("🔍 Фильтр файлов...")
.desired_width(130.0),
);
// Upload button if folder is Read-Write
@@ -3564,7 +3631,7 @@ impl ZeroSendApp {
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.label(RichText::new("⚡ ZeroSend").size(16.0).strong().color(theme.text_accent));
ui.label(RichText::new("v2.4.1").size(13.0).color(Color32::from_rgb(34, 197, 94)).strong());
ui.label(RichText::new(format!("v{}", env!("CARGO_PKG_VERSION"))).size(13.0).color(Color32::from_rgb(34, 197, 94)).strong());
});
ui.add_space(4.0);
ui.label(RichText::new("Fast, peer-to-peer file & text sharing optimized for ZeroTier, Tailscale, Radmin VPN & LAN.").color(theme.text_secondary));
@@ -3577,16 +3644,15 @@ impl ZeroSendApp {
ui.add_space(6.0);
ui.label(RichText::new("⚙ Technology Stack:").strong().color(theme.text_primary));
ui.label(RichText::new(" • Rust 1.98, Tokio Async Runtime, Axum HTTP Streaming").color(theme.text_secondary));
ui.label(RichText::new(" • HTTP 206 Partial Content Media Streaming & Real-time Seeking").color(theme.text_secondary));
ui.label(RichText::new(" • Full Portable Exe-Folder Configuration & Data Storage").color(theme.text_secondary));
ui.label(RichText::new(" • Embedded Lightweight Vim Code & Text Viewer").color(theme.text_secondary));
ui.label(RichText::new(" • SHA-256 On-The-Fly Cryptographic File Integrity Verification").color(theme.text_secondary));
ui.label(RichText::new(" • Mobile Web PWA with Thumbnails & Voice Notes Recorder").color(theme.text_secondary));
ui.label(RichText::new(" • 🔄 Two-Way Live Folder Synchronization Engine (Continuous Peer Mirroring)").color(theme.text_secondary));
ui.label(RichText::new(" • 🖧 Windows Explorer Network Drive (WebDAV RFC 4918)").color(theme.text_secondary));
ui.label(RichText::new(" • 🎬 HTTP 206 Partial Content Streaming & Watch Party Session Sync").color(theme.text_secondary));
ui.label(RichText::new(" • ✏️ Full Modal Vim Editor with Normal/Insert Modes, :w Save & Markdown Preview").color(theme.text_secondary));
ui.label(RichText::new(" • 🔎 Remote Full-Text Grep Code & Text Search Engine").color(theme.text_secondary));
ui.label(RichText::new(" • 📦 Single-Folder Portable Exe Configuration & Data Storage").color(theme.text_secondary));
ui.label(RichText::new(" • 🛡️ SHA-256 On-The-Fly Cryptographic File Integrity Verification").color(theme.text_secondary));
ui.label(RichText::new(" • 4-Stream Parallel Chunk Worker Engine (Multi-stream Range transfers)").color(theme.text_secondary));
ui.label(RichText::new(" • Resumable .zerosend_part File Checkpointing Engine").color(theme.text_secondary));
ui.label(RichText::new(" • Token-Bucket Bandwidth Rate Limiter & Priority Discovery").color(theme.text_secondary));
ui.label(RichText::new(" • Egui & Eframe Desktop GUI Engine with Dynamic Dark/Light Themes").color(theme.text_secondary));
ui.label(RichText::new(" • Zip Fast Deflate Streaming Compression Engine").color(theme.text_secondary));
ui.label(RichText::new(" • UDP Broadcast ZeroTier Mesh Discovery Engine").color(theme.text_secondary));
});
});