Support sending and accepting room invitations (#7)

This commit is contained in:
Ulyssa 2023-01-11 17:54:49 -08:00
parent b6f4b03c12
commit 54ce042384
No known key found for this signature in database
GPG key ID: 1B3965A3D18B9B64
8 changed files with 279 additions and 32 deletions

View file

@ -343,10 +343,10 @@ impl WindowOps<IambInfo> for IambWindow {
.render(area, buf, state);
},
IambWindow::RoomList(state) => {
let joined = store.application.worker.joined_rooms();
let joined = store.application.worker.active_rooms();
let mut items = joined
.into_iter()
.map(|(id, name)| RoomItem::new(id, name, store))
.map(|(room, name)| RoomItem::new(room, name, store))
.collect::<Vec<_>>();
items.sort();

View file

@ -92,6 +92,12 @@ impl ChatState {
}
}
pub fn refresh_room(&mut self, store: &mut ProgramStore) {
if let Some(room) = store.application.worker.client.get_room(self.id()) {
self.room = room;
}
}
pub async fn message_command(
&mut self,
act: MessageAction,

View file

@ -1,11 +1,15 @@
use matrix_sdk::{room::Room as MatrixRoom, ruma::RoomId, DisplayName};
use matrix_sdk::{
room::{Invited, Room as MatrixRoom},
ruma::RoomId,
DisplayName,
};
use modalkit::tui::{
buffer::Buffer,
layout::Rect,
layout::{Alignment, Rect},
style::{Modifier as StyleModifier, Style},
text::{Span, Spans},
widgets::StatefulWidget,
text::{Span, Spans, Text},
widgets::{Paragraph, StatefulWidget, Widget},
};
use modalkit::{
@ -93,6 +97,48 @@ impl RoomState {
}
}
pub fn refresh_room(&mut self, store: &mut ProgramStore) {
match self {
RoomState::Chat(chat) => chat.refresh_room(store),
RoomState::Space(space) => space.refresh_room(store),
}
}
fn draw_invite(
&self,
invited: Invited,
area: Rect,
buf: &mut Buffer,
store: &mut ProgramStore,
) {
let inviter = store.application.worker.get_inviter(invited.clone());
let name = match invited.canonical_alias() {
Some(alias) => alias.to_string(),
None => format!("{:?}", store.application.get_room_title(self.id())),
};
let mut invited = vec![Span::from(format!(
"You have been invited to join {}",
name
))];
if let Ok(Some(inviter)) = &inviter {
invited.push(Span::from(" by "));
invited.push(store.application.settings.get_user_span(inviter.user_id()));
}
let l1 = Spans(invited);
let l2 = Spans::from(
"You can run `:invite accept` or `:invite reject` to accept or reject this invitation.",
);
let text = Text { lines: vec![l1, l2] };
Paragraph::new(text).alignment(Alignment::Center).render(area, buf);
return;
}
pub async fn message_command(
&mut self,
act: MessageAction,
@ -124,6 +170,33 @@ impl RoomState {
store: &mut ProgramStore,
) -> IambResult<Vec<(Action<IambInfo>, ProgramContext)>> {
match act {
RoomAction::InviteAccept => {
if let Some(room) = store.application.worker.client.get_invited_room(self.id()) {
room.accept_invitation().await.map_err(IambError::from)?;
Ok(vec![])
} else {
Err(IambError::NotInvited.into())
}
},
RoomAction::InviteReject => {
if let Some(room) = store.application.worker.client.get_invited_room(self.id()) {
room.reject_invitation().await.map_err(IambError::from)?;
Ok(vec![])
} else {
Err(IambError::NotInvited.into())
}
},
RoomAction::InviteSend(user) => {
if let Some(room) = store.application.worker.client.get_joined_room(self.id()) {
room.invite_user_by_id(user.as_ref()).await.map_err(IambError::from)?;
Ok(vec![])
} else {
Err(IambError::NotJoined.into())
}
},
RoomAction::Members(mut cmd) => {
let width = Count::Exact(30);
let act =
@ -234,6 +307,14 @@ impl TerminalCursor for RoomState {
impl WindowOps<IambInfo> for RoomState {
fn draw(&mut self, area: Rect, buf: &mut Buffer, focused: bool, store: &mut ProgramStore) {
if let MatrixRoom::Invited(_) = self.room() {
self.refresh_room(store);
}
if let MatrixRoom::Invited(invited) = self.room() {
self.draw_invite(invited.clone(), area, buf, store);
}
match self {
RoomState::Chat(chat) => chat.draw(area, buf, focused, store),
RoomState::Space(space) => {

View file

@ -31,6 +31,12 @@ impl SpaceState {
SpaceState { room_id, room, list }
}
pub fn refresh_room(&mut self, store: &mut ProgramStore) {
if let Some(room) = store.application.worker.client.get_room(self.id()) {
self.room = room;
}
}
pub fn room(&self) -> &MatrixRoom {
&self.room
}
@ -88,7 +94,13 @@ impl<'a> StatefulWidget for Space<'a> {
type State = SpaceState;
fn render(self, area: Rect, buffer: &mut Buffer, state: &mut Self::State) {
let members = self.store.application.worker.space_members(state.room_id.clone()).unwrap();
let members =
if let Ok(m) = self.store.application.worker.space_members(state.room_id.clone()) {
m
} else {
return;
};
let items = members
.into_iter()
.filter_map(|id| {