Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Notedeck to notedeck crate #656

Merged
merged 1 commit into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ scripts/macos_build_secrets.sh
*.txt
/tags
*.mdb
.idea/
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion crates/notedeck/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ strum_macros = { workspace = true }
dirs = { workspace = true }
enostr = { workspace = true }
egui = { workspace = true }
eframe = { workspace = true }
image = { workspace = true }
base32 = { workspace = true }
poll-promise = { workspace = true }
Expand All @@ -22,6 +23,7 @@ serde = { workspace = true }
hex = { workspace = true }
thiserror = { workspace = true }
puffin = { workspace = true, optional = true }
puffin_egui = { workspace = true, optional = true }
sha2 = { workspace = true }

[dev-dependencies]
Expand All @@ -31,4 +33,4 @@ tempfile = { workspace = true }
security-framework = { workspace = true }

[features]
profiling = ["puffin"]
profiling = ["puffin", "puffin_egui"]
233 changes: 232 additions & 1 deletion crates/notedeck/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,236 @@
use crate::AppContext;
use crate::persist::{AppSizeHandler, ZoomHandler};
use crate::{
Accounts, AppContext, Args, DataPath, DataPathType, Directory, FileKeyStorage, ImageCache,
KeyStorageType, NoteCache, ThemeHandler, UnknownIds,
};
use egui::ThemePreference;
use enostr::RelayPool;
use nostrdb::{Config, Ndb, Transaction};
use std::cell::RefCell;
use std::path::Path;
use std::rc::Rc;
use tracing::{error, info};

pub trait App {
fn update(&mut self, ctx: &mut AppContext<'_>, ui: &mut egui::Ui);
}

/// Main notedeck app framework
pub struct Notedeck {
ndb: Ndb,
img_cache: ImageCache,
unknown_ids: UnknownIds,
pool: RelayPool,
note_cache: NoteCache,
accounts: Accounts,
path: DataPath,
args: Args,
theme: ThemeHandler,
app: Option<Rc<RefCell<dyn App>>>,
zoom: ZoomHandler,
app_size: AppSizeHandler,
}

fn margin_top(narrow: bool) -> f32 {
#[cfg(target_os = "android")]
{
// FIXME - query the system bar height and adjust more precisely
let _ = narrow; // suppress compiler warning on android
40.0
}
#[cfg(not(target_os = "android"))]
{
if narrow {
50.0
} else {
0.0
}
}
}

/// Our chrome, which is basically nothing
fn main_panel(style: &egui::Style, narrow: bool) -> egui::CentralPanel {
let inner_margin = egui::Margin {
top: margin_top(narrow),
left: 0.0,
right: 0.0,
bottom: 0.0,
};
egui::CentralPanel::default().frame(egui::Frame {
inner_margin,
fill: style.visuals.panel_fill,
..Default::default()
})
}

impl eframe::App for Notedeck {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
#[cfg(feature = "profiling")]
puffin::GlobalProfiler::lock().new_frame();

main_panel(&ctx.style(), crate::ui::is_narrow(ctx)).show(ctx, |ui| {
// render app
if let Some(app) = &self.app {
let app = app.clone();
app.borrow_mut().update(&mut self.app_context(), ui);
}
});

self.zoom.try_save_zoom_factor(ctx);
self.app_size.try_save_app_size(ctx);

if self.args.relay_debug && self.pool.debug.is_none() {
self.pool.use_debug();
}

#[cfg(feature = "profiling")]
puffin_egui::profiler_window(ctx);
}

/// Called by the framework to save state before shutdown.
fn save(&mut self, _storage: &mut dyn eframe::Storage) {
//eframe::set_value(storage, eframe::APP_KEY, self);
}
}

#[cfg(feature = "profiling")]
fn setup_profiling() {
puffin::set_scopes_on(true); // tell puffin to collect data
}

impl Notedeck {
pub fn new<P: AsRef<Path>>(ctx: &egui::Context, data_path: P, args: &[String]) -> Self {
#[cfg(feature = "profiling")]
setup_profiling();

let parsed_args = Args::parse(args);

let data_path = parsed_args
.datapath
.clone()
.unwrap_or(data_path.as_ref().to_str().expect("db path ok").to_string());
let path = DataPath::new(&data_path);
let dbpath_str = parsed_args
.dbpath
.clone()
.unwrap_or_else(|| path.path(DataPathType::Db).to_str().unwrap().to_string());

let _ = std::fs::create_dir_all(&dbpath_str);

let img_cache_dir = path.path(DataPathType::Cache).join(ImageCache::rel_dir());
let _ = std::fs::create_dir_all(img_cache_dir.clone());

let map_size = if cfg!(target_os = "windows") {
// 16 Gib on windows because it actually creates the file
1024usize * 1024usize * 1024usize * 16usize
} else {
// 1 TiB for everything else since its just virtually mapped
1024usize * 1024usize * 1024usize * 1024usize
};

let theme = ThemeHandler::new(&path);
let config = Config::new().set_ingester_threads(4).set_mapsize(map_size);

let keystore = if parsed_args.use_keystore {
let keys_path = path.path(DataPathType::Keys);
let selected_key_path = path.path(DataPathType::SelectedKey);
KeyStorageType::FileSystem(FileKeyStorage::new(
Directory::new(keys_path),
Directory::new(selected_key_path),
))
} else {
KeyStorageType::None
};

let mut accounts = Accounts::new(keystore, parsed_args.relays.clone());

let num_keys = parsed_args.keys.len();

let mut unknown_ids = UnknownIds::default();
let ndb = Ndb::new(&dbpath_str, &config).expect("ndb");

{
let txn = Transaction::new(&ndb).expect("txn");
for key in &parsed_args.keys {
info!("adding account: {}", &key.pubkey);
accounts
.add_account(key.clone())
.process_action(&mut unknown_ids, &ndb, &txn);
}
}

if num_keys != 0 {
accounts.select_account(0);
}

// AccountManager will setup the pool on first update
let mut pool = RelayPool::new();
{
let ctx = ctx.clone();
if let Err(err) = pool.add_multicast_relay(move || ctx.request_repaint()) {
error!("error setting up multicast relay: {err}");
}
}

let img_cache = ImageCache::new(img_cache_dir);
let note_cache = NoteCache::default();
let unknown_ids = UnknownIds::default();
let zoom = ZoomHandler::new(&path);
let app_size = AppSizeHandler::new(&path);

if let Some(z) = zoom.get_zoom_factor() {
ctx.set_zoom_factor(z);
}

// migrate
if let Err(e) = img_cache.migrate_v0() {
error!("error migrating image cache: {e}");
}

Self {
ndb,
img_cache,
unknown_ids,
pool,
note_cache,
accounts,
path: path.clone(),
args: parsed_args,
theme,
app: None,
zoom,
app_size,
}
}

pub fn app<A: App + 'static>(mut self, app: A) -> Self {
self.set_app(app);
self
}

pub fn app_context(&mut self) -> AppContext<'_> {
AppContext {
ndb: &mut self.ndb,
img_cache: &mut self.img_cache,
unknown_ids: &mut self.unknown_ids,
pool: &mut self.pool,
note_cache: &mut self.note_cache,
accounts: &mut self.accounts,
path: &self.path,
args: &self.args,
theme: &mut self.theme,
}
}

pub fn set_app<T: App + 'static>(&mut self, app: T) {
self.app = Some(Rc::new(RefCell::new(app)));
}

pub fn args(&self) -> &Args {
&self.args
}

pub fn theme(&self) -> ThemePreference {
self.theme.load()
}
}
7 changes: 4 additions & 3 deletions crates/notedeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@ mod imgcache;
mod muted;
pub mod note;
mod notecache;
mod persist;
mod result;
pub mod storage;
mod style;
pub mod theme;
mod theme_handler;
mod time;
mod timecache;
mod timed_serializer;
pub mod ui;
mod unknowns;
mod user_account;

pub use accounts::{AccountData, Accounts, AccountsAction, AddAccountAction, SwitchAccountAction};
pub use app::App;
pub use app::{App, Notedeck};
pub use args::Args;
pub use context::AppContext;
pub use error::{Error, FilterError};
Expand All @@ -31,13 +32,13 @@ pub use imgcache::ImageCache;
pub use muted::{MuteFun, Muted};
pub use note::{NoteRef, RootIdError, RootNoteId, RootNoteIdBuf};
pub use notecache::{CachedNote, NoteCache};
pub use persist::*;
pub use result::Result;
pub use storage::{
DataPath, DataPathType, Directory, FileKeyStorage, KeyStorageResponse, KeyStorageType,
};
pub use style::NotedeckTextStyle;
pub use theme::ColorTheme;
pub use theme_handler::ThemeHandler;
pub use time::time_ago_since;
pub use timecache::TimeCached;
pub use unknowns::{get_unknown_note_ids, NoteRefsUnkIdAction, SingleUnkIdAction, UnknownIds};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ use std::time::Duration;

use egui::Context;

use notedeck::{DataPath, DataPathType};

use crate::timed_serializer::TimedSerializer;
use crate::{DataPath, DataPathType};

pub struct AppSizeHandler {
serializer: TimedSerializer<egui::Vec2>,
Expand Down
7 changes: 7 additions & 0 deletions crates/notedeck/src/persist/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mod app_size;
mod theme_handler;
mod zoom;

pub use app_size::AppSizeHandler;
pub use theme_handler::ThemeHandler;
pub use zoom::ZoomHandler;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{DataPath, DataPathType};
use egui::Context;
use notedeck::{DataPath, DataPathType};

use crate::timed_serializer::TimedSerializer;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::time::{Duration, Instant};

use notedeck::{storage, DataPath, DataPathType, Directory};
use crate::{storage, DataPath, DataPathType, Directory};
use serde::{Deserialize, Serialize};
use tracing::info;

Expand Down
2 changes: 0 additions & 2 deletions crates/notedeck_chrome/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ description = "The nostr browser"
eframe = { workspace = true }
egui_extras = { workspace = true }
egui = { workspace = true }
enostr = { workspace = true }
nostrdb = { workspace = true }
notedeck_columns = { workspace = true }
notedeck = { workspace = true }
puffin = { workspace = true, optional = true }
Expand Down
Loading
Loading