|
1 | 1 | use crate::{ui, Damus};
|
2 | 2 | use egui::containers::scroll_area::ScrollBarVisibility;
|
| 3 | +use egui::{Direction, Layout}; |
| 4 | +use egui_tabs::TabColor; |
3 | 5 | use egui_virtual_list::VirtualList;
|
4 | 6 | use enostr::Filter;
|
5 | 7 | use nostrdb::{NoteKey, Subscription, Transaction};
|
@@ -56,21 +58,101 @@ impl Timeline {
|
56 | 58 | }
|
57 | 59 | }
|
58 | 60 |
|
| 61 | +fn get_label_width(ui: &mut egui::Ui, text: &str) -> f32 { |
| 62 | + let font_id = egui::FontId::default(); |
| 63 | + let galley = ui.fonts(|r| r.layout_no_wrap(text.to_string(), font_id, egui::Color32::WHITE)); |
| 64 | + galley.rect.width() |
| 65 | +} |
| 66 | + |
| 67 | +fn shrink_range_to_width(range: egui::Rangef, width: f32) -> egui::Rangef { |
| 68 | + let midpoint = (range.min + range.max) / 2.0; |
| 69 | + let half_width = width / 2.0; |
| 70 | + |
| 71 | + let min = midpoint - half_width; |
| 72 | + let max = midpoint + half_width; |
| 73 | + |
| 74 | + egui::Rangef::new(min, max) |
| 75 | +} |
| 76 | + |
| 77 | +fn tabs_ui(ui: &mut egui::Ui) { |
| 78 | + ui.spacing_mut().item_spacing.y = 0.0; |
| 79 | + |
| 80 | + let tab_res = egui_tabs::Tabs::new(2) |
| 81 | + .hover_bg(TabColor::none()) |
| 82 | + .selected_fg(TabColor::none()) |
| 83 | + .selected_bg(TabColor::none()) |
| 84 | + .hover_bg(TabColor::none()) |
| 85 | + //.hover_bg(TabColor::custom(egui::Color32::RED)) |
| 86 | + .height(32.0) |
| 87 | + .layout(Layout::centered_and_justified(Direction::TopDown)) |
| 88 | + .show(ui, |ui, state| { |
| 89 | + ui.spacing_mut().item_spacing.y = 0.0; |
| 90 | + |
| 91 | + let ind = state.index(); |
| 92 | + |
| 93 | + let txt = if ind == 0 { "Notes" } else { "Notes & Replies" }; |
| 94 | + |
| 95 | + let res = ui.add(egui::Label::new(txt).selectable(false)); |
| 96 | + |
| 97 | + // underline |
| 98 | + if state.is_selected() { |
| 99 | + let rect = res.rect; |
| 100 | + let underline = rect.x_range().shrink(rect.width() / 4.0); |
| 101 | + let underline = shrink_range_to_width(underline, get_label_width(ui, txt) * 1.15); |
| 102 | + let underline_y = ui.painter().round_to_pixel(rect.bottom()) - 1.5; |
| 103 | + return (underline, underline_y); |
| 104 | + } |
| 105 | + |
| 106 | + (egui::Rangef::new(0.0, 0.0), 0.0) |
| 107 | + }); |
| 108 | + |
| 109 | + //ui.add_space(0.5); |
| 110 | + ui::hline(ui); |
| 111 | + |
| 112 | + // fun animation |
| 113 | + if let Some(sel) = tab_res.selected() { |
| 114 | + let (underline, underline_y) = tab_res.inner()[sel as usize].inner; |
| 115 | + let underline_width = underline.span(); |
| 116 | + |
| 117 | + let tab_anim_id = ui.id().with("tab_anim"); |
| 118 | + let tab_anim_size = tab_anim_id.with("size"); |
| 119 | + |
| 120 | + let stroke = egui::Stroke { |
| 121 | + color: ui.visuals().hyperlink_color, |
| 122 | + width: 3.0, |
| 123 | + }; |
| 124 | + |
| 125 | + let speed = 0.1f32; |
| 126 | + |
| 127 | + // animate underline position |
| 128 | + let x = ui |
| 129 | + .ctx() |
| 130 | + .animate_value_with_time(tab_anim_id, underline.min, speed); |
| 131 | + |
| 132 | + // animate underline width |
| 133 | + let w = ui |
| 134 | + .ctx() |
| 135 | + .animate_value_with_time(tab_anim_size, underline_width, speed); |
| 136 | + |
| 137 | + let underline = egui::Rangef::new(x, x + w); |
| 138 | + |
| 139 | + ui.painter().hline(underline, underline_y, stroke); |
| 140 | + } |
| 141 | + |
| 142 | + ui.add_space(3.0); |
| 143 | +} |
| 144 | + |
59 | 145 | pub fn timeline_view(ui: &mut egui::Ui, app: &mut Damus, timeline: usize) {
|
60 | 146 | //padding(4.0, ui, |ui| ui.heading("Notifications"));
|
61 | 147 | /*
|
62 | 148 | let font_id = egui::TextStyle::Body.resolve(ui.style());
|
63 | 149 | let row_height = ui.fonts(|f| f.row_height(&font_id)) + ui.spacing().item_spacing.y;
|
64 | 150 | */
|
65 | 151 |
|
| 152 | + tabs_ui(ui); |
| 153 | + |
66 | 154 | egui::ScrollArea::vertical()
|
67 | 155 | .scroll_bar_visibility(ScrollBarVisibility::AlwaysVisible)
|
68 |
| - //.auto_shrink([false; 2]) |
69 |
| - /* |
70 |
| - .show_viewport(ui, |ui, viewport| { |
71 |
| - render_notes_in_viewport(ui, app, viewport, row_height, font_id); |
72 |
| - }); |
73 |
| - */ |
74 | 156 | .show(ui, |ui| {
|
75 | 157 | let len = app.timelines[timeline].notes.len();
|
76 | 158 | let list = app.timelines[timeline].list.clone();
|
|
0 commit comments