commit 8b5464641d140b137f05f4b5931587e545587c74
parent c06d18f76b9b1d0a7905e787530db2f453c320f7
Author: kernelkind <kernelkind@gmail.com>
Date: Mon, 25 Aug 2025 21:16:05 -0400
render follow pack by index from virtual list
Signed-off-by: kernelkind <kernelkind@gmail.com>
Diffstat:
2 files changed, 91 insertions(+), 43 deletions(-)
diff --git a/crates/notedeck_columns/src/ui/onboarding.rs b/crates/notedeck_columns/src/ui/onboarding.rs
@@ -5,7 +5,7 @@ use nostrdb::Ndb;
use notedeck::{Images, JobPool, JobsCache, Localization};
use notedeck_ui::{
colors,
- nip51_set::{Nip51SetUiCache, Nip51SetWidget, Nip51SetWidgetFlags, Nip51SetWidgetResponse},
+ nip51_set::{Nip51SetUiCache, Nip51SetWidget, Nip51SetWidgetAction, Nip51SetWidgetFlags},
};
use crate::{onboarding::Onboarding, ui::widgets::styled_button};
@@ -71,24 +71,37 @@ impl<'a> FollowPackOnboardingView<'a> {
.max_height(max_height)
.show(ui, |ui| {
egui::Frame::new().inner_margin(8.0).show(ui, |ui| {
- if let Some(resp) = Nip51SetWidget::new(
- follow_pack_state,
- self.ui_state,
- self.ndb,
- self.loc,
- self.images,
- self.job_pool,
- self.jobs,
- )
- .with_flags(Nip51SetWidgetFlags::TRUST_IMAGES)
- .ui(ui)
- {
- match resp {
- Nip51SetWidgetResponse::ViewProfile(pubkey) => {
- action = Some(OnboardingResponse::ViewProfile(pubkey));
+ self.onboarding.list.borrow_mut().ui_custom_layout(
+ ui,
+ follow_pack_state.len(),
+ |ui, index| {
+ let resp = Nip51SetWidget::new(
+ follow_pack_state,
+ self.ui_state,
+ self.ndb,
+ self.loc,
+ self.images,
+ self.job_pool,
+ self.jobs,
+ )
+ .with_flags(Nip51SetWidgetFlags::TRUST_IMAGES)
+ .render_at_index(ui, index);
+
+ if let Some(cur_action) = resp.action {
+ match cur_action {
+ Nip51SetWidgetAction::ViewProfile(pubkey) => {
+ action = Some(OnboardingResponse::ViewProfile(pubkey));
+ }
+ }
+ }
+
+ if resp.rendered {
+ 1
+ } else {
+ 0
}
- }
- }
+ },
+ );
})
});
diff --git a/crates/notedeck_ui/src/nip51_set.rs b/crates/notedeck_ui/src/nip51_set.rs
@@ -42,7 +42,7 @@ impl Default for Nip51SetWidgetFlags {
}
}
-pub enum Nip51SetWidgetResponse {
+pub enum Nip51SetWidgetAction {
ViewProfile(Pubkey),
}
@@ -73,32 +73,62 @@ impl<'a> Nip51SetWidget<'a> {
self
}
- pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<Nip51SetWidgetResponse> {
+ fn render_set(&mut self, ui: &mut egui::Ui, set: &Nip51Set) -> Nip51SetWidgetResponse {
+ if should_skip(set, &self.flags) {
+ return Nip51SetWidgetResponse {
+ action: None,
+ rendered: false,
+ };
+ }
+
+ let action = egui::Frame::new()
+ .corner_radius(CornerRadius::same(8))
+ .fill(ui.visuals().extreme_bg_color)
+ .inner_margin(Margin::same(8))
+ .show(ui, |ui| {
+ render_pack(
+ ui,
+ set,
+ self.ui_state,
+ self.ndb,
+ self.images,
+ self.job_pool,
+ self.jobs,
+ self.loc,
+ self.flags.contains(Nip51SetWidgetFlags::TRUST_IMAGES),
+ )
+ })
+ .inner;
+
+ Nip51SetWidgetResponse {
+ action,
+ rendered: true,
+ }
+ }
+
+ pub fn render_at_index(&mut self, ui: &mut egui::Ui, index: usize) -> Nip51SetWidgetResponse {
+ let Some(set) = self.state.at_index(index) else {
+ return Nip51SetWidgetResponse {
+ action: None,
+ rendered: false,
+ };
+ };
+
+ self.render_set(ui, set)
+ }
+
+ pub fn ui(&mut self, ui: &mut egui::Ui) -> Option<Nip51SetWidgetAction> {
let mut resp = None;
for pack in self.state.iter() {
- if should_skip(pack, &self.flags) {
- continue;
+ let res = self.render_set(ui, pack);
+
+ if let Some(action) = res.action {
+ resp = Some(action);
}
- egui::Frame::new()
- .corner_radius(CornerRadius::same(8))
- .fill(ui.visuals().extreme_bg_color)
- .inner_margin(Margin::same(8))
- .show(ui, |ui| {
- if let Some(cur_resp) = render_pack(
- ui,
- pack,
- self.ui_state,
- self.ndb,
- self.images,
- self.job_pool,
- self.jobs,
- self.loc,
- self.flags.contains(Nip51SetWidgetFlags::TRUST_IMAGES),
- ) {
- resp = Some(cur_resp);
- }
- });
+ if !res.rendered {
+ continue;
+ }
ui.add_space(8.0);
}
@@ -107,6 +137,11 @@ impl<'a> Nip51SetWidget<'a> {
}
}
+pub struct Nip51SetWidgetResponse {
+ pub action: Option<Nip51SetWidgetAction>,
+ pub rendered: bool,
+}
+
fn should_skip(set: &Nip51Set, required: &Nip51SetWidgetFlags) -> bool {
(required.contains(Nip51SetWidgetFlags::REQUIRES_TITLE) && set.title.is_none())
|| (required.contains(Nip51SetWidgetFlags::REQUIRES_IMAGE) && set.image.is_none())
@@ -126,7 +161,7 @@ fn render_pack(
jobs: &mut JobsCache,
loc: &mut Localization,
image_trusted: bool,
-) -> Option<Nip51SetWidgetResponse> {
+) -> Option<Nip51SetWidgetAction> {
let max_img_size = vec2(ui.available_width(), 200.0);
ui.allocate_new_ui(UiBuilder::new(), |ui| 's: {
@@ -210,7 +245,7 @@ fn render_pack(
ui.separator();
if render_profile_item(ui, images, m_profile.as_ref(), cur_state) {
- resp = Some(Nip51SetWidgetResponse::ViewProfile(*pk));
+ resp = Some(Nip51SetWidgetAction::ViewProfile(*pk));
}
}