add NotedeckOptions and feature flags, add notebook feature

This switches from bools to flags in our Args struct. We also add
notebook as an optional feature flag (--notebook) since its not ready.
This commit is contained in:
William Casarin
2025-07-31 16:03:13 -07:00
parent d12e5b363c
commit b1a5dd6cab
11 changed files with 100 additions and 46 deletions

1
Cargo.lock generated
View File

@@ -3483,6 +3483,7 @@ dependencies = [
"base32", "base32",
"bech32", "bech32",
"bincode", "bincode",
"bitflags 2.9.1",
"blurhash", "blurhash",
"dirs", "dirs",
"eframe", "eframe",

View File

@@ -47,6 +47,7 @@ fluent-langneg = { workspace = true }
unic-langid = { workspace = true } unic-langid = { workspace = true }
once_cell = { workspace = true } once_cell = { workspace = true }
md5 = { workspace = true } md5 = { workspace = true }
bitflags = { workspace = true }
regex = "1" regex = "1"
[dev-dependencies] [dev-dependencies]

View File

@@ -4,6 +4,7 @@ use crate::persist::{AppSizeHandler, SettingsHandler};
use crate::wallet::GlobalWallet; use crate::wallet::GlobalWallet;
use crate::zaps::Zaps; use crate::zaps::Zaps;
use crate::JobPool; use crate::JobPool;
use crate::NotedeckOptions;
use crate::{ use crate::{
frame_history::FrameHistory, AccountStorage, Accounts, AppContext, Args, DataPath, frame_history::FrameHistory, AccountStorage, Accounts, AppContext, Args, DataPath,
DataPathType, Directory, Images, NoteAction, NoteCache, RelayDebugView, UnknownIds, DataPathType, Directory, Images, NoteAction, NoteCache, RelayDebugView, UnknownIds,
@@ -109,7 +110,7 @@ impl eframe::App for Notedeck {
}); });
self.app_size.try_save_app_size(ctx); self.app_size.try_save_app_size(ctx);
if self.args.relay_debug { if self.args.options.contains(NotedeckOptions::RelayDebug) {
if self.pool.debug.is_none() { if self.pool.debug.is_none() {
self.pool.use_debug(); self.pool.use_debug();
} }
@@ -170,7 +171,7 @@ impl Notedeck {
let config = Config::new().set_ingester_threads(2).set_mapsize(map_size); let config = Config::new().set_ingester_threads(2).set_mapsize(map_size);
let keystore = if parsed_args.use_keystore { let keystore = if parsed_args.options.contains(NotedeckOptions::UseKeystore) {
let keys_path = path.path(DataPathType::Keys); let keys_path = path.path(DataPathType::Keys);
let selected_key_path = path.path(DataPathType::SelectedKey); let selected_key_path = path.path(DataPathType::SelectedKey);
Some(AccountStorage::new( Some(AccountStorage::new(
@@ -276,6 +277,10 @@ impl Notedeck {
} }
} }
pub fn options(&self) -> NotedeckOptions {
self.args.options
}
pub fn app<A: App + 'static>(mut self, app: A) -> Self { pub fn app<A: App + 'static>(mut self, app: A) -> Self {
self.set_app(app); self.set_app(app);
self self

View File

@@ -1,23 +1,15 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use crate::NotedeckOptions;
use enostr::{Keypair, Pubkey, SecretKey}; use enostr::{Keypair, Pubkey, SecretKey};
use tracing::error; use tracing::error;
use unic_langid::{LanguageIdentifier, LanguageIdentifierError}; use unic_langid::{LanguageIdentifier, LanguageIdentifierError};
pub struct Args { pub struct Args {
pub relays: Vec<String>, pub relays: Vec<String>,
pub is_mobile: Option<bool>,
pub locale: Option<LanguageIdentifier>, pub locale: Option<LanguageIdentifier>,
pub show_note_client: bool,
pub keys: Vec<Keypair>, pub keys: Vec<Keypair>,
pub light: bool, pub options: NotedeckOptions,
pub debug: bool,
pub relay_debug: bool,
/// Enable when running tests so we don't panic on app startup
pub tests: bool,
pub use_keystore: bool,
pub dbpath: Option<String>, pub dbpath: Option<String>,
pub datapath: Option<String>, pub datapath: Option<String>,
} }
@@ -28,14 +20,8 @@ impl Args {
let mut unrecognized_args = BTreeSet::new(); let mut unrecognized_args = BTreeSet::new();
let mut res = Args { let mut res = Args {
relays: vec![], relays: vec![],
is_mobile: None,
keys: vec![], keys: vec![],
light: false, options: NotedeckOptions::default(),
show_note_client: false,
debug: false,
relay_debug: false,
tests: false,
use_keystore: true,
dbpath: None, dbpath: None,
datapath: None, datapath: None,
locale: None, locale: None,
@@ -47,9 +33,9 @@ impl Args {
let arg = &args[i]; let arg = &args[i];
if arg == "--mobile" { if arg == "--mobile" {
res.is_mobile = Some(true); res.options.set(NotedeckOptions::Mobile, true);
} else if arg == "--light" { } else if arg == "--light" {
res.light = true; res.options.set(NotedeckOptions::LightTheme, true);
} else if arg == "--locale" { } else if arg == "--locale" {
i += 1; i += 1;
let Some(locale) = args.get(i) else { let Some(locale) = args.get(i) else {
@@ -68,11 +54,11 @@ impl Args {
} }
} }
} else if arg == "--dark" { } else if arg == "--dark" {
res.light = false; res.options.set(NotedeckOptions::LightTheme, false);
} else if arg == "--debug" { } else if arg == "--debug" {
res.debug = true; res.options.set(NotedeckOptions::Debug, true);
} else if arg == "--testrunner" { } else if arg == "--testrunner" {
res.tests = true; res.options.set(NotedeckOptions::Tests, true);
} else if arg == "--pub" || arg == "--npub" { } else if arg == "--pub" || arg == "--npub" {
i += 1; i += 1;
let pubstr = if let Some(next_arg) = args.get(i) { let pubstr = if let Some(next_arg) = args.get(i) {
@@ -135,11 +121,13 @@ impl Args {
}; };
res.relays.push(relay.clone()); res.relays.push(relay.clone());
} else if arg == "--no-keystore" { } else if arg == "--no-keystore" {
res.use_keystore = false; res.options.set(NotedeckOptions::UseKeystore, true);
} else if arg == "--relay-debug" { } else if arg == "--relay-debug" {
res.relay_debug = true; res.options.set(NotedeckOptions::RelayDebug, true);
} else if arg == "--show-note-client" { } else if arg == "--show-client" {
res.show_note_client = true; res.options.set(NotedeckOptions::ShowClient, true);
} else if arg == "--notebook" {
res.options.set(NotedeckOptions::FeatureNotebook, true);
} else { } else {
unrecognized_args.insert(arg.clone()); unrecognized_args.insert(arg.clone());
} }

View File

@@ -18,6 +18,7 @@ mod muted;
pub mod name; pub mod name;
pub mod note; pub mod note;
mod notecache; mod notecache;
mod options;
mod persist; mod persist;
pub mod platform; pub mod platform;
pub mod profile; pub mod profile;
@@ -68,6 +69,7 @@ pub use note::{
RootIdError, RootNoteId, RootNoteIdBuf, ScrollInfo, ZapAction, RootIdError, RootNoteId, RootNoteIdBuf, ScrollInfo, ZapAction,
}; };
pub use notecache::{CachedNote, NoteCache}; pub use notecache::{CachedNote, NoteCache};
pub use options::NotedeckOptions;
pub use persist::*; pub use persist::*;
pub use profile::get_profile_url; pub use profile::get_profile_url;
pub use relay_debug::RelayDebugView; pub use relay_debug::RelayDebugView;

View File

@@ -0,0 +1,39 @@
use bitflags::bitflags;
bitflags! {
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NotedeckOptions: u64 {
// ===== Settings ======
/// Are we on light theme?
const LightTheme = 1 << 0;
/// Debug controls, fps stats
const Debug = 1 << 1;
/// Show relay debug window?
const RelayDebug = 1 << 2;
/// Are we running as tests?
const Tests = 1 << 3;
/// Use keystore?
const UseKeystore = 1 << 4;
/// Show client on notes?
const ShowClient = 1 << 5;
/// Simulate is_compiled_as_mobile ?
const Mobile = 1 << 6;
// ===== Feature Flags ======
/// Is notebook enabled?
const FeatureNotebook = 1 << 32;
}
}
impl Default for NotedeckOptions {
fn default() -> Self {
NotedeckOptions::UseKeystore
}
}

View File

@@ -97,7 +97,13 @@ pub async fn android_main(app: AndroidApp) {
chrome.add_app(NotedeckApp::Columns(Box::new(columns))); chrome.add_app(NotedeckApp::Columns(Box::new(columns)));
chrome.add_app(NotedeckApp::Dave(Box::new(dave))); chrome.add_app(NotedeckApp::Dave(Box::new(dave)));
chrome.add_app(NotedeckApp::Notebook(Box::new(notebook)));
if notedeck
.options()
.contains(NotedeckOptions::FeaturesNotebook)
{
chrome.add_app(NotedeckApp::Notebook(Box::default()));
}
// test dav // test dav
chrome.set_active(0); chrome.set_active(0);

View File

@@ -6,7 +6,8 @@ use egui::{vec2, Button, Color32, Label, Layout, Rect, RichText, ThemePreference
use egui_extras::{Size, StripBuilder}; use egui_extras::{Size, StripBuilder};
use nostrdb::{ProfileRecord, Transaction}; use nostrdb::{ProfileRecord, Transaction};
use notedeck::{ use notedeck::{
tr, App, AppAction, AppContext, Localization, NotedeckTextStyle, UserAccount, WalletType, tr, App, AppAction, AppContext, Localization, NotedeckOptions, NotedeckTextStyle, UserAccount,
WalletType,
}; };
use notedeck_columns::{ use notedeck_columns::{
column::SelectionResult, timeline::kind::ListKind, timeline::TimelineKind, Damus, column::SelectionResult, timeline::kind::ListKind, timeline::TimelineKind, Damus,
@@ -612,10 +613,10 @@ fn accounts_button(ui: &mut egui::Ui) -> egui::Response {
fn notebook_button(ui: &mut egui::Ui) -> egui::Response { fn notebook_button(ui: &mut egui::Ui) -> egui::Response {
expanding_button( expanding_button(
"columns-button", "notebook-button",
40.0, 40.0,
app_images::new_message_image(), app_images::algo_image(),
app_images::new_message_image(), app_images::algo_image(),
ui, ui,
) )
} }
@@ -898,7 +899,7 @@ fn bottomup_sidebar(
.add(wallet_button()) .add(wallet_button())
.on_hover_cursor(egui::CursorIcon::PointingHand); .on_hover_cursor(egui::CursorIcon::PointingHand);
if ctx.args.debug { if ctx.args.options.contains(NotedeckOptions::Debug) {
ui.weak(format!("{}", ctx.frame_history.fps() as i32)); ui.weak(format!("{}", ctx.frame_history.fps() as i32));
ui.weak(format!( ui.weak(format!(
"{:10.1}", "{:10.1}",

View File

@@ -10,14 +10,13 @@ static GLOBAL: AccountingAllocator<std::alloc::System> =
AccountingAllocator::new(std::alloc::System); AccountingAllocator::new(std::alloc::System);
use notedeck::enostr::Error; use notedeck::enostr::Error;
use notedeck::{DataPath, DataPathType, Notedeck}; use notedeck::{DataPath, DataPathType, Notedeck, NotedeckOptions};
use notedeck_chrome::{ use notedeck_chrome::{
setup::{generate_native_options, setup_chrome}, setup::{generate_native_options, setup_chrome},
Chrome, NotedeckApp, Chrome, NotedeckApp,
}; };
use notedeck_columns::Damus; use notedeck_columns::Damus;
use notedeck_dave::Dave; use notedeck_dave::Dave;
use notedeck_notebook::Notebook;
use tracing::error; use tracing::error;
use tracing_appender::non_blocking::WorkerGuard; use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
@@ -98,7 +97,6 @@ async fn main() {
let mut chrome = Chrome::new(); let mut chrome = Chrome::new();
let columns = Damus::new(&mut notedeck.app_context(), &args); let columns = Damus::new(&mut notedeck.app_context(), &args);
let dave = Dave::new(cc.wgpu_render_state.as_ref()); let dave = Dave::new(cc.wgpu_render_state.as_ref());
let notebook = Notebook::default();
setup_chrome( setup_chrome(
ctx, ctx,
@@ -121,7 +119,13 @@ async fn main() {
chrome.add_app(NotedeckApp::Columns(Box::new(columns))); chrome.add_app(NotedeckApp::Columns(Box::new(columns)));
chrome.add_app(NotedeckApp::Dave(Box::new(dave))); chrome.add_app(NotedeckApp::Dave(Box::new(dave)));
chrome.add_app(NotedeckApp::Notebook(Box::new(notebook)));
if notedeck
.options()
.contains(NotedeckOptions::FeatureNotebook)
{
chrome.add_app(NotedeckApp::Notebook(Box::default()));
}
chrome.set_active(0); chrome.set_active(0);

View File

@@ -2,7 +2,7 @@ use crate::{fonts, theme};
use eframe::NativeOptions; use eframe::NativeOptions;
use egui::{FontId, ThemePreference}; use egui::{FontId, ThemePreference};
use notedeck::{AppSizeHandler, DataPath, NotedeckTextStyle}; use notedeck::{AppSizeHandler, DataPath, NotedeckOptions, NotedeckTextStyle};
use notedeck_ui::app_images; use notedeck_ui::app_images;
use tracing::info; use tracing::info;
@@ -13,16 +13,20 @@ pub fn setup_chrome(
note_body_font_size: f32, note_body_font_size: f32,
zoom_factor: f32, zoom_factor: f32,
) { ) {
let is_mobile = args let is_mobile =
.is_mobile args.options.contains(NotedeckOptions::Mobile) || notedeck::ui::is_compiled_as_mobile();
.unwrap_or(notedeck::ui::is_compiled_as_mobile());
let is_oled = notedeck::ui::is_oled(); let is_oled = notedeck::ui::is_oled();
// Some people have been running notedeck in debug, let's catch that! // Some people have been running notedeck in debug, let's catch that!
if !args.tests && cfg!(debug_assertions) && !args.debug { if !args.options.contains(NotedeckOptions::Tests)
&& cfg!(debug_assertions)
&& !args.options.contains(NotedeckOptions::Debug)
{
println!("--- WELCOME TO DAMUS NOTEDECK! ---"); 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!(
"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!("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!("For everyone else, try again with `cargo run --release`. Enjoy!");
println!("---------------------------------"); println!("---------------------------------");

View File

@@ -19,7 +19,7 @@ use enostr::{ClientMessage, PoolRelay, Pubkey, RelayEvent, RelayMessage, RelayPo
use nostrdb::Transaction; use nostrdb::Transaction;
use notedeck::{ use notedeck::{
tr, ui::is_narrow, Accounts, AppAction, AppContext, DataPath, DataPathType, FilterState, tr, ui::is_narrow, Accounts, AppAction, AppContext, DataPath, DataPathType, FilterState,
Images, JobsCache, Localization, SettingsHandler, UnknownIds, Images, JobsCache, Localization, NotedeckOptions, SettingsHandler, UnknownIds,
}; };
use notedeck_ui::{ use notedeck_ui::{
media::{MediaViewer, MediaViewerFlags, MediaViewerState}, media::{MediaViewer, MediaViewerFlags, MediaViewerState},
@@ -442,7 +442,10 @@ impl Damus {
let mut options = AppOptions::default(); let mut options = AppOptions::default();
let tmp_columns = !parsed_args.columns.is_empty(); let tmp_columns = !parsed_args.columns.is_empty();
options.set(AppOptions::TmpColumns, tmp_columns); options.set(AppOptions::TmpColumns, tmp_columns);
options.set(AppOptions::Debug, app_context.args.debug); options.set(
AppOptions::Debug,
app_context.args.options.contains(NotedeckOptions::Debug),
);
options.set( options.set(
AppOptions::SinceOptimize, AppOptions::SinceOptimize,
parsed_args.is_flag_set(ColumnsFlag::SinceOptimize), parsed_args.is_flag_set(ColumnsFlag::SinceOptimize),