mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-04 16:56:59 +01:00
feat(core,fuse,gui,cli): filter the photos timeline to photos in no album
A new pill next to the favorites filter narrows the timeline to the photos no album of ours holds yet, so what is left to file is easy to find. A RAW+JPEG pair counts as filed when any of its files is in an album. PhotosTimeline gains an optional not_in_album flag; older front-ends omit it and get the whole timeline. Album contents are fetched lazily, so the first filtered page fetches the contents of any album not yet listed. Photos added to an album while the filter is on leave the timeline at once.
This commit is contained in:
1 parent
0135c29a4f
commit
5c1da9d7a5
20 files changed
+2304
-1995
No files matched your search
@@ -175,6 +175,40 @@ impl Core {
|
||||
Ok(page.into_iter().map(|p| self.photo_item(p)).collect())
|
||||
}
|
||||
|
||||
/// Make sure every album of ours has its contents on disk, for a filter
|
||||
/// that asks which photos no album holds. Contents are otherwise fetched
|
||||
/// the first time an album is opened, so an album never opened would read
|
||||
/// as empty and its photos as unfiled.
|
||||
///
|
||||
/// Shared-with-me albums are skipped: their photos live on the sharer's
|
||||
/// volume and are never in our timeline. The freshness stamps are no guide
|
||||
/// here — any album change clears all of them — so only an album whose
|
||||
/// server count disagrees with an empty local copy is waited for.
|
||||
pub(crate) fn ensure_album_contents(&self) -> CoreResult<()> {
|
||||
if self.db.albums_count().map_err(CoreError::from)? == 0
|
||||
&& !self.rt.block_on(self.refresh_albums())?
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
let albums = self.db.albums_list().map_err(CoreError::from)?;
|
||||
for album in albums.iter().filter(|a| !a.shared && a.photo_count > 0) {
|
||||
let stored = self
|
||||
.db
|
||||
.album_photos_count(&album.uid)
|
||||
.map_err(CoreError::from)?;
|
||||
if stored > 0 {
|
||||
continue;
|
||||
}
|
||||
let Some(uid) = parse_uid(&album.uid) else {
|
||||
continue;
|
||||
};
|
||||
if let Err(error) = self.rt.block_on(self.refresh_album(&uid)) {
|
||||
warn!(album = %album.uid, %error, "fetching an album's contents failed");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Re-enumerate one album's photos and replace its persisted contents.
|
||||
pub(crate) async fn refresh_album(&self, album: &NodeUid) -> CoreResult<()> {
|
||||
let photos = self.photos();
|
||||
|
||||
@@ -440,7 +440,15 @@ fn handle_control_conn(core: &Core, username: &str, mountpoint: &Path, stream: U
|
||||
kind,
|
||||
range,
|
||||
favorites,
|
||||
}) => match core.photos_timeline(offset, clamp_limit(limit), kind, range, favorites) {
|
||||
not_in_album,
|
||||
}) => match core.photos_timeline(
|
||||
offset,
|
||||
clamp_limit(limit),
|
||||
kind,
|
||||
range,
|
||||
favorites,
|
||||
not_in_album,
|
||||
) {
|
||||
Ok(Some(items)) => CtlResponse::Photos {
|
||||
available: true,
|
||||
items,
|
||||
|
||||
@@ -637,6 +637,7 @@ impl Core {
|
||||
kind: Option<PhotoKind>,
|
||||
range: Option<(i64, i64)>,
|
||||
favorites: bool,
|
||||
not_in_album: bool,
|
||||
) -> CoreResult<Option<Vec<PhotoItem>>> {
|
||||
let count = self.db.photos_count().map_err(CoreError::from)?;
|
||||
if count == 0 {
|
||||
@@ -653,10 +654,16 @@ impl Core {
|
||||
} else if self.listing_stale(PHOTOS_SYNCED_MS, TIMELINE_TTL) {
|
||||
self.spawn_timeline_refresh();
|
||||
}
|
||||
// The filter is only as good as the album contents on disk, and those
|
||||
// are fetched lazily, per album opened. Fill in the missing ones before
|
||||
// the first page; later pages reuse what that fetch stored.
|
||||
if not_in_album && offset == 0 {
|
||||
self.ensure_album_contents()?;
|
||||
}
|
||||
|
||||
let page = self
|
||||
.db
|
||||
.photos_page(offset, limit, kind, range, favorites)
|
||||
.photos_page(offset, limit, kind, range, favorites, not_in_album)
|
||||
.map_err(CoreError::from)?;
|
||||
Ok(Some(page.into_iter().map(|p| self.photo_item(p)).collect()))
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user