mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-04 16:56:59 +01:00
feat(gui): show a grouped shot as one tile, and reach its other files
The grouping landed in the daemon; this is what it looks like. A tile whose shot was stored as more than one file badges that in the corner — "RAW" when one of the members is a raw file, since that is the word the person is looking for, and a plain count otherwise (a live photo, a burst). The lightbox gains a control that steps through the group's files, which is the only way to reach the RAW now that the grid shows the shot once. Deleting says what it will do: the daemon takes the whole group, so the confirmation names the file count when a selection stands for more files than tiles.
This commit is contained in:
1 parent
afd71713d5
commit
c1df3b6cc2
8 files changed
+283
-5
No files matched your search
@@ -293,6 +293,14 @@ fn handle_control_conn(core: &Core, username: &str, mountpoint: &Path, stream: U
|
||||
},
|
||||
Err(e) => CtlResponse::error(e),
|
||||
},
|
||||
Ok(CtlRequest::PhotoGroup { uid }) => match core.photo_group(&uid) {
|
||||
Ok(items) => CtlResponse::Photos {
|
||||
available: true,
|
||||
items,
|
||||
counts: None,
|
||||
},
|
||||
Err(e) => CtlResponse::error(e),
|
||||
},
|
||||
Ok(CtlRequest::SetPhotoFavorite { uid, favorite }) => match parse_uid(&uid) {
|
||||
Some(node_uid) => match core.set_photo_favorite(&node_uid, favorite) {
|
||||
Ok(()) => CtlResponse::Ok {
|
||||
|
||||
@@ -505,6 +505,41 @@ impl Core {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Every file of one photo's group, in server order, as wire items. A photo
|
||||
/// the timeline does not hold comes back empty, which the lightbox reads as
|
||||
/// "nothing to switch between".
|
||||
pub(crate) fn photo_group(&self, uid: &str) -> CoreResult<Vec<PhotoItem>> {
|
||||
let members = self.db.photos_group(uid).map_err(CoreError::from)?;
|
||||
Ok(members
|
||||
.into_iter()
|
||||
.map(|photo| self.photo_item(photo))
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Every uid asked for, plus the other files of any group they belong to,
|
||||
/// each once. A uid the timeline does not hold (an album photo on someone
|
||||
/// else's volume) is passed through unchanged.
|
||||
fn expand_photo_groups(&self, uids: &[NodeUid]) -> Vec<NodeUid> {
|
||||
let mut out: Vec<NodeUid> = Vec::with_capacity(uids.len());
|
||||
let mut seen: HashSet<String> = HashSet::new();
|
||||
for uid in uids {
|
||||
let members = self.db.photos_group(&uid.to_string()).unwrap_or_default();
|
||||
let mut group: Vec<NodeUid> = members
|
||||
.iter()
|
||||
.filter_map(|photo| parse_uid(&photo.uid))
|
||||
.collect();
|
||||
if group.is_empty() {
|
||||
group.push(uid.clone());
|
||||
}
|
||||
for member in group {
|
||||
if seen.insert(member.to_string()) {
|
||||
out.push(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Trash photos by uid, and forget them locally.
|
||||
///
|
||||
/// The gallery is not part of the FUSE mount, so this is the photos-side
|
||||
@@ -515,10 +550,16 @@ impl Core {
|
||||
/// The server answers per node, and so does this: a batch where one photo
|
||||
/// fails still removes the ones that went, and the caller is told which is
|
||||
/// which. Only what actually left the server is forgotten locally.
|
||||
///
|
||||
/// A photo that is one file of a group takes its whole group with it. The
|
||||
/// gallery shows a RAW+JPEG shot as one tile, so deleting that tile has to
|
||||
/// delete the shot — leaving the RAW behind would put the photo back on the
|
||||
/// Raw tab and nowhere else.
|
||||
pub(crate) fn trash_photos(&self, uids: &[NodeUid]) -> CoreResult<TrashOutcome> {
|
||||
if uids.is_empty() {
|
||||
return Ok((Vec::new(), Vec::new()));
|
||||
}
|
||||
let uids = &self.expand_photo_groups(uids);
|
||||
for uid in uids {
|
||||
self.require_uid_writable(uid)
|
||||
.map_err(|errno| self.errno_error(errno, "trash access"))?;
|
||||
|
||||
Reference in new issue
Block a user