mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-08-26 23:51:14 +00:00
Add 1:1 Chats using Groups (#139)
* Add Identified Trait for convo * Add PrivateV2Convo * Rename to DirectV1 * Rename ConvoTypeOwned variant * Update DirectV1 to support multiple members * Apply suggestion from @kaichaosun Co-authored-by: kaichao <kaichaosuna@gmail.com> --------- Co-authored-by: kaichao <kaichaosuna@gmail.com>
This commit is contained in:
co-authored by
kaichao
parent
c5b264c827
commit
7612b233c9
@@ -1,3 +1,4 @@
|
||||
mod direct_v1;
|
||||
pub mod group_v1;
|
||||
mod group_v2;
|
||||
mod privatev1;
|
||||
@@ -6,6 +7,7 @@ pub use crate::errors::ChatError;
|
||||
use crate::outcomes::ConvoOutcome;
|
||||
use crate::proto::EncryptedPayload;
|
||||
use crate::service_context::{ExternalServices, ServiceContext};
|
||||
pub use direct_v1::DirectV1Convo;
|
||||
pub use group_v1::GroupV1Convo;
|
||||
pub use group_v2::GroupV2Convo;
|
||||
pub use privatev1::PrivateV1Convo;
|
||||
@@ -15,7 +17,7 @@ pub type ConversationId = String;
|
||||
pub type ConversationIdRef<'a> = &'a str;
|
||||
|
||||
/// Behaviour shared by every conversation kind.
|
||||
pub(crate) trait Convo<S: ExternalServices>: Identified {
|
||||
pub(crate) trait Convo<S: ExternalServices>: Identified + Send {
|
||||
fn send_content(&mut self, cx: &mut ServiceContext<S>, content: &[u8])
|
||||
-> Result<(), ChatError>;
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
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<(), ChatError> {
|
||||
self.inner_group.wakeup(service_ctx)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::causal_history::{CausalHistoryStore, MissingMessage};
|
||||
use crate::conversation::{
|
||||
ConversationIdRef, GroupV1Convo, GroupV2Convo, Identified, PrivateV1Convo,
|
||||
ConversationIdRef, DirectV1Convo, GroupV1Convo, GroupV2Convo, Identified, PrivateV1Convo,
|
||||
};
|
||||
use crate::service_context::{ExternalServices, ServiceContext};
|
||||
use crate::{DeliveryService, IdentityProvider, RegistrationService, WakeupService};
|
||||
@@ -16,6 +16,7 @@ use crypto::{Identity, PublicKey};
|
||||
use openmls::group::GroupId;
|
||||
use shared_traits::IdentIdRef;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use storage::{ChatStore, ConversationKind, ConversationStore};
|
||||
use tracing::{info, instrument};
|
||||
|
||||
@@ -188,6 +189,14 @@ impl<'a, S: ExternalServices + 'static> Core<S> {
|
||||
&mut self,
|
||||
remote_bundle: &Introduction,
|
||||
content: &[u8],
|
||||
) -> Result<ConversationId, ChatError> {
|
||||
self.create_private_convo_v1(remote_bundle, content)
|
||||
}
|
||||
|
||||
pub fn create_private_convo_v1(
|
||||
&mut self,
|
||||
remote_bundle: &Introduction,
|
||||
content: &[u8],
|
||||
) -> Result<ConversationId, ChatError> {
|
||||
let (mut convo, payloads) =
|
||||
self.inbox
|
||||
@@ -204,6 +213,17 @@ impl<'a, S: ExternalServices + 'static> Core<S> {
|
||||
Ok(convo_id)
|
||||
}
|
||||
|
||||
pub fn create_direct_convo_v1(
|
||||
&mut self,
|
||||
members: &[IdentIdRef],
|
||||
) -> Result<ConversationId, ChatError> {
|
||||
let convo = DirectV1Convo::new(&mut self.services, members)?;
|
||||
let convo_id = convo.id().to_string();
|
||||
self.register_convo(ConvoTypeOwned::Direct(Box::new(convo)))?;
|
||||
|
||||
Ok(convo_id)
|
||||
}
|
||||
|
||||
pub fn create_group_convo(
|
||||
&mut self,
|
||||
participants: &[IdentIdRef],
|
||||
@@ -266,6 +286,10 @@ impl<'a, S: ExternalServices + 'static> Core<S> {
|
||||
ConvoTypeOwned::Group(group_convo) => {
|
||||
group_convo.add_member(&mut self.services, members)
|
||||
}
|
||||
ConvoTypeOwned::Direct(convo) => Err(ChatError::UnsupportedFunction(
|
||||
convo.id().into(),
|
||||
"Add Member".into(),
|
||||
)),
|
||||
}
|
||||
} else {
|
||||
let mut convo = self.load_group_convo(convo_id)?;
|
||||
@@ -397,6 +421,7 @@ impl<'a, S: ExternalServices + 'static> Core<S> {
|
||||
};
|
||||
let convo = match convo {
|
||||
ConvoTypeOwned::Group(c) => c.as_mut(),
|
||||
ConvoTypeOwned::Direct(c) => c.as_mut(),
|
||||
};
|
||||
|
||||
convo.wakeup(&mut self.services)
|
||||
@@ -466,15 +491,24 @@ impl<'a, S: ExternalServices + 'static> Core<S> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ConvoTypeOwned<S: ExternalServices> {
|
||||
// Pairwise(Box<dyn BaseConvo<S>>),
|
||||
Direct(Box<dyn Convo<S>>),
|
||||
Group(Box<dyn GroupConvo<S>>),
|
||||
}
|
||||
|
||||
impl<S: ExternalServices> Debug for ConvoTypeOwned<S> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Direct(arg0) => f.debug_tuple("Pairwise").field(&arg0.id()).finish(),
|
||||
Self::Group(arg0) => f.debug_tuple("Group").field(&arg0.id()).finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: ExternalServices> Identified for ConvoTypeOwned<S> {
|
||||
fn id(&self) -> ConversationIdRef<'_> {
|
||||
match self {
|
||||
ConvoTypeOwned::Direct(convo) => convo.id(),
|
||||
ConvoTypeOwned::Group(group_convo) => group_convo.id(),
|
||||
}
|
||||
}
|
||||
@@ -488,6 +522,7 @@ impl<S: ExternalServices> Convo<S> for ConvoTypeOwned<S> {
|
||||
) -> Result<(), ChatError> {
|
||||
match self {
|
||||
ConvoTypeOwned::Group(group_convo) => group_convo.send_content(cx, content),
|
||||
ConvoTypeOwned::Direct(convo) => convo.send_content(cx, content),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,12 +533,14 @@ impl<S: ExternalServices> Convo<S> for ConvoTypeOwned<S> {
|
||||
) -> Result<ConvoOutcome, ChatError> {
|
||||
match self {
|
||||
ConvoTypeOwned::Group(group_convo) => group_convo.handle_frame(cx, enc),
|
||||
ConvoTypeOwned::Direct(convo) => convo.handle_frame(cx, enc),
|
||||
}
|
||||
}
|
||||
|
||||
fn wakeup(&mut self, service_ctx: &mut ServiceContext<S>) -> Result<(), ChatError> {
|
||||
match self {
|
||||
ConvoTypeOwned::Group(group_convo) => group_convo.wakeup(service_ctx),
|
||||
ConvoTypeOwned::Direct(convo) => convo.wakeup(service_ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ pub use thiserror::Error;
|
||||
|
||||
use storage::StorageError;
|
||||
|
||||
use crate::ConversationId;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ChatError {
|
||||
#[error("protocol error: {0:?}")]
|
||||
@@ -42,6 +44,9 @@ pub enum ChatError {
|
||||
MlsError(#[from] MlsError),
|
||||
#[error("demls error: {0}")]
|
||||
DeMlsError(#[from] ConversationError),
|
||||
// Used when a core function is called with a convo_id which is unsupported
|
||||
#[error("convo:{0} does not support {1}")]
|
||||
UnsupportedFunction(ConversationId, String),
|
||||
}
|
||||
|
||||
impl ChatError {
|
||||
|
||||
Reference in New Issue
Block a user