Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35e590c718 | ||
|
|
9f9044646f |
Generated
+1
-1
@@ -6372,7 +6372,7 @@ checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerosend"
|
name = "zerosend"
|
||||||
version = "2.5.1"
|
version = "2.5.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arboard",
|
"arboard",
|
||||||
"axum",
|
"axum",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "zerosend"
|
name = "zerosend"
|
||||||
version = "2.5.1"
|
version = "2.5.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Fast, peer-to-peer file transfer designed for ZeroTier, Tailscale, Radmin VPN and LAN"
|
description = "Fast, peer-to-peer file transfer designed for ZeroTier, Tailscale, Radmin VPN and LAN"
|
||||||
authors = ["RarDog"]
|
authors = ["RarDog"]
|
||||||
|
|||||||
@@ -32,6 +32,14 @@ fn get_default_device_name() -> String {
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
|
// Clean up any old binaries or temp files from previous self-updates
|
||||||
|
if let Ok(current_exe) = std::env::current_exe() {
|
||||||
|
if let Some(exe_dir) = current_exe.parent() {
|
||||||
|
let _ = std::fs::remove_file(exe_dir.join("zerosend.exe.old"));
|
||||||
|
let _ = std::fs::remove_file(exe_dir.join("zerosend_update.exe"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let config = AppConfig::load();
|
let config = AppConfig::load();
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
||||||
|
|||||||
+914
-652
File diff suppressed because it is too large
Load Diff
+21
-21
@@ -100,9 +100,9 @@ impl VimViewerModal {
|
|||||||
self.is_command_mode = false;
|
self.is_command_mode = false;
|
||||||
self.is_dirty = false;
|
self.is_dirty = false;
|
||||||
self.status_msg = Some(format!(
|
self.status_msg = Some(format!(
|
||||||
"Loaded {} lines • {}",
|
"Загружено {} строк • {}",
|
||||||
self.lines.len(),
|
self.lines.len(),
|
||||||
if self.is_writable { "Writable [i: edit, :w: save]" } else { "Read-Only" }
|
if self.is_writable { "Доступна запись [i: правка, :w: сохранить]" } else { "Только чтение" }
|
||||||
));
|
));
|
||||||
self.last_g_press = None;
|
self.last_g_press = None;
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ impl VimViewerModal {
|
|||||||
|
|
||||||
pub fn trigger_save(&mut self) {
|
pub fn trigger_save(&mut self) {
|
||||||
if !self.is_writable {
|
if !self.is_writable {
|
||||||
self.status_msg = Some("❌ Cannot save: folder is Read-Only".to_string());
|
self.status_msg = Some("❌ Невозможно сохранить: папка только для чтения".to_string());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,10 +129,10 @@ impl VimViewerModal {
|
|||||||
self.buffer_content.clone(),
|
self.buffer_content.clone(),
|
||||||
self.pin.clone(),
|
self.pin.clone(),
|
||||||
));
|
));
|
||||||
self.status_msg = Some("⏳ Saving changes to remote peer...".to_string());
|
self.status_msg = Some("⏳ Сохранение изменений на удаленном узле...".to_string());
|
||||||
self.is_dirty = false;
|
self.is_dirty = false;
|
||||||
} else {
|
} else {
|
||||||
self.status_msg = Some("❌ No remote endpoint associated with this file".to_string());
|
self.status_msg = Some("❌ Нет удаленного подключения для этого файла".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,14 +361,14 @@ impl VimViewerModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.is_writable {
|
if self.is_writable {
|
||||||
ui.label(RichText::new("• [Writable]").color(Color32::from_rgb(34, 197, 94)).size(11.0));
|
ui.label(RichText::new("• [Доступна запись]").color(Color32::from_rgb(34, 197, 94)).size(11.0));
|
||||||
} else {
|
} else {
|
||||||
ui.label(RichText::new("• [Read-Only]").color(Color32::from_rgb(148, 163, 184)).size(11.0));
|
ui.label(RichText::new("• [Только чтение]").color(Color32::from_rgb(148, 163, 184)).size(11.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||||
if ui
|
if ui
|
||||||
.button(RichText::new("✕ Close (:q)").color(Color32::from_rgb(203, 213, 225)))
|
.button(RichText::new("✕ Закрыть (:q)").color(Color32::from_rgb(203, 213, 225)))
|
||||||
.clicked()
|
.clicked()
|
||||||
{
|
{
|
||||||
self.close();
|
self.close();
|
||||||
@@ -376,7 +376,7 @@ impl VimViewerModal {
|
|||||||
|
|
||||||
if self.is_writable {
|
if self.is_writable {
|
||||||
let save_btn = egui::Button::new(
|
let save_btn = egui::Button::new(
|
||||||
RichText::new("💾 Save (:w)")
|
RichText::new("💾 Сохранить (:w)")
|
||||||
.strong()
|
.strong()
|
||||||
.color(Color32::WHITE),
|
.color(Color32::WHITE),
|
||||||
)
|
)
|
||||||
@@ -387,7 +387,7 @@ impl VimViewerModal {
|
|||||||
self.trigger_save();
|
self.trigger_save();
|
||||||
}
|
}
|
||||||
|
|
||||||
let edit_label = if self.is_insert_mode { "👁 View Mode (Esc)" } else { "✏️ Edit (i)" };
|
let edit_label = if self.is_insert_mode { "👁 Просмотр (Esc)" } else { "✏️ Редактировать (i)" };
|
||||||
if ui.button(RichText::new(edit_label).color(Color32::from_rgb(226, 232, 240))).clicked() {
|
if ui.button(RichText::new(edit_label).color(Color32::from_rgb(226, 232, 240))).clicked() {
|
||||||
self.is_insert_mode = !self.is_insert_mode;
|
self.is_insert_mode = !self.is_insert_mode;
|
||||||
if !self.is_insert_mode {
|
if !self.is_insert_mode {
|
||||||
@@ -398,7 +398,7 @@ impl VimViewerModal {
|
|||||||
|
|
||||||
if self.file_name.to_lowercase().ends_with(".md") {
|
if self.file_name.to_lowercase().ends_with(".md") {
|
||||||
if ui
|
if ui
|
||||||
.selectable_label(self.is_markdown_view, "👁 Markdown Preview")
|
.selectable_label(self.is_markdown_view, "👁 Предпросмотр Markdown")
|
||||||
.clicked()
|
.clicked()
|
||||||
{
|
{
|
||||||
self.is_markdown_view = !self.is_markdown_view;
|
self.is_markdown_view = !self.is_markdown_view;
|
||||||
@@ -406,7 +406,7 @@ impl VimViewerModal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ui.label(
|
ui.label(
|
||||||
RichText::new(format!("{} lines", self.lines.len()))
|
RichText::new(format!("{} строк", self.lines.len()))
|
||||||
.size(11.0)
|
.size(11.0)
|
||||||
.color(Color32::from_rgb(148, 163, 184)),
|
.color(Color32::from_rgb(148, 163, 184)),
|
||||||
);
|
);
|
||||||
@@ -539,13 +539,13 @@ impl VimViewerModal {
|
|||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
// Mode Pill
|
// Mode Pill
|
||||||
let (mode_text, mode_bg, mode_fg) = if self.is_insert_mode {
|
let (mode_text, mode_bg, mode_fg) = if self.is_insert_mode {
|
||||||
("INSERT", Color32::from_rgb(34, 197, 94), Color32::BLACK)
|
("ВСТАВКА", Color32::from_rgb(34, 197, 94), Color32::BLACK)
|
||||||
} else if self.is_searching {
|
} else if self.is_searching {
|
||||||
("SEARCH", Color32::from_rgb(217, 119, 6), Color32::WHITE)
|
("ПОИСК", Color32::from_rgb(217, 119, 6), Color32::WHITE)
|
||||||
} else if self.is_command_mode {
|
} else if self.is_command_mode {
|
||||||
("COMMAND", Color32::from_rgb(147, 51, 234), Color32::WHITE)
|
("КОМАНДА", Color32::from_rgb(147, 51, 234), Color32::WHITE)
|
||||||
} else {
|
} else {
|
||||||
("NORMAL", Color32::from_rgb(37, 99, 235), Color32::WHITE)
|
("ОБЫЧНЫЙ", Color32::from_rgb(37, 99, 235), Color32::WHITE)
|
||||||
};
|
};
|
||||||
|
|
||||||
Frame::none()
|
Frame::none()
|
||||||
@@ -559,16 +559,16 @@ impl VimViewerModal {
|
|||||||
if self.is_searching {
|
if self.is_searching {
|
||||||
ui.label(RichText::new("/").monospace().color(Color32::from_rgb(245, 158, 11)));
|
ui.label(RichText::new("/").monospace().color(Color32::from_rgb(245, 158, 11)));
|
||||||
let edit = TextEdit::singleline(&mut self.search_query)
|
let edit = TextEdit::singleline(&mut self.search_query)
|
||||||
.hint_text("pattern (press Enter)...")
|
.hint_text("поиск (нажмите Enter)...")
|
||||||
.font(egui::TextStyle::Monospace)
|
.font(egui::TextStyle::Monospace)
|
||||||
.desired_width(200.0);
|
.desired_width(200.0);
|
||||||
ui.add(edit).request_focus();
|
ui.add(edit).request_focus();
|
||||||
} else if self.is_command_mode {
|
} else if self.is_command_mode {
|
||||||
ui.label(RichText::new(":").monospace().color(Color32::from_rgb(168, 85, 247)));
|
ui.label(RichText::new(":").monospace().color(Color32::from_rgb(168, 85, 247)));
|
||||||
let edit = TextEdit::singleline(&mut self.command_input)
|
let edit = TextEdit::singleline(&mut self.command_input)
|
||||||
.hint_text("w (save) / q (quit) / line...")
|
.hint_text("w (сохранить) / q (выход) / номер...")
|
||||||
.font(egui::TextStyle::Monospace)
|
.font(egui::TextStyle::Monospace)
|
||||||
.desired_width(200.0);
|
.desired_width(220.0);
|
||||||
ui.add(edit).request_focus();
|
ui.add(edit).request_focus();
|
||||||
} else {
|
} else {
|
||||||
if let Some(msg) = &self.status_msg {
|
if let Some(msg) = &self.status_msg {
|
||||||
@@ -578,7 +578,7 @@ impl VimViewerModal {
|
|||||||
|
|
||||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||||
ui.label(
|
ui.label(
|
||||||
RichText::new("i: edit • Esc: normal • :w: save • :q: exit")
|
RichText::new("i: правка • Esc: обычный • :w: сохранить • :q: выход")
|
||||||
.size(10.0)
|
.size(10.0)
|
||||||
.color(Color32::from_rgb(100, 116, 139)),
|
.color(Color32::from_rgb(100, 116, 139)),
|
||||||
);
|
);
|
||||||
@@ -586,7 +586,7 @@ impl VimViewerModal {
|
|||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
ui.label(
|
ui.label(
|
||||||
RichText::new(format!("Ln {}, Col 1", self.cursor_line))
|
RichText::new(format!("Стр {}, Кол 1", self.cursor_line))
|
||||||
.size(11.0)
|
.size(11.0)
|
||||||
.monospace()
|
.monospace()
|
||||||
.color(Color32::from_rgb(148, 163, 184)),
|
.color(Color32::from_rgb(148, 163, 184)),
|
||||||
|
|||||||
+15
-5
@@ -335,17 +335,27 @@ pub async fn perform_update_download(
|
|||||||
info!("Update successfully installed to {:?}", current_exe);
|
info!("Update successfully installed to {:?}", current_exe);
|
||||||
let _ = progress_tx.send(UpdateProgress::Completed);
|
let _ = progress_tx.send(UpdateProgress::Completed);
|
||||||
|
|
||||||
|
// Spawn background PowerShell cleanup script to delete old binary once this process terminates
|
||||||
|
let cleanup_script = format!(
|
||||||
|
"Start-Sleep -Seconds 1; Remove-Item -Force -ErrorAction SilentlyContinue '{}'",
|
||||||
|
old_backup_path.to_string_lossy()
|
||||||
|
);
|
||||||
|
let _ = std::process::Command::new("powershell")
|
||||||
|
.args(["-NoProfile", "-WindowStyle", "Hidden", "-Command", &cleanup_script])
|
||||||
|
.spawn();
|
||||||
|
|
||||||
// Spawn updated application and exit
|
// Spawn updated application and exit
|
||||||
let _ = std::process::Command::new(¤t_exe).spawn();
|
let _ = std::process::Command::new(¤t_exe).spawn();
|
||||||
std::thread::sleep(Duration::from_millis(500));
|
std::thread::sleep(Duration::from_millis(400));
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
} else {
|
} else {
|
||||||
// Fallback: Use PowerShell deferred replacement
|
// Fallback: Use PowerShell deferred replacement and cleanup
|
||||||
info!("Direct rename locked; triggering background PowerShell replacement...");
|
info!("Direct rename locked; triggering background PowerShell replacement...");
|
||||||
let script = format!(
|
let script = format!(
|
||||||
"Start-Sleep -Milliseconds 600; Move-Item -Force '{temp}' '{target}'; Start-Process '{target}'",
|
"Start-Sleep -Milliseconds 600; Move-Item -Force '{temp}' '{target}'; Start-Sleep -Seconds 1; Remove-Item -Force -ErrorAction SilentlyContinue '{old}'; Start-Process '{target}'",
|
||||||
temp = temp_download_path.to_string_lossy(),
|
temp = temp_download_path.to_string_lossy(),
|
||||||
target = current_exe.to_string_lossy()
|
target = current_exe.to_string_lossy(),
|
||||||
|
old = old_backup_path.to_string_lossy()
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ = std::process::Command::new("powershell")
|
let _ = std::process::Command::new("powershell")
|
||||||
@@ -353,7 +363,7 @@ pub async fn perform_update_download(
|
|||||||
.spawn();
|
.spawn();
|
||||||
|
|
||||||
let _ = progress_tx.send(UpdateProgress::Completed);
|
let _ = progress_tx.send(UpdateProgress::Completed);
|
||||||
std::thread::sleep(Duration::from_millis(500));
|
std::thread::sleep(Duration::from_millis(400));
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user