notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

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 }