diff --git a/shell.nix b/shell.nix index 7ded031..ad8f9ce 100644 --- a/shell.nix +++ b/shell.nix @@ -4,6 +4,8 @@ cargo clippy clang + rust-analyzer + rustPlatform.rustcSrc llvmPackages.bintools pkg-config @@ -23,30 +25,32 @@ xorg.libXi xorg.libX11 ]; + RUSTC_VERSION = pkgs.lib.readFile ./rust-toolchain; - # https://github.com/rust-lang/rust-bindgen#environment-variables LIBCLANG_PATH = pkgs.lib.makeLibraryPath [ pkgs.llvmPackages_latest.libclang.lib ]; + shellHook = '' export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin export PATH=$PATH:''${RUSTUP_HOME:-~/.rustup}/toolchains/$RUSTC_VERSION-x86_64-unknown-linux-gnu/bin/ - ''; + ''; + # Add libvmi precompiled library to rustc search path RUSTFLAGS = (builtins.map (a: ''-L ${a}/lib'') [ - # pkgs.libvmi + #pkgs.libvmi ]); # Add libvmi, glibc, clang, glib headers to bindgen search path BINDGEN_EXTRA_CLANG_ARGS = - # Includes with normal include path - (builtins.map (a: ''-I"${a}/include"'') [ - # pkgs.libvmi - # pkgs.glibc.dev - ]) - # Includes with special directory paths - ++ [ - ''-I"${pkgs.llvmPackages_latest.libclang.lib}/lib/clang/${pkgs.llvmPackages_latest.libclang.version}/include"'' - ''-I"${pkgs.glib.dev}/include/glib-2.0"'' - ''-I${pkgs.glib.out}/lib/glib-2.0/include/'' - ]; - LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath buildInputs}"; + # Includes with normal include path + (builtins.map (a: ''-I"${a}/include"'') [ + # pkgs.libvmi + # pkgs.glibc.dev + ]) + # Includes with special directory paths + ++ [ + ''-I"${pkgs.llvmPackages_latest.libclang.lib}/lib/clang/${pkgs.llvmPackages_latest.libclang.version}/include"'' + ''-I"${pkgs.glib.dev}/include/glib-2.0"'' + ''-I${pkgs.glib.out}/lib/glib-2.0/include/'' + ]; + LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath buildInputs}"; } diff --git a/src/main.rs b/src/main.rs index 89a66d0..999d626 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use std::cell::RefCell; use color_eyre::eyre::Result; use futures::StreamExt; +use iced::alignment::Horizontal; use iced::theme::Theme; use iced::widget::{column, container, mouse_area, row, scrollable, text, text_input}; use iced::{executor, Application, Background, Color, Length, Settings}; @@ -194,31 +195,75 @@ impl Application for Cri { } fn view(&self) -> iced::Element<'_, Self::Message, iced::Renderer> { - let dark_green = Color::new(0.153, 0.682, 0.377, 1.0); - let dark_grey = Color::new(0.584, 0.647, 0.651, 1.0); - let _darker_grey = Color::new(0.498, 0.549, 0.553, 1.0); + let lighter_grey = Color::new(0.93, 0.94, 0.95, 1.0); + let dark_grey = Color::new(0.58, 0.65, 0.65, 1.0); + let lighter_green = Color::new(0.94, 0.99, 0.87, 1.0); + let dark_red = Color::new(0.75, 0.22, 0.17, 1.0); - let log = scrollable(column( - self.message_log - .get(&self.active_channel) - .unwrap() - .iter() - .flat_map(|message| match message { - IrcMessage::Join { nickname } => { - Some(text(format!("* {nickname} joined the channel")).style(dark_green)) - } + let event_appearance = container::Appearance { + background: Some(Background::Color(dark_grey)), + border_radius: 8.0.into(), + text_color: Some(Color::WHITE), + ..Default::default() + }; + + let message_appearance = container::Appearance { + background: Some(Background::Color(Color::WHITE)), + border_radius: 8.0.into(), + ..Default::default() + }; + + let own_message_appearance = container::Appearance { + background: Some(Background::Color(lighter_green)), + border_radius: 8.0.into(), + ..Default::default() + }; + + let messages = self + .message_log + .get(&self.active_channel) + .unwrap() + .iter() + .flat_map(|message| -> Option> { + match message { + IrcMessage::Join { nickname } => Some( + container( + container(text(format!("{nickname} joined the channel"))) + .style(move |_: &_| event_appearance) + .padding([3, 10]), + ) + .width(Length::Fill) + .center_x() + .padding([3, 0]) + .into(), + ), IrcMessage::Part { nickname, reason } => { let reason = match reason { Some(reason) => format!(" ({reason})"), None => String::new(), }; Some( - text(format!("* {nickname} left the channel{reason}")) - .style(dark_green), + container( + container(text(format!("{nickname} left the channel{reason}"))) + .style(move |_: &_| event_appearance) + .padding([3, 10]), + ) + .width(Length::Fill) + .center_x() + .padding([3, 0]) + .into(), ) } IrcMessage::Nick { old, new } => Some( - text(format!("* {old} changed their nickname to {new}")).style(dark_green), + container( + container(text(format!("{old} changed their nickname to {new}"))) + .style(move |_: &_| event_appearance) + .padding([3, 10]), + ) + .width(Length::Fill) + .center_x() + .padding([3, 0]) + .into(), ), IrcMessage::Quit { nickname, reason } => { let reason = match reason { @@ -227,18 +272,65 @@ impl Application for Cri { }; Some( - text(format!("* {nickname} quit the server{reason}")).style(dark_green), + container( + container(text(format!("{nickname} left the server{reason}"))) + .style(move |_: &_| event_appearance) + .padding([3, 10]), + ) + .width(Length::Fill) + .center_x() + .padding([3, 0]) + .into(), ) } IrcMessage::Privmsg { nickname, message } => { - Some(text(format!("<{nickname}> {message}"))) + // TODO don't hardcode nickname lol + let is_self = nickname == "cri"; + + let mut elements = Vec::new(); + if !is_self { + elements.push(text(nickname).style(dark_red).into()) + } + elements.push(text(message).into()); + + Some( + container( + container(column(elements)) + .style(move |_: &_| { + if is_self { + own_message_appearance + } else { + message_appearance + } + }) + .padding([4, 10]), + ) + .width(Length::Fill) + .align_x(if is_self { + Horizontal::Right + } else { + Horizontal::Left + }) + .padding([4, 8]) + .into(), + ) } - }) - .map(|element| element.into()) - .collect::>(), - )) + } + }) + .map(|element| element.into()) + .collect::>(); + + let log = container( + scrollable(column(messages)) + .height(Length::Fill) + .width(Length::Fill), + ) .height(Length::Fill) - .width(Length::Fill); + .width(Length::Fill) + .style(move |_: &_| container::Appearance { + background: Some(Background::Color(lighter_grey)), + ..Default::default() + }); let message_box = text_input("your magnum opus", &self.input_value) .id(INPUT_ID.clone())