Merge remote-tracking branch 'pr/656'
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,3 +17,4 @@ scripts/macos_build_secrets.sh
|
|||||||
*.txt
|
*.txt
|
||||||
/tags
|
/tags
|
||||||
*.mdb
|
*.mdb
|
||||||
|
.idea/
|
||||||
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -2495,6 +2495,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"base32",
|
"base32",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
"eframe",
|
||||||
"egui",
|
"egui",
|
||||||
"enostr",
|
"enostr",
|
||||||
"hex",
|
"hex",
|
||||||
@@ -2502,6 +2503,7 @@ dependencies = [
|
|||||||
"nostrdb",
|
"nostrdb",
|
||||||
"poll-promise",
|
"poll-promise",
|
||||||
"puffin 0.19.1 (git+https://github.com/jb55/puffin?rev=70ff86d5503815219b01a009afd3669b7903a057)",
|
"puffin 0.19.1 (git+https://github.com/jb55/puffin?rev=70ff86d5503815219b01a009afd3669b7903a057)",
|
||||||
|
"puffin_egui",
|
||||||
"security-framework",
|
"security-framework",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -2523,9 +2525,7 @@ dependencies = [
|
|||||||
"eframe",
|
"eframe",
|
||||||
"egui",
|
"egui",
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
"enostr",
|
|
||||||
"log",
|
"log",
|
||||||
"nostrdb",
|
|
||||||
"notedeck",
|
"notedeck",
|
||||||
"notedeck_columns",
|
"notedeck_columns",
|
||||||
"puffin 0.19.1 (git+https://github.com/jb55/puffin?rev=70ff86d5503815219b01a009afd3669b7903a057)",
|
"puffin 0.19.1 (git+https://github.com/jb55/puffin?rev=70ff86d5503815219b01a009afd3669b7903a057)",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ strum_macros = { workspace = true }
|
|||||||
dirs = { workspace = true }
|
dirs = { workspace = true }
|
||||||
enostr = { workspace = true }
|
enostr = { workspace = true }
|
||||||
egui = { workspace = true }
|
egui = { workspace = true }
|
||||||
|
eframe = { workspace = true }
|
||||||
image = { workspace = true }
|
image = { workspace = true }
|
||||||
base32 = { workspace = true }
|
base32 = { workspace = true }
|
||||||
poll-promise = { workspace = true }
|
poll-promise = { workspace = true }
|
||||||
@@ -22,6 +23,7 @@ serde = { workspace = true }
|
|||||||
hex = { workspace = true }
|
hex = { workspace = true }
|
||||||
thiserror = { workspace = true }
|
thiserror = { workspace = true }
|
||||||
puffin = { workspace = true, optional = true }
|
puffin = { workspace = true, optional = true }
|
||||||
|
puffin_egui = { workspace = true, optional = true }
|
||||||
sha2 = { workspace = true }
|
sha2 = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
@@ -31,4 +33,4 @@ tempfile = { workspace = true }
|
|||||||
security-framework = { workspace = true }
|
security-framework = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
profiling = ["puffin"]
|
profiling = ["puffin", "puffin_egui"]
|
||||||
|
|||||||
@@ -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 {
|
pub trait App {
|
||||||
fn update(&mut self, ctx: &mut AppContext<'_>, ui: &mut egui::Ui);
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,19 +9,20 @@ mod imgcache;
|
|||||||
mod muted;
|
mod muted;
|
||||||
pub mod note;
|
pub mod note;
|
||||||
mod notecache;
|
mod notecache;
|
||||||
|
mod persist;
|
||||||
mod result;
|
mod result;
|
||||||
pub mod storage;
|
pub mod storage;
|
||||||
mod style;
|
mod style;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
mod theme_handler;
|
|
||||||
mod time;
|
mod time;
|
||||||
mod timecache;
|
mod timecache;
|
||||||
|
mod timed_serializer;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
mod unknowns;
|
mod unknowns;
|
||||||
mod user_account;
|
mod user_account;
|
||||||
|
|
||||||
pub use accounts::{AccountData, Accounts, AccountsAction, AddAccountAction, SwitchAccountAction};
|
pub use accounts::{AccountData, Accounts, AccountsAction, AddAccountAction, SwitchAccountAction};
|
||||||
pub use app::App;
|
pub use app::{App, Notedeck};
|
||||||
pub use args::Args;
|
pub use args::Args;
|
||||||
pub use context::AppContext;
|
pub use context::AppContext;
|
||||||
pub use error::{Error, FilterError};
|
pub use error::{Error, FilterError};
|
||||||
@@ -31,13 +32,13 @@ pub use imgcache::ImageCache;
|
|||||||
pub use muted::{MuteFun, Muted};
|
pub use muted::{MuteFun, Muted};
|
||||||
pub use note::{NoteRef, RootIdError, RootNoteId, RootNoteIdBuf};
|
pub use note::{NoteRef, RootIdError, RootNoteId, RootNoteIdBuf};
|
||||||
pub use notecache::{CachedNote, NoteCache};
|
pub use notecache::{CachedNote, NoteCache};
|
||||||
|
pub use persist::*;
|
||||||
pub use result::Result;
|
pub use result::Result;
|
||||||
pub use storage::{
|
pub use storage::{
|
||||||
DataPath, DataPathType, Directory, FileKeyStorage, KeyStorageResponse, KeyStorageType,
|
DataPath, DataPathType, Directory, FileKeyStorage, KeyStorageResponse, KeyStorageType,
|
||||||
};
|
};
|
||||||
pub use style::NotedeckTextStyle;
|
pub use style::NotedeckTextStyle;
|
||||||
pub use theme::ColorTheme;
|
pub use theme::ColorTheme;
|
||||||
pub use theme_handler::ThemeHandler;
|
|
||||||
pub use time::time_ago_since;
|
pub use time::time_ago_since;
|
||||||
pub use timecache::TimeCached;
|
pub use timecache::TimeCached;
|
||||||
pub use unknowns::{get_unknown_note_ids, NoteRefsUnkIdAction, SingleUnkIdAction, UnknownIds};
|
pub use unknowns::{get_unknown_note_ids, NoteRefsUnkIdAction, SingleUnkIdAction, UnknownIds};
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use egui::Context;
|
use egui::Context;
|
||||||
|
|
||||||
use notedeck::{DataPath, DataPathType};
|
|
||||||
|
|
||||||
use crate::timed_serializer::TimedSerializer;
|
use crate::timed_serializer::TimedSerializer;
|
||||||
|
use crate::{DataPath, DataPathType};
|
||||||
|
|
||||||
pub struct AppSizeHandler {
|
pub struct AppSizeHandler {
|
||||||
serializer: TimedSerializer<egui::Vec2>,
|
serializer: TimedSerializer<egui::Vec2>,
|
||||||
7
crates/notedeck/src/persist/mod.rs
Normal file
7
crates/notedeck/src/persist/mod.rs
Normal file
@@ -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;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
use crate::{DataPath, DataPathType};
|
||||||
use egui::Context;
|
use egui::Context;
|
||||||
use notedeck::{DataPath, DataPathType};
|
|
||||||
|
|
||||||
use crate::timed_serializer::TimedSerializer;
|
use crate::timed_serializer::TimedSerializer;
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use notedeck::{storage, DataPath, DataPathType, Directory};
|
use crate::{storage, DataPath, DataPathType, Directory};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
@@ -12,8 +12,6 @@ description = "The nostr browser"
|
|||||||
eframe = { workspace = true }
|
eframe = { workspace = true }
|
||||||
egui_extras = { workspace = true }
|
egui_extras = { workspace = true }
|
||||||
egui = { workspace = true }
|
egui = { workspace = true }
|
||||||
enostr = { workspace = true }
|
|
||||||
nostrdb = { workspace = true }
|
|
||||||
notedeck_columns = { workspace = true }
|
notedeck_columns = { workspace = true }
|
||||||
notedeck = { workspace = true }
|
notedeck = { workspace = true }
|
||||||
puffin = { workspace = true, optional = true }
|
puffin = { workspace = true, optional = true }
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
//#[cfg(target_os = "android")]
|
//#[cfg(target_os = "android")]
|
||||||
//use egui_android::run_android;
|
//use egui_android::run_android;
|
||||||
|
|
||||||
use crate::app::Notedeck;
|
|
||||||
use notedeck_columns::Damus;
|
use notedeck_columns::Damus;
|
||||||
use winit::platform::android::activity::AndroidApp;
|
use winit::platform::android::activity::AndroidApp;
|
||||||
use winit::platform::android::EventLoopBuilderExtAndroid;
|
use winit::platform::android::EventLoopBuilderExtAndroid;
|
||||||
|
|
||||||
|
use crate::setup::setup_chrome;
|
||||||
|
use notedeck::Notedeck;
|
||||||
|
use serde_json::Value;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
pub async fn android_main(app: AndroidApp) {
|
pub async fn android_main(app: AndroidApp) {
|
||||||
@@ -50,18 +55,17 @@ pub async fn android_main(app: AndroidApp) {
|
|||||||
"Damus Notedeck",
|
"Damus Notedeck",
|
||||||
options,
|
options,
|
||||||
Box::new(move |cc| {
|
Box::new(move |cc| {
|
||||||
let mut notedeck = Notedeck::new(&cc.egui_ctx, path, &app_args);
|
let ctx = &cc.egui_ctx;
|
||||||
|
let mut notedeck = Notedeck::new(ctx, path, &app_args);
|
||||||
|
setup_chrome(ctx, ¬edeck.args(), notedeck.theme());
|
||||||
|
|
||||||
let damus = Damus::new(&mut notedeck.app_context(), &app_args);
|
let damus = Damus::new(&mut notedeck.app_context(), &app_args);
|
||||||
notedeck.add_app(damus);
|
notedeck.set_app(damus);
|
||||||
|
|
||||||
Ok(Box::new(notedeck))
|
Ok(Box::new(notedeck))
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
use serde_json::Value;
|
|
||||||
use std::fs;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read args from a config file:
|
Read args from a config file:
|
||||||
- allows use of more interesting args w/o risk of checking them in by mistake
|
- allows use of more interesting args w/o risk of checking them in by mistake
|
||||||
|
|||||||
@@ -1,265 +0,0 @@
|
|||||||
use crate::{app_size::AppSizeHandler, persist_zoom::ZoomHandler, setup::setup_cc, theme};
|
|
||||||
|
|
||||||
use notedeck::{
|
|
||||||
Accounts, AppContext, Args, DataPath, DataPathType, Directory, FileKeyStorage, ImageCache,
|
|
||||||
KeyStorageType, NoteCache, ThemeHandler, UnknownIds,
|
|
||||||
};
|
|
||||||
|
|
||||||
use enostr::RelayPool;
|
|
||||||
use nostrdb::{Config, Ndb, Transaction};
|
|
||||||
use notedeck_columns::ui::relay_debug::RelayDebugView;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use tracing::{error, info};
|
|
||||||
|
|
||||||
/// Our browser app state
|
|
||||||
pub struct Notedeck {
|
|
||||||
ndb: Ndb,
|
|
||||||
img_cache: ImageCache,
|
|
||||||
unknown_ids: UnknownIds,
|
|
||||||
pool: RelayPool,
|
|
||||||
note_cache: NoteCache,
|
|
||||||
accounts: Accounts,
|
|
||||||
path: DataPath,
|
|
||||||
args: Args,
|
|
||||||
theme: ThemeHandler,
|
|
||||||
tabs: Tabs,
|
|
||||||
app_rect_handler: AppSizeHandler,
|
|
||||||
zoom_handler: ZoomHandler,
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
/// Called by the frame work to save state before shutdown.
|
|
||||||
fn save(&mut self, _storage: &mut dyn eframe::Storage) {
|
|
||||||
//eframe::set_value(storage, eframe::APP_KEY, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
|
||||||
// TODO: render chrome
|
|
||||||
#[cfg(feature = "profiling")]
|
|
||||||
puffin::GlobalProfiler::lock().new_frame();
|
|
||||||
|
|
||||||
main_panel(&ctx.style(), notedeck::ui::is_narrow(ctx)).show(ctx, |ui| {
|
|
||||||
// render app
|
|
||||||
if let Some(app) = &self.tabs.app {
|
|
||||||
let app = app.clone();
|
|
||||||
app.borrow_mut().update(&mut self.app_context(), ui);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
self.app_rect_handler.try_save_app_size(ctx);
|
|
||||||
self.zoom_handler.try_save_zoom_factor(ctx);
|
|
||||||
|
|
||||||
if self.args.relay_debug {
|
|
||||||
if self.pool.debug.is_none() {
|
|
||||||
self.pool.use_debug();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(debug) = &mut self.pool.debug {
|
|
||||||
RelayDebugView::window(ctx, debug);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "profiling")]
|
|
||||||
puffin_egui::profiler_window(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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 is_mobile = parsed_args
|
|
||||||
.is_mobile
|
|
||||||
.unwrap_or(notedeck::ui::is_compiled_as_mobile());
|
|
||||||
|
|
||||||
// Some people have been running notedeck in debug, let's catch that!
|
|
||||||
if !parsed_args.tests && cfg!(debug_assertions) && !parsed_args.debug {
|
|
||||||
println!("--- WELCOME TO DAMUS NOTEDECK! ---");
|
|
||||||
println!("It looks like are running notedeck in debug mode, unless you are a developer, this is not likely what you want.");
|
|
||||||
println!("If you are a developer, run `cargo run -- --debug` to skip this message.");
|
|
||||||
println!("For everyone else, try again with `cargo run --release`. Enjoy!");
|
|
||||||
println!("---------------------------------");
|
|
||||||
panic!();
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_cc(ctx, is_mobile, parsed_args.light);
|
|
||||||
|
|
||||||
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 imgcache_dir = path.path(DataPathType::Cache).join(ImageCache::rel_dir());
|
|
||||||
let _ = std::fs::create_dir_all(imgcache_dir.clone());
|
|
||||||
|
|
||||||
let mapsize = 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);
|
|
||||||
ctx.options_mut(|o| {
|
|
||||||
let cur_theme = theme.load();
|
|
||||||
info!("Loaded theme {:?} from disk", cur_theme);
|
|
||||||
o.theme_preference = cur_theme;
|
|
||||||
});
|
|
||||||
ctx.set_visuals_of(
|
|
||||||
egui::Theme::Dark,
|
|
||||||
theme::dark_mode(notedeck::ui::is_compiled_as_mobile()),
|
|
||||||
);
|
|
||||||
ctx.set_visuals_of(egui::Theme::Light, theme::light_mode());
|
|
||||||
|
|
||||||
let config = Config::new().set_ingester_threads(4).set_mapsize(mapsize);
|
|
||||||
|
|
||||||
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(imgcache_dir);
|
|
||||||
let note_cache = NoteCache::default();
|
|
||||||
let unknown_ids = UnknownIds::default();
|
|
||||||
let tabs = Tabs::new(None);
|
|
||||||
let app_rect_handler = AppSizeHandler::new(&path);
|
|
||||||
let zoom_handler = ZoomHandler::new(&path);
|
|
||||||
|
|
||||||
if let Some(zoom_factor) = zoom_handler.get_zoom_factor() {
|
|
||||||
ctx.set_zoom_factor(zoom_factor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// migrate
|
|
||||||
if let Err(e) = img_cache.migrate_v0() {
|
|
||||||
error!("error migrating image cache: {e}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
|
||||||
ndb,
|
|
||||||
img_cache,
|
|
||||||
app_rect_handler,
|
|
||||||
unknown_ids,
|
|
||||||
pool,
|
|
||||||
note_cache,
|
|
||||||
accounts,
|
|
||||||
path: path.clone(),
|
|
||||||
args: parsed_args,
|
|
||||||
theme,
|
|
||||||
tabs,
|
|
||||||
zoom_handler,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 add_app<T: notedeck::App + 'static>(&mut self, app: T) {
|
|
||||||
self.tabs.app = Some(Rc::new(RefCell::new(app)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Tabs {
|
|
||||||
app: Option<Rc<RefCell<dyn notedeck::App>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Tabs {
|
|
||||||
pub fn new(app: Option<Rc<RefCell<dyn notedeck::App>>>) -> Self {
|
|
||||||
Self { app }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,6 @@
|
|||||||
pub mod app_size;
|
|
||||||
pub mod fonts;
|
pub mod fonts;
|
||||||
pub mod persist_zoom;
|
|
||||||
pub mod setup;
|
pub mod setup;
|
||||||
pub mod theme;
|
pub mod theme;
|
||||||
pub mod timed_serializer;
|
|
||||||
|
|
||||||
mod app;
|
|
||||||
|
|
||||||
pub use app::Notedeck;
|
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
mod android;
|
mod android;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
use notedeck_chrome::{setup::generate_native_options, Notedeck};
|
// hide console window on Windows in release
|
||||||
|
use notedeck_chrome::setup::{generate_native_options, setup_chrome};
|
||||||
|
|
||||||
use notedeck::{DataPath, DataPathType};
|
use notedeck::{DataPath, DataPathType, Notedeck};
|
||||||
use notedeck_columns::Damus;
|
use notedeck_columns::Damus;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
@@ -72,10 +73,13 @@ async fn main() {
|
|||||||
generate_native_options(path),
|
generate_native_options(path),
|
||||||
Box::new(|cc| {
|
Box::new(|cc| {
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
let mut notedeck = Notedeck::new(&cc.egui_ctx, base_path, &args);
|
let ctx = &cc.egui_ctx;
|
||||||
|
let mut notedeck = Notedeck::new(ctx, base_path, &args);
|
||||||
|
setup_chrome(ctx, ¬edeck.args(), notedeck.theme());
|
||||||
|
|
||||||
let damus = Damus::new(&mut notedeck.app_context(), &args);
|
let damus = Damus::new(&mut notedeck.app_context(), &args);
|
||||||
notedeck.add_app(damus);
|
// TODO: move "chrome" frame over Damus app somehow
|
||||||
|
notedeck.set_app(damus);
|
||||||
|
|
||||||
Ok(Box::new(notedeck))
|
Ok(Box::new(notedeck))
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use notedeck::DataPath;
|
use notedeck::{DataPath, Notedeck};
|
||||||
use notedeck_chrome::setup::generate_native_options;
|
use notedeck_chrome::setup::{generate_native_options, setup_chrome};
|
||||||
use notedeck_chrome::Notedeck;
|
|
||||||
use notedeck_columns::ui::configure_deck::ConfigureDeckView;
|
use notedeck_columns::ui::configure_deck::ConfigureDeckView;
|
||||||
use notedeck_columns::ui::edit_deck::EditDeckView;
|
use notedeck_columns::ui::edit_deck::EditDeckView;
|
||||||
use notedeck_columns::ui::profile::EditProfileView;
|
use notedeck_columns::ui::profile::EditProfileView;
|
||||||
@@ -31,9 +30,12 @@ impl PreviewRunner {
|
|||||||
generate_native_options(path),
|
generate_native_options(path),
|
||||||
Box::new(|cc| {
|
Box::new(|cc| {
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
let mut notedeck = Notedeck::new(&cc.egui_ctx, &base_path, &args);
|
let ctx = &cc.egui_ctx;
|
||||||
|
|
||||||
notedeck.add_app(PreviewApp::new(preview));
|
let mut notedeck = Notedeck::new(ctx, &base_path, &args);
|
||||||
|
setup_chrome(ctx, ¬edeck.args(), notedeck.theme());
|
||||||
|
|
||||||
|
notedeck.set_app(PreviewApp::new(preview));
|
||||||
|
|
||||||
Ok(Box::new(notedeck))
|
Ok(Box::new(notedeck))
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,9 +1,35 @@
|
|||||||
use crate::{app_size::AppSizeHandler, fonts, theme};
|
use crate::{fonts, theme};
|
||||||
|
|
||||||
use eframe::NativeOptions;
|
use eframe::NativeOptions;
|
||||||
use notedeck::DataPath;
|
use egui::ThemePreference;
|
||||||
|
use notedeck::{AppSizeHandler, DataPath};
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
pub fn setup_cc(ctx: &egui::Context, is_mobile: bool, light: bool) {
|
pub fn setup_chrome(ctx: &egui::Context, args: ¬edeck::Args, theme: ThemePreference) {
|
||||||
|
let is_mobile = args
|
||||||
|
.is_mobile
|
||||||
|
.unwrap_or(notedeck::ui::is_compiled_as_mobile());
|
||||||
|
|
||||||
|
// Some people have been running notedeck in debug, let's catch that!
|
||||||
|
if !args.tests && cfg!(debug_assertions) && !args.debug {
|
||||||
|
println!("--- WELCOME TO DAMUS NOTEDECK! ---");
|
||||||
|
println!("It looks like are running notedeck in debug mode, unless you are a developer, this is not likely what you want.");
|
||||||
|
println!("If you are a developer, run `cargo run -- --debug` to skip this message.");
|
||||||
|
println!("For everyone else, try again with `cargo run --release`. Enjoy!");
|
||||||
|
println!("---------------------------------");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.options_mut(|o| {
|
||||||
|
info!("Loaded theme {:?} from disk", theme);
|
||||||
|
o.theme_preference = theme;
|
||||||
|
});
|
||||||
|
ctx.set_visuals_of(egui::Theme::Dark, theme::dark_mode(is_mobile));
|
||||||
|
ctx.set_visuals_of(egui::Theme::Light, theme::light_mode());
|
||||||
|
setup_cc(ctx, is_mobile);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup_cc(ctx: &egui::Context, is_mobile: bool) {
|
||||||
fonts::setup_fonts(ctx);
|
fonts::setup_fonts(ctx);
|
||||||
|
|
||||||
//ctx.set_pixels_per_point(ctx.pixels_per_point() + UI_SCALE_FACTOR);
|
//ctx.set_pixels_per_point(ctx.pixels_per_point() + UI_SCALE_FACTOR);
|
||||||
@@ -14,12 +40,6 @@ pub fn setup_cc(ctx: &egui::Context, is_mobile: bool, light: bool) {
|
|||||||
|
|
||||||
egui_extras::install_image_loaders(ctx);
|
egui_extras::install_image_loaders(ctx);
|
||||||
|
|
||||||
if light {
|
|
||||||
ctx.set_visuals(theme::light_mode())
|
|
||||||
} else {
|
|
||||||
ctx.set_visuals(theme::dark_mode(is_mobile));
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.all_styles_mut(|style| theme::add_custom_style(is_mobile, style));
|
ctx.all_styles_mut(|style| theme::add_custom_style(is_mobile, style));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user