aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@bunny.garden>2025-04-11 15:10:25 +0100
committerLibravatar cel 🌸 <cel@bunny.garden>2025-04-11 15:10:25 +0100
commit80524e515406007915cb9978f403407a98c44e1e (patch)
tree895e7b8be01f6f13270c9f0604083df4be38b958 /src
parent4deb7470413a9d53323f6bedf26882ad2b0844a6 (diff)
downloadmacaw-80524e515406007915cb9978f403407a98c44e1e.tar.gz
macaw-80524e515406007915cb9978f403407a98c44e1e.tar.bz2
macaw-80524e515406007915cb9978f403407a98c44e1e.zip
feat: icons
Diffstat (limited to '')
-rw-r--r--src/icons.rs127
-rw-r--r--src/main.rs87
-rw-r--r--src/message_view.rs4
3 files changed, 178 insertions, 40 deletions
diff --git a/src/icons.rs b/src/icons.rs
new file mode 100644
index 0000000..934a0c8
--- /dev/null
+++ b/src/icons.rs
@@ -0,0 +1,127 @@
+use iced::widget::svg;
+use iced::widget::{svg::Handle, Svg};
+use iced::Element;
+
+pub enum Icon {
+ AddContact24,
+ Attachment24,
+ Away16,
+ Away16Color,
+ Bubble16,
+ Bubble16Color,
+ Bubble24,
+ Contact24,
+ Delivered16,
+ Dnd16,
+ Dnd16Color,
+ Error16Color,
+ Forward24,
+ Heart24,
+ NewBubble24,
+ Reply24,
+ Sending16,
+ Sent16,
+}
+
+impl From<Icon> for Svg<'_> {
+ fn from(value: Icon) -> Self {
+ match value {
+ Icon::AddContact24 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/addcontact24.svg"
+ )))
+ .width(24)
+ .height(24),
+ Icon::Attachment24 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/attachment24.svg"
+ )))
+ .width(24)
+ .height(24),
+ Icon::Away16 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/away16.svg"
+ )))
+ .width(16)
+ .height(16),
+ Icon::Away16Color => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/away16color.svg"
+ )))
+ .width(16)
+ .height(16),
+ Icon::Bubble16 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/bubble16.svg"
+ )))
+ .width(16)
+ .height(16),
+ Icon::Bubble16Color => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/bubble16color.svg"
+ )))
+ .width(16)
+ .height(16),
+ Icon::Bubble24 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/bubble24.svg"
+ )))
+ .width(24)
+ .height(24),
+ Icon::Contact24 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/contact24.svg"
+ )))
+ .width(24)
+ .height(24),
+ Icon::Delivered16 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/delivered16.svg"
+ )))
+ .width(16)
+ .height(16),
+ Icon::Dnd16 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/dnd16.svg"
+ )))
+ .width(16)
+ .height(16),
+ Icon::Dnd16Color => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/dnd16color.svg"
+ )))
+ .width(16)
+ .height(16),
+ Icon::Error16Color => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/error16color.svg"
+ )))
+ .width(16)
+ .height(16),
+ Icon::Forward24 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/forward24.svg"
+ )))
+ .width(24)
+ .height(24),
+ Icon::Heart24 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/heart24.svg"
+ )))
+ .width(24)
+ .height(24),
+ Icon::NewBubble24 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/newbubble24.svg"
+ )))
+ .width(24)
+ .height(24),
+ Icon::Reply24 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/reply24.svg"
+ )))
+ .width(24)
+ .height(24),
+ Icon::Sending16 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/sending16.svg"
+ )))
+ .width(16)
+ .height(16),
+ Icon::Sent16 => svg(Handle::from_memory(include_bytes!(
+ "../assets/icons/sent16.svg"
+ )))
+ .width(16)
+ .height(16),
+ }
+ }
+}
+
+impl<Message> From<Icon> for Element<'_, Message> {
+ fn from(value: Icon) -> Self {
+ Into::<Svg>::into(value).into()
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 0b8b3b8..106df79 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -23,10 +23,11 @@ use iced::widget::button::Status;
use iced::widget::text::{Fragment, IntoFragment, Wrapping};
use iced::widget::{
button, center, checkbox, column, container, horizontal_space, image, mouse_area, opaque, row,
- scrollable, stack, text, text_input, toggler, Column, Text, Toggler,
+ scrollable, stack, text, text_input, toggler, Column, Svg, Text, Toggler,
};
use iced::Length::{self, Fill, Shrink};
use iced::{color, stream, Color, Element, Subscription, Task, Theme};
+use icons::Icon;
use indexmap::{indexmap, IndexMap};
use jid::JID;
use keyring::Entry;
@@ -37,9 +38,10 @@ use thiserror::Error;
use tokio::sync::mpsc::Sender;
use tokio::sync::{mpsc, oneshot};
use tokio_stream::wrappers::ReceiverStream;
-use tracing::{error, info};
+use tracing::{debug, error, info};
use uuid::Uuid;
+mod icons;
mod login_modal;
mod message_view;
@@ -488,6 +490,7 @@ async fn main() -> iced::Result {
Task::stream(stream),
])
} else {
+ debug!("no auto connect");
Task::batch([
Task::perform(
async move { luz_handle1.get_roster_with_users().await },
@@ -524,7 +527,7 @@ async fn main() -> iced::Result {
};
iced::application("Macaw", Macaw::update, Macaw::view)
.subscription(subscription)
- .theme(Macaw::theme)
+ // .theme(Macaw::theme)
.run_with(|| {
(
Macaw::new(
@@ -698,7 +701,8 @@ impl Macaw {
}
UpdateMessage::Presence { from, presence } => {
// TODO: presence handling
- self.presences.insert(from, presence);
+ info!("got presence from {:?} {:?}", from, presence);
+ self.presences.insert(from.as_bare(), presence);
Task::none()
}
UpdateMessage::Message { to, message, from } => {
@@ -886,7 +890,7 @@ impl Macaw {
client.connection_state = ConnectionState::Connecting;
let client = client.client.clone();
Task::future(async move {
- client.connect().await;
+ client.connect().await.unwrap();
})
.discard()
}
@@ -896,7 +900,7 @@ impl Macaw {
Account::LoggedIn(client) => {
let client = client.client.clone();
Task::future(async move {
- client.disconnect(Offline::default()).await;
+ client.disconnect(Offline::default()).await.unwrap();
})
.discard()
}
@@ -1105,8 +1109,13 @@ impl Macaw {
open = true;
}
}
- let chat_list_item =
- chat_list_item(&self.roster, client.files_root(), chat, open);
+ let chat_list_item = chat_list_item(
+ &self.presences,
+ &self.roster,
+ client.files_root(),
+ chat,
+ open,
+ );
chats_list = chats_list.push(chat_list_item);
}
}
@@ -1288,6 +1297,7 @@ where
}
fn chat_list_item<'a>(
+ presences: &HashMap<JID, Presence>,
roster: &HashMap<JID, MacawContact>,
file_root: &'a Path,
chat_list_item: &'a ChatListItem,
@@ -1339,36 +1349,37 @@ fn chat_list_item<'a>(
latest_message_text = None;
}
- let avatar_image = if let Some(avatar) = avatar {
+ let mut avatar_stack = stack([]);
+ if let Some(avatar) = avatar {
let mut path = file_root.join(avatar);
path.set_extension("jpg");
info!("got avatar: {:?}", path);
- Some(image(path).width(48).height(48))
- } else {
- None
- };
- let content: Element<Message> = if let Some(avatar_image) = avatar_image {
- if let Some((message, time)) = latest_message_text {
- row![
- avatar_image,
- column![
- text(name),
- row![
- container(text(message).wrapping(Wrapping::None))
- .clip(true)
- .width(Fill),
- text(time)
- ]
- .spacing(8)
- .width(Fill)
- ]
- ]
- .into()
- } else {
- row![avatar_image, text(name)].into()
+ avatar_stack = avatar_stack.push(image(path).width(48).height(48));
+ }
+ let mut status_icon: Option<Icon> = None;
+ if let Some(presence) = presences.get(&chat_list_item.user.jid) {
+ debug!("found a presence");
+ match &presence.presence {
+ PresenceType::Online(online) => match online.show {
+ Some(s) => match s {
+ filamento::presence::Show::Away => status_icon = Some(Icon::Away16Color),
+ filamento::presence::Show::Chat => status_icon = Some(Icon::Bubble16Color),
+ filamento::presence::Show::DoNotDisturb => status_icon = Some(Icon::Dnd16Color),
+ filamento::presence::Show::ExtendedAway => {
+ status_icon = Some(Icon::Away16Color)
+ }
+ },
+ None => status_icon = Some(Icon::Bubble16Color),
+ },
+ PresenceType::Offline(offline) => {}
}
- } else {
- if let Some((message, time)) = latest_message_text {
+ }
+ if let Some(status_icon) = status_icon {
+ avatar_stack = avatar_stack.push(Into::<Svg>::into(status_icon));
+ }
+ let content: Element<Message> = if let Some((message, time)) = latest_message_text {
+ row![
+ avatar_stack,
column![
text(name),
row![
@@ -1380,10 +1391,10 @@ fn chat_list_item<'a>(
.spacing(8)
.width(Fill)
]
- .into()
- } else {
- text(name).into()
- }
+ ]
+ .into()
+ } else {
+ row![avatar_stack, text(name)].into()
};
let mut button =
button(content).on_press(Message::ToggleChat(chat_list_item.correspondent().clone()));
diff --git a/src/message_view.rs b/src/message_view.rs
index e936b69..fdb1a59 100644
--- a/src/message_view.rs
+++ b/src/message_view.rs
@@ -10,7 +10,7 @@ use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
-use crate::{MacawChat, MacawMessage};
+use crate::{icons::Icon, MacawChat, MacawMessage};
pub struct MessageView {
// references chats, users
@@ -152,7 +152,7 @@ impl MessageView {
.wrapping(text::Wrapping::WordOrGlyph);
let message_send_input = row![
text_editor,
- button("send").on_press(Message::SendMessage(self.new_message.text()))
+ button(Icon::NewBubble24).on_press(Message::SendMessage(self.new_message.text()))
]
.padding(8);
column![