diff --git a/assets/icons/reply-dark.png b/assets/icons/reply-dark.png deleted file mode 100644 index fabe1b05..00000000 Binary files a/assets/icons/reply-dark.png and /dev/null differ diff --git a/assets/icons/reply.png b/assets/icons/reply.png deleted file mode 100644 index d85a55e0..00000000 Binary files a/assets/icons/reply.png and /dev/null differ diff --git a/assets/icons/reply.svg b/assets/icons/reply.svg index 11076bd8..db373c3d 100644 --- a/assets/icons/reply.svg +++ b/assets/icons/reply.svg @@ -1 +1,6 @@ - + + + + + + \ No newline at end of file diff --git a/assets/icons/repost.svg b/assets/icons/repost.svg new file mode 100644 index 00000000..c48957c8 --- /dev/null +++ b/assets/icons/repost.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/repost_icon_4x.png b/assets/icons/repost_icon_4x.png deleted file mode 100644 index 6573f8f1..00000000 Binary files a/assets/icons/repost_icon_4x.png and /dev/null differ diff --git a/assets/icons/repost_light.png b/assets/icons/repost_light.png new file mode 100644 index 00000000..57efa20d Binary files /dev/null and b/assets/icons/repost_light.png differ diff --git a/assets/icons/repost_light_4x.png b/assets/icons/repost_light_4x.png deleted file mode 100644 index 67646de7..00000000 Binary files a/assets/icons/repost_light_4x.png and /dev/null differ diff --git a/assets/icons/zap.svg b/assets/icons/zap.svg new file mode 100644 index 00000000..f1983004 --- /dev/null +++ b/assets/icons/zap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/zap_4x.png b/assets/icons/zap_4x.png deleted file mode 100644 index cc231965..00000000 Binary files a/assets/icons/zap_4x.png and /dev/null differ diff --git a/crates/notedeck_ui/src/app_images.rs b/crates/notedeck_ui/src/app_images.rs index 627b8d40..4e80d508 100644 --- a/crates/notedeck_ui/src/app_images.rs +++ b/crates/notedeck_ui/src/app_images.rs @@ -1,5 +1,5 @@ use eframe::icon_data::from_png_bytes; -use egui::{include_image, IconData, Image}; +use egui::{include_image, Color32, IconData, Image}; pub fn app_icon() -> IconData { from_png_bytes(include_bytes!("../../../assets/damus-app-icon.png")).expect("icon") @@ -153,19 +153,19 @@ pub fn notifications_image() -> Image<'static> { )) } pub fn repost_dark_image() -> Image<'static> { - Image::new(include_image!("../../../assets/icons/repost_icon_4x.png")) + Image::new(include_image!("../../../assets/icons/repost.svg")) } pub fn repost_light_image() -> Image<'static> { - Image::new(include_image!("../../../assets/icons/repost_light_4x.png")) + Image::new(include_image!("../../../assets/icons/repost_light.png")) } pub fn reply_dark_image() -> Image<'static> { - Image::new(include_image!("../../../assets/icons/reply.png")) + Image::new(include_image!("../../../assets/icons/reply.svg")) } pub fn reply_light_image() -> Image<'static> { - Image::new(include_image!("../../../assets/icons/reply-dark.png")) + Image::new(include_image!("../../../assets/icons/reply.svg")).tint(Color32::BLACK) } pub fn profile_image() -> Image<'static> { @@ -203,5 +203,5 @@ pub fn wallet_image() -> Image<'static> { } pub fn zap_image() -> Image<'static> { - Image::new(include_image!("../../../assets/icons/zap_4x.png")) + Image::new(include_image!("../../../assets/icons/zap.svg")) } diff --git a/crates/notedeck_ui/src/note/mod.rs b/crates/notedeck_ui/src/note/mod.rs index b4713ba6..aba42812 100644 --- a/crates/notedeck_ui/src/note/mod.rs +++ b/crates/notedeck_ui/src/note/mod.rs @@ -30,6 +30,10 @@ use notedeck::{ NotedeckTextStyle, ZapTarget, Zaps, }; +const ACTION_BAR_ICON_SIZE: f32 = 14.0; +const ACTION_BAR_EXPAND_SIZE: f32 = 5.0; +const ACTION_BAR_ANIM_SPEED: f32 = 0.05; + pub struct NoteView<'a, 'd> { note_context: &'a mut NoteContext<'d>, zapping_acc: Option<&'a KeypairUnowned<'a>>, @@ -67,14 +71,6 @@ impl NoteResponse { } } -/* -impl View for NoteView<'_, '_> { - fn ui(&mut self, ui: &mut egui::Ui) { - self.show(ui); - } -} -*/ - impl egui::Widget for &mut NoteView<'_, '_> { fn ui(self, ui: &mut egui::Ui) -> egui::Response { self.show(ui).response @@ -784,73 +780,91 @@ fn render_note_actionbar( note_pubkey: &[u8; 32], note_key: NoteKey, ) -> egui::InnerResponse> { - ui.horizontal(|ui| 's: { - let reply_resp = reply_button(ui, note_key); - let quote_resp = quote_repost_button(ui, note_key); + ui.add_space(10.0); - let to_noteid = |id: &[u8; 32]| NoteId::new(*id); - if reply_resp.clicked() { - break 's Some(NoteAction::Reply(to_noteid(note_id))); - } else if reply_resp.hovered() { - crate::show_pointer(ui); - } + let icon_space = ACTION_BAR_ICON_SIZE * 2.0; + let width = ui.available_width(); + let height = 22.0; - if quote_resp.clicked() { - break 's Some(NoteAction::Quote(to_noteid(note_id))); - } else if quote_resp.hovered() { - crate::show_pointer(ui); - } + let (rect, _response) = ui.allocate_exact_size(egui::vec2(width, height), egui::Sense::click()); - let Some(Zapper { zaps, cur_acc }) = zapper else { - break 's None; - }; + #[allow(deprecated)] + ui.allocate_ui_at_rect(rect, |ui| { + ui.horizontal(|ui| 's: { + let reply_resp = reply_button(ui, note_key); - let zap_target = ZapTarget::Note(NoteZapTarget { - note_id, - zap_recipient: note_pubkey, - }); + ui.add_space(icon_space); - let zap_state = zaps.any_zap_state_for(cur_acc.pubkey.bytes(), zap_target); + let quote_resp = quote_repost_button(ui, note_key); - let target = NoteZapTargetOwned { - note_id: to_noteid(note_id), - zap_recipient: Pubkey::new(*note_pubkey), - }; - - if zap_state.is_err() { - break 's Some(NoteAction::Zap(ZapAction::ClearError(target))); - } - - let zap_resp = { - cur_acc.secret_key.as_ref()?; - - match zap_state { - Ok(any_zap_state) => ui.add(zap_button(any_zap_state, note_id)), - Err(err) => { - let (rect, _) = - ui.allocate_at_least(egui::vec2(10.0, 10.0), egui::Sense::click()); - ui.add(x_button(rect)).on_hover_text(err.to_string()) - } + let to_noteid = |id: &[u8; 32]| NoteId::new(*id); + if reply_resp.clicked() { + break 's Some(NoteAction::Reply(to_noteid(note_id))); + } else if reply_resp.hovered() { + crate::show_pointer(ui); } - }; - if zap_resp.hovered() { - crate::show_pointer(ui); - } + if quote_resp.clicked() { + break 's Some(NoteAction::Quote(to_noteid(note_id))); + } else if quote_resp.hovered() { + crate::show_pointer(ui); + } - if zap_resp.secondary_clicked() { - break 's Some(NoteAction::Zap(ZapAction::CustomizeAmount(target))); - } + let Some(Zapper { zaps, cur_acc }) = zapper else { + break 's None; + }; - if !zap_resp.clicked() { - break 's None; - } + let zap_target = ZapTarget::Note(NoteZapTarget { + note_id, + zap_recipient: note_pubkey, + }); - Some(NoteAction::Zap(ZapAction::Send(ZapTargetAmount { - target, - specified_msats: None, - }))) + let zap_state = zaps.any_zap_state_for(cur_acc.pubkey.bytes(), zap_target); + + let target = NoteZapTargetOwned { + note_id: to_noteid(note_id), + zap_recipient: Pubkey::new(*note_pubkey), + }; + + if zap_state.is_err() { + break 's Some(NoteAction::Zap(ZapAction::ClearError(target))); + } + + let zap_resp = { + cur_acc.secret_key.as_ref()?; + + match zap_state { + Ok(any_zap_state) => { + ui.add_space(icon_space); + ui.add(zap_button(any_zap_state, note_id)) + } + Err(err) => { + let (rect, _) = + ui.allocate_at_least(egui::vec2(10.0, 10.0), egui::Sense::click()); + ui.add(x_button(rect)).on_hover_text(err.to_string()) + } + } + }; + + if zap_resp.hovered() { + crate::show_pointer(ui); + } + + if zap_resp.secondary_clicked() { + break 's Some(NoteAction::Zap(ZapAction::CustomizeAmount(target))); + } + + if !zap_resp.clicked() { + break 's None; + } + + Some(NoteAction::Zap(ZapAction::Send(ZapTargetAmount { + target, + specified_msats: None, + }))) + }) }) + .inner } fn secondary_label(ui: &mut egui::Ui, s: impl Into) { @@ -878,19 +892,24 @@ fn render_reltime( } fn reply_button(ui: &mut egui::Ui, note_key: NoteKey) -> egui::Response { + let id = ui.id().with(("reply_anim", note_key)); + + let (rect, size, resp) = crate::anim::hover_expand( + ui, + id, + ACTION_BAR_ICON_SIZE, + ACTION_BAR_EXPAND_SIZE, + ACTION_BAR_ANIM_SPEED, + ); + + let rect = rect.translate(egui::vec2(-(ACTION_BAR_EXPAND_SIZE / 2.0), -1.0)); + let img = if ui.style().visuals.dark_mode { app_images::reply_dark_image() } else { app_images::reply_light_image() }; - let (rect, size, resp) = - crate::anim::hover_expand_small(ui, ui.id().with(("reply_anim", note_key))); - - // align rect to note contents - let expand_size = 5.0; // from hover_expand_small - let rect = rect.translate(egui::vec2(-(expand_size / 2.0), 0.0)); - let put_resp = ui .put(rect, img.max_width(size)) .on_hover_text("Reply to this note"); @@ -907,14 +926,17 @@ fn repost_icon(dark_mode: bool) -> egui::Image<'static> { } fn quote_repost_button(ui: &mut egui::Ui, note_key: NoteKey) -> egui::Response { - let size = 14.0; - let expand_size = 5.0; - let anim_speed = 0.05; let id = ui.id().with(("repost_anim", note_key)); - let (rect, size, resp) = crate::anim::hover_expand(ui, id, size, expand_size, anim_speed); + let (rect, size, resp) = crate::anim::hover_expand( + ui, + id, + ACTION_BAR_ICON_SIZE, + ACTION_BAR_EXPAND_SIZE, + ACTION_BAR_ANIM_SPEED, + ); - let rect = rect.translate(egui::vec2(-(expand_size / 2.0), -1.0)); + let rect = rect.translate(egui::vec2(-(ACTION_BAR_EXPAND_SIZE / 2.0), -1.0)); let put_resp = ui .put(rect, repost_icon(ui.visuals().dark_mode).max_width(size)) @@ -925,9 +947,19 @@ fn quote_repost_button(ui: &mut egui::Ui, note_key: NoteKey) -> egui::Response { fn zap_button(state: AnyZapState, noteid: &[u8; 32]) -> impl egui::Widget + use<'_> { move |ui: &mut egui::Ui| -> egui::Response { - let (rect, size, resp) = crate::anim::hover_expand_small(ui, ui.id().with("zap")); + let id = ui.id().with(("zap", noteid)); - let mut img = app_images::zap_image().max_width(size); + let (rect, size, resp) = crate::anim::hover_expand( + ui, + id, + ACTION_BAR_ICON_SIZE, + ACTION_BAR_EXPAND_SIZE, + ACTION_BAR_ANIM_SPEED, + ); + + let mut img = app_images::zap_image() + .max_width(size) + .tint(egui::Color32::WHITE); let id = ui.id().with(("pulse", noteid)); let ctx = ui.ctx().clone();