mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 05:39:52 -07:00
Display room tags in list of direct messages (#21)
This commit is contained in:
parent
a6888bbc93
commit
d8713141f2
2 changed files with 115 additions and 76 deletions
|
@ -124,6 +124,57 @@ fn room_cmp(a: &MatrixRoom, b: &MatrixRoom) -> Ordering {
|
||||||
ord.then_with(|| a.room_id().cmp(b.room_id()))
|
ord.then_with(|| a.room_id().cmp(b.room_id()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tag_cmp(a: &Option<Tags>, b: &Option<Tags>) -> Ordering {
|
||||||
|
let (fava, lowa) = a
|
||||||
|
.as_ref()
|
||||||
|
.map(|tags| {
|
||||||
|
(tags.contains_key(&TagName::Favorite), tags.contains_key(&TagName::LowPriority))
|
||||||
|
})
|
||||||
|
.unwrap_or((false, false));
|
||||||
|
|
||||||
|
let (favb, lowb) = b
|
||||||
|
.as_ref()
|
||||||
|
.map(|tags| {
|
||||||
|
(tags.contains_key(&TagName::Favorite), tags.contains_key(&TagName::LowPriority))
|
||||||
|
})
|
||||||
|
.unwrap_or((false, false));
|
||||||
|
|
||||||
|
// If a has Favorite and b doesn't, it should sort earlier in room list.
|
||||||
|
let cmpf = favb.cmp(&fava);
|
||||||
|
|
||||||
|
// If a has LowPriority and b doesn't, it should sort later in room list.
|
||||||
|
let cmpl = lowa.cmp(&lowb);
|
||||||
|
|
||||||
|
cmpl.then(cmpf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn append_tags<'a>(tags: &'a Tags, spans: &mut Vec<Span<'a>>, style: Style) {
|
||||||
|
if tags.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spans.push(Span::styled(" (", style));
|
||||||
|
|
||||||
|
for (i, tag) in tags.keys().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
spans.push(Span::styled(", ", style));
|
||||||
|
}
|
||||||
|
|
||||||
|
match tag {
|
||||||
|
TagName::Favorite => spans.push(Span::styled("Favorite", style)),
|
||||||
|
TagName::LowPriority => spans.push(Span::styled("Low Priority", style)),
|
||||||
|
TagName::ServerNotice => spans.push(Span::styled("Server Notice", style)),
|
||||||
|
TagName::User(tag) => {
|
||||||
|
spans.push(Span::styled("User Tag: ", style));
|
||||||
|
spans.push(Span::styled(tag.as_ref(), style));
|
||||||
|
},
|
||||||
|
tag => spans.push(Span::styled(format!("{:?}", tag), style)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spans.push(Span::styled(")", style));
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn room_prompt(
|
fn room_prompt(
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
|
@ -326,8 +377,13 @@ impl WindowOps<IambInfo> for IambWindow {
|
||||||
IambWindow::Room(state) => state.draw(area, buf, focused, store),
|
IambWindow::Room(state) => state.draw(area, buf, focused, store),
|
||||||
IambWindow::DirectList(state) => {
|
IambWindow::DirectList(state) => {
|
||||||
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 mut items = dms
|
||||||
state.set(items.collect());
|
.into_iter()
|
||||||
|
.map(|(id, name, tags)| DirectItem::new(id, name, tags, store))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
items.sort();
|
||||||
|
|
||||||
|
state.set(items);
|
||||||
|
|
||||||
List::new(store)
|
List::new(store)
|
||||||
.empty_message("No direct messages yet!")
|
.empty_message("No direct messages yet!")
|
||||||
|
@ -583,29 +639,7 @@ impl Eq for RoomItem {}
|
||||||
|
|
||||||
impl Ord for RoomItem {
|
impl Ord for RoomItem {
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
let (fava, lowa) = self
|
tag_cmp(&self.tags, &other.tags).then_with(|| room_cmp(&self.room, &other.room))
|
||||||
.tags
|
|
||||||
.as_ref()
|
|
||||||
.map(|tags| {
|
|
||||||
(tags.contains_key(&TagName::Favorite), tags.contains_key(&TagName::LowPriority))
|
|
||||||
})
|
|
||||||
.unwrap_or((false, false));
|
|
||||||
|
|
||||||
let (favb, lowb) = other
|
|
||||||
.tags
|
|
||||||
.as_ref()
|
|
||||||
.map(|tags| {
|
|
||||||
(tags.contains_key(&TagName::Favorite), tags.contains_key(&TagName::LowPriority))
|
|
||||||
})
|
|
||||||
.unwrap_or((false, false));
|
|
||||||
|
|
||||||
// If self has Favorite and other doesn't, it should sort earlier in room list.
|
|
||||||
let cmpf = favb.cmp(&fava);
|
|
||||||
|
|
||||||
// If self has LowPriority and other doesn't, it should sort later in room list.
|
|
||||||
let cmpl = lowa.cmp(&lowb);
|
|
||||||
|
|
||||||
cmpl.then(cmpf).then_with(|| room_cmp(&self.room, &other.room))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,30 +661,7 @@ impl ListItem<IambInfo> for RoomItem {
|
||||||
let style = selected_style(selected);
|
let style = selected_style(selected);
|
||||||
let mut spans = vec![Span::styled(self.name.as_str(), style)];
|
let mut spans = vec![Span::styled(self.name.as_str(), style)];
|
||||||
|
|
||||||
if tags.is_empty() {
|
append_tags(tags, &mut spans, style);
|
||||||
return Text::from(Spans(spans));
|
|
||||||
}
|
|
||||||
|
|
||||||
spans.push(Span::styled(" (", style));
|
|
||||||
|
|
||||||
for (i, tag) in tags.keys().enumerate() {
|
|
||||||
if i > 0 {
|
|
||||||
spans.push(Span::styled(", ", style));
|
|
||||||
}
|
|
||||||
|
|
||||||
match tag {
|
|
||||||
TagName::Favorite => spans.push(Span::styled("Favorite", style)),
|
|
||||||
TagName::LowPriority => spans.push(Span::styled("Low Priority", style)),
|
|
||||||
TagName::ServerNotice => spans.push(Span::styled("Server Notice", style)),
|
|
||||||
TagName::User(tag) => {
|
|
||||||
spans.push(Span::styled("User Tag: ", style));
|
|
||||||
spans.push(Span::styled(tag.as_ref(), style));
|
|
||||||
},
|
|
||||||
tag => spans.push(Span::styled(format!("{:?}", tag), style)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spans.push(Span::styled(")", style));
|
|
||||||
|
|
||||||
Text::from(Spans(spans))
|
Text::from(Spans(spans))
|
||||||
} else {
|
} else {
|
||||||
|
@ -677,16 +688,22 @@ impl Promptable<ProgramContext, ProgramStore, IambInfo> for RoomItem {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DirectItem {
|
pub struct DirectItem {
|
||||||
room: MatrixRoom,
|
room: MatrixRoom,
|
||||||
|
tags: Option<Tags>,
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DirectItem {
|
impl DirectItem {
|
||||||
fn new(room: MatrixRoom, name: DisplayName, store: &mut ProgramStore) -> Self {
|
fn new(
|
||||||
|
room: MatrixRoom,
|
||||||
|
name: DisplayName,
|
||||||
|
tags: Option<Tags>,
|
||||||
|
store: &mut ProgramStore,
|
||||||
|
) -> Self {
|
||||||
let name = name.to_string();
|
let name = name.to_string();
|
||||||
|
|
||||||
store.application.set_room_name(room.room_id(), name.as_str());
|
store.application.set_room_name(room.room_id(), name.as_str());
|
||||||
|
|
||||||
DirectItem { room, name }
|
DirectItem { room, tags, name }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,14 +715,43 @@ impl ToString for DirectItem {
|
||||||
|
|
||||||
impl ListItem<IambInfo> for DirectItem {
|
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 {
|
||||||
|
if let Some(tags) = &self.tags {
|
||||||
|
let style = selected_style(selected);
|
||||||
|
let mut spans = vec![Span::styled(self.name.as_str(), style)];
|
||||||
|
|
||||||
|
append_tags(tags, &mut spans, style);
|
||||||
|
|
||||||
|
Text::from(Spans(spans))
|
||||||
|
} else {
|
||||||
selected_text(self.name.as_str(), selected)
|
selected_text(self.name.as_str(), selected)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_word(&self) -> Option<String> {
|
fn get_word(&self) -> Option<String> {
|
||||||
self.room.room_id().to_string().into()
|
self.room.room_id().to_string().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for DirectItem {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.room.room_id() == other.room.room_id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for DirectItem {}
|
||||||
|
|
||||||
|
impl Ord for DirectItem {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
tag_cmp(&self.tags, &other.tags).then_with(|| room_cmp(&self.room, &other.room))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for DirectItem {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
self.cmp(other).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Promptable<ProgramContext, ProgramStore, IambInfo> for DirectItem {
|
impl Promptable<ProgramContext, ProgramStore, IambInfo> for DirectItem {
|
||||||
fn prompt(
|
fn prompt(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -99,14 +99,16 @@ fn oneshot<T>() -> (ClientReply<T>, ClientResponse<T>) {
|
||||||
return (reply, response);
|
return (reply, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type FetchedRoom = (MatrixRoom, DisplayName, Option<Tags>);
|
||||||
|
|
||||||
pub enum WorkerTask {
|
pub enum WorkerTask {
|
||||||
ActiveRooms(ClientReply<Vec<(MatrixRoom, DisplayName, Option<Tags>)>>),
|
ActiveRooms(ClientReply<Vec<FetchedRoom>>),
|
||||||
DirectMessages(ClientReply<Vec<(MatrixRoom, DisplayName)>>),
|
DirectMessages(ClientReply<Vec<FetchedRoom>>),
|
||||||
Init(AsyncProgramStore, ClientReply<()>),
|
Init(AsyncProgramStore, ClientReply<()>),
|
||||||
LoadOlder(OwnedRoomId, Option<String>, u32, ClientReply<MessageFetchResult>),
|
LoadOlder(OwnedRoomId, Option<String>, u32, ClientReply<MessageFetchResult>),
|
||||||
Login(LoginStyle, ClientReply<IambResult<EditInfo>>),
|
Login(LoginStyle, ClientReply<IambResult<EditInfo>>),
|
||||||
GetInviter(Invited, ClientReply<IambResult<Option<RoomMember>>>),
|
GetInviter(Invited, ClientReply<IambResult<Option<RoomMember>>>),
|
||||||
GetRoom(OwnedRoomId, ClientReply<IambResult<(MatrixRoom, DisplayName, Option<Tags>)>>),
|
GetRoom(OwnedRoomId, ClientReply<IambResult<FetchedRoom>>),
|
||||||
JoinRoom(String, ClientReply<IambResult<OwnedRoomId>>),
|
JoinRoom(String, ClientReply<IambResult<OwnedRoomId>>),
|
||||||
Members(OwnedRoomId, ClientReply<IambResult<Vec<RoomMember>>>),
|
Members(OwnedRoomId, ClientReply<IambResult<Vec<RoomMember>>>),
|
||||||
SpaceMembers(OwnedRoomId, ClientReply<IambResult<Vec<OwnedRoomId>>>),
|
SpaceMembers(OwnedRoomId, ClientReply<IambResult<Vec<OwnedRoomId>>>),
|
||||||
|
@ -235,7 +237,7 @@ impl Requester {
|
||||||
return response.recv();
|
return response.recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn direct_messages(&self) -> Vec<(MatrixRoom, DisplayName)> {
|
pub fn direct_messages(&self) -> Vec<FetchedRoom> {
|
||||||
let (reply, response) = oneshot();
|
let (reply, response) = oneshot();
|
||||||
|
|
||||||
self.tx.send(WorkerTask::DirectMessages(reply)).unwrap();
|
self.tx.send(WorkerTask::DirectMessages(reply)).unwrap();
|
||||||
|
@ -251,10 +253,7 @@ impl Requester {
|
||||||
return response.recv();
|
return response.recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_room(
|
pub fn get_room(&self, room_id: OwnedRoomId) -> IambResult<FetchedRoom> {
|
||||||
&self,
|
|
||||||
room_id: OwnedRoomId,
|
|
||||||
) -> IambResult<(MatrixRoom, DisplayName, Option<Tags>)> {
|
|
||||||
let (reply, response) = oneshot();
|
let (reply, response) = oneshot();
|
||||||
|
|
||||||
self.tx.send(WorkerTask::GetRoom(room_id, reply)).unwrap();
|
self.tx.send(WorkerTask::GetRoom(room_id, reply)).unwrap();
|
||||||
|
@ -270,7 +269,7 @@ impl Requester {
|
||||||
return response.recv();
|
return response.recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn active_rooms(&self) -> Vec<(MatrixRoom, DisplayName, Option<Tags>)> {
|
pub fn active_rooms(&self) -> Vec<FetchedRoom> {
|
||||||
let (reply, response) = oneshot();
|
let (reply, response) = oneshot();
|
||||||
|
|
||||||
self.tx.send(WorkerTask::ActiveRooms(reply)).unwrap();
|
self.tx.send(WorkerTask::ActiveRooms(reply)).unwrap();
|
||||||
|
@ -704,14 +703,9 @@ impl ClientWorker {
|
||||||
Ok(Some(InfoMessage::from("Successfully logged in!")))
|
Ok(Some(InfoMessage::from("Successfully logged in!")))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn direct_message(
|
async fn direct_message(&mut self, user: OwnedUserId) -> IambResult<FetchedRoom> {
|
||||||
&mut self,
|
for (room, name, tags) in self.direct_messages().await {
|
||||||
user: OwnedUserId,
|
|
||||||
) -> IambResult<(MatrixRoom, DisplayName, Option<Tags>)> {
|
|
||||||
for (room, name) in self.direct_messages().await {
|
|
||||||
if room.get_member(user.as_ref()).await.map_err(IambError::from)?.is_some() {
|
if room.get_member(user.as_ref()).await.map_err(IambError::from)?.is_some() {
|
||||||
let tags = room.tags().await.map_err(IambError::from)?;
|
|
||||||
|
|
||||||
return Ok((room, name, tags));
|
return Ok((room, name, tags));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -746,10 +740,7 @@ impl ClientWorker {
|
||||||
Ok(details.inviter)
|
Ok(details.inviter)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_room(
|
async fn get_room(&mut self, room_id: OwnedRoomId) -> IambResult<FetchedRoom> {
|
||||||
&mut self,
|
|
||||||
room_id: OwnedRoomId,
|
|
||||||
) -> IambResult<(MatrixRoom, DisplayName, Option<Tags>)> {
|
|
||||||
if let Some(room) = self.client.get_room(&room_id) {
|
if let Some(room) = self.client.get_room(&room_id) {
|
||||||
let name = room.display_name().await.map_err(IambError::from)?;
|
let name = room.display_name().await.map_err(IambError::from)?;
|
||||||
let tags = room.tags().await.map_err(IambError::from)?;
|
let tags = room.tags().await.map_err(IambError::from)?;
|
||||||
|
@ -783,7 +774,7 @@ impl ClientWorker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn direct_messages(&self) -> Vec<(MatrixRoom, DisplayName)> {
|
async fn direct_messages(&self) -> Vec<FetchedRoom> {
|
||||||
let mut rooms = vec![];
|
let mut rooms = vec![];
|
||||||
|
|
||||||
for room in self.client.invited_rooms().into_iter() {
|
for room in self.client.invited_rooms().into_iter() {
|
||||||
|
@ -792,8 +783,9 @@ impl ClientWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = room.display_name().await.unwrap_or(DisplayName::Empty);
|
let name = room.display_name().await.unwrap_or(DisplayName::Empty);
|
||||||
|
let tags = room.tags().await.unwrap_or_default();
|
||||||
|
|
||||||
rooms.push((room.into(), name));
|
rooms.push((room.into(), name, tags));
|
||||||
}
|
}
|
||||||
|
|
||||||
for room in self.client.joined_rooms().into_iter() {
|
for room in self.client.joined_rooms().into_iter() {
|
||||||
|
@ -802,14 +794,15 @@ impl ClientWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = room.display_name().await.unwrap_or(DisplayName::Empty);
|
let name = room.display_name().await.unwrap_or(DisplayName::Empty);
|
||||||
|
let tags = room.tags().await.unwrap_or_default();
|
||||||
|
|
||||||
rooms.push((room.into(), name));
|
rooms.push((room.into(), name, tags));
|
||||||
}
|
}
|
||||||
|
|
||||||
return rooms;
|
return rooms;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn active_rooms(&self) -> Vec<(MatrixRoom, DisplayName, Option<Tags>)> {
|
async fn active_rooms(&self) -> Vec<FetchedRoom> {
|
||||||
let mut rooms = vec![];
|
let mut rooms = vec![];
|
||||||
|
|
||||||
for room in self.client.invited_rooms().into_iter() {
|
for room in self.client.invited_rooms().into_iter() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue