main.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. mod actions;
  2. mod ui;
  3. use client_shared::{LOGO, LOGO_DURATION};
  4. use cursive::align::Align;
  5. use cursive::view::Resizable as _;
  6. use cursive::views::TextView;
  7. use cursive::{event, Cursive};
  8. use cursive::CursiveExt as _;
  9. use std::ffi::OsString;
  10. use std::str::FromStr;
  11. use std::thread;
  12. use std::time::Duration;
  13. use ui::INPUT_FIELD_ID;
  14. use client_shared::persistence::{Appdata, load_appdata, save_appdata};
  15. pub fn get_appdata(siv: &mut Cursive) -> Appdata {
  16. siv.with_user_data(|appdata: &mut Appdata| appdata.clone())
  17. .expect("Failed to retrieve appdata.")
  18. }
  19. fn main() {
  20. if cfg!(debug_assertions) {
  21. logging::set_global_log_level(logging::LogLevel::Trace);
  22. } else {
  23. logging::set_global_log_level(logging::LogLevel::Debug);
  24. }
  25. logging::set_global_log_path(Some(OsString::from_str("./client-log.txt").unwrap()));
  26. utils::rng::shuffle_rng();
  27. let mut siv = Cursive::default();
  28. // TODO (low): Add a notice when the file is corrupted.
  29. let appdata = match load_appdata() {
  30. Ok(Some(x)) => x,
  31. _ => Appdata::new(),
  32. };
  33. siv.set_user_data(appdata);
  34. // Global hotkeys
  35. siv.add_global_callback(event::Key::Backspace, |siv| {
  36. let _ = siv.focus_name(INPUT_FIELD_ID);
  37. });
  38. // Logo intro screen
  39. siv.add_fullscreen_layer(TextView::new(LOGO).align(Align::center()).full_screen());
  40. // Background thread
  41. {
  42. let cb_sink = siv.cb_sink().clone();
  43. thread::spawn(move || {
  44. let mut timer = 0;
  45. loop {
  46. cb_sink
  47. .send(Box::new(move |siv| {
  48. let appdata = get_appdata(siv);
  49. if appdata.intro_screen_shown_until > utils::time::time_millis() {
  50. thread::sleep(Duration::from_millis(
  51. appdata
  52. .intro_screen_shown_until
  53. .saturating_sub(utils::time::time_millis())
  54. as u64,
  55. ));
  56. // Main layout
  57. let main_layout = ui::setup_ui(siv);
  58. siv.pop_layer();
  59. siv.add_fullscreen_layer(main_layout);
  60. }
  61. ui::visual_update(siv);
  62. if timer % appdata.persistent_data.api_refresh_rate == 0 {
  63. // TODO (low): Add a notice when automatic refresh fails.
  64. let _ = actions::load_messages(siv);
  65. }
  66. save_appdata(get_appdata(siv));
  67. }))
  68. .expect("Failed to send callback from background thread.");
  69. timer += 1;
  70. thread::sleep(Duration::from_secs(1));
  71. }
  72. });
  73. }
  74. siv.with_user_data(|appdata: &mut Appdata| {
  75. appdata.intro_screen_shown_until = utils::time::time_millis() + LOGO_DURATION;
  76. });
  77. siv.run();
  78. }