feat: browse your own shares as a peer receives them
The window could show any peer's share tree but never this account's, so "am I actually sharing that?" had no answer short of asking a friend to browse you. The tree is already there; what was missing was feeding it from our own index. B opens it — the same collapsible tree, filter, and navigation the peer browse offers, built from `Shares::directories()`, which is the listing GetShareFileList answers with. So what it shows is what the network sees, not what the config meant to share. r re-scans the disk rather than re-asking a peer, o steps across to the folders that feed it, and nothing here queues a download from ourselves. Attached to a daemon the index lives on the daemon's host, so it comes back over a new `shares.files` method rather than being scanned locally; `shares files [--filter]` prints the same listing headless, through the `emit_listing` that `browse` now shares with it — the two are only comparable while they are built the same way. Two allocation fixes came out of the review, both on paths this reaches: the daemon hands its listing to the DTO instead of deep-copying one it already owns, and `Shares::directories()` allocates its map key once per folder rather than once per file, which the peer-facing serve path has been paying for all along.
This commit is contained in:
@@ -1474,6 +1474,17 @@ impl Client {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// The share index as a peer receives it: the same directory listing
|
||||
/// `GetShareFileList` answers with, so what this returns is what the
|
||||
/// network sees.
|
||||
#[must_use]
|
||||
pub fn shared_listing(&self) -> Vec<crate::message::peer::SharedDirectory> {
|
||||
self.context
|
||||
.read_safe()
|
||||
.map(|ctx| ctx.shares.directories())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// `(folders, files)` currently shared with peers.
|
||||
#[must_use]
|
||||
pub fn shared_counts(&self) -> (u32, u32) {
|
||||
|
||||
@@ -146,14 +146,18 @@ impl Shares {
|
||||
.virtual_path
|
||||
.rsplit_once('\\')
|
||||
.unwrap_or(("", file.virtual_path.as_str()));
|
||||
by_dir
|
||||
.entry(dir.to_string())
|
||||
.or_default()
|
||||
.push(SharedFileEntry {
|
||||
name: base.to_string(),
|
||||
size: file.size,
|
||||
attributes: file.attributes.clone(),
|
||||
});
|
||||
let entry = SharedFileEntry {
|
||||
name: base.to_string(),
|
||||
size: file.size,
|
||||
attributes: file.attributes.clone(),
|
||||
};
|
||||
// Looked up before inserting: `entry()` would allocate the key
|
||||
// for every file, and a folder holds many.
|
||||
if let Some(files) = by_dir.get_mut(dir) {
|
||||
files.push(entry);
|
||||
} else {
|
||||
by_dir.insert(dir.to_string(), vec![entry]);
|
||||
}
|
||||
}
|
||||
by_dir
|
||||
.into_iter()
|
||||
|
||||
Reference in New Issue
Block a user