initial postbox for testing
not sure if we want to put this here yet, but it matches the design and will be useful for testing Fixes: https://github.com/damus-io/notedeck/issues/110 Suggested-by: Rob
This commit is contained in:
102
src/app.rs
102
src/app.rs
@@ -1,7 +1,7 @@
|
|||||||
use crate::account_manager::AccountManager;
|
use crate::account_manager::AccountManager;
|
||||||
use crate::app_creation::setup_cc;
|
use crate::app_creation::setup_cc;
|
||||||
use crate::app_style::user_requested_visuals_change;
|
use crate::app_style::user_requested_visuals_change;
|
||||||
use crate::draft::Draft;
|
use crate::draft::{DraftSource, Drafts};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::frame_history::FrameHistory;
|
use crate::frame_history::FrameHistory;
|
||||||
use crate::imgcache::ImageCache;
|
use crate::imgcache::ImageCache;
|
||||||
@@ -16,7 +16,6 @@ use crate::Result;
|
|||||||
use egui_nav::{Nav, NavAction};
|
use egui_nav::{Nav, NavAction};
|
||||||
use enostr::RelayPool;
|
use enostr::RelayPool;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use egui::{Context, Frame, Style};
|
use egui::{Context, Frame, Style};
|
||||||
@@ -48,10 +47,10 @@ pub struct Damus {
|
|||||||
/// global navigation for account management popups, etc.
|
/// global navigation for account management popups, etc.
|
||||||
pub global_nav: Vec<Route>,
|
pub global_nav: Vec<Route>,
|
||||||
pub textmode: bool,
|
pub textmode: bool,
|
||||||
pub drafts: HashMap<enostr::NoteId, Draft>,
|
|
||||||
|
|
||||||
pub timelines: Vec<Timeline>,
|
pub timelines: Vec<Timeline>,
|
||||||
pub selected_timeline: i32,
|
pub selected_timeline: i32,
|
||||||
|
pub drafts: Drafts,
|
||||||
|
|
||||||
pub img_cache: ImageCache,
|
pub img_cache: ImageCache,
|
||||||
pub ndb: Ndb,
|
pub ndb: Ndb,
|
||||||
@@ -711,7 +710,7 @@ impl Damus {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
is_mobile,
|
is_mobile,
|
||||||
drafts: HashMap::new(),
|
drafts: Drafts::default(),
|
||||||
state: DamusState::Initializing,
|
state: DamusState::Initializing,
|
||||||
pool: RelayPool::new(),
|
pool: RelayPool::new(),
|
||||||
img_cache: ImageCache::new(imgcache_dir),
|
img_cache: ImageCache::new(imgcache_dir),
|
||||||
@@ -746,7 +745,7 @@ impl Damus {
|
|||||||
config.set_ingester_threads(2);
|
config.set_ingester_threads(2);
|
||||||
Self {
|
Self {
|
||||||
is_mobile,
|
is_mobile,
|
||||||
drafts: HashMap::new(),
|
drafts: Drafts::default(),
|
||||||
state: DamusState::Initializing,
|
state: DamusState::Initializing,
|
||||||
pool: RelayPool::new(),
|
pool: RelayPool::new(),
|
||||||
img_cache: ImageCache::new(imgcache_dir),
|
img_cache: ImageCache::new(imgcache_dir),
|
||||||
@@ -891,53 +890,68 @@ fn render_nav(routes: Vec<Route>, timeline_ind: usize, app: &mut Damus, ui: &mut
|
|||||||
let navigating = app.timelines[timeline_ind].navigating;
|
let navigating = app.timelines[timeline_ind].navigating;
|
||||||
let app_ctx = Rc::new(RefCell::new(app));
|
let app_ctx = Rc::new(RefCell::new(app));
|
||||||
|
|
||||||
let nav_response =
|
let nav_response = Nav::new(routes)
|
||||||
Nav::new(routes)
|
.navigating(navigating)
|
||||||
.navigating(navigating)
|
.title(false)
|
||||||
.show(ui, |ui, nav| match nav.top() {
|
.show(ui, |ui, nav| match nav.top() {
|
||||||
Route::Timeline(_n) => {
|
Route::Timeline(_n) => {
|
||||||
timeline::timeline_view(ui, &mut app_ctx.borrow_mut(), timeline_ind);
|
let app = &mut app_ctx.borrow_mut();
|
||||||
|
|
||||||
|
if timeline_ind == 0 {
|
||||||
|
// show a postbox in the first timeline
|
||||||
|
|
||||||
|
// TODO: don't show the post box if we have no accounts
|
||||||
|
let poster = app
|
||||||
|
.account_manager
|
||||||
|
.get_selected_account_index()
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
if let Ok(txn) = Transaction::new(&app.ndb) {
|
||||||
|
ui::PostView::new(app, DraftSource::Compose, poster).ui(&txn, ui);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
timeline::timeline_view(ui, app, timeline_ind);
|
||||||
|
}
|
||||||
|
|
||||||
Route::ManageAccount => {
|
Route::ManageAccount => {
|
||||||
ui.label("account management view");
|
ui.label("account management view");
|
||||||
}
|
}
|
||||||
|
|
||||||
Route::Thread(_key) => {
|
Route::Thread(_key) => {
|
||||||
ui.label("thread view");
|
ui.label("thread view");
|
||||||
}
|
}
|
||||||
|
|
||||||
Route::Relays => {
|
Route::Relays => {
|
||||||
let pool = &mut app_ctx.borrow_mut().pool;
|
let pool = &mut app_ctx.borrow_mut().pool;
|
||||||
let manager = RelayPoolManager::new(pool);
|
let manager = RelayPoolManager::new(pool);
|
||||||
RelayView::new(manager).ui(ui);
|
RelayView::new(manager).ui(ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
Route::Reply(id) => {
|
Route::Reply(id) => {
|
||||||
let mut app = app_ctx.borrow_mut();
|
let mut app = app_ctx.borrow_mut();
|
||||||
|
|
||||||
let txn = if let Ok(txn) = Transaction::new(&app.ndb) {
|
let txn = if let Ok(txn) = Transaction::new(&app.ndb) {
|
||||||
txn
|
txn
|
||||||
} else {
|
} else {
|
||||||
ui.label("Reply to unknown note");
|
ui.label("Reply to unknown note");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let note = if let Ok(note) = app.ndb.get_note_by_id(&txn, id.bytes()) {
|
let note = if let Ok(note) = app.ndb.get_note_by_id(&txn, id.bytes()) {
|
||||||
note
|
note
|
||||||
} else {
|
} else {
|
||||||
ui.label("Reply to unknown note");
|
ui.label("Reply to unknown note");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let id = egui::Id::new(("post", timeline_ind, note.key().unwrap()));
|
let id = egui::Id::new(("post", timeline_ind, note.key().unwrap()));
|
||||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||||
ui::PostReplyView::new(&mut app, ¬e)
|
ui::PostReplyView::new(&mut app, ¬e)
|
||||||
.id_source(id)
|
.id_source(id)
|
||||||
.show(ui);
|
.show(ui);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(NavAction::Returned) = nav_response.action {
|
if let Some(NavAction::Returned) = nav_response.action {
|
||||||
app_ctx.borrow_mut().timelines[timeline_ind].routes.pop();
|
app_ctx.borrow_mut().timelines[timeline_ind].routes.pop();
|
||||||
|
|||||||
22
src/draft.rs
22
src/draft.rs
@@ -1,8 +1,30 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Draft {
|
pub struct Draft {
|
||||||
pub buffer: String,
|
pub buffer: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Drafts {
|
||||||
|
pub replies: HashMap<[u8; 32], Draft>,
|
||||||
|
pub compose: Draft,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum DraftSource<'a> {
|
||||||
|
Compose,
|
||||||
|
Reply(&'a [u8; 32]), // note id
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DraftSource<'a> {
|
||||||
|
pub fn draft(&self, drafts: &'a mut Drafts) -> &'a mut Draft {
|
||||||
|
match self {
|
||||||
|
DraftSource::Compose => &mut drafts.compose,
|
||||||
|
DraftSource::Reply(id) => drafts.replies.entry(**id).or_default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Draft {
|
impl Draft {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Draft::default()
|
Draft::default()
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
use crate::app::Damus;
|
use crate::app::Damus;
|
||||||
use crate::draft::Draft;
|
use crate::draft::{Draft, DraftSource};
|
||||||
use crate::ui;
|
use crate::ui;
|
||||||
use crate::ui::{Preview, PreviewConfig, View};
|
use crate::ui::{Preview, PreviewConfig, View};
|
||||||
use egui::widgets::text_edit::TextEdit;
|
use egui::widgets::text_edit::TextEdit;
|
||||||
use nostrdb::Transaction;
|
use nostrdb::Transaction;
|
||||||
|
|
||||||
pub struct PostView<'app, 'p> {
|
pub struct PostView<'app, 'd> {
|
||||||
app: &'app mut Damus,
|
app: &'app mut Damus,
|
||||||
/// account index
|
/// account index
|
||||||
poster: usize,
|
poster: usize,
|
||||||
|
draft_source: DraftSource<'d>,
|
||||||
id_source: Option<egui::Id>,
|
id_source: Option<egui::Id>,
|
||||||
replying_to: &'p [u8; 32],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NewPost {
|
pub struct NewPost {
|
||||||
@@ -27,14 +27,14 @@ pub struct PostResponse {
|
|||||||
pub edit_response: egui::Response,
|
pub edit_response: egui::Response,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'app, 'p> PostView<'app, 'p> {
|
impl<'app, 'd> PostView<'app, 'd> {
|
||||||
pub fn new(app: &'app mut Damus, poster: usize, replying_to: &'p [u8; 32]) -> Self {
|
pub fn new(app: &'app mut Damus, draft_source: DraftSource<'d>, poster: usize) -> Self {
|
||||||
let id_source: Option<egui::Id> = None;
|
let id_source: Option<egui::Id> = None;
|
||||||
PostView {
|
PostView {
|
||||||
id_source,
|
id_source,
|
||||||
app,
|
app,
|
||||||
poster,
|
poster,
|
||||||
replying_to,
|
draft_source,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,10 +44,7 @@ impl<'app, 'p> PostView<'app, 'p> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn draft(&mut self) -> &mut Draft {
|
fn draft(&mut self) -> &mut Draft {
|
||||||
self.app
|
self.draft_source.draft(&mut self.app.drafts)
|
||||||
.drafts
|
|
||||||
.entry(enostr::NoteId::new(*self.replying_to))
|
|
||||||
.or_default()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn editbox(&mut self, txn: &nostrdb::Transaction, ui: &mut egui::Ui) -> egui::Response {
|
fn editbox(&mut self, txn: &nostrdb::Transaction, ui: &mut egui::Ui) -> egui::Response {
|
||||||
@@ -82,7 +79,12 @@ impl<'app, 'p> PostView<'app, 'p> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = ui.add(TextEdit::multiline(&mut self.draft().buffer).frame(false));
|
let buffer = &mut self.draft_source.draft(&mut self.app.drafts).buffer;
|
||||||
|
let response = ui.add(
|
||||||
|
TextEdit::multiline(buffer)
|
||||||
|
.hint_text(egui::RichText::new("Write a banger note here...").weak())
|
||||||
|
.frame(false),
|
||||||
|
);
|
||||||
|
|
||||||
let focused = response.has_focus();
|
let focused = response.has_focus();
|
||||||
|
|
||||||
@@ -183,9 +185,8 @@ mod preview {
|
|||||||
|
|
||||||
impl View for PostPreview {
|
impl View for PostPreview {
|
||||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
let test_note_id = test_data::test_pubkey();
|
|
||||||
let txn = Transaction::new(&self.app.ndb).unwrap();
|
let txn = Transaction::new(&self.app.ndb).unwrap();
|
||||||
PostView::new(&mut self.app, 0, test_note_id).ui(&txn, ui);
|
PostView::new(&mut self.app, DraftSource::Compose, 0).ui(&txn, ui);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::draft::DraftSource;
|
||||||
use crate::{ui, Damus};
|
use crate::{ui, Damus};
|
||||||
|
|
||||||
pub struct PostReplyView<'a> {
|
pub struct PostReplyView<'a> {
|
||||||
@@ -58,7 +59,8 @@ impl<'a> PostReplyView<'a> {
|
|||||||
let rect_before_post = ui.min_rect();
|
let rect_before_post = ui.min_rect();
|
||||||
|
|
||||||
let id = self.id();
|
let id = self.id();
|
||||||
let post_response = ui::PostView::new(self.app, poster, replying_to)
|
let draft_source = DraftSource::Reply(replying_to);
|
||||||
|
let post_response = ui::PostView::new(self.app, draft_source, poster)
|
||||||
.id_source(id)
|
.id_source(id)
|
||||||
.ui(self.note.txn().unwrap(), ui);
|
.ui(self.note.txn().unwrap(), ui);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user