mirror of
https://github.com/aljazceru/notedeck.git
synced 2026-01-24 02:34:20 +01:00
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1108,7 +1108,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "egui_nav"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/damus-io/egui-nav?rev=ac22dfccbaa3d2fee57a8b0250bde11ebf4c5563#ac22dfccbaa3d2fee57a8b0250bde11ebf4c5563"
|
||||
source = "git+https://github.com/damus-io/egui-nav?rev=ef7018a261aa0de13b5074ab3e812ef56e44db09#ef7018a261aa0de13b5074ab3e812ef56e44db09"
|
||||
dependencies = [
|
||||
"egui",
|
||||
"egui_extras",
|
||||
|
||||
@@ -32,7 +32,7 @@ eframe = { version = "0.27.2", default-features = false, features = [ "glow", "w
|
||||
egui_extras = { version = "0.27.2", features = ["all_loaders"] }
|
||||
ehttp = "0.2.0"
|
||||
egui_tabs = { git = "https://github.com/damus-io/egui-tabs", rev = "120971fc43db6ba0b6f194f4bd4a66f7e00a4e22" }
|
||||
egui_nav = { git = "https://github.com/damus-io/egui-nav", rev = "ac22dfccbaa3d2fee57a8b0250bde11ebf4c5563" }
|
||||
egui_nav = { git = "https://github.com/damus-io/egui-nav", rev = "ef7018a261aa0de13b5074ab3e812ef56e44db09" }
|
||||
reqwest = { version = "0.12.4", default-features = false, features = [ "rustls-tls-native-roots" ] }
|
||||
image = { version = "0.24", features = ["jpeg", "png", "webp"] }
|
||||
log = "0.4.17"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub struct NoteId([u8; 32]);
|
||||
|
||||
impl NoteId {
|
||||
|
||||
24
src/app.rs
24
src/app.rs
@@ -1,6 +1,7 @@
|
||||
use crate::account_manager::AccountManager;
|
||||
use crate::app_creation::setup_cc;
|
||||
use crate::app_style::user_requested_visuals_change;
|
||||
use crate::draft::Draft;
|
||||
use crate::error::Error;
|
||||
use crate::frame_history::FrameHistory;
|
||||
use crate::imgcache::ImageCache;
|
||||
@@ -15,6 +16,7 @@ use crate::Result;
|
||||
use egui_nav::{Nav, NavAction};
|
||||
use enostr::RelayPool;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use egui::{Context, Frame, Style};
|
||||
@@ -46,6 +48,7 @@ pub struct Damus {
|
||||
/// global navigation for account management popups, etc.
|
||||
//nav: Vec<Route>,
|
||||
pub textmode: bool,
|
||||
pub drafts: HashMap<enostr::NoteId, Draft>,
|
||||
|
||||
pub timelines: Vec<Timeline>,
|
||||
pub selected_timeline: i32,
|
||||
@@ -706,6 +709,7 @@ impl Damus {
|
||||
|
||||
Self {
|
||||
is_mobile,
|
||||
drafts: HashMap::new(),
|
||||
state: DamusState::Initializing,
|
||||
pool: RelayPool::new(),
|
||||
img_cache: ImageCache::new(imgcache_dir),
|
||||
@@ -737,6 +741,7 @@ impl Damus {
|
||||
config.set_ingester_threads(2);
|
||||
Self {
|
||||
is_mobile,
|
||||
drafts: HashMap::new(),
|
||||
state: DamusState::Initializing,
|
||||
pool: RelayPool::new(),
|
||||
img_cache: ImageCache::new(imgcache_dir),
|
||||
@@ -901,7 +906,8 @@ fn render_nav(routes: Vec<Route>, timeline_ind: usize, app: &mut Damus, ui: &mut
|
||||
}
|
||||
|
||||
Route::Reply(id) => {
|
||||
let app = app_ctx.borrow();
|
||||
let mut app = app_ctx.borrow_mut();
|
||||
|
||||
let txn = if let Ok(txn) = Transaction::new(&app.ndb) {
|
||||
txn
|
||||
} else {
|
||||
@@ -916,15 +922,13 @@ fn render_nav(routes: Vec<Route>, timeline_ind: usize, app: &mut Damus, ui: &mut
|
||||
return;
|
||||
};
|
||||
|
||||
ui.label(format!(
|
||||
"Replying to note by {}",
|
||||
app.ndb
|
||||
.get_profile_by_pubkey(&txn, note.pubkey())
|
||||
.as_ref()
|
||||
.ok()
|
||||
.and_then(|pr| Some(crate::profile::get_profile_name(pr)?.username()))
|
||||
.unwrap_or("??")
|
||||
));
|
||||
let poster = app
|
||||
.account_manager
|
||||
.get_selected_account_index()
|
||||
.unwrap_or(0);
|
||||
|
||||
let replying_to = note.pubkey();
|
||||
let _r = ui::PostView::new(&mut app, poster, replying_to).ui(&txn, ui);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ const ORANGE_700: Color32 = Color32::from_rgb(0xF6, 0xB1, 0x4A);
|
||||
const SEMI_DARKER_BG: Color32 = Color32::from_rgb(0x39, 0x39, 0x39);
|
||||
const DARKER_BG: Color32 = Color32::from_rgb(0x1F, 0x1F, 0x1F);
|
||||
const DARK_BG: Color32 = Color32::from_rgb(0x2C, 0x2C, 0x2C);
|
||||
const DARK_ISH_BG: Color32 = Color32::from_rgb(0x22, 0x22, 0x22);
|
||||
const DARK_ISH_BG: Color32 = Color32::from_rgb(0x25, 0x25, 0x25);
|
||||
const SEMI_DARK_BG: Color32 = Color32::from_rgb(0x44, 0x44, 0x44);
|
||||
|
||||
const LIGHTER_GRAY: Color32 = Color32::from_rgb(0xf8, 0xf8, 0xf8);
|
||||
@@ -53,7 +53,7 @@ pub fn desktop_dark_color_theme() -> ColorTheme {
|
||||
ColorTheme {
|
||||
// VISUALS
|
||||
panel_fill: DARKER_BG,
|
||||
extreme_bg_color: SEMI_DARKER_BG,
|
||||
extreme_bg_color: DARK_ISH_BG,
|
||||
text_color: Color32::WHITE,
|
||||
err_fg_color: RED_700,
|
||||
warn_fg_color: ORANGE_700,
|
||||
|
||||
10
src/draft.rs
Normal file
10
src/draft.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
#[derive(Default)]
|
||||
pub struct Draft {
|
||||
pub buffer: String,
|
||||
}
|
||||
|
||||
impl Draft {
|
||||
pub fn new() -> Self {
|
||||
Draft::default()
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ pub mod account_manager;
|
||||
pub mod app_creation;
|
||||
mod app_style;
|
||||
mod colors;
|
||||
mod draft;
|
||||
mod filter;
|
||||
mod fonts;
|
||||
mod frame_history;
|
||||
|
||||
@@ -55,6 +55,15 @@ const TEST_PROFILE_DATA: [u8; 448] = [
|
||||
0x0c, 0x00, 0x24, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x1c, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
];
|
||||
|
||||
const TEST_PUBKEY: [u8; 32] = [
|
||||
0x32, 0xe1, 0x82, 0x76, 0x35, 0x45, 0x0e, 0xbb, 0x3c, 0x5a, 0x7d, 0x12, 0xc1, 0xf8, 0xe7, 0xb2,
|
||||
0xb5, 0x14, 0x43, 0x9a, 0xc1, 0x0a, 0x67, 0xee, 0xf3, 0xd9, 0xfd, 0x9c, 0x5c, 0x68, 0xe2, 0x45,
|
||||
];
|
||||
|
||||
pub fn test_pubkey() -> &'static [u8; 32] {
|
||||
&TEST_PUBKEY
|
||||
}
|
||||
|
||||
pub fn test_profile_record() -> ProfileRecord<'static> {
|
||||
ProfileRecord::new_owned(&TEST_PROFILE_DATA).unwrap()
|
||||
}
|
||||
@@ -83,7 +92,7 @@ pub fn get_test_accounts() -> Vec<UserAccount> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn get_account_manager_test_app(is_mobile: bool) -> Damus {
|
||||
pub fn test_app(is_mobile: bool) -> Damus {
|
||||
let db_dir = Path::new(".");
|
||||
let path = db_dir.to_str().unwrap();
|
||||
let mut app = Damus::mock(path, is_mobile);
|
||||
|
||||
@@ -201,7 +201,7 @@ fn selected_widget() -> impl egui::Widget {
|
||||
mod preview {
|
||||
|
||||
use super::*;
|
||||
use crate::test_data::get_account_manager_test_app;
|
||||
use crate::test_data;
|
||||
|
||||
pub struct AccountManagementPreview {
|
||||
is_mobile: bool,
|
||||
@@ -210,7 +210,7 @@ mod preview {
|
||||
|
||||
impl AccountManagementPreview {
|
||||
fn new(is_mobile: bool) -> Self {
|
||||
let app = get_account_manager_test_app(is_mobile);
|
||||
let app = test_data::test_app(is_mobile);
|
||||
|
||||
AccountManagementPreview { is_mobile, app }
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ mod previews {
|
||||
|
||||
impl AccountSelectionPreview {
|
||||
fn new(is_mobile: bool) -> Self {
|
||||
let app = test_data::get_account_manager_test_app(is_mobile);
|
||||
let app = test_data::test_app(is_mobile);
|
||||
AccountSelectionPreview { app }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ pub mod username;
|
||||
pub use account_management::AccountManagementView;
|
||||
pub use account_switcher::AccountSelectionWidget;
|
||||
pub use mention::Mention;
|
||||
pub use note::{BarAction, Note, NoteResponse};
|
||||
pub use note::{BarAction, Note, NoteResponse, PostView};
|
||||
pub use preview::{Preview, PreviewApp, PreviewConfig};
|
||||
pub use profile::{profile_preview_controller, ProfilePic, ProfilePreview};
|
||||
pub use relay::RelayView;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
pub mod contents;
|
||||
pub mod options;
|
||||
pub mod post;
|
||||
|
||||
pub use contents::NoteContents;
|
||||
pub use options::NoteOptions;
|
||||
pub use post::PostView;
|
||||
|
||||
use crate::{colors, notecache::CachedNote, ui, ui::View, Damus};
|
||||
use egui::{Label, RichText, Sense};
|
||||
|
||||
112
src/ui/note/post.rs
Normal file
112
src/ui/note/post.rs
Normal file
@@ -0,0 +1,112 @@
|
||||
use crate::app::Damus;
|
||||
use crate::draft::Draft;
|
||||
use crate::ui::{Preview, PreviewConfig, View};
|
||||
use crate::{ui, Error};
|
||||
use egui::widgets::text_edit::TextEdit;
|
||||
use nostrdb::Transaction;
|
||||
|
||||
pub struct PostView<'app, 'p> {
|
||||
app: &'app mut Damus,
|
||||
/// account index
|
||||
poster: usize,
|
||||
replying_to: &'p [u8; 32],
|
||||
}
|
||||
|
||||
impl<'app, 'p> PostView<'app, 'p> {
|
||||
pub fn new(app: &'app mut Damus, poster: usize, replying_to: &'p [u8; 32]) -> Self {
|
||||
PostView {
|
||||
app,
|
||||
poster,
|
||||
replying_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ui(&mut self, txn: &nostrdb::Transaction, ui: &mut egui::Ui) -> Result<(), Error> {
|
||||
egui::Frame::default()
|
||||
.inner_margin(egui::Margin::same(12.0))
|
||||
.inner_margin(egui::Margin::same(12.0))
|
||||
.fill(ui.visuals().extreme_bg_color)
|
||||
.stroke(ui.visuals().noninteractive().bg_stroke)
|
||||
.rounding(12.0)
|
||||
.show(ui, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 12.0;
|
||||
|
||||
let pfp_size = 24.0;
|
||||
|
||||
let poster_pubkey = self
|
||||
.app
|
||||
.account_manager
|
||||
.get_account(self.poster)
|
||||
.map(|acc| acc.pubkey.bytes())
|
||||
.unwrap_or(crate::test_data::test_pubkey());
|
||||
|
||||
// TODO: refactor pfp control to do all of this for us
|
||||
let poster_pfp = self
|
||||
.app
|
||||
.ndb
|
||||
.get_profile_by_pubkey(&txn, poster_pubkey)
|
||||
.as_ref()
|
||||
.ok()
|
||||
.and_then(|p| ui::ProfilePic::from_profile(&mut self.app.img_cache, p));
|
||||
|
||||
if let Some(pfp) = poster_pfp {
|
||||
ui.add(pfp);
|
||||
} else {
|
||||
ui.add(
|
||||
ui::ProfilePic::new(
|
||||
&mut self.app.img_cache,
|
||||
ui::ProfilePic::no_pfp_url(),
|
||||
)
|
||||
.size(pfp_size),
|
||||
);
|
||||
}
|
||||
|
||||
let draft = self
|
||||
.app
|
||||
.drafts
|
||||
.entry(enostr::NoteId::new(*self.replying_to))
|
||||
.or_insert_with(|| Draft::new());
|
||||
|
||||
ui.add(TextEdit::multiline(&mut draft.buffer).frame(false));
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.inner
|
||||
})
|
||||
.inner
|
||||
}
|
||||
}
|
||||
|
||||
mod preview {
|
||||
use super::*;
|
||||
use crate::test_data;
|
||||
|
||||
pub struct PostPreview {
|
||||
app: Damus,
|
||||
}
|
||||
|
||||
impl PostPreview {
|
||||
fn new(is_mobile: bool) -> Self {
|
||||
PostPreview {
|
||||
app: test_data::test_app(is_mobile),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl View for PostPreview {
|
||||
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 _r = PostView::new(&mut self.app, 0, test_note_id).ui(&txn, ui);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'app, 'p> Preview for PostView<'app, 'p> {
|
||||
type Prev = PostPreview;
|
||||
|
||||
fn preview(cfg: PreviewConfig) -> Self::Prev {
|
||||
PostPreview::new(cfg.is_mobile)
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/ui/note/reply.rs
Normal file
1
src/ui/note/reply.rs
Normal file
@@ -0,0 +1 @@
|
||||
struct PostReplyView {}
|
||||
@@ -20,6 +20,17 @@ impl<'cache, 'url> ProfilePic<'cache, 'url> {
|
||||
ProfilePic { cache, url, size }
|
||||
}
|
||||
|
||||
pub fn from_profile(
|
||||
cache: &'cache mut ImageCache,
|
||||
profile: &nostrdb::ProfileRecord<'url>,
|
||||
) -> Option<Self> {
|
||||
if let Some(url) = profile.record().profile().and_then(|p| p.picture()) {
|
||||
Some(ProfilePic::new(cache, url))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_size() -> f32 {
|
||||
38.0
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ mod preview {
|
||||
|
||||
impl DesktopSidePanelPreview {
|
||||
fn new(is_mobile: bool) -> Self {
|
||||
let app = test_data::get_account_manager_test_app(is_mobile);
|
||||
let app = test_data::test_app(is_mobile);
|
||||
DesktopSidePanelPreview { app }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,10 @@ use notedeck::app_creation::{
|
||||
};
|
||||
use notedeck::ui::account_login_view::AccountLoginView;
|
||||
use notedeck::ui::{
|
||||
AccountManagementView, AccountSelectionWidget, DesktopSidePanel, Preview, PreviewApp,
|
||||
AccountManagementView, AccountSelectionWidget, DesktopSidePanel, PostView, Preview, PreviewApp,
|
||||
PreviewConfig, ProfilePic, ProfilePreview, RelayView,
|
||||
};
|
||||
use std::env;
|
||||
use tracing::info;
|
||||
|
||||
struct PreviewRunner {
|
||||
force_mobile: bool,
|
||||
@@ -16,7 +15,10 @@ struct PreviewRunner {
|
||||
|
||||
impl PreviewRunner {
|
||||
fn new(force_mobile: bool, light_mode: bool) -> Self {
|
||||
PreviewRunner { force_mobile, light_mode }
|
||||
PreviewRunner {
|
||||
force_mobile,
|
||||
light_mode,
|
||||
}
|
||||
}
|
||||
|
||||
async fn run<P>(self, preview: P)
|
||||
@@ -83,7 +85,10 @@ async fn main() {
|
||||
return;
|
||||
};
|
||||
|
||||
println!("light mode previews: {}", if light_mode { "enabled" } else { "disabled" });
|
||||
println!(
|
||||
"light mode previews: {}",
|
||||
if light_mode { "enabled" } else { "disabled" }
|
||||
);
|
||||
let is_mobile = is_mobile.unwrap_or(notedeck::ui::is_compiled_as_mobile());
|
||||
let runner = PreviewRunner::new(is_mobile, light_mode);
|
||||
|
||||
@@ -98,5 +103,6 @@ async fn main() {
|
||||
AccountManagementView,
|
||||
AccountSelectionWidget,
|
||||
DesktopSidePanel,
|
||||
PostView,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user