notedeck

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

android.rs (3978B)


      1 //#[cfg(target_os = "android")]
      2 //use egui_android::run_android;
      3 
      4 use notedeck_columns::Damus;
      5 use winit::platform::android::activity::AndroidApp;
      6 use winit::platform::android::EventLoopBuilderExtAndroid;
      7 
      8 use crate::setup::setup_chrome;
      9 use notedeck::Notedeck;
     10 use serde_json::Value;
     11 use std::fs;
     12 use std::path::PathBuf;
     13 
     14 #[no_mangle]
     15 #[tokio::main]
     16 pub async fn android_main(app: AndroidApp) {
     17     use tracing_logcat::{LogcatMakeWriter, LogcatTag};
     18     use tracing_subscriber::{prelude::*, EnvFilter};
     19 
     20     std::env::set_var("RUST_BACKTRACE", "full");
     21     std::env::set_var(
     22         "RUST_LOG",
     23         "enostr=debug,notedeck_columns=debug,notedeck_chrome=debug",
     24     );
     25 
     26     let writer =
     27         LogcatMakeWriter::new(LogcatTag::Target).expect("Failed to initialize logcat writer");
     28 
     29     let fmt_layer = tracing_subscriber::fmt::layer()
     30         .with_level(false)
     31         .with_target(false)
     32         .without_time();
     33 
     34     let filter_layer = EnvFilter::try_from_default_env()
     35         .or_else(|_| EnvFilter::try_new("info"))
     36         .unwrap();
     37 
     38     tracing_subscriber::registry()
     39         .with(filter_layer)
     40         .with(fmt_layer)
     41         .init();
     42 
     43     let path = app.internal_data_path().expect("data path");
     44     let mut options = eframe::NativeOptions::default();
     45     options.renderer = eframe::Renderer::Wgpu;
     46     // Clone `app` to use it both in the closure and later in the function
     47     let app_clone_for_event_loop = app.clone();
     48     options.event_loop_builder = Some(Box::new(move |builder| {
     49         builder.with_android_app(app_clone_for_event_loop);
     50     }));
     51 
     52     let app_args = get_app_args(app);
     53 
     54     let _res = eframe::run_native(
     55         "Damus Notedeck",
     56         options,
     57         Box::new(move |cc| {
     58             let ctx = &cc.egui_ctx;
     59             let mut notedeck = Notedeck::new(ctx, path, &app_args);
     60             setup_chrome(ctx, &notedeck.args(), notedeck.theme());
     61 
     62             let damus = Damus::new(&mut notedeck.app_context(), &app_args);
     63             notedeck.set_app(damus);
     64 
     65             Ok(Box::new(notedeck))
     66         }),
     67     );
     68 }
     69 /*
     70 Read args from a config file:
     71 - allows use of more interesting args w/o risk of checking them in by mistake
     72 - allows use of different args w/o rebuilding the app
     73 - uses compiled in defaults if config file missing or broken
     74 
     75 Example android-config.json:
     76 ```
     77 {
     78   "args": [
     79     "--npub",
     80     "npub1h50pnxqw9jg7dhr906fvy4mze2yzawf895jhnc3p7qmljdugm6gsrurqev",
     81     "-c",
     82     "contacts",
     83     "-c",
     84     "notifications"
     85   ]
     86 }
     87 ```
     88 
     89 Install/update android-config.json with:
     90 ```
     91 adb push android-config.json /sdcard/Android/data/com.damus.app/files/android-config.json
     92 ```
     93 
     94 Using internal storage would be better but it seems hard to get the config file onto
     95 the device ...
     96 */
     97 
     98 fn get_app_args(app: AndroidApp) -> Vec<String> {
     99     let external_data_path: PathBuf = app
    100         .external_data_path()
    101         .expect("external data path")
    102         .to_path_buf();
    103     let config_file = external_data_path.join("android-config.json");
    104 
    105     let default_args = vec![
    106         "--pub",
    107         "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",
    108         "-c",
    109         "contacts",
    110         "-c",
    111         "notifications",
    112         "-c",
    113         "notifications:3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681",
    114     ]
    115     .into_iter()
    116     .map(|s| s.to_string())
    117     .collect();
    118 
    119     if config_file.exists() {
    120         if let Ok(config_contents) = fs::read_to_string(config_file) {
    121             if let Ok(json) = serde_json::from_str::<Value>(&config_contents) {
    122                 if let Some(args_array) = json.get("args").and_then(|v| v.as_array()) {
    123                     let config_args = args_array
    124                         .iter()
    125                         .filter_map(|v| v.as_str().map(String::from))
    126                         .collect();
    127 
    128                     return config_args;
    129                 }
    130             }
    131         }
    132     }
    133 
    134     default_args // Return the default args if config is missing or invalid
    135 }