notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

reply.rs (5378B)


      1 use crate::draft::Draft;
      2 use crate::ui::{
      3     self,
      4     note::{PostAction, PostResponse, PostType},
      5 };
      6 
      7 use egui::{Rect, Response, Ui};
      8 use enostr::{FilledKeypair, NoteId};
      9 use notedeck::NoteContext;
     10 use notedeck_ui::jobs::JobsCache;
     11 use notedeck_ui::{NoteOptions, NoteView, ProfilePic};
     12 
     13 pub struct PostReplyView<'a, 'd> {
     14     note_context: &'a mut NoteContext<'d>,
     15     poster: FilledKeypair<'a>,
     16     draft: &'a mut Draft,
     17     note: &'a nostrdb::Note<'a>,
     18     id_source: Option<egui::Id>,
     19     inner_rect: egui::Rect,
     20     note_options: NoteOptions,
     21     jobs: &'a mut JobsCache,
     22 }
     23 
     24 impl<'a, 'd> PostReplyView<'a, 'd> {
     25     #[allow(clippy::too_many_arguments)]
     26     pub fn new(
     27         note_context: &'a mut NoteContext<'d>,
     28         poster: FilledKeypair<'a>,
     29         draft: &'a mut Draft,
     30         note: &'a nostrdb::Note<'a>,
     31         inner_rect: egui::Rect,
     32         note_options: NoteOptions,
     33         jobs: &'a mut JobsCache,
     34     ) -> Self {
     35         let id_source: Option<egui::Id> = None;
     36         PostReplyView {
     37             note_context,
     38             poster,
     39             draft,
     40             note,
     41             id_source,
     42             inner_rect,
     43             note_options,
     44             jobs,
     45         }
     46     }
     47 
     48     pub fn id_source(mut self, id: egui::Id) -> Self {
     49         self.id_source = Some(id);
     50         self
     51     }
     52 
     53     pub fn id(&self) -> egui::Id {
     54         self.id_source
     55             .unwrap_or_else(|| egui::Id::new("post-reply-view"))
     56     }
     57 
     58     pub fn show(&mut self, ui: &mut egui::Ui) -> PostResponse {
     59         ui.vertical(|ui| {
     60             let avail_rect = ui.available_rect_before_wrap();
     61 
     62             // This is the offset of the post view's pfp. We use this
     63             // to indent things so that the reply line is aligned
     64             let pfp_offset: i8 = ui::PostView::outer_margin()
     65                 + ui::PostView::inner_margin()
     66                 + ProfilePic::small_size() / 2;
     67 
     68             let note_offset: i8 =
     69                 pfp_offset - ProfilePic::medium_size() / 2 - NoteView::expand_size() / 2;
     70 
     71             let quoted_note = egui::Frame::NONE
     72                 .outer_margin(egui::Margin::same(note_offset))
     73                 .show(ui, |ui| {
     74                     NoteView::new(self.note_context, self.note, self.note_options, self.jobs)
     75                         .truncate(false)
     76                         .selectable_text(true)
     77                         .actionbar(false)
     78                         .medium_pfp(true)
     79                         .options_button(true)
     80                         .show(ui)
     81                 })
     82                 .inner;
     83 
     84             let id = self.id();
     85             let replying_to = self.note.id();
     86             let rect_before_post = ui.min_rect();
     87 
     88             let mut post_response = {
     89                 ui::PostView::new(
     90                     self.note_context,
     91                     self.draft,
     92                     PostType::Reply(NoteId::new(*replying_to)),
     93                     self.poster,
     94                     self.inner_rect,
     95                     self.note_options,
     96                     self.jobs,
     97                 )
     98                 .id_source(id)
     99                 .ui(self.note.txn().unwrap(), ui)
    100             };
    101 
    102             post_response.action = post_response
    103                 .action
    104                 .or(quoted_note.action.map(PostAction::QuotedNoteAction));
    105 
    106             reply_line_ui(
    107                 &rect_before_post,
    108                 &post_response.edit_response,
    109                 pfp_offset as f32,
    110                 &avail_rect,
    111                 ui,
    112             );
    113 
    114             //
    115             // NOTE(jb55): We add some space so that you can scroll to
    116             // put the input box higher.  This can happen in some
    117             // situations where the input box gets covered or if its too
    118             // large and things start breaking. I think this is an ok
    119             // solution but there could be a better one.
    120             //
    121             ui.add_space(500.0);
    122 
    123             post_response
    124         })
    125         .inner
    126     }
    127 }
    128 
    129 /// The vertical line in the reply view
    130 fn reply_line_ui(
    131     rect_before_post: &Rect,
    132     edit_response: &Response,
    133     pfp_offset: f32,
    134     avail_rect: &Rect,
    135     ui: &mut Ui,
    136 ) {
    137     // Position and draw the reply line
    138     let mut rect = ui.min_rect();
    139 
    140     // Position the line right above the poster's profile pic in
    141     // the post box. Use the PostView's margin values to
    142     // determine this offset.
    143     rect.min.x = avail_rect.min.x + pfp_offset;
    144 
    145     // honestly don't know what the fuck I'm doing here. just trying
    146     // to get the line under the profile picture
    147     rect.min.y = avail_rect.min.y
    148         + (ProfilePic::medium_size() as f32 / 2.0
    149             + ProfilePic::medium_size() as f32
    150             + NoteView::expand_size() as f32 * 2.0)
    151         + 1.0;
    152 
    153     // For some reason we need to nudge the reply line's height a
    154     // few more pixels?
    155     let nudge = if edit_response.has_focus() {
    156         // we nudge by one less pixel if focused, otherwise it
    157         // overlaps the focused PostView purple border color
    158         2.0
    159     } else {
    160         // we have to nudge by one more pixel when not focused
    161         // otherwise it looks like there's a gap(?)
    162         3.0
    163     };
    164 
    165     rect.max.y = rect_before_post.max.y + ui::PostView::outer_margin() as f32 + nudge;
    166 
    167     ui.painter().vline(
    168         rect.left(),
    169         rect.y_range(),
    170         ui.visuals().widgets.noninteractive.bg_stroke,
    171     );
    172 }