notedeck

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

android.rs (4638B)


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