use std::collections::HashMap;
use matrix_sdk::Client;
use matrix_sdk::ruma::OwnedRoomId;
use crate::room::call::call_state::CallState;
use crate::state::notification_state::NotificationState;
use crate::state::room_state::{EditingMessage, ReplyingTo, RoomFilter, RoomSortOrder, RoomSummary};
use crate::state::user_state::UserProfile;
use crate::theme::colors::Theme;
#[derive(Clone, Debug, PartialEq)]
pub enum AuthStatus {
Unknown,
LoggedOut,
LoggingIn,
LoggedIn,
Error(String),
}
#[derive(Clone, Debug, PartialEq)]
pub enum AppView {
Home,
Room(OwnedRoomId),
Settings,
Welcome,
}
#[derive(Clone, Debug, PartialEq)]
pub enum RightPanelView {
Closed,
RoomInfo,
MemberList,
MemberDetail(String),
PinnedMessages,
FilePanel,
NotificationPanel,
Thread(String),
}
#[derive(Clone)]
pub struct AppState {
pub auth_status: AuthStatus,
pub client: Option<Client>,
pub user_profile: Option<UserProfile>,
pub current_view: AppView,
pub rooms: HashMap<OwnedRoomId, RoomSummary>,
pub sorted_room_ids: Vec<OwnedRoomId>,
pub active_room_id: Option<OwnedRoomId>,
pub room_filter: RoomFilter,
pub room_sort_order: RoomSortOrder,
pub room_search_query: String,
pub right_panel: RightPanelView,
pub notifications: NotificationState,
pub theme: Theme,
pub replying_to: Option<ReplyingTo>,
pub editing_message: Option<EditingMessage>,
pub sync_status: SyncStatus,
pub sync_generation: u64,
pub composer_history: Vec<String>,
pub composer_history_index: i32,
pub spotlight_search_open: bool,
pub breadcrumbs: Vec<OwnedRoomId>,
pub labs_flags: std::collections::HashMap<String, bool>,
pub call_state: CallState,
pub bubble_layout: bool,
pub use_24h_time: bool,
pub show_join_leave: bool,
pub active_effect: Option<crate::components::message_effects::EffectType>,
pub send_read_receipts: bool,
pub send_typing_notifications: bool,
pub show_read_receipts: bool,
pub show_display_name_changes: bool,
pub show_avatar_changes: bool,
pub show_session_verification: bool,
pub show_backup_toast: bool,
pub ignored_users: Vec<String>,
pub low_priority_rooms: Vec<String>,
pub custom_status: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum SyncStatus {
Idle,
Syncing,
Synced,
Error(String),
}
impl Default for AppState {
fn default() -> Self {
Self {
auth_status: AuthStatus::Unknown,
client: None,
user_profile: None,
current_view: AppView::Home,
rooms: HashMap::new(),
sorted_room_ids: Vec::new(),
active_room_id: None,
room_filter: RoomFilter::All,
room_sort_order: RoomSortOrder::Activity,
room_search_query: String::new(),
replying_to: None,
editing_message: None,
right_panel: RightPanelView::Closed,
notifications: NotificationState::default(),
theme: Theme::Dark,
sync_status: SyncStatus::Idle,
sync_generation: 0,
composer_history: Vec::new(),
composer_history_index: -1,
spotlight_search_open: false,
breadcrumbs: Vec::new(),
labs_flags: std::collections::HashMap::new(),
call_state: CallState::default(),
bubble_layout: false,
use_24h_time: false,
show_join_leave: true,
active_effect: None,
send_read_receipts: true,
send_typing_notifications: true,
show_read_receipts: true,
show_display_name_changes: true,
show_avatar_changes: true,
show_session_verification: false,
show_backup_toast: false,
ignored_users: Vec::new(),
low_priority_rooms: Vec::new(),
custom_status: None,
}
}
}
impl AppState {
pub fn active_room(&self) -> Option<&RoomSummary> {
self.active_room_id
.as_ref()
.and_then(|id| self.rooms.get(id))
}
pub fn update_sorted_rooms(&mut self) {
let query = self.room_search_query.to_lowercase();
let mut ids: Vec<OwnedRoomId> = self
.rooms
.iter()
.filter(|(_, room)| {
match &self.room_filter {
RoomFilter::All => true,
RoomFilter::DirectMessages => room.is_direct,
RoomFilter::Rooms => !room.is_direct,
RoomFilter::Favorites => room.is_favorite,
RoomFilter::Space(space_id) => {
room.parent_spaces.contains(space_id)
}
}
})
.filter(|(_, room)| {
if query.is_empty() {
true
} else {
room.display_name.to_lowercase().contains(&query)
}
})
.map(|(id, _)| id.clone())
.collect();
match self.room_sort_order {
RoomSortOrder::Activity => {
ids.sort_by(|a, b| {
let a_ts = self
.rooms
.get(a)
.and_then(|r| r.last_activity_ts)
.unwrap_or(0);
let b_ts = self
.rooms
.get(b)
.and_then(|r| r.last_activity_ts)
.unwrap_or(0);
b_ts.cmp(&a_ts)
});
}
RoomSortOrder::Alphabetical => {
ids.sort_by(|a, b| {
let a_name = self
.rooms
.get(a)
.map(|r| r.display_name.as_str())
.unwrap_or("");
let b_name = self
.rooms
.get(b)
.map(|r| r.display_name.as_str())
.unwrap_or("");
a_name.to_lowercase().cmp(&b_name.to_lowercase())
});
}
RoomSortOrder::Unread => {
ids.sort_by(|a, b| {
let a_unread = self
.rooms
.get(a)
.map(|r| r.unread_count)
.unwrap_or(0);
let b_unread = self
.rooms
.get(b)
.map(|r| r.unread_count)
.unwrap_or(0);
b_unread.cmp(&a_unread)
});
}
}
self.sorted_room_ids = ids;
}
}