notedeck

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

notedeck.rs (5830B)


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