main.rs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{fs::File, io, io::Read};
  19. use async_std::sync::Arc;
  20. use clap::Parser;
  21. use easy_parallel::Parallel;
  22. use log::info;
  23. use simplelog::*;
  24. use smol::Executor;
  25. use termion::{async_stdin, event::Key, input::TermRead, raw::IntoRawMode};
  26. use tui::{
  27. backend::{Backend, TermionBackend},
  28. Terminal,
  29. };
  30. use darkfi::util::{
  31. async_util,
  32. cli::{get_log_config, get_log_level, spawn_config, Config},
  33. path::{expand_path, get_config_path},
  34. };
  35. pub mod config;
  36. pub mod error;
  37. pub mod model;
  38. pub mod options;
  39. pub mod parser;
  40. pub mod rpc;
  41. pub mod util;
  42. pub mod view;
  43. use crate::{
  44. config::{DnvConfig, CONFIG_FILE, CONFIG_FILE_CONTENTS},
  45. error::{DnetViewError, DnetViewResult},
  46. model::Model,
  47. options::Args,
  48. parser::DataParser,
  49. view::View,
  50. };
  51. struct DnetView {
  52. model: Arc<Model>,
  53. view: View,
  54. }
  55. impl DnetView {
  56. fn new(model: Arc<Model>, view: View) -> Self {
  57. Self { model, view }
  58. }
  59. async fn render_view<B: Backend>(&mut self, terminal: &mut Terminal<B>) -> DnetViewResult<()> {
  60. let mut asi = async_stdin();
  61. terminal.clear()?;
  62. self.view.id_menu.state.select(Some(0));
  63. self.view.msg_list.state.select(Some(0));
  64. loop {
  65. self.view.update(
  66. self.model.msg_map.lock().await.clone(),
  67. self.model.selectables.lock().await.clone(),
  68. //self.model.selectables2.lock().await.clone(),
  69. );
  70. //debug!(target: "dnetview::render_view()", "ID MENU: {:?}", self.view.id_menu.ids);
  71. //debug!(target: "dnetview::render_view()", "SELECTABLES ID LIST: {:?}", self.model.selectables.lock().await.keys());
  72. let mut err: Option<DnetViewError> = None;
  73. terminal.draw(|f| match self.view.render(f) {
  74. Ok(()) => {}
  75. Err(e) => {
  76. err = Some(e);
  77. }
  78. })?;
  79. if let Some(e) = err {
  80. return Err(e)
  81. }
  82. self.view.msg_list.scroll()?;
  83. for k in asi.by_ref().keys() {
  84. match k.unwrap() {
  85. Key::Char('q') => {
  86. terminal.clear()?;
  87. return Ok(())
  88. }
  89. Key::Char('j') => {
  90. self.view.id_menu.next();
  91. }
  92. Key::Char('k') => {
  93. self.view.id_menu.previous();
  94. }
  95. Key::Char('u') => {
  96. // TODO
  97. //view.msg_list.next();
  98. }
  99. Key::Char('d') => {
  100. // TODO
  101. //view.msg_list.previous();
  102. }
  103. _ => (),
  104. }
  105. }
  106. async_util::msleep(100).await;
  107. }
  108. }
  109. }
  110. #[async_std::main]
  111. async fn main() -> DnetViewResult<()> {
  112. //debug!(target: "dnetview", "main() START");
  113. let args = Args::parse();
  114. let log_level = get_log_level(args.verbose.into());
  115. let log_config = get_log_config();
  116. let log_file_path = expand_path(&args.log_path)?;
  117. if let Some(parent) = log_file_path.parent() {
  118. std::fs::create_dir_all(parent)?;
  119. };
  120. let file = File::create(log_file_path)?;
  121. WriteLogger::init(log_level, log_config, file)?;
  122. info!("Log level: {}", log_level);
  123. let config_path = get_config_path(args.config, CONFIG_FILE)?;
  124. spawn_config(&config_path, CONFIG_FILE_CONTENTS)?;
  125. let config = Config::<DnvConfig>::load(config_path)?;
  126. let stdout = io::stdout().into_raw_mode()?;
  127. let backend = TermionBackend::new(stdout);
  128. let mut terminal = Terminal::new(backend)?;
  129. terminal.clear()?;
  130. let model = Model::new();
  131. let view = View::new();
  132. let ex = Arc::new(Executor::new());
  133. let ex2 = ex.clone();
  134. let mut dnetview = DnetView::new(model.clone(), view);
  135. let parser = DataParser::new(model, config);
  136. let nthreads = num_cpus::get();
  137. let (signal, shutdown) = async_channel::unbounded::<()>();
  138. let (_, result) = Parallel::new()
  139. .each(0..nthreads, |_| smol::future::block_on(ex.run(shutdown.recv())))
  140. .finish(|| {
  141. smol::future::block_on(async move {
  142. parser.start_connect_slots(ex2).await?;
  143. dnetview.render_view(&mut terminal).await?;
  144. drop(signal);
  145. Ok(())
  146. })
  147. });
  148. result
  149. }