From c4f471179cb39607c1a48677ddeb6209572e6b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20RENIERS?= Date: Wed, 27 Aug 2025 19:19:49 +0200 Subject: [PATCH] added channels front-end --- front/src/buttons.rs | 47 +++++++++++++++++++++++++++ front/src/channels.rs | 42 ++++++++++++++++++++++-- front/src/main.rs | 75 ++++++++++++++++++++++++++++--------------- front/src/servers.rs | 65 +++++++++++++------------------------ 4 files changed, 159 insertions(+), 70 deletions(-) create mode 100644 front/src/buttons.rs diff --git a/front/src/buttons.rs b/front/src/buttons.rs new file mode 100644 index 0000000..585e56b --- /dev/null +++ b/front/src/buttons.rs @@ -0,0 +1,47 @@ +use iced::{ + Border, + widget::{Button, container}, +}; +use iced::{Length, Shadow}; + +use crate::servers::colors; + +use crate::Event; + +pub trait MessagingGroup { + fn get_id(&self) -> i32; + fn get_name(&self) -> &String; +} + +pub fn button<'a, MG>( + messaging_group: MG, + selected: Option, + press_variant: fn(i32) -> Event, +) -> Button<'a, Event> +where + MG: MessagingGroup + Clone + 'a, +{ + let id = messaging_group.get_id(); + Button::new( + container(iced::widget::text(messaging_group.get_name().clone()).size(20)) + .center_x(Length::Fill) + .center_y(Length::Fill), + ) + .padding(10) + .width(iced::Length::Fill) + .height(Length::Fixed(100.0)) + .style(move |_theme, _status| iced::widget::button::Style { + background: Some(iced::Background::Color(if Some(id) == selected { + colors::SELECTED_BUTTON_COLOR + } else { + colors::BUTTON_COLOR + })), + border: Border::default().rounded(10), + shadow: Shadow { + offset: iced::Vector { x: 3., y: 3. }, + ..Default::default() + }, + ..Default::default() + }) + .on_press(press_variant(id)) +} diff --git a/front/src/channels.rs b/front/src/channels.rs index 03c4286..a584031 100644 --- a/front/src/channels.rs +++ b/front/src/channels.rs @@ -1,15 +1,53 @@ +use crate::buttons::{self, MessagingGroup}; +use crate::{Event, Liscord, User}; +use iced::widget::{Button, Column}; + #[allow(dead_code)] -#[derive(Clone, Default)] +#[derive(Clone, Default, Debug)] pub struct Channel { + pub channel_id: i32, pub server_id: i32, pub channel_name: String, } impl Channel { - fn new(server_id: i32, channel_name: &str) -> Self { + fn new(channel_id: i32, server_id: i32, channel_name: &str) -> Self { Channel { + channel_id, server_id, channel_name: channel_name.to_string(), } } } + +impl MessagingGroup for Channel { + fn get_id(&self) -> i32 { + self.channel_id + } + + fn get_name(&self) -> &String { + &self.channel_name + } +} + +fn channel_button<'a>(channel: Channel, instance: &'a Liscord) -> Button<'a, Event> { + buttons::button(channel, instance.selected_channel, Event::ChannelPressed) +} + +pub fn get_channels(_user: &User, server_id: i32) -> Vec { + let friend_serv0 = Channel::new(0, server_id, "Channel 0"); + let friend_serv1 = Channel::new(1, server_id, "Channel 1"); + let friend_serv2 = Channel::new(2, server_id, "Channel 2"); + vec![friend_serv0, friend_serv1, friend_serv2] +} + +pub fn get_channels_buttons<'a>( + user: &User, + server_id: i32, + instance: &'a Liscord, +) -> Column<'a, Event> { + get_channels(user, server_id) + .into_iter() + .map(|channel| channel_button(channel, instance)) + .fold(Column::new(), |col, btn| col.push(btn)) +} diff --git a/front/src/main.rs b/front/src/main.rs index db45e2e..43e9ec4 100644 --- a/front/src/main.rs +++ b/front/src/main.rs @@ -5,11 +5,14 @@ use iced::{ widget::{Image, column, container::Style, row, text}, }; +mod buttons; mod channels; mod servers; use servers::{User, get_servers_buttons}; +use crate::channels::get_channels_buttons; + fn main() -> Result<(), iced::Error> { iced::application(Liscord::title, Liscord::update, Liscord::view) .theme(Liscord::theme) @@ -19,19 +22,22 @@ fn main() -> Result<(), iced::Error> { struct Liscord { user: Option, selected_server: Option, + selected_channel: Option, } #[derive(Debug, Clone)] enum Event { ServerPressed(i32), + ChannelPressed(i32), } impl Liscord { fn new() -> (Self, Task) { ( - Liscord { + Self { user: Some(User::default()), selected_server: None, + selected_channel: None, }, Task::none(), ) @@ -44,38 +50,37 @@ impl Liscord { fn update(&mut self, event: Event) -> Task { match event { Event::ServerPressed(server_id) => { + println!("Server pressed: {server_id}"); self.selected_server = Some(server_id); - // println!("Server Pressed ! Id: {server_id}") + self.selected_channel = None; + // could kick off async load: return Task::perform(...) + } + Event::ChannelPressed(channel_id) => { + println!("Channel pressed: {channel_id}"); + self.selected_channel = Some(channel_id); + // async tasks } } Task::none() } fn view(&self) -> Element<'_, Event> { - let app_body = { - let server_bar = { - let mut content = column![text("Servers")]; + let server_bar = { + let mut content = column![text("Servers")]; + if let Some(user) = &self.user { + content = content.push(get_servers_buttons(user, self)); + } + container(content) + .padding(10) + .width(iced::Length::Fixed(200.)) + .height(Fill) + .style(|_| Style { + background: Some(Background::Color(Color::from_rgb(0.0, 0.0, 1.0))), + ..Default::default() + }) + }; - if let Some(user) = &self.user { - content = content.push(get_servers_buttons(user, self)) - } - - container(content) - .padding(10) - .width(iced::Length::Fixed(300.)) - .height(Fill) - .style(|_theme| Style { - background: Some(Background::Color(Color::from_rgb(0.0, 0.0, 1.0))), - ..Default::default() - }) - }; - - let message_content = container(text("Messages")) - .width(iced::Length::Fill) - .height(Fill); - row![server_bar, message_content] - } - .height(FillPortion(19)); + let app_body = row![server_bar, self.inner_server_content()].height(FillPortion(19)); let app_header = { let liscord_logo = Image::new("assets/liscord.png"); @@ -84,7 +89,6 @@ impl Liscord { .width(Fill) .center_x(Length::Fill) .center_y(Length::Fill); - row![liscord_logo, centered_text].width(Fill).height(Fill) } .height(FillPortion(1)); @@ -95,4 +99,23 @@ impl Liscord { fn theme(&self) -> Theme { Theme::Dark } + + fn inner_server_content(&self) -> Element<'_, Event> { + match self.selected_server { + Some(id) => { + let channels = get_channels_buttons(&self.user.clone().unwrap(), id, self) + .width(Length::Fixed(200.)) + .padding(10) + .spacing(10); + container(channels) + .width(iced::Length::Fill) + .height(iced::Length::Fill) + .into() + } + None => container(text("Select a server")) + .width(iced::Length::Fill) + .height(iced::Length::Fill) + .into(), + } + } } diff --git a/front/src/servers.rs b/front/src/servers.rs index 6982e94..2b4a0c6 100644 --- a/front/src/servers.rs +++ b/front/src/servers.rs @@ -1,12 +1,11 @@ -use iced::{ - Border, - widget::{Button, Column, container}, +use iced::widget::{Button, Column}; + +use crate::{ + Event, Liscord, + buttons::{self, MessagingGroup}, }; -use iced::{Length, Shadow}; -use crate::{Event, Liscord}; - -mod colors { +pub mod colors { use iced::Color; pub const BUTTON_COLOR: Color = Color::from_rgb(0.2, 0.2, 0.2); @@ -14,7 +13,7 @@ mod colors { } #[allow(dead_code)] -#[derive(Default, Clone)] +#[derive(Default, Clone, Debug)] pub struct Server { pub server_id: i32, pub server_name: String, @@ -31,6 +30,16 @@ impl Server { } } +impl MessagingGroup for Server { + fn get_id(&self) -> i32 { + self.server_id + } + + fn get_name(&self) -> &String { + &self.server_name + } +} + impl PartialEq for Server { fn eq(&self, other: &Self) -> bool { self.server_id == other.server_id @@ -38,7 +47,7 @@ impl PartialEq for Server { } #[allow(dead_code)] -#[derive(Default)] +#[derive(Default, Clone)] pub struct User { pub user_id: i32, pub username: String, @@ -54,40 +63,12 @@ pub fn get_servers(_user: &User) -> Vec { } pub fn get_servers_buttons<'a>(user: &User, instance: &'a Liscord) -> Column<'a, Event> { - let servers = get_servers(user); - - let mut col = Column::new(); - - for server in servers { - col = col.push(server_button(server, instance)); - } - - col + get_servers(user) + .into_iter() + .map(|server| server_button(server, instance)) + .fold(Column::new(), |col, button| col.push(button)) } fn server_button<'a>(server: Server, instance: &'a Liscord) -> Button<'a, Event> { - Button::new( - container(iced::widget::text(server.server_name).size(20)) - .center_x(Length::Fill) - .center_y(Length::Fill), - ) - .padding(10) - .width(iced::Length::Fill) - .height(Length::Fixed(100.0)) - .style(move |_theme, _status| iced::widget::button::Style { - background: Some(iced::Background::Color( - if Some(server.server_id) == instance.selected_server { - colors::SELECTED_BUTTON_COLOR - } else { - colors::BUTTON_COLOR - }, - )), - border: Border::default().rounded(10), - shadow: Shadow { - offset: iced::Vector { x: 3., y: 3. }, - ..Default::default() - }, - ..Default::default() - }) - .on_press(Event::ServerPressed(server.server_id)) + buttons::button(server, instance.selected_server, Event::ServerPressed) }