refactor(threads): flatten the ThreadStatus enum
This commit is contained in:
@@ -1129,25 +1129,22 @@ impl Room {
|
||||
pub async fn fetch_thread_subscription(
|
||||
&self,
|
||||
thread_root_event_id: String,
|
||||
) -> Result<Option<ThreadStatus>, ClientError> {
|
||||
) -> Result<Option<ThreadSubscription>, ClientError> {
|
||||
let thread_root = EventId::parse(thread_root_event_id)?;
|
||||
Ok(self.inner.fetch_thread_subscription(thread_root).await?.map(|sub| match sub {
|
||||
matrix_sdk::room::ThreadStatus::Subscribed { automatic } => {
|
||||
ThreadStatus::Subscribed { automatic }
|
||||
}
|
||||
}))
|
||||
Ok(self
|
||||
.inner
|
||||
.fetch_thread_subscription(thread_root)
|
||||
.await?
|
||||
.map(|sub| ThreadSubscription { automatic: sub.automatic }))
|
||||
}
|
||||
}
|
||||
|
||||
/// Status of a thread subscription (MSC4306).
|
||||
#[derive(uniffi::Enum)]
|
||||
pub enum ThreadStatus {
|
||||
/// The thread is subscribed to.
|
||||
Subscribed {
|
||||
/// Whether the thread subscription happened automatically (e.g. after a
|
||||
/// mention) or if it was manually requested by the user.
|
||||
automatic: bool,
|
||||
},
|
||||
/// A thread subscription (MSC4306).
|
||||
#[derive(uniffi::Record)]
|
||||
pub struct ThreadSubscription {
|
||||
/// Whether the thread subscription happened automatically (e.g. after a
|
||||
/// mention) or if it was manually requested by the user.
|
||||
automatic: bool,
|
||||
}
|
||||
|
||||
/// A listener for receiving new live location shares in a room.
|
||||
|
||||
@@ -48,7 +48,7 @@ use crate::{
|
||||
deserialized_responses::MemberEvent,
|
||||
store::{
|
||||
ChildTransactionId, QueueWedgeError, Result, SerializableEventContent, StateStoreExt,
|
||||
ThreadStatus,
|
||||
ThreadSubscription,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1790,7 +1790,7 @@ impl StateStoreIntegrationTests for DynStateStore {
|
||||
self.upsert_thread_subscription(
|
||||
room_id(),
|
||||
first_thread,
|
||||
ThreadStatus::Subscribed { automatic: true },
|
||||
ThreadSubscription { automatic: true },
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -1798,32 +1798,32 @@ impl StateStoreIntegrationTests for DynStateStore {
|
||||
self.upsert_thread_subscription(
|
||||
room_id(),
|
||||
second_thread,
|
||||
ThreadStatus::Subscribed { automatic: false },
|
||||
ThreadSubscription { automatic: false },
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Now, reading the thread subscription returns the expected status.
|
||||
let maybe_status = self.load_thread_subscription(room_id(), first_thread).await.unwrap();
|
||||
assert_eq!(maybe_status, Some(ThreadStatus::Subscribed { automatic: true }));
|
||||
assert_eq!(maybe_status, Some(ThreadSubscription { automatic: true }));
|
||||
let maybe_status = self.load_thread_subscription(room_id(), second_thread).await.unwrap();
|
||||
assert_eq!(maybe_status, Some(ThreadStatus::Subscribed { automatic: false }));
|
||||
assert_eq!(maybe_status, Some(ThreadSubscription { automatic: false }));
|
||||
|
||||
// We can override the thread subscription status.
|
||||
self.upsert_thread_subscription(
|
||||
room_id(),
|
||||
first_thread,
|
||||
ThreadStatus::Subscribed { automatic: false },
|
||||
ThreadSubscription { automatic: false },
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// And it's correctly reflected.
|
||||
let maybe_status = self.load_thread_subscription(room_id(), first_thread).await.unwrap();
|
||||
assert_eq!(maybe_status, Some(ThreadStatus::Subscribed { automatic: false }));
|
||||
assert_eq!(maybe_status, Some(ThreadSubscription { automatic: false }));
|
||||
// And the second thread is still subscribed.
|
||||
let maybe_status = self.load_thread_subscription(room_id(), second_thread).await.unwrap();
|
||||
assert_eq!(maybe_status, Some(ThreadStatus::Subscribed { automatic: false }));
|
||||
assert_eq!(maybe_status, Some(ThreadSubscription { automatic: false }));
|
||||
|
||||
// We can remove a thread subscription.
|
||||
self.remove_thread_subscription(room_id(), second_thread).await.unwrap();
|
||||
@@ -1833,7 +1833,7 @@ impl StateStoreIntegrationTests for DynStateStore {
|
||||
assert_eq!(maybe_status, None);
|
||||
// And the first thread is still subscribed.
|
||||
let maybe_status = self.load_thread_subscription(room_id(), first_thread).await.unwrap();
|
||||
assert_eq!(maybe_status, Some(ThreadStatus::Subscribed { automatic: false }));
|
||||
assert_eq!(maybe_status, Some(ThreadSubscription { automatic: false }));
|
||||
|
||||
// Removing a thread subscription for an unknown thread is a no-op.
|
||||
self.remove_thread_subscription(room_id(), second_thread).await.unwrap();
|
||||
|
||||
@@ -46,7 +46,7 @@ use super::{
|
||||
use crate::{
|
||||
MinimalRoomMemberEvent, RoomMemberships, StateStoreDataKey, StateStoreDataValue,
|
||||
deserialized_responses::{DisplayName, RawAnySyncOrStrippedState},
|
||||
store::{QueueWedgeError, ThreadStatus},
|
||||
store::{QueueWedgeError, ThreadSubscription},
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@@ -84,7 +84,7 @@ struct MemoryStoreInner {
|
||||
send_queue_events: BTreeMap<OwnedRoomId, Vec<QueuedRequest>>,
|
||||
dependent_send_queue_events: BTreeMap<OwnedRoomId, Vec<DependentQueuedRequest>>,
|
||||
seen_knock_requests: BTreeMap<OwnedRoomId, BTreeMap<OwnedEventId, OwnedUserId>>,
|
||||
thread_subscriptions: BTreeMap<OwnedRoomId, BTreeMap<OwnedEventId, ThreadStatus>>,
|
||||
thread_subscriptions: BTreeMap<OwnedRoomId, BTreeMap<OwnedEventId, ThreadSubscription>>,
|
||||
}
|
||||
|
||||
/// In-memory, non-persistent implementation of the `StateStore`.
|
||||
@@ -958,7 +958,7 @@ impl StateStore for MemoryStore {
|
||||
&self,
|
||||
room: &RoomId,
|
||||
thread_id: &EventId,
|
||||
status: ThreadStatus,
|
||||
subscription: ThreadSubscription,
|
||||
) -> Result<(), Self::Error> {
|
||||
self.inner
|
||||
.write()
|
||||
@@ -966,7 +966,7 @@ impl StateStore for MemoryStore {
|
||||
.thread_subscriptions
|
||||
.entry(room.to_owned())
|
||||
.or_default()
|
||||
.insert(thread_id.to_owned(), status);
|
||||
.insert(thread_id.to_owned(), subscription);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -974,7 +974,7 @@ impl StateStore for MemoryStore {
|
||||
&self,
|
||||
room: &RoomId,
|
||||
thread_id: &EventId,
|
||||
) -> Result<Option<ThreadStatus>, Self::Error> {
|
||||
) -> Result<Option<ThreadSubscription>, Self::Error> {
|
||||
let inner = self.inner.read().unwrap();
|
||||
Ok(inner
|
||||
.thread_subscriptions
|
||||
|
||||
@@ -453,37 +453,26 @@ pub enum RoomLoadSettings {
|
||||
One(OwnedRoomId),
|
||||
}
|
||||
|
||||
/// Status of a thread subscription, as saved in the state store.
|
||||
/// A thread subscription, as saved in the state store.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum ThreadStatus {
|
||||
/// The thread is subscribed to.
|
||||
Subscribed {
|
||||
/// Whether the subscription was made automatically by a client, not by
|
||||
/// manual user choice.
|
||||
automatic: bool,
|
||||
},
|
||||
pub struct ThreadSubscription {
|
||||
/// Whether the subscription was made automatically by a client, not by
|
||||
/// manual user choice.
|
||||
pub automatic: bool,
|
||||
}
|
||||
|
||||
impl ThreadStatus {
|
||||
/// Convert the current [`ThreadStatus`] into a string representation.
|
||||
impl ThreadSubscription {
|
||||
/// Convert the current [`ThreadSubscription`] into a string representation.
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
ThreadStatus::Subscribed { automatic } => {
|
||||
if *automatic {
|
||||
"automatic"
|
||||
} else {
|
||||
"manual"
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.automatic { "automatic" } else { "manual" }
|
||||
}
|
||||
|
||||
/// Convert a string representation into a [`ThreadStatus`], if it is a
|
||||
/// valid one, or `None` otherwise.
|
||||
/// Convert a string representation into a [`ThreadSubscription`], if it is
|
||||
/// a valid one, or `None` otherwise.
|
||||
pub fn from_value(s: &str) -> Option<Self> {
|
||||
match s {
|
||||
"automatic" => Some(ThreadStatus::Subscribed { automatic: true }),
|
||||
"manual" => Some(ThreadStatus::Subscribed { automatic: false }),
|
||||
"automatic" => Some(Self { automatic: true }),
|
||||
"manual" => Some(Self { automatic: false }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ use crate::{
|
||||
deserialized_responses::{
|
||||
DisplayName, RawAnySyncOrStrippedState, RawMemberEvent, RawSyncOrStrippedState,
|
||||
},
|
||||
store::ThreadStatus,
|
||||
store::ThreadSubscription,
|
||||
};
|
||||
|
||||
/// An abstract state store trait that can be used to implement different stores
|
||||
@@ -485,7 +485,7 @@ pub trait StateStore: AsyncTraitDeps {
|
||||
&self,
|
||||
room: &RoomId,
|
||||
thread_id: &EventId,
|
||||
status: ThreadStatus,
|
||||
subscription: ThreadSubscription,
|
||||
) -> Result<(), Self::Error>;
|
||||
|
||||
/// Remove a previous thread subscription for a given room and thread.
|
||||
@@ -504,7 +504,7 @@ pub trait StateStore: AsyncTraitDeps {
|
||||
&self,
|
||||
room: &RoomId,
|
||||
thread_id: &EventId,
|
||||
) -> Result<Option<ThreadStatus>, Self::Error>;
|
||||
) -> Result<Option<ThreadSubscription>, Self::Error>;
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
@@ -804,16 +804,16 @@ impl<T: StateStore> StateStore for EraseStateStoreError<T> {
|
||||
&self,
|
||||
room: &RoomId,
|
||||
thread_id: &EventId,
|
||||
status: ThreadStatus,
|
||||
subscription: ThreadSubscription,
|
||||
) -> Result<(), Self::Error> {
|
||||
self.0.upsert_thread_subscription(room, thread_id, status).await.map_err(Into::into)
|
||||
self.0.upsert_thread_subscription(room, thread_id, subscription).await.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn load_thread_subscription(
|
||||
&self,
|
||||
room: &RoomId,
|
||||
thread_id: &EventId,
|
||||
) -> Result<Option<ThreadStatus>, Self::Error> {
|
||||
) -> Result<Option<ThreadSubscription>, Self::Error> {
|
||||
self.0.load_thread_subscription(room, thread_id).await.map_err(Into::into)
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ use matrix_sdk_base::{
|
||||
store::{
|
||||
ChildTransactionId, ComposerDraft, DependentQueuedRequest, DependentQueuedRequestKind,
|
||||
QueuedRequest, QueuedRequestKind, RoomLoadSettings, SentRequestKey,
|
||||
SerializableEventContent, ServerInfo, StateChanges, StateStore, StoreError, ThreadStatus,
|
||||
SerializableEventContent, ServerInfo, StateChanges, StateStore, StoreError,
|
||||
ThreadSubscription,
|
||||
},
|
||||
MinimalRoomMemberEvent, RoomInfo, RoomMemberships, StateStoreDataKey, StateStoreDataValue,
|
||||
ROOM_VERSION_FALLBACK, ROOM_VERSION_RULES_FALLBACK,
|
||||
@@ -1790,7 +1791,7 @@ impl_state_store!({
|
||||
&self,
|
||||
room: &RoomId,
|
||||
thread_id: &EventId,
|
||||
status: ThreadStatus,
|
||||
subscription: ThreadSubscription,
|
||||
) -> Result<()> {
|
||||
let encoded_key = self.encode_key(keys::THREAD_SUBSCRIPTIONS, (room, thread_id));
|
||||
|
||||
@@ -1800,7 +1801,7 @@ impl_state_store!({
|
||||
)?;
|
||||
let obj = tx.object_store(keys::THREAD_SUBSCRIPTIONS)?;
|
||||
|
||||
let serialized_value = self.serialize_value(&status.as_str().to_owned());
|
||||
let serialized_value = self.serialize_value(&subscription.as_str().to_owned());
|
||||
obj.put_key_val(&encoded_key, &serialized_value?)?;
|
||||
|
||||
tx.await.into_result()?;
|
||||
@@ -1812,7 +1813,7 @@ impl_state_store!({
|
||||
&self,
|
||||
room: &RoomId,
|
||||
thread_id: &EventId,
|
||||
) -> Result<Option<ThreadStatus>> {
|
||||
) -> Result<Option<ThreadSubscription>> {
|
||||
let encoded_key = self.encode_key(keys::THREAD_SUBSCRIPTIONS, (room, thread_id));
|
||||
|
||||
let js_value = self
|
||||
@@ -1828,12 +1829,13 @@ impl_state_store!({
|
||||
};
|
||||
|
||||
let status_string: String = self.deserialize_value(&js_value)?;
|
||||
let status =
|
||||
ThreadStatus::from_value(&status_string).ok_or_else(|| StoreError::InvalidData {
|
||||
let status = ThreadSubscription::from_value(&status_string).ok_or_else(|| {
|
||||
StoreError::InvalidData {
|
||||
details: format!(
|
||||
"invalid thread status for room {room} and thread {thread_id}: {status_string}"
|
||||
),
|
||||
})?;
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(Some(status))
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ use matrix_sdk_base::{
|
||||
store::{
|
||||
migration_helpers::RoomInfoV1, ChildTransactionId, DependentQueuedRequest,
|
||||
DependentQueuedRequestKind, QueueWedgeError, QueuedRequest, QueuedRequestKind,
|
||||
RoomLoadSettings, SentRequestKey, ThreadStatus,
|
||||
RoomLoadSettings, SentRequestKey, ThreadSubscription,
|
||||
},
|
||||
MinimalRoomMemberEvent, RoomInfo, RoomMemberships, RoomState, StateChanges, StateStore,
|
||||
StateStoreDataKey, StateStoreDataValue, ROOM_VERSION_FALLBACK, ROOM_VERSION_RULES_FALLBACK,
|
||||
@@ -2098,11 +2098,11 @@ impl StateStore for SqliteStateStore {
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
thread_id: &EventId,
|
||||
status: ThreadStatus,
|
||||
subscription: ThreadSubscription,
|
||||
) -> Result<(), Self::Error> {
|
||||
let room_id = self.encode_key(keys::THREAD_SUBSCRIPTIONS, room_id);
|
||||
let thread_id = self.encode_key(keys::THREAD_SUBSCRIPTIONS, thread_id);
|
||||
let status = status.as_str();
|
||||
let status = subscription.as_str();
|
||||
|
||||
self.acquire()
|
||||
.await?
|
||||
@@ -2121,7 +2121,7 @@ impl StateStore for SqliteStateStore {
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
thread_id: &EventId,
|
||||
) -> Result<Option<ThreadStatus>, Self::Error> {
|
||||
) -> Result<Option<ThreadSubscription>, Self::Error> {
|
||||
let room_id = self.encode_key(keys::THREAD_SUBSCRIPTIONS, room_id);
|
||||
let thread_id = self.encode_key(keys::THREAD_SUBSCRIPTIONS, thread_id);
|
||||
|
||||
@@ -2136,7 +2136,7 @@ impl StateStore for SqliteStateStore {
|
||||
.await
|
||||
.optional()?
|
||||
.map(|data| {
|
||||
ThreadStatus::from_value(&data).ok_or_else(|| Error::InvalidData {
|
||||
ThreadSubscription::from_value(&data).ok_or_else(|| Error::InvalidData {
|
||||
details: format!("Invalid thread status: {data}"),
|
||||
})
|
||||
})
|
||||
|
||||
@@ -34,7 +34,7 @@ use http::StatusCode;
|
||||
pub use identity_status_changes::IdentityStatusChanges;
|
||||
#[cfg(feature = "e2e-encryption")]
|
||||
use matrix_sdk_base::crypto::{IdentityStatusChange, RoomIdentityProvider, UserIdentity};
|
||||
pub use matrix_sdk_base::store::ThreadStatus;
|
||||
pub use matrix_sdk_base::store::ThreadSubscription;
|
||||
#[cfg(feature = "e2e-encryption")]
|
||||
use matrix_sdk_base::{crypto::RoomEventDecryptionResult, deserialized_responses::EncryptionInfo};
|
||||
use matrix_sdk_base::{
|
||||
@@ -3700,7 +3700,7 @@ impl Room {
|
||||
.upsert_thread_subscription(
|
||||
self.room_id(),
|
||||
&thread_root,
|
||||
ThreadStatus::Subscribed { automatic: is_automatic },
|
||||
ThreadSubscription { automatic: is_automatic },
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -3761,8 +3761,8 @@ impl Room {
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// - An `Ok` result with `Some(ThreadStatus)` if we have some subscription
|
||||
/// information.
|
||||
/// - An `Ok` result with `Some(ThreadSubscription)` if we have some
|
||||
/// subscription information.
|
||||
/// - An `Ok` result with `None` if the subscription does not exist, or the
|
||||
/// event couldn't be found, or the event isn't a thread.
|
||||
/// - An error if the request fails for any other reason, such as a network
|
||||
@@ -3771,7 +3771,7 @@ impl Room {
|
||||
pub async fn fetch_thread_subscription(
|
||||
&self,
|
||||
thread_root: OwnedEventId,
|
||||
) -> Result<Option<ThreadStatus>> {
|
||||
) -> Result<Option<ThreadSubscription>> {
|
||||
let result = self
|
||||
.client
|
||||
.send(get_thread_subscription::unstable::Request::new(
|
||||
@@ -3780,8 +3780,8 @@ impl Room {
|
||||
))
|
||||
.await;
|
||||
|
||||
let sub = match result {
|
||||
Ok(response) => Some(ThreadStatus::Subscribed { automatic: response.automatic }),
|
||||
let subscription = match result {
|
||||
Ok(response) => Some(ThreadSubscription { automatic: response.automatic }),
|
||||
Err(http_error) => match http_error.as_client_api_error() {
|
||||
Some(error) if error.status_code == StatusCode::NOT_FOUND => None,
|
||||
_ => return Err(http_error.into()),
|
||||
@@ -3789,7 +3789,7 @@ impl Room {
|
||||
};
|
||||
|
||||
// Keep the database in sync.
|
||||
if let Some(sub) = &sub {
|
||||
if let Some(sub) = &subscription {
|
||||
self.client
|
||||
.state_store()
|
||||
.upsert_thread_subscription(self.room_id(), &thread_root, *sub)
|
||||
@@ -3802,7 +3802,7 @@ impl Room {
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(sub)
|
||||
Ok(subscription)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use assert_matches2::assert_matches;
|
||||
use matrix_sdk::{room::ThreadStatus, test_utils::mocks::MatrixMockServer};
|
||||
use matrix_sdk::{room::ThreadSubscription, test_utils::mocks::MatrixMockServer};
|
||||
use matrix_sdk_test::async_test;
|
||||
use ruma::{owned_event_id, room_id};
|
||||
|
||||
@@ -34,9 +34,9 @@ async fn test_subscribe_thread() {
|
||||
.mount()
|
||||
.await;
|
||||
|
||||
// I can get the subscription status for that same thread.
|
||||
// I can get the subscription for that same thread.
|
||||
let subscription = room.fetch_thread_subscription(root_id.clone()).await.unwrap().unwrap();
|
||||
assert_matches!(subscription, ThreadStatus::Subscribed { automatic: true });
|
||||
assert_matches!(subscription, ThreadSubscription { automatic: true });
|
||||
|
||||
// If I try to get a subscription for a thread event that's unknown, I get no
|
||||
// `ThreadSubscription`, not an error.
|
||||
@@ -56,8 +56,8 @@ async fn test_subscribe_thread() {
|
||||
|
||||
room.unsubscribe_thread(root_id.clone()).await.unwrap();
|
||||
|
||||
// Now, if I retry to get the subscription status for this thread, it doesn't
|
||||
// exist anymore.
|
||||
// Now, if I retry to get the subscription for this thread, it doesn't exist
|
||||
// anymore.
|
||||
let subscription = room.fetch_thread_subscription(root_id.clone()).await.unwrap();
|
||||
assert_matches!(subscription, None);
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ use matrix_sdk::{
|
||||
api::client::receipt::create_receipt::v3::ReceiptType,
|
||||
events::room::message::RoomMessageEventContent,
|
||||
},
|
||||
store::ThreadStatus,
|
||||
};
|
||||
use matrix_sdk_ui::{
|
||||
Timeline,
|
||||
@@ -526,14 +525,10 @@ impl RoomView {
|
||||
Ok(Some(subscription)) => {
|
||||
status_handle.set_message(format!(
|
||||
"Thread subscription status: {}",
|
||||
match subscription {
|
||||
ThreadStatus::Subscribed { automatic } => {
|
||||
if automatic {
|
||||
"subscribed (automatic)"
|
||||
} else {
|
||||
"subscribed (manual)"
|
||||
}
|
||||
}
|
||||
if subscription.automatic {
|
||||
"subscribed (automatic)"
|
||||
} else {
|
||||
"subscribed (manual)"
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user