column: add individual column

A column for following a single user

Closes: https://github.com/damus-io/notedeck/pull/583
Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2024-12-16 18:01:36 -05:00
committed by William Casarin
parent 5b4c7a6371
commit 69a6bf3664
4 changed files with 133 additions and 10 deletions

View File

@@ -5,6 +5,7 @@ use egui::{
pos2, vec2, Align, Button, Color32, FontId, Id, ImageSource, Margin, Pos2, Rect, RichText,
Separator, Ui, Vec2,
};
use enostr::Pubkey;
use nostrdb::Ndb;
use tracing::error;
@@ -24,6 +25,8 @@ pub enum AddColumnResponse {
UndecidedNotification,
ExternalNotification,
Hashtag,
UndecidedIndividual,
ExternalIndividual,
}
pub enum NotificationColumnType {
@@ -40,6 +43,9 @@ enum AddColumnOption {
Home(PubkeySource),
UndecidedHashtag,
Hashtag(String),
UndecidedIndividual,
ExternalIndividual,
Individual(PubkeySource),
}
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
@@ -48,6 +54,8 @@ pub enum AddColumnRoute {
UndecidedNotification,
ExternalNotification,
Hashtag,
UndecidedIndividual,
ExternalIndividual,
}
impl AddColumnOption {
@@ -76,6 +84,13 @@ impl AddColumnOption {
AddColumnOption::Hashtag(hashtag) => TimelineKind::Hashtag(hashtag)
.into_timeline(ndb, None)
.map(AddColumnResponse::Timeline),
AddColumnOption::UndecidedIndividual => Some(AddColumnResponse::UndecidedIndividual),
AddColumnOption::ExternalIndividual => Some(AddColumnResponse::ExternalIndividual),
AddColumnOption::Individual(pubkey_source) => {
let tlk = TimelineKind::profile(pubkey_source);
tlk.into_timeline(ndb, cur_account.map(|a| a.pubkey.bytes()))
.map(AddColumnResponse::Timeline)
}
}
}
}
@@ -128,8 +143,42 @@ impl<'a> AddColumnView<'a> {
}
fn external_notification_ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> {
let id = ui.id().with("external_notif");
self.external_ui(ui, id, |pubkey| {
AddColumnOption::Notification(PubkeySource::Explicit(pubkey))
})
}
fn individual_ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> {
let mut selected_option: Option<AddColumnResponse> = None;
for column_option_data in self.get_individual_options() {
let option = column_option_data.option.clone();
if self.column_option_ui(ui, column_option_data).clicked() {
selected_option = option.take_as_response(self.ndb, self.cur_account);
}
ui.add(Separator::default().spacing(0.0));
}
selected_option
}
fn external_individual_ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> {
let id = ui.id().with("external_individual");
self.external_ui(ui, id, |pubkey| {
AddColumnOption::Individual(PubkeySource::Explicit(pubkey))
})
}
fn external_ui(
&mut self,
ui: &mut Ui,
id: egui::Id,
to_tl: fn(Pubkey) -> AddColumnOption,
) -> Option<AddColumnResponse> {
padding(16.0, ui, |ui| {
let id = ui.id().with("external_notif");
let key_state = self.key_state_map.entry(id).or_default();
let text_edit = key_state.get_acquire_textedit(|text| {
@@ -164,8 +213,7 @@ impl<'a> AddColumnView<'a> {
if let Some(keypair) = key_state.check_for_successful_login() {
key_state.should_create_new();
AddColumnOption::Notification(PubkeySource::Explicit(keypair.pubkey))
.take_as_response(self.ndb, self.cur_account)
to_tl(keypair.pubkey).take_as_response(self.ndb, self.cur_account)
} else {
None
}
@@ -309,6 +357,12 @@ impl<'a> AddColumnView<'a> {
icon: egui::include_image!("../../../../assets/icons/notifications_icon_dark_4x.png"),
option: AddColumnOption::UndecidedHashtag,
});
vec.push(ColumnOptionData {
title: "Individual",
description: "Stay up to date with someone's notes & replies",
icon: egui::include_image!("../../../../assets/icons/notifications_icon_dark_4x.png"),
option: AddColumnOption::UndecidedIndividual,
});
vec
}
@@ -342,6 +396,36 @@ impl<'a> AddColumnView<'a> {
vec
}
fn get_individual_options(&self) -> Vec<ColumnOptionData> {
let mut vec = Vec::new();
if let Some(acc) = self.cur_account {
let source = if acc.secret_key.is_some() {
PubkeySource::DeckAuthor
} else {
PubkeySource::Explicit(acc.pubkey)
};
vec.push(ColumnOptionData {
title: "Your Notes",
description: "Keep track of your notes & replies",
icon: egui::include_image!(
"../../../../assets/icons/notifications_icon_dark_4x.png"
),
option: AddColumnOption::Individual(source),
});
}
vec.push(ColumnOptionData {
title: "Someone else's Notes",
description: "Stay up to date with someone else's notes & replies",
icon: egui::include_image!("../../../../assets/icons/notifications_icon_dark_4x.png"),
option: AddColumnOption::ExternalIndividual,
});
vec
}
}
struct ColumnOptionData {
@@ -368,6 +452,8 @@ pub fn render_add_column_routes(
AddColumnRoute::UndecidedNotification => add_column_view.notifications_ui(ui),
AddColumnRoute::ExternalNotification => add_column_view.external_notification_ui(ui),
AddColumnRoute::Hashtag => hashtag_ui(ui, ctx.ndb, &mut app.view_state.id_string_map),
AddColumnRoute::UndecidedIndividual => add_column_view.individual_ui(ui),
AddColumnRoute::ExternalIndividual => add_column_view.external_individual_ui(ui),
};
if let Some(resp) = resp {
@@ -407,6 +493,22 @@ pub fn render_add_column_routes(
.router_mut()
.route_to(crate::route::Route::AddColumn(AddColumnRoute::Hashtag));
}
AddColumnResponse::UndecidedIndividual => {
app.columns_mut(ctx.accounts)
.column_mut(col)
.router_mut()
.route_to(crate::route::Route::AddColumn(
AddColumnRoute::UndecidedIndividual,
));
}
AddColumnResponse::ExternalIndividual => {
app.columns_mut(ctx.accounts)
.column_mut(col)
.router_mut()
.route_to(crate::route::Route::AddColumn(
AddColumnRoute::ExternalIndividual,
));
}
};
}
}