Initial commit: LoFlum FTP/SFTP client

Tauri 2 + Rust + Svelte 5. SFTP via ssh2, FTP via suppaftp.
Transfer queue with async worker, SQLite site storage, keychain.
This commit is contained in:
loki5512344 2026-06-13 12:06:56 +02:00
parent 0f182ab76f
commit 79855585bd
60 changed files with 14532 additions and 18 deletions

54
src-tauri/src/fs/local.rs Normal file
View file

@ -0,0 +1,54 @@
use anyhow::Result;
use std::fs;
use crate::domain::file_entry::{FileEntry, EntryKind};
pub fn list(path: &str) -> Result<Vec<FileEntry>> {
let mut entries: Vec<FileEntry> = fs::read_dir(path)?
.filter_map(|e| e.ok())
.map(|e| {
let meta = e.metadata().ok();
let kind = meta.as_ref().map(|m| {
if m.is_dir() { EntryKind::Dir }
else if m.is_symlink() { EntryKind::Symlink }
else { EntryKind::File }
}).unwrap_or(EntryKind::File);
let size = meta.as_ref().and_then(|m| {
if m.is_file() { Some(m.len()) } else { None }
});
let modified = meta.as_ref()
.and_then(|m| m.modified().ok())
.and_then(|t| t.duration_since(std::time::UNIX_EPOCH).ok())
.map(|d| d.as_secs() as i64);
FileEntry {
name: e.file_name().to_string_lossy().to_string(),
path: e.path().to_string_lossy().to_string(),
kind,
size,
modified,
permissions: None,
}
})
.collect();
// папки сначала, потом файлы, по имени
entries.sort_by(|a, b| {
match (&a.kind, &b.kind) {
(EntryKind::Dir, EntryKind::Dir) => a.name.cmp(&b.name),
(EntryKind::Dir, _) => std::cmp::Ordering::Less,
(_, EntryKind::Dir) => std::cmp::Ordering::Greater,
_ => a.name.cmp(&b.name),
}
});
Ok(entries)
}
pub fn home_dir() -> String {
dirs::home_dir()
.unwrap_or_default()
.to_string_lossy()
.to_string()
}