notedeck.rs (5925B)
1 #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] 2 // hide console window on Windows in release 3 use notedeck_chrome::setup::{generate_native_options, setup_chrome}; 4 5 use notedeck::{DataPath, DataPathType, Notedeck}; 6 use notedeck_columns::Damus; 7 use tracing_subscriber::EnvFilter; 8 9 // Entry point for wasm 10 //#[cfg(target_arch = "wasm32")] 11 //use wasm_bindgen::prelude::*; 12 13 fn setup_logging(path: &DataPath) { 14 #[allow(unused_variables)] // need guard to live for lifetime of program 15 let (maybe_non_blocking, maybe_guard) = { 16 let log_path = path.path(DataPathType::Log); 17 // Setup logging to file 18 19 use tracing_appender::{ 20 non_blocking, 21 rolling::{RollingFileAppender, Rotation}, 22 }; 23 24 let file_appender = RollingFileAppender::new( 25 Rotation::DAILY, 26 log_path, 27 format!("notedeck-{}.log", env!("CARGO_PKG_VERSION")), 28 ); 29 30 let (non_blocking, _guard) = non_blocking(file_appender); 31 32 (Some(non_blocking), Some(_guard)) 33 }; 34 35 // Log to stdout (if you run with `RUST_LOG=debug`). 36 if let Some(non_blocking_writer) = maybe_non_blocking { 37 use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt}; 38 39 let console_layer = fmt::layer().with_target(true).with_writer(std::io::stdout); 40 41 // Create the file layer (writes to the file) 42 let file_layer = fmt::layer() 43 .with_ansi(false) 44 .with_writer(non_blocking_writer); 45 46 let env_filter = 47 EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("notedeck=info")); 48 49 // Set up the subscriber to combine both layers 50 tracing_subscriber::registry() 51 .with(console_layer) 52 .with(file_layer) 53 .with(env_filter) 54 .init(); 55 } else { 56 tracing_subscriber::fmt() 57 .with_env_filter(EnvFilter::from_default_env()) 58 .init(); 59 } 60 } 61 62 // Desktop 63 #[cfg(not(target_arch = "wasm32"))] 64 #[tokio::main] 65 async fn main() { 66 let base_path = DataPath::default_base_or_cwd(); 67 let path = DataPath::new(base_path.clone()); 68 69 setup_logging(&path); 70 71 let _res = eframe::run_native( 72 "Damus Notedeck", 73 generate_native_options(path), 74 Box::new(|cc| { 75 let args: Vec<String> = std::env::args().collect(); 76 let ctx = &cc.egui_ctx; 77 let mut notedeck = Notedeck::new(ctx, base_path, &args); 78 setup_chrome(ctx, notedeck.args(), notedeck.theme()); 79 80 let damus = Damus::new(&mut notedeck.app_context(), &args); 81 // TODO: move "chrome" frame over Damus app somehow 82 notedeck.set_app(damus); 83 84 Ok(Box::new(notedeck)) 85 }), 86 ); 87 } 88 89 /* 90 * TODO: nostrdb not supported on web 91 * 92 #[cfg(target_arch = "wasm32")] 93 pub fn main() { 94 // Make sure panics are logged using `console.error`. 95 console_error_panic_hook::set_once(); 96 97 // Redirect tracing to console.log and friends: 98 tracing_wasm::set_as_global_default(); 99 100 wasm_bindgen_futures::spawn_local(async { 101 let web_options = eframe::WebOptions::default(); 102 eframe::start_web( 103 "the_canvas_id", // hardcode it 104 web_options, 105 Box::new(|cc| Box::new(Damus::new(cc, "."))), 106 ) 107 .await 108 .expect("failed to start eframe"); 109 }); 110 } 111 */ 112 113 #[cfg(test)] 114 mod tests { 115 use super::{Damus, Notedeck}; 116 use std::path::{Path, PathBuf}; 117 118 fn create_tmp_dir() -> PathBuf { 119 tempfile::TempDir::new() 120 .expect("tmp path") 121 .path() 122 .to_path_buf() 123 } 124 125 fn rmrf(path: impl AsRef<Path>) { 126 let _ = std::fs::remove_dir_all(path); 127 } 128 129 /// Ensure dbpath actually sets the dbpath correctly. 130 #[tokio::test] 131 async fn test_dbpath() { 132 let datapath = create_tmp_dir(); 133 let dbpath = create_tmp_dir(); 134 let args: Vec<String> = vec![ 135 "--testrunner", 136 "--datapath", 137 &datapath.to_str().unwrap(), 138 "--dbpath", 139 &dbpath.to_str().unwrap(), 140 ] 141 .iter() 142 .map(|s| s.to_string()) 143 .collect(); 144 145 let ctx = egui::Context::default(); 146 let _app = Notedeck::new(&ctx, &datapath, &args); 147 148 assert!(Path::new(&dbpath.join("data.mdb")).exists()); 149 assert!(Path::new(&dbpath.join("lock.mdb")).exists()); 150 assert!(!Path::new(&datapath.join("db")).exists()); 151 152 rmrf(datapath); 153 rmrf(dbpath); 154 } 155 156 #[tokio::test] 157 async fn test_column_args() { 158 let tmpdir = create_tmp_dir(); 159 let npub = "npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s"; 160 let args: Vec<String> = vec![ 161 "--testrunner", 162 "--no-keystore", 163 "--pub", 164 npub, 165 "-c", 166 "notifications", 167 "-c", 168 "contacts", 169 ] 170 .iter() 171 .map(|s| s.to_string()) 172 .collect(); 173 174 let ctx = egui::Context::default(); 175 let mut notedeck = Notedeck::new(&ctx, &tmpdir, &args); 176 let mut app_ctx = notedeck.app_context(); 177 let app = Damus::new(&mut app_ctx, &args); 178 179 assert_eq!(app.columns(app_ctx.accounts).columns().len(), 2); 180 181 let tl1 = app 182 .columns(app_ctx.accounts) 183 .column(0) 184 .router() 185 .top() 186 .timeline_id(); 187 188 let tl2 = app 189 .columns(app_ctx.accounts) 190 .column(1) 191 .router() 192 .top() 193 .timeline_id(); 194 195 assert_eq!(tl1.is_some(), true); 196 assert_eq!(tl2.is_some(), true); 197 198 let timelines = app.columns(app_ctx.accounts).timelines(); 199 assert!(timelines[0].kind.is_notifications()); 200 assert!(timelines[1].kind.is_contacts()); 201 202 rmrf(tmpdir); 203 } 204 }