This splits notedeck into: - notedeck - notedeck_chrome - notedeck_columns The `notedeck` crate is the library that `notedeck_chrome` and `notedeck_columns`, use. It contains common functionality related to notedeck apps such as the NoteCache, ImageCache, etc. The `notedeck_chrome` crate is the binary and ui chrome. It is responsible for managing themes, user accounts, signing, data paths, nostrdb, image caches etc. It will eventually have its own ui which has yet to be determined. For now it just manages the browser data, which is passed to apps via a new struct called `AppContext`. `notedeck_columns` is our columns app, with less responsibility now that more things are handled by `notedeck_chrome` There is still much work left to do before this is a proper browser: - process isolation - sandboxing - etc This is the beginning of a new era! We're just getting started. Signed-off-by: William Casarin <jb55@jb55.com>
165 lines
4.7 KiB
Rust
165 lines
4.7 KiB
Rust
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;
|
|
use notedeck::NotedeckTextStyle;
|
|
|
|
pub struct AccountLoginView<'a> {
|
|
manager: &'a mut AcquireKeyState,
|
|
}
|
|
|
|
pub enum AccountLoginResponse {
|
|
CreateNew,
|
|
LoginWith(Keypair),
|
|
}
|
|
|
|
impl<'a> AccountLoginView<'a> {
|
|
pub fn new(state: &'a mut AcquireKeyState) -> Self {
|
|
AccountLoginView { manager: state }
|
|
}
|
|
|
|
pub fn ui(&mut self, ui: &mut egui::Ui) -> InnerResponse<Option<AccountLoginResponse>> {
|
|
Frame::none()
|
|
.outer_margin(12.0)
|
|
.show(ui, |ui| self.show(ui))
|
|
}
|
|
|
|
fn show(&mut self, ui: &mut egui::Ui) -> Option<AccountLoginResponse> {
|
|
ui.vertical(|ui| {
|
|
ui.vertical_centered(|ui| {
|
|
ui.add_space(32.0);
|
|
ui.label(login_title_text());
|
|
});
|
|
|
|
ui.horizontal(|ui| {
|
|
ui.label(login_textedit_info_text());
|
|
});
|
|
|
|
ui.vertical_centered_justified(|ui| {
|
|
ui.add(login_textedit(self.manager));
|
|
|
|
self.loading_and_error(ui);
|
|
|
|
if ui.add(login_button()).clicked() {
|
|
self.manager.apply_acquire();
|
|
}
|
|
});
|
|
|
|
ui.horizontal(|ui| {
|
|
ui.label(
|
|
RichText::new("New to Nostr?")
|
|
.color(ui.style().visuals.noninteractive().fg_stroke.color)
|
|
.text_style(NotedeckTextStyle::Body.text_style()),
|
|
);
|
|
|
|
if ui
|
|
.add(Button::new(RichText::new("Create Account")).frame(false))
|
|
.clicked()
|
|
{
|
|
self.manager.should_create_new();
|
|
}
|
|
});
|
|
});
|
|
|
|
if self.manager.check_for_create_new() {
|
|
return Some(AccountLoginResponse::CreateNew);
|
|
}
|
|
|
|
if let Some(keypair) = self.manager.check_for_successful_login() {
|
|
return Some(AccountLoginResponse::LoginWith(keypair));
|
|
}
|
|
None
|
|
}
|
|
|
|
fn loading_and_error(&mut self, ui: &mut egui::Ui) {
|
|
ui.add_space(8.0);
|
|
|
|
ui.vertical_centered(|ui| {
|
|
if self.manager.is_awaiting_network() {
|
|
ui.add(egui::Spinner::new());
|
|
}
|
|
});
|
|
|
|
if let Some(err) = self.manager.check_for_error() {
|
|
show_error(ui, err);
|
|
}
|
|
|
|
ui.add_space(8.0);
|
|
}
|
|
}
|
|
|
|
fn show_error(ui: &mut egui::Ui, err: &AcquireKeyError) {
|
|
ui.horizontal(|ui| {
|
|
let error_label = match err {
|
|
AcquireKeyError::InvalidKey => {
|
|
egui::Label::new(RichText::new("Invalid key.").color(ui.visuals().error_fg_color))
|
|
}
|
|
AcquireKeyError::Nip05Failed(e) => {
|
|
egui::Label::new(RichText::new(e).color(ui.visuals().error_fg_color))
|
|
}
|
|
};
|
|
ui.add(error_label.truncate());
|
|
});
|
|
}
|
|
|
|
fn login_title_text() -> RichText {
|
|
RichText::new("Login")
|
|
.text_style(NotedeckTextStyle::Heading2.text_style())
|
|
.strong()
|
|
}
|
|
|
|
fn login_textedit_info_text() -> RichText {
|
|
RichText::new("Enter your key")
|
|
.strong()
|
|
.text_style(NotedeckTextStyle::Body.text_style())
|
|
}
|
|
|
|
fn login_button() -> Button<'static> {
|
|
Button::new(
|
|
RichText::new("Login now — let's do this!")
|
|
.text_style(NotedeckTextStyle::Body.text_style())
|
|
.strong(),
|
|
)
|
|
.fill(Color32::from_rgb(0xF8, 0x69, 0xB6)) // TODO: gradient
|
|
.min_size(Vec2::new(0.0, 40.0))
|
|
}
|
|
|
|
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), nostr address (e.g. vrod@damus.io), or private key (nsec) here...")
|
|
.text_style(NotedeckTextStyle::Body.text_style()),
|
|
)
|
|
.vertical_align(Align::Center)
|
|
.min_size(Vec2::new(0.0, 40.0))
|
|
.margin(Margin::same(12.0))
|
|
})
|
|
}
|
|
|
|
mod preview {
|
|
use super::*;
|
|
|
|
pub struct AccountLoginPreview {
|
|
manager: AcquireKeyState,
|
|
}
|
|
|
|
impl View for AccountLoginPreview {
|
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
|
AccountLoginView::new(&mut self.manager).ui(ui);
|
|
}
|
|
}
|
|
|
|
impl Preview for AccountLoginView<'_> {
|
|
type Prev = AccountLoginPreview;
|
|
|
|
fn preview(cfg: PreviewConfig) -> Self::Prev {
|
|
let _ = cfg;
|
|
let manager = AcquireKeyState::new();
|
|
AccountLoginPreview { manager }
|
|
}
|
|
}
|
|
}
|