timeline(code motion): move the poll code to other files

The content of a poll timeline item goes to the content directory. The
data structure handling pending poll events goes into state.

No functional changes, only code motion.
This commit is contained in:
Benjamin Bouvier
2024-10-02 16:36:25 +02:00
parent 56ccda4ded
commit d403bf3431
7 changed files with 101 additions and 83 deletions

View File

@@ -13,7 +13,7 @@
// limitations under the License.
use std::{
collections::VecDeque,
collections::{HashMap, VecDeque},
future::Future,
num::NonZeroUsize,
sync::{Arc, RwLock},
@@ -29,8 +29,12 @@ use matrix_sdk_base::deserialized_responses::TimelineEvent;
use ruma::events::receipt::ReceiptEventContent;
use ruma::{
events::{
poll::unstable_start::NewUnstablePollStartEventContentWithoutRelation,
relation::Replacement, room::message::RoomMessageEventContentWithoutRelation,
poll::{
unstable_response::UnstablePollResponseEventContent,
unstable_start::NewUnstablePollStartEventContentWithoutRelation,
},
relation::Replacement,
room::message::RoomMessageEventContentWithoutRelation,
AnySyncEphemeralRoomEvent,
},
push::Action,
@@ -49,8 +53,7 @@ use crate::{
Flow, HandleEventResult, TimelineEventContext, TimelineEventHandler, TimelineEventKind,
TimelineItemPosition,
},
event_item::RemoteEventOrigin,
polls::PendingPollEvents,
event_item::{PollState, RemoteEventOrigin, ResponseData},
reactions::Reactions,
read_receipts::ReadReceipts,
traits::RoomDataProvider,
@@ -755,6 +758,58 @@ impl TimelineStateTransaction<'_> {
}
}
/// Cache holding poll response and end events handled before their poll start
/// event has been handled.
#[derive(Clone, Debug, Default)]
pub(in crate::timeline) struct PendingPollEvents {
/// Responses to a poll (identified by the poll's start event id).
responses: HashMap<OwnedEventId, Vec<ResponseData>>,
/// Mapping of a poll (identified by its start event's id) to its end date.
end_dates: HashMap<OwnedEventId, MilliSecondsSinceUnixEpoch>,
}
impl PendingPollEvents {
pub(crate) fn add_response(
&mut self,
start_event_id: &EventId,
sender: &UserId,
timestamp: MilliSecondsSinceUnixEpoch,
content: &UnstablePollResponseEventContent,
) {
self.responses.entry(start_event_id.to_owned()).or_default().push(ResponseData {
sender: sender.to_owned(),
timestamp,
answers: content.poll_response.answers.clone(),
});
}
pub(crate) fn clear(&mut self) {
self.end_dates.clear();
self.responses.clear();
}
/// Mark a poll as finished by inserting its poll date.
pub(crate) fn mark_as_ended(
&mut self,
start_event_id: &EventId,
timestamp: MilliSecondsSinceUnixEpoch,
) {
self.end_dates.insert(start_event_id.to_owned(), timestamp);
}
/// Dumps all response and end events present in the cache that belong to
/// the given start_event_id into the given poll_state.
pub(crate) fn apply_pending(&mut self, start_event_id: &EventId, poll_state: &mut PollState) {
if let Some(pending_responses) = self.responses.remove(start_event_id) {
poll_state.response_data.extend(pending_responses);
}
if let Some(pending_end) = self.end_dates.remove(start_event_id) {
poll_state.end_event_timestamp = Some(pending_end);
}
}
}
#[derive(Clone)]
pub(in crate::timeline) enum PendingEdit {
RoomMessage(Replacement<RoomMessageEventContentWithoutRelation>),

View File

@@ -51,10 +51,9 @@ use super::{
day_dividers::DayDividerAdjuster,
event_item::{
extract_edit_content, AnyOtherFullStateEventContent, EventSendState, EventTimelineItemKind,
LocalEventTimelineItem, Profile, ReactionsByKeyBySender, RemoteEventOrigin,
LocalEventTimelineItem, PollState, Profile, ReactionsByKeyBySender, RemoteEventOrigin,
RemoteEventTimelineItem, TimelineEventItemId,
},
polls::PollState,
reactions::FullReactionKey,
util::{rfind_event_by_id, rfind_event_item},
EventTimelineItem, InReplyToDetails, OtherState, Sticker, TimelineDetails, TimelineItem,

View File

@@ -58,15 +58,19 @@ use ruma::{
};
use tracing::warn;
use crate::timeline::{polls::PollState, TimelineItem};
use crate::timeline::TimelineItem;
mod message;
pub(crate) mod pinned_events;
mod polls;
pub use pinned_events::RoomPinnedEventsChange;
pub(crate) use self::message::extract_edit_content;
pub use self::message::{InReplyToDetails, Message, RepliedToEvent};
pub(in crate::timeline) use self::{message::extract_edit_content, polls::ResponseData};
pub use self::{
message::{InReplyToDetails, Message, RepliedToEvent},
polls::{PollResult, PollState},
};
/// The content of an [`EventTimelineItem`][super::EventTimelineItem].
#[derive(Clone, Debug)]

View File

@@ -1,3 +1,17 @@
// Copyright 2024 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! This module handles rendering of MSC3381 polls in the timeline.
use std::collections::HashMap;
@@ -13,7 +27,7 @@ use ruma::{
},
PollResponseData,
},
EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedUserId, UserId,
MilliSecondsSinceUnixEpoch, OwnedUserId, UserId,
};
/// Holds the state of a poll.
@@ -23,21 +37,21 @@ use ruma::{
/// to the same poll start event.
#[derive(Clone, Debug)]
pub struct PollState {
pub(super) start_event_content: NewUnstablePollStartEventContent,
pub(super) response_data: Vec<ResponseData>,
pub(super) end_event_timestamp: Option<MilliSecondsSinceUnixEpoch>,
pub(super) has_been_edited: bool,
pub(in crate::timeline) start_event_content: NewUnstablePollStartEventContent,
pub(in crate::timeline) response_data: Vec<ResponseData>,
pub(in crate::timeline) end_event_timestamp: Option<MilliSecondsSinceUnixEpoch>,
pub(in crate::timeline) has_been_edited: bool,
}
#[derive(Clone, Debug)]
pub(super) struct ResponseData {
pub(super) sender: OwnedUserId,
pub(super) timestamp: MilliSecondsSinceUnixEpoch,
pub(super) answers: Vec<String>,
pub(in crate::timeline) struct ResponseData {
pub sender: OwnedUserId,
pub timestamp: MilliSecondsSinceUnixEpoch,
pub answers: Vec<String>,
}
impl PollState {
pub(super) fn new(content: NewUnstablePollStartEventContent) -> Self {
pub(crate) fn new(content: NewUnstablePollStartEventContent) -> Self {
Self {
start_event_content: content,
response_data: vec![],
@@ -48,7 +62,7 @@ impl PollState {
/// Applies an edit to a poll, returns `None` if the poll was already marked
/// as finished.
pub(super) fn edit(
pub(crate) fn edit(
&self,
replacement: &NewUnstablePollStartEventContentWithoutRelation,
) -> Option<Self> {
@@ -63,7 +77,7 @@ impl PollState {
}
}
pub(super) fn add_response(
pub(crate) fn add_response(
&self,
sender: &UserId,
timestamp: MilliSecondsSinceUnixEpoch,
@@ -81,7 +95,7 @@ impl PollState {
/// Marks the poll as ended.
///
/// If the poll has already ended, returns `Err(())`.
pub(super) fn end(&self, timestamp: MilliSecondsSinceUnixEpoch) -> Result<Self, ()> {
pub(crate) fn end(&self, timestamp: MilliSecondsSinceUnixEpoch) -> Result<Self, ()> {
if self.end_event_timestamp.is_none() {
let mut clone = self.clone();
clone.end_event_timestamp = Some(timestamp);
@@ -146,58 +160,6 @@ impl From<PollState> for NewUnstablePollStartEventContent {
}
}
/// Cache holding poll response and end events handled before their poll start
/// event has been handled.
#[derive(Clone, Debug, Default)]
pub(super) struct PendingPollEvents {
/// Responses to a poll (identified by the poll's start event id).
responses: HashMap<OwnedEventId, Vec<ResponseData>>,
/// Mapping of a poll (identified by its start event's id) to its end date.
end_dates: HashMap<OwnedEventId, MilliSecondsSinceUnixEpoch>,
}
impl PendingPollEvents {
pub(super) fn add_response(
&mut self,
start_event_id: &EventId,
sender: &UserId,
timestamp: MilliSecondsSinceUnixEpoch,
content: &UnstablePollResponseEventContent,
) {
self.responses.entry(start_event_id.to_owned()).or_default().push(ResponseData {
sender: sender.to_owned(),
timestamp,
answers: content.poll_response.answers.clone(),
});
}
pub(super) fn clear(&mut self) {
self.end_dates.clear();
self.responses.clear();
}
/// Mark a poll as finished by inserting its poll date.
pub(super) fn mark_as_ended(
&mut self,
start_event_id: &EventId,
timestamp: MilliSecondsSinceUnixEpoch,
) {
self.end_dates.insert(start_event_id.to_owned(), timestamp);
}
/// Dumps all response and end events present in the cache that belong to
/// the given start_event_id into the given poll_state.
pub(super) fn apply_pending(&mut self, start_event_id: &EventId, poll_state: &mut PollState) {
if let Some(pending_responses) = self.responses.remove(start_event_id) {
poll_state.response_data.extend(pending_responses);
}
if let Some(pending_end) = self.end_dates.remove(start_event_id) {
poll_state.end_event_timestamp = Some(pending_end);
}
}
}
#[derive(Debug)]
pub struct PollResult {
pub question: String,

View File

@@ -42,15 +42,15 @@ mod local;
mod remote;
pub(super) use self::{
content::extract_edit_content,
content::{extract_edit_content, ResponseData},
local::LocalEventTimelineItem,
remote::{RemoteEventOrigin, RemoteEventTimelineItem},
};
pub use self::{
content::{
AnyOtherFullStateEventContent, EncryptedMessage, InReplyToDetails, MemberProfileChange,
MembershipChange, Message, OtherState, RepliedToEvent, RoomMembershipChange,
RoomPinnedEventsChange, Sticker, TimelineItemContent,
MembershipChange, Message, OtherState, PollResult, PollState, RepliedToEvent,
RoomMembershipChange, RoomPinnedEventsChange, Sticker, TimelineItemContent,
},
local::EventSendState,
};

View File

@@ -68,7 +68,6 @@ pub mod futures;
mod item;
mod pagination;
mod pinned_events_loader;
mod polls;
mod reactions;
mod read_receipts;
#[cfg(test)]
@@ -85,14 +84,13 @@ pub use self::{
event_item::{
AnyOtherFullStateEventContent, EncryptedMessage, EventItemOrigin, EventSendState,
EventTimelineItem, InReplyToDetails, MemberProfileChange, MembershipChange, Message,
OtherState, Profile, ReactionInfo, ReactionStatus, ReactionsByKeyBySender, RepliedToEvent,
RoomMembershipChange, RoomPinnedEventsChange, Sticker, TimelineDetails,
OtherState, PollResult, Profile, ReactionInfo, ReactionStatus, ReactionsByKeyBySender,
RepliedToEvent, RoomMembershipChange, RoomPinnedEventsChange, Sticker, TimelineDetails,
TimelineEventItemId, TimelineItemContent,
},
event_type_filter::TimelineEventTypeFilter,
item::{TimelineItem, TimelineItemKind},
pagination::LiveBackPaginationStatus,
polls::PollResult,
traits::RoomExt,
virtual_item::VirtualTimelineItem,
};

View File

@@ -15,7 +15,7 @@ use ruma::{
};
use crate::timeline::{
polls::PollState, tests::TestTimeline, EventTimelineItem, TimelineItemContent,
event_item::PollState, tests::TestTimeline, EventTimelineItem, TimelineItemContent,
};
#[async_test]