feat(fuse,core,cli,gui): make folders available offline from the app

The daemon has kept recursive folder pins for a long time, but the app
offered "Available offline" for files only. The context menu, the
details pane and the selection bar now offer it for folders too, and a
pinned folder carries the offline badge in the browser and the launcher.

A folder pin used to download the whole subtree inside the control
request, so a large folder outlasted the client's 120 s read timeout,
and every pinned file was read into memory before it was cached. The
daemon now records the pin, answers at once and downloads on a
background thread as a job the tray and the app show, stopping when the
folder is unpinned or the daemon stops. Pins of files and folders both
go through fetch_content, which streams to disk and skips fresh blobs.
A folder pin is refused while offline instead of looking kept.

A file kept only because a folder above it is pinned has no pin of its
own, and unpinning it silently did nothing. ListDir now reports
pinned_by_folder; the app shows such an entry as available offline with
the toggle greyed out, and the daemon refuses the unpin with a message
naming the folder. Unpinning a folder no longer evicts files that are
pinned on their own.

Requested on Reddit.
This commit is contained in:
nvrl committed 2026-10-12 00:07:18 +02:00
1 parent e0442c56b9
commit d481dcc15c
24 files changed
+3353 -2856

No files matched your search

+8 -1
View File
@@ -1260,8 +1260,15 @@ pub struct DirEntry {
pub size: u64,
/// Modification time, epoch seconds.
pub modified: i64,
/// Whether the file is pinned to this device.
/// Whether the node is pinned to this device, on its own or through a
/// pinned folder above it.
pub pinned: bool,
/// Whether the node is kept on this device because a folder above it is
/// pinned. Such a node cannot be unpinned on its own. Set in
/// [`Request::ListDir`] listings only. Defaulted for wire-compat with
/// daemons predating the field.
#[serde(default)]
pub pinned_by_folder: bool,
/// Whether the file's full content is present in the local cache (a current,
/// non-stale blob). Always false for folders. Defaulted for wire-compat with
/// clients/daemons predating the field.