notedeck

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

android.rs (5288B)


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