Merge Add External Notifications Column setting #395
kernelkind (2):
init external notifs column
use AcquireKeyState for AddColumn
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
use crate::app_style::NotedeckTextStyle;
|
||||
use crate::key_parsing::LoginError;
|
||||
use crate::login_manager::LoginState;
|
||||
use crate::key_parsing::AcquireKeyError;
|
||||
use crate::login_manager::AcquireKeyState;
|
||||
use crate::ui::{Preview, PreviewConfig, View};
|
||||
use egui::TextEdit;
|
||||
use egui::{Align, Button, Color32, Frame, InnerResponse, Margin, RichText, Vec2};
|
||||
use enostr::Keypair;
|
||||
|
||||
pub struct AccountLoginView<'a> {
|
||||
manager: &'a mut LoginState,
|
||||
manager: &'a mut AcquireKeyState,
|
||||
}
|
||||
|
||||
pub enum AccountLoginResponse {
|
||||
@@ -16,7 +16,7 @@ pub enum AccountLoginResponse {
|
||||
}
|
||||
|
||||
impl<'a> AccountLoginView<'a> {
|
||||
pub fn new(state: &'a mut LoginState) -> Self {
|
||||
pub fn new(state: &'a mut AcquireKeyState) -> Self {
|
||||
AccountLoginView { manager: state }
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ impl<'a> AccountLoginView<'a> {
|
||||
self.loading_and_error(ui);
|
||||
|
||||
if ui.add(login_button()).clicked() {
|
||||
self.manager.apply_login();
|
||||
self.manager.apply_acquire();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -90,13 +90,13 @@ impl<'a> AccountLoginView<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn show_error(ui: &mut egui::Ui, err: &LoginError) {
|
||||
fn show_error(ui: &mut egui::Ui, err: &AcquireKeyError) {
|
||||
ui.horizontal(|ui| {
|
||||
let error_label = match err {
|
||||
LoginError::InvalidKey => {
|
||||
AcquireKeyError::InvalidKey => {
|
||||
egui::Label::new(RichText::new("Invalid key.").color(ui.visuals().error_fg_color))
|
||||
}
|
||||
LoginError::Nip05Failed(e) => {
|
||||
AcquireKeyError::Nip05Failed(e) => {
|
||||
egui::Label::new(RichText::new(e).color(ui.visuals().error_fg_color))
|
||||
}
|
||||
};
|
||||
@@ -126,8 +126,8 @@ fn login_button() -> Button<'static> {
|
||||
.min_size(Vec2::new(0.0, 40.0))
|
||||
}
|
||||
|
||||
fn login_textedit(manager: &mut LoginState) -> TextEdit {
|
||||
manager.get_login_textedit(|text| {
|
||||
fn login_textedit(manager: &mut AcquireKeyState) -> TextEdit {
|
||||
manager.get_acquire_textedit(|text| {
|
||||
egui::TextEdit::singleline(text)
|
||||
.hint_text(
|
||||
RichText::new("Enter your public key (npub, nip05), or private key (nsec) here...")
|
||||
@@ -143,7 +143,7 @@ mod preview {
|
||||
use super::*;
|
||||
|
||||
pub struct AccountLoginPreview {
|
||||
manager: LoginState,
|
||||
manager: AcquireKeyState,
|
||||
}
|
||||
|
||||
impl View for AccountLoginPreview {
|
||||
@@ -157,7 +157,7 @@ mod preview {
|
||||
|
||||
fn preview(cfg: PreviewConfig) -> Self::Prev {
|
||||
let _ = cfg;
|
||||
let manager = LoginState::new();
|
||||
let manager = AcquireKeyState::new();
|
||||
AccountLoginPreview { manager }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,51 @@
|
||||
use egui::{pos2, vec2, Color32, FontId, ImageSource, Pos2, Rect, Separator, Ui};
|
||||
use core::f32;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use egui::{
|
||||
pos2, vec2, Align, Color32, FontId, Id, ImageSource, Margin, Pos2, Rect, RichText, Separator,
|
||||
Ui, Vec2,
|
||||
};
|
||||
use nostrdb::Ndb;
|
||||
use tracing::error;
|
||||
|
||||
use crate::{
|
||||
app_style::{get_font_size, NotedeckTextStyle},
|
||||
login_manager::AcquireKeyState,
|
||||
timeline::{PubkeySource, Timeline, TimelineKind},
|
||||
ui::anim::ICON_EXPANSION_MULTIPLE,
|
||||
user_account::UserAccount,
|
||||
Damus,
|
||||
};
|
||||
|
||||
use super::anim::AnimationHelper;
|
||||
use super::{anim::AnimationHelper, padding};
|
||||
|
||||
pub enum AddColumnResponse {
|
||||
Timeline(Timeline),
|
||||
UndecidedNotification,
|
||||
ExternalNotification,
|
||||
}
|
||||
|
||||
pub enum NotificationColumnType {
|
||||
Home,
|
||||
External,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum AddColumnOption {
|
||||
Universe,
|
||||
UndecidedNotification,
|
||||
ExternalNotification,
|
||||
Notification(PubkeySource),
|
||||
Home(PubkeySource),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
pub enum AddColumnRoute {
|
||||
Base,
|
||||
UndecidedNotification,
|
||||
ExternalNotification,
|
||||
}
|
||||
|
||||
impl AddColumnOption {
|
||||
pub fn take_as_response(
|
||||
self,
|
||||
@@ -34,28 +59,41 @@ impl AddColumnOption {
|
||||
AddColumnOption::Notification(pubkey) => TimelineKind::Notifications(pubkey)
|
||||
.into_timeline(ndb, cur_account.map(|a| a.pubkey.bytes()))
|
||||
.map(AddColumnResponse::Timeline),
|
||||
AddColumnOption::UndecidedNotification => {
|
||||
Some(AddColumnResponse::UndecidedNotification)
|
||||
}
|
||||
AddColumnOption::Home(pubkey) => {
|
||||
let tlk = TimelineKind::contact_list(pubkey);
|
||||
tlk.into_timeline(ndb, cur_account.map(|a| a.pubkey.bytes()))
|
||||
.map(AddColumnResponse::Timeline)
|
||||
}
|
||||
AddColumnOption::ExternalNotification => Some(AddColumnResponse::ExternalNotification),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AddColumnView<'a> {
|
||||
key_state_map: &'a mut HashMap<Id, AcquireKeyState>,
|
||||
ndb: &'a Ndb,
|
||||
cur_account: Option<&'a UserAccount>,
|
||||
}
|
||||
|
||||
impl<'a> AddColumnView<'a> {
|
||||
pub fn new(ndb: &'a Ndb, cur_account: Option<&'a UserAccount>) -> Self {
|
||||
Self { ndb, cur_account }
|
||||
pub fn new(
|
||||
key_state_map: &'a mut HashMap<Id, AcquireKeyState>,
|
||||
ndb: &'a Ndb,
|
||||
cur_account: Option<&'a UserAccount>,
|
||||
) -> Self {
|
||||
Self {
|
||||
key_state_map,
|
||||
ndb,
|
||||
cur_account,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> {
|
||||
let mut selected_option: Option<AddColumnResponse> = None;
|
||||
for column_option_data in self.get_column_options() {
|
||||
for column_option_data in self.get_base_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);
|
||||
@@ -67,6 +105,66 @@ impl<'a> AddColumnView<'a> {
|
||||
selected_option
|
||||
}
|
||||
|
||||
fn notifications_ui(&mut self, ui: &mut Ui) -> Option<AddColumnResponse> {
|
||||
let mut selected_option: Option<AddColumnResponse> = None;
|
||||
for column_option_data in self.get_notifications_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_notification_ui(&mut self, ui: &mut Ui) -> 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| {
|
||||
egui::TextEdit::singleline(text)
|
||||
.hint_text(
|
||||
RichText::new("Enter the user's key (npub, hex, nip05) here...")
|
||||
.text_style(NotedeckTextStyle::Body.text_style()),
|
||||
)
|
||||
.vertical_align(Align::Center)
|
||||
.desired_width(f32::INFINITY)
|
||||
.min_size(Vec2::new(0.0, 40.0))
|
||||
.margin(Margin::same(12.0))
|
||||
});
|
||||
|
||||
ui.add(text_edit);
|
||||
|
||||
if ui.button("Add").clicked() {
|
||||
key_state.apply_acquire();
|
||||
}
|
||||
|
||||
if key_state.is_awaiting_network() {
|
||||
ui.spinner();
|
||||
}
|
||||
|
||||
if let Some(error) = key_state.check_for_error() {
|
||||
error!("acquire key error: {}", error);
|
||||
ui.colored_label(
|
||||
Color32::RED,
|
||||
"Please enter a valid npub, public hex key or nip05",
|
||||
);
|
||||
}
|
||||
|
||||
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)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.inner
|
||||
}
|
||||
|
||||
fn column_option_ui(&mut self, ui: &mut Ui, data: ColumnOptionData) -> egui::Response {
|
||||
let icon_padding = 8.0;
|
||||
let min_icon_width = 32.0;
|
||||
@@ -168,7 +266,7 @@ impl<'a> AddColumnView<'a> {
|
||||
helper.take_animation_response()
|
||||
}
|
||||
|
||||
fn get_column_options(&self) -> Vec<ColumnOptionData> {
|
||||
fn get_base_options(&self) -> Vec<ColumnOptionData> {
|
||||
let mut vec = Vec::new();
|
||||
vec.push(ColumnOptionData {
|
||||
title: "Universe",
|
||||
@@ -190,14 +288,42 @@ impl<'a> AddColumnView<'a> {
|
||||
icon: egui::include_image!("../../assets/icons/home_icon_dark_4x.png"),
|
||||
option: AddColumnOption::Home(source.clone()),
|
||||
});
|
||||
}
|
||||
vec.push(ColumnOptionData {
|
||||
title: "Notifications",
|
||||
description: "Stay up to date with notifications and mentions",
|
||||
icon: egui::include_image!("../../assets/icons/notifications_icon_dark_4x.png"),
|
||||
option: AddColumnOption::UndecidedNotification,
|
||||
});
|
||||
|
||||
vec
|
||||
}
|
||||
|
||||
fn get_notifications_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: "Notifications",
|
||||
description: "Stay up to date with notifications and mentions",
|
||||
title: "Your Notifications",
|
||||
description: "Stay up to date with your notifications and mentions",
|
||||
icon: egui::include_image!("../../assets/icons/notifications_icon_dark_4x.png"),
|
||||
option: AddColumnOption::Notification(source),
|
||||
});
|
||||
}
|
||||
|
||||
vec.push(ColumnOptionData {
|
||||
title: "Someone else's Notifications",
|
||||
description: "Stay up to date with someone else's notifications and mentions",
|
||||
icon: egui::include_image!("../../assets/icons/notifications_icon_dark_4x.png"),
|
||||
option: AddColumnOption::ExternalNotification,
|
||||
});
|
||||
|
||||
vec
|
||||
}
|
||||
}
|
||||
@@ -209,6 +335,54 @@ struct ColumnOptionData {
|
||||
option: AddColumnOption,
|
||||
}
|
||||
|
||||
pub fn render_add_column_routes(
|
||||
ui: &mut egui::Ui,
|
||||
app: &mut Damus,
|
||||
col: usize,
|
||||
route: &AddColumnRoute,
|
||||
) {
|
||||
let resp = match route {
|
||||
AddColumnRoute::Base => AddColumnView::new(
|
||||
&mut app.view_state.id_state_map,
|
||||
&app.ndb,
|
||||
app.accounts.get_selected_account(),
|
||||
)
|
||||
.ui(ui),
|
||||
AddColumnRoute::UndecidedNotification => AddColumnView::new(
|
||||
&mut app.view_state.id_state_map,
|
||||
&app.ndb,
|
||||
app.accounts.get_selected_account(),
|
||||
)
|
||||
.notifications_ui(ui),
|
||||
AddColumnRoute::ExternalNotification => AddColumnView::new(
|
||||
&mut app.view_state.id_state_map,
|
||||
&app.ndb,
|
||||
app.accounts.get_selected_account(),
|
||||
)
|
||||
.external_notification_ui(ui),
|
||||
};
|
||||
|
||||
if let Some(resp) = resp {
|
||||
match resp {
|
||||
AddColumnResponse::Timeline(timeline) => {
|
||||
let id = timeline.id;
|
||||
app.columns_mut().add_timeline_to_column(col, timeline);
|
||||
app.subscribe_new_timeline(id);
|
||||
}
|
||||
AddColumnResponse::UndecidedNotification => {
|
||||
app.columns_mut().column_mut(col).router_mut().route_to(
|
||||
crate::route::Route::AddColumn(AddColumnRoute::UndecidedNotification),
|
||||
);
|
||||
}
|
||||
AddColumnResponse::ExternalNotification => {
|
||||
app.columns_mut().column_mut(col).router_mut().route_to(
|
||||
crate::route::Route::AddColumn(AddColumnRoute::ExternalNotification),
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
mod preview {
|
||||
use crate::{
|
||||
test_data,
|
||||
@@ -232,7 +406,12 @@ mod preview {
|
||||
|
||||
impl View for AddColumnPreview {
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
AddColumnView::new(&self.app.ndb, self.app.accounts.get_selected_account()).ui(ui);
|
||||
AddColumnView::new(
|
||||
&mut self.app.view_state.id_state_map,
|
||||
&self.app.ndb,
|
||||
self.app.accounts.get_selected_account(),
|
||||
)
|
||||
.ui(ui);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,11 @@ impl<'a> DesktopSidePanel<'a> {
|
||||
}
|
||||
}
|
||||
SidePanelAction::Columns => {
|
||||
if router.routes().iter().any(|&r| r == Route::AddColumn) {
|
||||
if router
|
||||
.routes()
|
||||
.iter()
|
||||
.any(|&r| matches!(r, Route::AddColumn(_)))
|
||||
{
|
||||
router.go_back();
|
||||
} else {
|
||||
columns.new_column_picker();
|
||||
|
||||
Reference in New Issue
Block a user