diff --git a/crates/tinyclient/src/gui/conversation.rs b/crates/tinyclient/src/gui/conversation.rs index fecf7e2..44b1696 100644 --- a/crates/tinyclient/src/gui/conversation.rs +++ b/crates/tinyclient/src/gui/conversation.rs @@ -395,7 +395,8 @@ impl Pane { root: Option<(Rc, u32)>, cx: &mut Context, ) { - let around = self.landing.take().or(self.around.take()); + let landing = self.landing.take(); + let around = self.around.take(); // Where the one being left was, for coming back to it. if let Some((left, place)) = self.key().cloned().zip(self.place()) { self.places.put(left, place); @@ -450,13 +451,18 @@ impl Pane { self.pending_at.clear(); self.relay(true, ListOffset::default()); self.ask_reactions(cx); - // M2: a conversation opens at its newest message rather than the first unread. + // M2: a conversation opens at its newest message rather than the first unread. The + // search hit is the user's own ask: it wins over where this conversation was left, and + // lands as a jump, flashed, with the pill. let around = around.filter(|_| !super::app::prefs::choices().newest); - match back { - Some(place) => self.load(Page::Around { id: place.id.clone() }, Purpose::Restore(place.id, place.offset), cx), - None => match around { - Some(id) => self.load(Page::Around { id }, Purpose::Open, cx), - None => self.load(Page::Newest, Purpose::Open, cx), + match landing { + Some(id) => self.load(Page::Around { id: id.clone() }, Purpose::Jump(id), cx), + None => match back { + Some(place) => self.load(Page::Around { id: place.id.clone() }, Purpose::Restore(place.id, place.offset), cx), + None => match around { + Some(id) => self.load(Page::Around { id }, Purpose::Open, cx), + None => self.load(Page::Newest, Purpose::Open, cx), + }, }, } cx.notify(); @@ -540,6 +546,12 @@ impl Pane { self.load(Page::Newest, Purpose::Open, cx); return; } + if matches!(purpose, Purpose::Jump(_)) && self.window.messages.is_empty() { + // The message a search hit asked for is gone from the history, and nothing + // is held beside it: open as if for the first time. + self.load(Page::Newest, Purpose::Open, cx); + return; + } if matches!(purpose, Purpose::Older | Purpose::Open) { self.older_failed = Some(match other { Ok(Response::Error { detail, .. }) => detail, diff --git a/crates/tinyclient/src/gui/conversation/side.rs b/crates/tinyclient/src/gui/conversation/side.rs index 1cfed63..d0af73c 100644 --- a/crates/tinyclient/src/gui/conversation/side.rs +++ b/crates/tinyclient/src/gui/conversation/side.rs @@ -384,15 +384,14 @@ impl Shell { /// jumps to it. pub(in crate::gui) fn open_search_hit(&mut self, hit: &MessageHit, cx: &mut Context) { let key = hit.conversation.clone(); + // The pane may never have been built: nothing may have opened yet. It is made here, so + // the landing reaches it before the conversation is told to open. + let pane = self.pane(cx); if self.open.as_ref() == Some(&key) { - if let Some(pane) = self.conversation_state.pane.get() { - pane.update(cx, |pane, cx| pane.jump_to(&hit.message_id, cx)); - } + pane.update(cx, |pane, cx| pane.jump_to(&hit.message_id, cx)); return; } - if let Some(pane) = self.conversation_state.pane.get() { - pane.update(cx, |pane, _| pane.land_next(hit.message_id.clone())); - } + pane.update(cx, |pane, _| pane.land_next(hit.message_id.clone())); let title = if hit.title.is_empty() { hit.conversation.id.clone() } else { hit.title.clone() }; self.select(key, &title, cx); }