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:
@@ -48,6 +48,42 @@ pub fn fetch_listing(
|
||||
})
|
||||
}
|
||||
|
||||
/// Emit `user`'s listing one file per record, keeping only the paths that
|
||||
/// contain `needle` (already lowercased; `None` keeps all). Returns how many
|
||||
/// were emitted.
|
||||
///
|
||||
/// Shared with `shares files`, which prints this session's own index: the two
|
||||
/// are only comparable while they are built the same way, and a field added
|
||||
/// here has to reach both.
|
||||
pub fn emit_listing(
|
||||
ctx: &Ctx,
|
||||
user: &str,
|
||||
directories: &[SharedDirectory],
|
||||
needle: Option<&str>,
|
||||
) -> usize {
|
||||
let mut emitted = 0usize;
|
||||
for directory in directories {
|
||||
for file in &directory.files {
|
||||
let path = full_path(&directory.name, &file.name);
|
||||
if needle
|
||||
.is_some_and(|needle| !path.to_lowercase().contains(needle))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
emitted += 1;
|
||||
ctx.out.emit(&BrowseRecord {
|
||||
user: user.to_string(),
|
||||
directory: directory.name.clone(),
|
||||
path,
|
||||
size: file.size,
|
||||
bitrate: file.attribute(super::transfer::ATTR_BITRATE),
|
||||
duration: file.attribute(super::transfer::ATTR_DURATION),
|
||||
});
|
||||
}
|
||||
}
|
||||
emitted
|
||||
}
|
||||
|
||||
pub fn browse(ctx: &Ctx, args: &BrowseArgs) -> CliResult {
|
||||
let session = Session::open(ctx)?;
|
||||
ctx.out
|
||||
@@ -59,22 +95,7 @@ pub fn browse(ctx: &Ctx, args: &BrowseArgs) -> CliResult {
|
||||
Duration::from_secs(args.timeout),
|
||||
)?;
|
||||
|
||||
let mut files = 0usize;
|
||||
for directory in &directories {
|
||||
for file in &directory.files {
|
||||
files += 1;
|
||||
ctx.out.emit(&BrowseRecord {
|
||||
user: args.user.clone(),
|
||||
directory: directory.name.clone(),
|
||||
path: full_path(&directory.name, &file.name),
|
||||
size: file.size,
|
||||
bitrate: file.attribute(super::transfer::ATTR_BITRATE),
|
||||
duration: file.attribute(super::transfer::ATTR_DURATION),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if files == 0 {
|
||||
if emit_listing(ctx, &args.user, &directories, None) == 0 {
|
||||
return Err(CliError::no_results(format!(
|
||||
"{} shares no files",
|
||||
args.user
|
||||
|
||||
Reference in New Issue
Block a user