mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 05:39:52 -07:00
Support listing room members (#6)
This commit is contained in:
parent
d038da6844
commit
8ed037afca
11 changed files with 316 additions and 52 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -1600,9 +1600,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "modalkit"
|
name = "modalkit"
|
||||||
version = "0.0.7"
|
version = "0.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc4385b7136847cd063fbf093f0aa21a098398e26dc9213137fdd4e4f593d6bf"
|
checksum = "7f4e400066e546471efee517b7e5e3ca5af2c04014e76289aecc7af621011bba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anymap2",
|
"anymap2",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
|
|
@ -19,7 +19,7 @@ dirs = "4.0.0"
|
||||||
futures = "0.3.21"
|
futures = "0.3.21"
|
||||||
gethostname = "0.4.1"
|
gethostname = "0.4.1"
|
||||||
matrix-sdk = {version = "0.6", default-features = false, features = ["e2e-encryption", "sled", "rustls-tls"]}
|
matrix-sdk = {version = "0.6", default-features = false, features = ["e2e-encryption", "sled", "rustls-tls"]}
|
||||||
modalkit = "0.0.7"
|
modalkit = "0.0.8"
|
||||||
regex = "^1.5"
|
regex = "^1.5"
|
||||||
rpassword = "^7.2"
|
rpassword = "^7.2"
|
||||||
serde = "^1.0"
|
serde = "^1.0"
|
||||||
|
|
|
@ -42,7 +42,7 @@ two other TUI clients and Element Web:
|
||||||
| Room tag showing | :x: ([#15]) | :heavy_check_mark: | :x: | :heavy_check_mark: |
|
| Room tag showing | :x: ([#15]) | :heavy_check_mark: | :x: | :heavy_check_mark: |
|
||||||
| Room tag editing | :x: ([#15]) | :heavy_check_mark: | :x: | :heavy_check_mark: |
|
| Room tag editing | :x: ([#15]) | :heavy_check_mark: | :x: | :heavy_check_mark: |
|
||||||
| Search joined rooms | :x: ([#16]) | :heavy_check_mark: | :x: | :heavy_check_mark: |
|
| Search joined rooms | :x: ([#16]) | :heavy_check_mark: | :x: | :heavy_check_mark: |
|
||||||
| Room user list | :x: ([#6]) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
| Room user list | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| Display Room Description | :x: ([#12]) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
| Display Room Description | :x: ([#12]) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| Edit Room Description | :x: ([#12]) | :x: | :heavy_check_mark: | :heavy_check_mark: |
|
| Edit Room Description | :x: ([#12]) | :x: | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| Highlights | :x: ([#8]) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
| Highlights | :x: ([#8]) | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
|
|
23
src/base.rs
23
src/base.rs
|
@ -26,7 +26,7 @@ use modalkit::{
|
||||||
store::Store,
|
store::Store,
|
||||||
},
|
},
|
||||||
env::vim::{
|
env::vim::{
|
||||||
command::{VimCommand, VimCommandMachine},
|
command::{CommandContext, VimCommand, VimCommandMachine},
|
||||||
keybindings::VimMachine,
|
keybindings::VimMachine,
|
||||||
VimContext,
|
VimContext,
|
||||||
},
|
},
|
||||||
|
@ -59,8 +59,14 @@ pub enum VerifyAction {
|
||||||
Mismatch,
|
Mismatch,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum RoomAction {
|
||||||
|
Members(Box<CommandContext<ProgramContext>>),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum IambAction {
|
pub enum IambAction {
|
||||||
|
Room(RoomAction),
|
||||||
Verify(VerifyAction, String),
|
Verify(VerifyAction, String),
|
||||||
VerifyRequest(String),
|
VerifyRequest(String),
|
||||||
SendMessage(OwnedRoomId, String),
|
SendMessage(OwnedRoomId, String),
|
||||||
|
@ -70,6 +76,7 @@ pub enum IambAction {
|
||||||
impl ApplicationAction for IambAction {
|
impl ApplicationAction for IambAction {
|
||||||
fn is_edit_sequence<C: EditContext>(&self, _: &C) -> SequenceStatus {
|
fn is_edit_sequence<C: EditContext>(&self, _: &C) -> SequenceStatus {
|
||||||
match self {
|
match self {
|
||||||
|
IambAction::Room(..) => SequenceStatus::Break,
|
||||||
IambAction::SendMessage(..) => SequenceStatus::Break,
|
IambAction::SendMessage(..) => SequenceStatus::Break,
|
||||||
IambAction::ToggleScrollbackFocus => SequenceStatus::Break,
|
IambAction::ToggleScrollbackFocus => SequenceStatus::Break,
|
||||||
IambAction::Verify(..) => SequenceStatus::Break,
|
IambAction::Verify(..) => SequenceStatus::Break,
|
||||||
|
@ -79,6 +86,7 @@ impl ApplicationAction for IambAction {
|
||||||
|
|
||||||
fn is_last_action<C: EditContext>(&self, _: &C) -> SequenceStatus {
|
fn is_last_action<C: EditContext>(&self, _: &C) -> SequenceStatus {
|
||||||
match self {
|
match self {
|
||||||
|
IambAction::Room(..) => SequenceStatus::Atom,
|
||||||
IambAction::SendMessage(..) => SequenceStatus::Atom,
|
IambAction::SendMessage(..) => SequenceStatus::Atom,
|
||||||
IambAction::ToggleScrollbackFocus => SequenceStatus::Atom,
|
IambAction::ToggleScrollbackFocus => SequenceStatus::Atom,
|
||||||
IambAction::Verify(..) => SequenceStatus::Atom,
|
IambAction::Verify(..) => SequenceStatus::Atom,
|
||||||
|
@ -88,6 +96,7 @@ impl ApplicationAction for IambAction {
|
||||||
|
|
||||||
fn is_last_selection<C: EditContext>(&self, _: &C) -> SequenceStatus {
|
fn is_last_selection<C: EditContext>(&self, _: &C) -> SequenceStatus {
|
||||||
match self {
|
match self {
|
||||||
|
IambAction::Room(..) => SequenceStatus::Ignore,
|
||||||
IambAction::SendMessage(..) => SequenceStatus::Ignore,
|
IambAction::SendMessage(..) => SequenceStatus::Ignore,
|
||||||
IambAction::ToggleScrollbackFocus => SequenceStatus::Ignore,
|
IambAction::ToggleScrollbackFocus => SequenceStatus::Ignore,
|
||||||
IambAction::Verify(..) => SequenceStatus::Ignore,
|
IambAction::Verify(..) => SequenceStatus::Ignore,
|
||||||
|
@ -97,6 +106,7 @@ impl ApplicationAction for IambAction {
|
||||||
|
|
||||||
fn is_switchable<C: EditContext>(&self, _: &C) -> bool {
|
fn is_switchable<C: EditContext>(&self, _: &C) -> bool {
|
||||||
match self {
|
match self {
|
||||||
|
IambAction::Room(..) => false,
|
||||||
IambAction::SendMessage(..) => false,
|
IambAction::SendMessage(..) => false,
|
||||||
IambAction::ToggleScrollbackFocus => false,
|
IambAction::ToggleScrollbackFocus => false,
|
||||||
IambAction::Verify(..) => false,
|
IambAction::Verify(..) => false,
|
||||||
|
@ -275,6 +285,14 @@ impl ChatStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_room_title(&self, room_id: &RoomId) -> String {
|
||||||
|
self.rooms
|
||||||
|
.get(room_id)
|
||||||
|
.and_then(|i| i.name.as_ref())
|
||||||
|
.map(String::from)
|
||||||
|
.unwrap_or_else(|| "Untitled Matrix Room".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mark_for_load(&mut self, room_id: OwnedRoomId) {
|
pub fn mark_for_load(&mut self, room_id: OwnedRoomId) {
|
||||||
self.need_load.insert(room_id);
|
self.need_load.insert(room_id);
|
||||||
}
|
}
|
||||||
|
@ -346,6 +364,7 @@ impl ApplicationStore for ChatStore {}
|
||||||
pub enum IambId {
|
pub enum IambId {
|
||||||
Room(OwnedRoomId),
|
Room(OwnedRoomId),
|
||||||
DirectList,
|
DirectList,
|
||||||
|
MemberList(OwnedRoomId),
|
||||||
RoomList,
|
RoomList,
|
||||||
SpaceList,
|
SpaceList,
|
||||||
VerifyList,
|
VerifyList,
|
||||||
|
@ -375,6 +394,7 @@ pub enum IambBufferId {
|
||||||
Command,
|
Command,
|
||||||
Room(OwnedRoomId, RoomFocus),
|
Room(OwnedRoomId, RoomFocus),
|
||||||
DirectList,
|
DirectList,
|
||||||
|
MemberList(OwnedRoomId),
|
||||||
RoomList,
|
RoomList,
|
||||||
SpaceList,
|
SpaceList,
|
||||||
VerifyList,
|
VerifyList,
|
||||||
|
@ -387,6 +407,7 @@ impl IambBufferId {
|
||||||
IambBufferId::Command => None,
|
IambBufferId::Command => None,
|
||||||
IambBufferId::Room(room, _) => Some(IambId::Room(room.clone())),
|
IambBufferId::Room(room, _) => Some(IambId::Room(room.clone())),
|
||||||
IambBufferId::DirectList => Some(IambId::DirectList),
|
IambBufferId::DirectList => Some(IambId::DirectList),
|
||||||
|
IambBufferId::MemberList(room) => Some(IambId::MemberList(room.clone())),
|
||||||
IambBufferId::RoomList => Some(IambId::RoomList),
|
IambBufferId::RoomList => Some(IambId::RoomList),
|
||||||
IambBufferId::SpaceList => Some(IambId::SpaceList),
|
IambBufferId::SpaceList => Some(IambId::SpaceList),
|
||||||
IambBufferId::VerifyList => Some(IambId::VerifyList),
|
IambBufferId::VerifyList => Some(IambId::VerifyList),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use modalkit::{
|
use modalkit::{
|
||||||
editing::{action::WindowAction, base::OpenTarget},
|
editing::base::OpenTarget,
|
||||||
env::vim::command::{CommandContext, CommandDescription},
|
env::vim::command::{CommandContext, CommandDescription},
|
||||||
input::commands::{CommandError, CommandResult, CommandStep},
|
input::commands::{CommandError, CommandResult, CommandStep},
|
||||||
input::InputContext,
|
input::InputContext,
|
||||||
|
@ -11,6 +11,7 @@ use crate::base::{
|
||||||
ProgramCommand,
|
ProgramCommand,
|
||||||
ProgramCommands,
|
ProgramCommands,
|
||||||
ProgramContext,
|
ProgramContext,
|
||||||
|
RoomAction,
|
||||||
VerifyAction,
|
VerifyAction,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,8 +23,8 @@ fn iamb_verify(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||||
|
|
||||||
match args.len() {
|
match args.len() {
|
||||||
0 => {
|
0 => {
|
||||||
let open = WindowAction::Switch(OpenTarget::Application(IambId::VerifyList));
|
let open = ctx.switch(OpenTarget::Application(IambId::VerifyList));
|
||||||
let step = CommandStep::Continue(open.into(), ctx.context.take());
|
let step = CommandStep::Continue(open, ctx.context.take());
|
||||||
|
|
||||||
return Ok(step);
|
return Ok(step);
|
||||||
},
|
},
|
||||||
|
@ -61,7 +62,18 @@ fn iamb_dms(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||||
return Result::Err(CommandError::InvalidArgument);
|
return Result::Err(CommandError::InvalidArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
let open = WindowAction::Switch(OpenTarget::Application(IambId::DirectList));
|
let open = ctx.switch(OpenTarget::Application(IambId::DirectList));
|
||||||
|
let step = CommandStep::Continue(open, ctx.context.take());
|
||||||
|
|
||||||
|
return Ok(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iamb_members(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||||
|
if !desc.arg.text.is_empty() {
|
||||||
|
return Result::Err(CommandError::InvalidArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
let open = IambAction::Room(RoomAction::Members(ctx.clone().into()));
|
||||||
let step = CommandStep::Continue(open.into(), ctx.context.take());
|
let step = CommandStep::Continue(open.into(), ctx.context.take());
|
||||||
|
|
||||||
return Ok(step);
|
return Ok(step);
|
||||||
|
@ -72,8 +84,8 @@ fn iamb_rooms(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||||
return Result::Err(CommandError::InvalidArgument);
|
return Result::Err(CommandError::InvalidArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
let open = WindowAction::Switch(OpenTarget::Application(IambId::RoomList));
|
let open = ctx.switch(OpenTarget::Application(IambId::RoomList));
|
||||||
let step = CommandStep::Continue(open.into(), ctx.context.take());
|
let step = CommandStep::Continue(open, ctx.context.take());
|
||||||
|
|
||||||
return Ok(step);
|
return Ok(step);
|
||||||
}
|
}
|
||||||
|
@ -83,8 +95,8 @@ fn iamb_spaces(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||||
return Result::Err(CommandError::InvalidArgument);
|
return Result::Err(CommandError::InvalidArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
let open = WindowAction::Switch(OpenTarget::Application(IambId::SpaceList));
|
let open = ctx.switch(OpenTarget::Application(IambId::SpaceList));
|
||||||
let step = CommandStep::Continue(open.into(), ctx.context.take());
|
let step = CommandStep::Continue(open, ctx.context.take());
|
||||||
|
|
||||||
return Ok(step);
|
return Ok(step);
|
||||||
}
|
}
|
||||||
|
@ -94,8 +106,8 @@ fn iamb_welcome(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||||
return Result::Err(CommandError::InvalidArgument);
|
return Result::Err(CommandError::InvalidArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
let open = WindowAction::Switch(OpenTarget::Application(IambId::Welcome));
|
let open = ctx.switch(OpenTarget::Application(IambId::Welcome));
|
||||||
let step = CommandStep::Continue(open.into(), ctx.context.take());
|
let step = CommandStep::Continue(open, ctx.context.take());
|
||||||
|
|
||||||
return Ok(step);
|
return Ok(step);
|
||||||
}
|
}
|
||||||
|
@ -107,8 +119,8 @@ fn iamb_join(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||||
return Result::Err(CommandError::InvalidArgument);
|
return Result::Err(CommandError::InvalidArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
let open = WindowAction::Switch(args.remove(0));
|
let open = ctx.switch(args.remove(0));
|
||||||
let step = CommandStep::Continue(open.into(), ctx.context.take());
|
let step = CommandStep::Continue(open, ctx.context.take());
|
||||||
|
|
||||||
return Ok(step);
|
return Ok(step);
|
||||||
}
|
}
|
||||||
|
@ -116,6 +128,7 @@ fn iamb_join(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||||
fn add_iamb_commands(cmds: &mut ProgramCommands) {
|
fn add_iamb_commands(cmds: &mut ProgramCommands) {
|
||||||
cmds.add_command(ProgramCommand { names: vec!["dms".into()], f: iamb_dms });
|
cmds.add_command(ProgramCommand { names: vec!["dms".into()], f: iamb_dms });
|
||||||
cmds.add_command(ProgramCommand { names: vec!["join".into()], f: iamb_join });
|
cmds.add_command(ProgramCommand { names: vec!["join".into()], f: iamb_join });
|
||||||
|
cmds.add_command(ProgramCommand { names: vec!["members".into()], f: iamb_members });
|
||||||
cmds.add_command(ProgramCommand { names: vec!["rooms".into()], f: iamb_rooms });
|
cmds.add_command(ProgramCommand { names: vec!["rooms".into()], f: iamb_rooms });
|
||||||
cmds.add_command(ProgramCommand { names: vec!["spaces".into()], f: iamb_spaces });
|
cmds.add_command(ProgramCommand { names: vec!["spaces".into()], f: iamb_spaces });
|
||||||
cmds.add_command(ProgramCommand { names: vec!["verify".into()], f: iamb_verify });
|
cmds.add_command(ProgramCommand { names: vec!["verify".into()], f: iamb_verify });
|
||||||
|
@ -133,6 +146,8 @@ pub fn setup_commands() -> ProgramCommands {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use modalkit::editing::action::WindowAction;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cmd_verify() {
|
fn test_cmd_verify() {
|
||||||
let mut cmds = setup_commands();
|
let mut cmds = setup_commands();
|
||||||
|
|
|
@ -317,7 +317,7 @@ impl Application {
|
||||||
fn iamb_run(
|
fn iamb_run(
|
||||||
&mut self,
|
&mut self,
|
||||||
action: IambAction,
|
action: IambAction,
|
||||||
_: ProgramContext,
|
ctx: ProgramContext,
|
||||||
store: &mut ProgramStore,
|
store: &mut ProgramStore,
|
||||||
) -> IambResult<EditInfo> {
|
) -> IambResult<EditInfo> {
|
||||||
let info = match action {
|
let info = match action {
|
||||||
|
@ -327,6 +327,13 @@ impl Application {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
|
||||||
|
IambAction::Room(act) => {
|
||||||
|
let acts = self.screen.current_window_mut()?.room_command(act, ctx, store)?;
|
||||||
|
self.action_prepend(acts);
|
||||||
|
|
||||||
|
None
|
||||||
|
},
|
||||||
|
|
||||||
IambAction::SendMessage(room_id, msg) => {
|
IambAction::SendMessage(room_id, msg) => {
|
||||||
let (event_id, msg) = self.worker.send_message(room_id.clone(), msg)?;
|
let (event_id, msg) = self.worker.send_message(room_id.clone(), msg)?;
|
||||||
let user = store.application.settings.profile.user_id.clone();
|
let user = store.application.settings.profile.user_id.clone();
|
||||||
|
|
|
@ -3,22 +3,23 @@ use std::collections::hash_map::Entry;
|
||||||
|
|
||||||
use matrix_sdk::{
|
use matrix_sdk::{
|
||||||
encryption::verification::{format_emojis, SasVerification},
|
encryption::verification::{format_emojis, SasVerification},
|
||||||
room::Room as MatrixRoom,
|
room::{Room as MatrixRoom, RoomMember},
|
||||||
ruma::RoomId,
|
ruma::{events::room::member::MembershipState, OwnedRoomId, RoomId},
|
||||||
DisplayName,
|
DisplayName,
|
||||||
};
|
};
|
||||||
|
|
||||||
use modalkit::tui::{
|
use modalkit::tui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
layout::Rect,
|
layout::{Alignment, Rect},
|
||||||
style::{Modifier as StyleModifier, Style},
|
style::{Modifier as StyleModifier, Style},
|
||||||
text::{Span, Spans, Text},
|
text::{Span, Spans, Text},
|
||||||
widgets::{Block, Borders, Widget},
|
widgets::{Block, Borders, StatefulWidget, Widget},
|
||||||
};
|
};
|
||||||
|
|
||||||
use modalkit::{
|
use modalkit::{
|
||||||
editing::{
|
editing::{
|
||||||
action::{
|
action::{
|
||||||
|
Action,
|
||||||
EditError,
|
EditError,
|
||||||
EditInfo,
|
EditInfo,
|
||||||
EditResult,
|
EditResult,
|
||||||
|
@ -42,7 +43,7 @@ use modalkit::{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
widgets::{
|
widgets::{
|
||||||
list::{ListCursor, ListItem, ListState},
|
list::{List, ListCursor, ListItem, ListState},
|
||||||
TermOffset,
|
TermOffset,
|
||||||
TerminalCursor,
|
TerminalCursor,
|
||||||
Window,
|
Window,
|
||||||
|
@ -50,15 +51,19 @@ use modalkit::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::base::{
|
use crate::{
|
||||||
ChatStore,
|
base::{
|
||||||
IambBufferId,
|
ChatStore,
|
||||||
IambId,
|
IambBufferId,
|
||||||
IambInfo,
|
IambId,
|
||||||
IambResult,
|
IambInfo,
|
||||||
ProgramAction,
|
IambResult,
|
||||||
ProgramContext,
|
ProgramAction,
|
||||||
ProgramStore,
|
ProgramContext,
|
||||||
|
ProgramStore,
|
||||||
|
RoomAction,
|
||||||
|
},
|
||||||
|
message::user_style,
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::{room::RoomState, welcome::WelcomeState};
|
use self::{room::RoomState, welcome::WelcomeState};
|
||||||
|
@ -120,6 +125,7 @@ macro_rules! delegate {
|
||||||
match $s {
|
match $s {
|
||||||
IambWindow::Room($id) => $e,
|
IambWindow::Room($id) => $e,
|
||||||
IambWindow::DirectList($id) => $e,
|
IambWindow::DirectList($id) => $e,
|
||||||
|
IambWindow::MemberList($id, _) => $e,
|
||||||
IambWindow::RoomList($id) => $e,
|
IambWindow::RoomList($id) => $e,
|
||||||
IambWindow::SpaceList($id) => $e,
|
IambWindow::SpaceList($id) => $e,
|
||||||
IambWindow::VerifyList($id) => $e,
|
IambWindow::VerifyList($id) => $e,
|
||||||
|
@ -130,6 +136,7 @@ macro_rules! delegate {
|
||||||
|
|
||||||
pub enum IambWindow {
|
pub enum IambWindow {
|
||||||
DirectList(DirectListState),
|
DirectList(DirectListState),
|
||||||
|
MemberList(MemberListState, OwnedRoomId),
|
||||||
Room(RoomState),
|
Room(RoomState),
|
||||||
VerifyList(VerifyListState),
|
VerifyList(VerifyListState),
|
||||||
RoomList(RoomListState),
|
RoomList(RoomListState),
|
||||||
|
@ -146,19 +153,41 @@ impl IambWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn room_command(
|
||||||
|
&mut self,
|
||||||
|
act: RoomAction,
|
||||||
|
ctx: ProgramContext,
|
||||||
|
store: &mut ProgramStore,
|
||||||
|
) -> IambResult<Vec<(Action<IambInfo>, ProgramContext)>> {
|
||||||
|
if let IambWindow::Room(w) = self {
|
||||||
|
w.room_command(act, ctx, store)
|
||||||
|
} else {
|
||||||
|
let msg = "No room currently focused!";
|
||||||
|
let err = UIError::Failure(msg.into());
|
||||||
|
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_title(&self, store: &mut ProgramStore) -> String {
|
pub fn get_title(&self, store: &mut ProgramStore) -> String {
|
||||||
match self {
|
match self {
|
||||||
IambWindow::Room(w) => w.get_title(store),
|
|
||||||
IambWindow::DirectList(_) => "Direct Messages".to_string(),
|
IambWindow::DirectList(_) => "Direct Messages".to_string(),
|
||||||
IambWindow::RoomList(_) => "Rooms".to_string(),
|
IambWindow::RoomList(_) => "Rooms".to_string(),
|
||||||
IambWindow::SpaceList(_) => "Spaces".to_string(),
|
IambWindow::SpaceList(_) => "Spaces".to_string(),
|
||||||
IambWindow::VerifyList(_) => "Verifications".to_string(),
|
IambWindow::VerifyList(_) => "Verifications".to_string(),
|
||||||
IambWindow::Welcome(_) => "Welcome to iamb".to_string(),
|
IambWindow::Welcome(_) => "Welcome to iamb".to_string(),
|
||||||
|
|
||||||
|
IambWindow::Room(w) => w.get_title(store),
|
||||||
|
IambWindow::MemberList(_, room_id) => {
|
||||||
|
let title = store.application.get_room_title(room_id.as_ref());
|
||||||
|
format!("Room Members: {}", title)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DirectListState = ListState<DirectItem, IambInfo>;
|
pub type DirectListState = ListState<DirectItem, IambInfo>;
|
||||||
|
pub type MemberListState = ListState<MemberItem, IambInfo>;
|
||||||
pub type RoomListState = ListState<RoomItem, IambInfo>;
|
pub type RoomListState = ListState<RoomItem, IambInfo>;
|
||||||
pub type SpaceListState = ListState<SpaceItem, IambInfo>;
|
pub type SpaceListState = ListState<SpaceItem, IambInfo>;
|
||||||
pub type VerifyListState = ListState<VerifyItem, IambInfo>;
|
pub type VerifyListState = ListState<VerifyItem, IambInfo>;
|
||||||
|
@ -263,13 +292,35 @@ impl WindowOps<IambInfo> for IambWindow {
|
||||||
let dms = store.application.worker.direct_messages();
|
let dms = store.application.worker.direct_messages();
|
||||||
let items = dms.into_iter().map(|(id, name)| DirectItem::new(id, name, store));
|
let items = dms.into_iter().map(|(id, name)| DirectItem::new(id, name, store));
|
||||||
state.set(items.collect());
|
state.set(items.collect());
|
||||||
state.draw(inner, buf, focused, store);
|
|
||||||
|
List::new(store)
|
||||||
|
.empty_message("No direct messages yet!")
|
||||||
|
.empty_alignment(Alignment::Center)
|
||||||
|
.focus(focused)
|
||||||
|
.render(inner, buf, state);
|
||||||
|
},
|
||||||
|
IambWindow::MemberList(state, room_id) => {
|
||||||
|
if let Ok(mems) = store.application.worker.members(room_id.clone()) {
|
||||||
|
let items = mems.into_iter().map(MemberItem::new);
|
||||||
|
state.set(items.collect());
|
||||||
|
}
|
||||||
|
|
||||||
|
List::new(store)
|
||||||
|
.empty_message("No users here yet!")
|
||||||
|
.empty_alignment(Alignment::Center)
|
||||||
|
.focus(focused)
|
||||||
|
.render(inner, buf, state);
|
||||||
},
|
},
|
||||||
IambWindow::RoomList(state) => {
|
IambWindow::RoomList(state) => {
|
||||||
let joined = store.application.worker.joined_rooms();
|
let joined = store.application.worker.joined_rooms();
|
||||||
let items = joined.into_iter().map(|(id, name)| RoomItem::new(id, name, store));
|
let items = joined.into_iter().map(|(id, name)| RoomItem::new(id, name, store));
|
||||||
state.set(items.collect());
|
state.set(items.collect());
|
||||||
state.draw(inner, buf, focused, store);
|
|
||||||
|
List::new(store)
|
||||||
|
.empty_message("You haven't joined any rooms yet")
|
||||||
|
.empty_alignment(Alignment::Center)
|
||||||
|
.focus(focused)
|
||||||
|
.render(inner, buf, state);
|
||||||
},
|
},
|
||||||
IambWindow::SpaceList(state) => {
|
IambWindow::SpaceList(state) => {
|
||||||
let spaces = store.application.worker.spaces();
|
let spaces = store.application.worker.spaces();
|
||||||
|
@ -277,6 +328,12 @@ impl WindowOps<IambInfo> for IambWindow {
|
||||||
spaces.into_iter().map(|(room, name)| SpaceItem::new(room, name, store));
|
spaces.into_iter().map(|(room, name)| SpaceItem::new(room, name, store));
|
||||||
state.set(items.collect());
|
state.set(items.collect());
|
||||||
state.draw(inner, buf, focused, store);
|
state.draw(inner, buf, focused, store);
|
||||||
|
|
||||||
|
List::new(store)
|
||||||
|
.empty_message("You haven't joined any spaces yet")
|
||||||
|
.empty_alignment(Alignment::Center)
|
||||||
|
.focus(focused)
|
||||||
|
.render(inner, buf, state);
|
||||||
},
|
},
|
||||||
IambWindow::VerifyList(state) => {
|
IambWindow::VerifyList(state) => {
|
||||||
let verifications = &store.application.verifications;
|
let verifications = &store.application.verifications;
|
||||||
|
@ -286,14 +343,29 @@ impl WindowOps<IambInfo> for IambWindow {
|
||||||
items.sort();
|
items.sort();
|
||||||
|
|
||||||
state.set(items);
|
state.set(items);
|
||||||
state.draw(inner, buf, focused, store);
|
|
||||||
|
List::new(store)
|
||||||
|
.empty_message("No in-progress verifications")
|
||||||
|
.empty_alignment(Alignment::Center)
|
||||||
|
.focus(focused)
|
||||||
|
.render(inner, buf, state);
|
||||||
},
|
},
|
||||||
IambWindow::Welcome(state) => state.draw(inner, buf, focused, store),
|
IambWindow::Welcome(state) => state.draw(inner, buf, focused, store),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dup(&self, store: &mut ProgramStore) -> Self {
|
fn dup(&self, store: &mut ProgramStore) -> Self {
|
||||||
delegate!(self, w => w.dup(store).into())
|
match self {
|
||||||
|
IambWindow::Room(w) => w.dup(store).into(),
|
||||||
|
IambWindow::DirectList(w) => w.dup(store).into(),
|
||||||
|
IambWindow::MemberList(w, room_id) => {
|
||||||
|
IambWindow::MemberList(w.dup(store), room_id.clone())
|
||||||
|
},
|
||||||
|
IambWindow::RoomList(w) => w.dup(store).into(),
|
||||||
|
IambWindow::SpaceList(w) => w.dup(store).into(),
|
||||||
|
IambWindow::VerifyList(w) => w.dup(store).into(),
|
||||||
|
IambWindow::Welcome(w) => w.dup(store).into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(&mut self, flags: CloseFlags, store: &mut ProgramStore) -> bool {
|
fn close(&mut self, flags: CloseFlags, store: &mut ProgramStore) -> bool {
|
||||||
|
@ -314,6 +386,7 @@ impl Window<IambInfo> for IambWindow {
|
||||||
match self {
|
match self {
|
||||||
IambWindow::Room(room) => IambId::Room(room.id().to_owned()),
|
IambWindow::Room(room) => IambId::Room(room.id().to_owned()),
|
||||||
IambWindow::DirectList(_) => IambId::DirectList,
|
IambWindow::DirectList(_) => IambId::DirectList,
|
||||||
|
IambWindow::MemberList(_, room_id) => IambId::MemberList(room_id.clone()),
|
||||||
IambWindow::RoomList(_) => IambId::RoomList,
|
IambWindow::RoomList(_) => IambId::RoomList,
|
||||||
IambWindow::SpaceList(_) => IambId::SpaceList,
|
IambWindow::SpaceList(_) => IambId::SpaceList,
|
||||||
IambWindow::VerifyList(_) => IambId::VerifyList,
|
IambWindow::VerifyList(_) => IambId::VerifyList,
|
||||||
|
@ -334,6 +407,13 @@ impl Window<IambInfo> for IambWindow {
|
||||||
|
|
||||||
return Ok(list.into());
|
return Ok(list.into());
|
||||||
},
|
},
|
||||||
|
IambId::MemberList(room_id) => {
|
||||||
|
let id = IambBufferId::MemberList(room_id.clone());
|
||||||
|
let list = MemberListState::new(id, vec![]);
|
||||||
|
let win = IambWindow::MemberList(list, room_id);
|
||||||
|
|
||||||
|
return Ok(win);
|
||||||
|
},
|
||||||
IambId::RoomList => {
|
IambId::RoomList => {
|
||||||
let list = RoomListState::new(IambBufferId::RoomList, vec![]);
|
let list = RoomListState::new(IambBufferId::RoomList, vec![]);
|
||||||
|
|
||||||
|
@ -412,6 +492,10 @@ impl ListItem<IambInfo> for RoomItem {
|
||||||
fn show(&self, selected: bool, _: &ViewportContext<ListCursor>, _: &mut ProgramStore) -> Text {
|
fn show(&self, selected: bool, _: &ViewportContext<ListCursor>, _: &mut ProgramStore) -> Text {
|
||||||
selected_text(self.name.as_str(), selected)
|
selected_text(self.name.as_str(), selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_word(&self) -> Option<String> {
|
||||||
|
self.room.room_id().to_string().into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Promptable<ProgramContext, ProgramStore, IambInfo> for RoomItem {
|
impl Promptable<ProgramContext, ProgramStore, IambInfo> for RoomItem {
|
||||||
|
@ -451,6 +535,10 @@ impl ListItem<IambInfo> for DirectItem {
|
||||||
fn show(&self, selected: bool, _: &ViewportContext<ListCursor>, _: &mut ProgramStore) -> Text {
|
fn show(&self, selected: bool, _: &ViewportContext<ListCursor>, _: &mut ProgramStore) -> Text {
|
||||||
selected_text(self.name.as_str(), selected)
|
selected_text(self.name.as_str(), selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_word(&self) -> Option<String> {
|
||||||
|
self.room.room_id().to_string().into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Promptable<ProgramContext, ProgramStore, IambInfo> for DirectItem {
|
impl Promptable<ProgramContext, ProgramStore, IambInfo> for DirectItem {
|
||||||
|
@ -490,6 +578,10 @@ impl ListItem<IambInfo> for SpaceItem {
|
||||||
fn show(&self, selected: bool, _: &ViewportContext<ListCursor>, _: &mut ProgramStore) -> Text {
|
fn show(&self, selected: bool, _: &ViewportContext<ListCursor>, _: &mut ProgramStore) -> Text {
|
||||||
selected_text(self.name.as_str(), selected)
|
selected_text(self.name.as_str(), selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_word(&self) -> Option<String> {
|
||||||
|
self.room.room_id().to_string().into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Promptable<ProgramContext, ProgramStore, IambInfo> for SpaceItem {
|
impl Promptable<ProgramContext, ProgramStore, IambInfo> for SpaceItem {
|
||||||
|
@ -667,6 +759,10 @@ impl ListItem<IambInfo> for VerifyItem {
|
||||||
|
|
||||||
Text { lines }
|
Text { lines }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_word(&self) -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Promptable<ProgramContext, ProgramStore, IambInfo> for VerifyItem {
|
impl Promptable<ProgramContext, ProgramStore, IambInfo> for VerifyItem {
|
||||||
|
@ -694,3 +790,77 @@ impl Promptable<ProgramContext, ProgramStore, IambInfo> for VerifyItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct MemberItem {
|
||||||
|
member: RoomMember,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MemberItem {
|
||||||
|
fn new(member: RoomMember) -> Self {
|
||||||
|
Self { member }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for MemberItem {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
self.member.user_id().to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListItem<IambInfo> for MemberItem {
|
||||||
|
fn show(&self, selected: bool, _: &ViewportContext<ListCursor>, _: &mut ProgramStore) -> Text {
|
||||||
|
let mut style = user_style(self.member.user_id().as_str());
|
||||||
|
|
||||||
|
if selected {
|
||||||
|
style = style.add_modifier(StyleModifier::REVERSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
let user = Span::styled(self.to_string(), style);
|
||||||
|
|
||||||
|
let state = match self.member.membership() {
|
||||||
|
MembershipState::Ban => Span::raw(" (banned)").into(),
|
||||||
|
MembershipState::Invite => Span::raw(" (invited)").into(),
|
||||||
|
MembershipState::Knock => Span::raw(" (wants to join)").into(),
|
||||||
|
MembershipState::Leave => Span::raw(" (left)").into(),
|
||||||
|
MembershipState::Join => None,
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(state) = state {
|
||||||
|
Spans(vec![user, state]).into()
|
||||||
|
} else {
|
||||||
|
user.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_word(&self) -> Option<String> {
|
||||||
|
self.member.user_id().to_string().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Promptable<ProgramContext, ProgramStore, IambInfo> for MemberItem {
|
||||||
|
fn prompt(
|
||||||
|
&mut self,
|
||||||
|
act: &PromptAction,
|
||||||
|
_: &ProgramContext,
|
||||||
|
_: &mut ProgramStore,
|
||||||
|
) -> EditResult<Vec<(ProgramAction, ProgramContext)>, IambInfo> {
|
||||||
|
match act {
|
||||||
|
PromptAction::Submit => Ok(vec![]),
|
||||||
|
PromptAction::Abort(_) => {
|
||||||
|
let msg = "Cannot abort entry inside a list";
|
||||||
|
let err = EditError::Failure(msg.into());
|
||||||
|
|
||||||
|
Err(err)
|
||||||
|
},
|
||||||
|
PromptAction::Recall(_, _) => {
|
||||||
|
let msg = "Cannot recall history inside a list";
|
||||||
|
let err = EditError::Failure(msg.into());
|
||||||
|
|
||||||
|
Err(err)
|
||||||
|
},
|
||||||
|
_ => Err(EditError::Unimplemented("unknown prompt action".to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -94,10 +94,6 @@ impl ChatState {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches!(act, EditorAction::History(_)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !store.application.settings.tunables.typing_notice {
|
if !store.application.settings.tunables.typing_notice {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use modalkit::tui::{buffer::Buffer, layout::Rect, widgets::StatefulWidget};
|
||||||
|
|
||||||
use modalkit::{
|
use modalkit::{
|
||||||
editing::action::{
|
editing::action::{
|
||||||
|
Action,
|
||||||
EditInfo,
|
EditInfo,
|
||||||
EditResult,
|
EditResult,
|
||||||
Editable,
|
Editable,
|
||||||
|
@ -15,11 +16,29 @@ use modalkit::{
|
||||||
Promptable,
|
Promptable,
|
||||||
Scrollable,
|
Scrollable,
|
||||||
},
|
},
|
||||||
editing::base::{CloseFlags, MoveDir1D, PositionList, ScrollStyle, WordStyle},
|
editing::base::{
|
||||||
|
Axis,
|
||||||
|
CloseFlags,
|
||||||
|
Count,
|
||||||
|
MoveDir1D,
|
||||||
|
OpenTarget,
|
||||||
|
PositionList,
|
||||||
|
ScrollStyle,
|
||||||
|
WordStyle,
|
||||||
|
},
|
||||||
|
input::InputContext,
|
||||||
widgets::{TermOffset, TerminalCursor, WindowOps},
|
widgets::{TermOffset, TerminalCursor, WindowOps},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::base::{IambInfo, IambResult, ProgramAction, ProgramContext, ProgramStore};
|
use crate::base::{
|
||||||
|
IambId,
|
||||||
|
IambInfo,
|
||||||
|
IambResult,
|
||||||
|
ProgramAction,
|
||||||
|
ProgramContext,
|
||||||
|
ProgramStore,
|
||||||
|
RoomAction,
|
||||||
|
};
|
||||||
|
|
||||||
use self::chat::ChatState;
|
use self::chat::ChatState;
|
||||||
use self::space::{Space, SpaceState};
|
use self::space::{Space, SpaceState};
|
||||||
|
@ -67,14 +86,28 @@ impl RoomState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn room_command(
|
||||||
|
&mut self,
|
||||||
|
act: RoomAction,
|
||||||
|
_: ProgramContext,
|
||||||
|
_: &mut ProgramStore,
|
||||||
|
) -> IambResult<Vec<(Action<IambInfo>, ProgramContext)>> {
|
||||||
|
match act {
|
||||||
|
RoomAction::Members(mut cmd) => {
|
||||||
|
let width = Count::Exact(30);
|
||||||
|
let act =
|
||||||
|
cmd.default_axis(Axis::Vertical).default_relation(MoveDir1D::Next).window(
|
||||||
|
OpenTarget::Application(IambId::MemberList(self.id().to_owned())),
|
||||||
|
width.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(vec![(act, cmd.context.take())])
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_title(&self, store: &mut ProgramStore) -> String {
|
pub fn get_title(&self, store: &mut ProgramStore) -> String {
|
||||||
store
|
store.application.get_room_title(self.id())
|
||||||
.application
|
|
||||||
.rooms
|
|
||||||
.get(self.id())
|
|
||||||
.and_then(|i| i.name.as_ref())
|
|
||||||
.map(String::from)
|
|
||||||
.unwrap_or_else(|| "Untitled Matrix Room".to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn focus_toggle(&mut self) {
|
pub fn focus_toggle(&mut self) {
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
## Useful Keybindings
|
## Useful Keybindings
|
||||||
|
|
||||||
- `<Enter>` will send a typed message
|
- `<Enter>` will send a typed message
|
||||||
|
- `^V^J` can be used in Insert mode to enter a newline without submitting
|
||||||
- `O`/`o` can be used to insert blank lines before and after the cursor line
|
- `O`/`o` can be used to insert blank lines before and after the cursor line
|
||||||
- `^O` can be used in Insert mode to enter a single Normal mode keybinding sequence
|
|
||||||
- `^Wm` can be used to toggle whether the message bar or scrollback is selected
|
- `^Wm` can be used to toggle whether the message bar or scrollback is selected
|
||||||
- `^Wz` can be used to toggle whether the current window takes up the full screen
|
- `^Wz` can be used to toggle whether the current window takes up the full screen
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
- `:dms` will open a list of direct messages
|
- `:dms` will open a list of direct messages
|
||||||
- `:rooms` will open a list of joined rooms
|
- `:rooms` will open a list of joined rooms
|
||||||
|
- `:members` will open a list of members for the currently focused room or space
|
||||||
- `:spaces` will open a list of joined spaces
|
- `:spaces` will open a list of joined spaces
|
||||||
- `:join` can be used to switch to join a new room or start a direct message
|
- `:join` can be used to switch to join a new room or start a direct message
|
||||||
- `:split` and `:vsplit` can be used to open rooms in a new window
|
- `:split` and `:vsplit` can be used to open rooms in a new window
|
||||||
|
|
|
@ -15,7 +15,7 @@ use matrix_sdk::{
|
||||||
encryption::verification::{SasVerification, Verification},
|
encryption::verification::{SasVerification, Verification},
|
||||||
event_handler::Ctx,
|
event_handler::Ctx,
|
||||||
reqwest,
|
reqwest,
|
||||||
room::{Messages, MessagesOptions, Room as MatrixRoom},
|
room::{Messages, MessagesOptions, Room as MatrixRoom, RoomMember},
|
||||||
ruma::{
|
ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
room::create_room::v3::{Request as CreateRoomRequest, RoomPreset},
|
room::create_room::v3::{Request as CreateRoomRequest, RoomPreset},
|
||||||
|
@ -102,6 +102,7 @@ pub enum WorkerTask {
|
||||||
GetRoom(OwnedRoomId, ClientReply<IambResult<(MatrixRoom, DisplayName)>>),
|
GetRoom(OwnedRoomId, ClientReply<IambResult<(MatrixRoom, DisplayName)>>),
|
||||||
JoinRoom(String, ClientReply<IambResult<OwnedRoomId>>),
|
JoinRoom(String, ClientReply<IambResult<OwnedRoomId>>),
|
||||||
JoinedRooms(ClientReply<Vec<(MatrixRoom, DisplayName)>>),
|
JoinedRooms(ClientReply<Vec<(MatrixRoom, DisplayName)>>),
|
||||||
|
Members(OwnedRoomId, ClientReply<IambResult<Vec<RoomMember>>>),
|
||||||
SpaceMembers(OwnedRoomId, ClientReply<IambResult<Vec<OwnedRoomId>>>),
|
SpaceMembers(OwnedRoomId, ClientReply<IambResult<Vec<OwnedRoomId>>>),
|
||||||
Spaces(ClientReply<Vec<(MatrixRoom, DisplayName)>>),
|
Spaces(ClientReply<Vec<(MatrixRoom, DisplayName)>>),
|
||||||
SendMessage(OwnedRoomId, String, ClientReply<IambResult<EchoPair>>),
|
SendMessage(OwnedRoomId, String, ClientReply<IambResult<EchoPair>>),
|
||||||
|
@ -187,6 +188,14 @@ impl Requester {
|
||||||
return response.recv();
|
return response.recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn members(&self, room_id: OwnedRoomId) -> IambResult<Vec<RoomMember>> {
|
||||||
|
let (reply, response) = oneshot();
|
||||||
|
|
||||||
|
self.tx.send(WorkerTask::Members(room_id, reply)).unwrap();
|
||||||
|
|
||||||
|
return response.recv();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn space_members(&self, space: OwnedRoomId) -> IambResult<Vec<OwnedRoomId>> {
|
pub fn space_members(&self, space: OwnedRoomId) -> IambResult<Vec<OwnedRoomId>> {
|
||||||
let (reply, response) = oneshot();
|
let (reply, response) = oneshot();
|
||||||
|
|
||||||
|
@ -327,6 +336,10 @@ impl ClientWorker {
|
||||||
assert!(self.initialized);
|
assert!(self.initialized);
|
||||||
reply.send(self.login_and_sync(style).await);
|
reply.send(self.login_and_sync(style).await);
|
||||||
},
|
},
|
||||||
|
WorkerTask::Members(room_id, reply) => {
|
||||||
|
assert!(self.initialized);
|
||||||
|
reply.send(self.members(room_id).await);
|
||||||
|
},
|
||||||
WorkerTask::SpaceMembers(space, reply) => {
|
WorkerTask::SpaceMembers(space, reply) => {
|
||||||
assert!(self.initialized);
|
assert!(self.initialized);
|
||||||
reply.send(self.space_members(space).await);
|
reply.send(self.space_members(space).await);
|
||||||
|
@ -744,6 +757,14 @@ impl ClientWorker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn members(&mut self, room_id: OwnedRoomId) -> IambResult<Vec<RoomMember>> {
|
||||||
|
if let Some(room) = self.client.get_room(room_id.as_ref()) {
|
||||||
|
Ok(room.active_members().await.map_err(IambError::from)?)
|
||||||
|
} else {
|
||||||
|
Err(IambError::UnknownRoom(room_id).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn space_members(&mut self, space: OwnedRoomId) -> IambResult<Vec<OwnedRoomId>> {
|
async fn space_members(&mut self, space: OwnedRoomId) -> IambResult<Vec<OwnedRoomId>> {
|
||||||
let mut req = SpaceHierarchyRequest::new(&space);
|
let mut req = SpaceHierarchyRequest::new(&space);
|
||||||
req.limit = Some(1000u32.into());
|
req.limit = Some(1000u32.into());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue