mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-08-03 21:53:31 +00:00
A group's roster changed silently. An add merges on the steward's commit-inactivity timer, and the members that receive its commit apply it, but neither surfaced any observation: Core::wakeup returned () and the client worker discarded it, and GroupV2Convo mapped only chat messages into a ConvoOutcome, so a commit produced an empty outcome. An app could learn a group grew only by re-selecting the conversation, a manual refresh, or a later message from the new member.
de-mls already reports the change: CommitApplied (adds and removes) and WelcomeReady (adds) both fire, on every member, when a commit merges. Drain them into the observation and emit a new event.
- ConvoOutcome gains members_changed, set by GroupV2Convo when a poll cycle's drained de-mls events include CommitApplied or WelcomeReady. It rides alongside content, the same way a protocol-only frame already yields content: None.
- Convo::wakeup returns a ConvoOutcome instead of (), mirroring handle_frame, so the steward's own timer-driven commit is observable. Kinds with no timers return ConvoOutcome::empty; Core::wakeup and the worker translate it through the same events_from_inbound path inbound payloads use.
- New Event::ConversationMembersChanged { convo_id }: the app re-fetches group_members. Fires on every member a commit reaches, so the inviter sees its own add land and existing members see later joins.
65 lines
1.6 KiB
Rust
65 lines
1.6 KiB
Rust
use chat_proto::logoschat::encryption::EncryptedPayload;
|
|
use shared_traits::IdentIdRef;
|
|
|
|
use crate::{
|
|
ChatError, ExternalServices,
|
|
conversation::{ConversationIdRef, Convo, GroupConvo, GroupV1Convo, Identified},
|
|
service_context::ServiceContext,
|
|
};
|
|
|
|
type DelegateGroup = GroupV1Convo;
|
|
|
|
/// A Conversation between two participants.
|
|
#[derive(Debug)]
|
|
pub struct DirectV1Convo {
|
|
inner_group: DelegateGroup,
|
|
}
|
|
|
|
impl DirectV1Convo {
|
|
// Constructor must accept multiple IdentId's
|
|
// While the conversation is limited to 2 participants, each participants may
|
|
// have multiple Installations.
|
|
pub fn new<S: ExternalServices>(
|
|
cx: &mut ServiceContext<S>,
|
|
members: &[IdentIdRef],
|
|
) -> Result<Self, ChatError> {
|
|
let mut inner_group = DelegateGroup::new(cx)?;
|
|
inner_group.add_member(cx, members)?;
|
|
Ok(Self { inner_group })
|
|
}
|
|
}
|
|
|
|
impl Identified for DirectV1Convo {
|
|
fn id(&self) -> ConversationIdRef<'_> {
|
|
self.inner_group.id()
|
|
}
|
|
}
|
|
|
|
impl<S> Convo<S> for DirectV1Convo
|
|
where
|
|
S: ExternalServices,
|
|
{
|
|
fn send_content(
|
|
&mut self,
|
|
cx: &mut ServiceContext<S>,
|
|
content: &[u8],
|
|
) -> Result<(), super::ChatError> {
|
|
self.inner_group.send_content(cx, content)
|
|
}
|
|
|
|
fn handle_frame(
|
|
&mut self,
|
|
cx: &mut ServiceContext<S>,
|
|
enc: EncryptedPayload,
|
|
) -> Result<crate::ConvoOutcome, ChatError> {
|
|
self.inner_group.handle_frame(cx, enc)
|
|
}
|
|
|
|
fn wakeup(
|
|
&mut self,
|
|
service_ctx: &mut ServiceContext<S>,
|
|
) -> Result<crate::ConvoOutcome, ChatError> {
|
|
self.inner_group.wakeup(service_ctx)
|
|
}
|
|
}
|