ui: setup buttons style, add server loading progress for node and metrics, optimize node status

This commit is contained in:
ardocrat 2023-06-02 21:19:34 +03:00
parent 532a79fc47
commit ffc68bc6ae
14 changed files with 203 additions and 135 deletions

View file

@ -5,6 +5,7 @@ import android.os.Bundle;
import android.os.Process;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
import android.view.KeyEvent;
import android.view.OrientationEventListener;
import com.google.androidgamesdk.GameActivity;
@ -29,7 +30,7 @@ public class MainActivity extends GameActivity {
// Callback to update display cutouts at native code.
OrientationEventListener orientationEventListener = new OrientationEventListener(this,
SensorManager.SENSOR_DELAY_GAME) {
SensorManager.SENSOR_DELAY_FASTEST) {
@Override
public void onOrientationChanged(int orientation) {
onDisplayCutoutsChanged(Utils.getDisplayCutouts(MainActivity.this));
@ -82,6 +83,7 @@ public class MainActivity extends GameActivity {
// Called from native code
public void onExit() {
Log.d("12345", "onExit");
mManualExit = true;
BackgroundService.stop(this);
finish();

View file

@ -5,6 +5,9 @@ network:
metrics: Metrics
mining: Mining
settings: Server settings
enable: Enable
disable: Disable
restart: Restart
sync_status:
server_restarting: Server is restarting
server_down: Server is down
@ -36,6 +39,7 @@ network_node:
size: Size (GB)
peers: Peers
network_metrics:
loading: Metrics will be available after the synchronization
emission: Emission
inflation: Inflation
supply: Supply

View file

@ -5,6 +5,9 @@ network:
metrics: Метрики
mining: Майнинг
settings: Настройки сервера
enable: Включить
disable: Выключить
restart: Перезапустить
sync_status:
server_restarting: Сервер перезапускается
server_down: Сервер выключен
@ -36,6 +39,7 @@ network_node:
size: Размер (ГБ)
peers: Пиры
network_metrics:
loading: Метрики будут доступны после синхронизации
emission: Эмиссия
inflation: Инфляция
supply: Предложение

View file

@ -12,15 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Context, Stroke, Widget};
use egui::{Color32, Context, RichText, Spinner, Stroke, Widget};
use egui::os::OperatingSystem;
use egui::style::Margin;
use crate::gui::colors::COLOR_LIGHT;
use crate::gui::colors::{COLOR_DARK, COLOR_LIGHT, COLOR_YELLOW};
use crate::gui::Navigator;
use crate::gui::platform::PlatformCallbacks;
use crate::gui::screens::Root;
use crate::gui::views::{Modal, ModalId, ModalLocation, ProgressLoading, View};
use crate::gui::views::{Modal, ModalId, ModalLocation, View};
use crate::node::Node;
pub struct PlatformApp<Platform> {
@ -36,18 +36,17 @@ pub struct App {
impl App {
pub fn ui(&mut self, ctx: &Context, frame: &mut eframe::Frame, cb: &dyn PlatformCallbacks) {
let modal_open = Navigator::is_modal_open(ModalLocation::Global);
egui::CentralPanel::default()
.frame(egui::Frame {
fill: COLOR_LIGHT,
.. Default::default()
})
.show(ctx, |ui| {
if modal_open {
if Navigator::is_modal_open(ModalLocation::Global) {
self.show_global_modal(ui, frame, cb);
}
self.root.ui(ui, frame, cb);
}).response.enabled = !modal_open;
});
}
fn show_global_modal(&mut self,
@ -60,12 +59,18 @@ impl App {
ModalId::Exit => {
if self.show_exit_progress {
if !Node::is_running() {
modal.close();
Self::exit(frame, cb);
modal.close();
}
ui.add_space(12.0);
let text = Node::get_sync_status_text(Node::get_sync_status());
ProgressLoading::new(text).ui(ui);
ui.add_space(16.0);
ui.vertical_centered(|ui| {
Spinner::new().size(42.0).color(COLOR_YELLOW).ui(ui);
ui.add_space(10.0);
ui.label(RichText::new(Node::get_sync_status_text())
.size(18.0)
.color(COLOR_DARK)
);
});
ui.add_space(12.0);
} else {
ui.add_space(8.0);
@ -77,19 +82,19 @@ impl App {
ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0);
ui.columns(2, |columns| {
columns[0].vertical_centered_justified(|ui| {
View::modal_button(ui, t!("modal_exit.exit"), || {
View::button(ui, t!("modal_exit.exit"), Color32::WHITE, || {
if !Node::is_running() {
Self::exit(frame, cb);
modal.close();
} else {
modal.disable_closing();
Node::stop();
modal.disable_closing();
self.show_exit_progress = true;
}
});
});
columns[1].vertical_centered_justified(|ui| {
View::modal_button(ui, t!("modal.cancel"), || {
View::button(ui, t!("modal.cancel"), Color32::WHITE, || {
modal.close();
});
});

View file

@ -96,11 +96,13 @@ impl PlatformApp<Android> {
fn setup_visuals(ctx: &egui::Context) {
// Setup style
let mut style = (*ctx.style()).clone();
// Make scroll-bar thinner
// Setup spacing for buttons.
style.spacing.button_padding = egui::vec2(12.0, 8.0);
// Make scroll-bar thinner.
style.spacing.scroll_bar_width = 4.0;
//
// Disable spacing between items.
style.spacing.item_spacing = egui::vec2(0.0, 0.0);
ctx.set_style(style);
// Setup visuals
@ -183,7 +185,7 @@ fn padding_panels(ctx: &egui::Context) {
.show_separator_line(false)
.resizable(false)
.exact_height(DISPLAY_CUTOUT_TOP.load(Ordering::Relaxed) as f32)
.show(ctx, |ui| {});
.show(ctx, |_ui| {});
egui::TopBottomPanel::bottom("bottom_padding_panel")
.frame(egui::Frame {
@ -194,7 +196,7 @@ fn padding_panels(ctx: &egui::Context) {
.show_separator_line(false)
.resizable(false)
.exact_height(DISPLAY_CUTOUT_BOTTOM.load(Ordering::Relaxed) as f32)
.show(ctx, |ui| {});
.show(ctx, |_ui| {});
egui::SidePanel::right("right_padding_panel")
.frame(egui::Frame {
@ -205,7 +207,7 @@ fn padding_panels(ctx: &egui::Context) {
.show_separator_line(false)
.resizable(false)
.max_width(DISPLAY_CUTOUT_RIGHT.load(Ordering::Relaxed) as f32)
.show(ctx, |ui| {});
.show(ctx, |_ui| {});
egui::SidePanel::left("left_padding_panel")
.frame(egui::Frame {
@ -216,7 +218,7 @@ fn padding_panels(ctx: &egui::Context) {
.show_separator_line(false)
.resizable(false)
.max_width(DISPLAY_CUTOUT_LEFT.load(Ordering::Relaxed) as f32)
.show(ctx, |ui| {});
.show(ctx, |_ui| {});
}
lazy_static! {

View file

@ -22,14 +22,12 @@ mod modal;
pub use modal::*;
mod network;
pub use network::Network;
mod network_node;
mod network_settings;
mod network_metrics;
mod network_mining;
pub use network::Network;
mod progress_loading;
pub use progress_loading::ProgressLoading;
pub trait NetworkTab {
fn name(&self) -> &String;

View file

@ -15,7 +15,7 @@
use std::cmp::min;
use std::sync::atomic::{AtomicBool, Ordering};
use egui::{Align2, Color32, RichText, Rounding, Sense, Stroke, Vec2};
use egui::{Align2, Color32, RichText, Rounding, Sense, Separator, Stroke, Vec2, Widget};
use egui::epaint::RectShape;
use egui::style::Margin;
use egui_extras::{Size, StripBuilder};
@ -29,7 +29,6 @@ pub enum ModalId {
}
/// Location for [`Modal`] at application UI.
#[derive(Clone, Copy)]
pub enum ModalLocation {
/// To draw globally above side panel and screen.
Global,
@ -204,7 +203,7 @@ impl Modal {
rect,
rounding,
fill: COLOR_LIGHT,
stroke: View::DEFAULT_STROKE,
stroke: Stroke::NONE,
};
let bg_idx = ui.painter().add(bg_shape);
@ -250,5 +249,11 @@ impl Modal {
// Setup background shape to be painted behind title content.
bg_shape.rect = title_resp.rect;
ui.painter().set(bg_idx, bg_shape);
let (rect, _) = ui.allocate_exact_size(Vec2::new(ui.available_width(), 1.0),Sense::hover());
let painter = ui.painter();
painter.hline(rect.x_range(),
painter.round_to_pixel(rect.center().y),
View::DEFAULT_STROKE);
}
}

View file

@ -20,8 +20,8 @@ use egui_extras::{Size, StripBuilder};
use grin_chain::SyncStatus;
use grin_core::global::ChainTypes;
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY_DARK, COLOR_YELLOW};
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE};
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_GRAY_DARK, COLOR_YELLOW};
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, PLUGS, POWER};
use crate::gui::Navigator;
use crate::gui::platform::PlatformCallbacks;
use crate::gui::views::{NetworkTab, View};
@ -71,7 +71,7 @@ impl Network {
egui::TopBottomPanel::bottom("network_tabs")
.frame(egui::Frame {
outer_margin: Margin::same(6.0),
outer_margin: Margin::same(5.0),
.. Default::default()
})
.resizable(false)
@ -93,26 +93,28 @@ impl Network {
fn draw_tabs(&mut self, ui: &mut egui::Ui) {
ui.scope(|ui| {
//Setup spacing between tabs
ui.style_mut().spacing.item_spacing = egui::vec2(6.0, 0.0);
// Setup spacing between tabs.
ui.style_mut().spacing.item_spacing = egui::vec2(5.0, 0.0);
// Setup vertical padding inside tab button.
ui.style_mut().spacing.button_padding = egui::vec2(0.0, 3.0);
ui.columns(4, |columns| {
columns[0].vertical_centered(|ui| {
columns[0].vertical_centered_justified(|ui| {
View::tab_button(ui, DATABASE, self.current_mode == Mode::Node, || {
self.current_mode = Mode::Node;
});
});
columns[1].vertical_centered(|ui| {
columns[1].vertical_centered_justified(|ui| {
View::tab_button(ui, GAUGE, self.current_mode == Mode::Metrics, || {
self.current_mode = Mode::Metrics;
});
});
columns[2].vertical_centered(|ui| {
columns[2].vertical_centered_justified(|ui| {
View::tab_button(ui, FACTORY, self.current_mode == Mode::Miner, || {
self.current_mode = Mode::Miner;
});
});
columns[3].vertical_centered(|ui| {
columns[3].vertical_centered_justified(|ui| {
View::tab_button(ui, FADERS, self.current_mode == Mode::Tuning, || {
self.current_mode = Mode::Tuning;
});
@ -200,9 +202,7 @@ impl Network {
});
strip.cell(|ui| {
ui.centered_and_justified(|ui| {
// Select sync status text
let sync_status = Node::get_sync_status();
let status_text = Node::get_sync_status_text(sync_status);
// Setup text color animation based on sync status
let idle = match sync_status {
@ -219,7 +219,7 @@ impl Network {
// Draw sync text
let status_color_rgba = Rgba::from(COLOR_GRAY_DARK) * color_factor as f32;
let status_color = Color32::from(status_color_rgba);
View::ellipsize_text(ui, status_text, 15.0, status_color);
View::ellipsize_text(ui, Node::get_sync_status_text(), 15.0, status_color);
// Repaint based on sync status
if idle {
@ -231,5 +231,23 @@ impl Network {
});
});
}
pub fn server_off_content(ui: &mut egui::Ui) {
View::center_content(ui, [240.0, 214.0], |ui| {
ui.label(RichText::new(PLUGS)
.size(84.0)
.color(Color32::from_gray(200))
);
ui.add_space(-16.0);
ui.label(RichText::new(Node::get_sync_status_text())
.size(19.0)
.color(Color32::from_gray(150))
);
ui.add_space(12.0);
View::button(ui, format!("{} {}", POWER, t!("network.enable")), COLOR_YELLOW, || {
Node::start(ChainTypes::Mainnet);
});
});
}
}

View file

@ -15,11 +15,12 @@
use chrono::{DateTime, NaiveDateTime, Utc};
use eframe::epaint::{Color32, Rounding, Stroke};
use egui::{RichText, ScrollArea, Spinner, Widget};
use grin_core::global::ChainTypes;
use grin_servers::DiffBlock;
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_GRAY_LIGHT};
use crate::gui::icons::{AT, COINS, CUBE_TRANSPARENT, HASH, HOURGLASS_LOW, HOURGLASS_MEDIUM, TIMER};
use crate::gui::views::{NetworkTab, View};
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_GRAY_LIGHT, COLOR_YELLOW};
use crate::gui::icons::{AT, COINS, CUBE_TRANSPARENT, HASH, HOURGLASS_LOW, HOURGLASS_MEDIUM, PLUGS, POWER, TIMER};
use crate::gui::views::{Network, NetworkTab, View};
use crate::node::Node;
pub struct NetworkMetrics {
@ -45,11 +46,19 @@ impl NetworkTab for NetworkMetrics {
fn ui(&mut self, ui: &mut egui::Ui) {
let server_stats = Node::get_stats();
// Show loading widget if server is not working or difficulty height is zero.
if !server_stats.is_some() || server_stats.as_ref().unwrap().diff_stats.height == 0 {
ui.centered_and_justified(|ui| {
Spinner::new().size(42.0).color(COLOR_GRAY).ui(ui);
});
if server_stats.is_none() || server_stats.as_ref().unwrap().diff_stats.height == 0 {
if !Node::is_running() {
Network::server_off_content(ui);
} else {
View::center_content(ui, [280.0, 160.0], |ui| {
Spinner::new().size(104.0).color(COLOR_YELLOW).ui(ui);
ui.add_space(18.0);
ui.label(RichText::new(t!("network_metrics.loading"))
.size(16.0)
.color(Color32::from_gray(150))
);
});
}
return;
}

View file

@ -11,3 +11,28 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::Ui;
use crate::gui::views::NetworkTab;
pub struct NetworkMining {
title: String
}
impl Default for NetworkMining {
fn default() -> Self {
Self {
title: t!("network.mining").to_uppercase(),
}
}
}
impl NetworkTab for NetworkMining {
fn name(&self) -> &String {
&self.title
}
fn ui(&mut self, ui: &mut Ui) {
todo!()
}
}

View file

@ -14,11 +14,13 @@
use eframe::epaint::Stroke;
use egui::{Color32, RichText, Rounding, ScrollArea, Spinner, Widget};
use egui_extras::{Size, StripBuilder};
use grin_core::global::ChainTypes;
use grin_servers::PeerStats;
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_GRAY_LIGHT};
use crate::gui::icons::{AT, CUBE, DEVICES, FLOW_ARROW, HANDSHAKE, PACKAGE, PLUGS_CONNECTED, SHARE_NETWORK};
use crate::gui::views::{NetworkTab, View};
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_GRAY_LIGHT, COLOR_YELLOW};
use crate::gui::icons::{AT, CUBE, DEVICES, FLOW_ARROW, HANDSHAKE, PACKAGE, PLUGS, PLUGS_CONNECTED, POWER, SHARE_NETWORK};
use crate::gui::views::{Network, NetworkTab, View};
use crate::node::Node;
pub struct NetworkNode {
@ -41,9 +43,13 @@ impl NetworkTab for NetworkNode {
fn ui(&mut self, ui: &mut egui::Ui) {
let server_stats = Node::get_stats();
if !server_stats.is_some() {
ui.centered_and_justified(|ui| {
Spinner::new().size(42.0).color(COLOR_GRAY).ui(ui);
});
if !Node::is_running() {
Network::server_off_content(ui);
} else {
ui.centered_and_justified(|ui| {
Spinner::new().size(104.0).color(COLOR_YELLOW).ui(ui);
});
}
return;
}

View file

@ -1,40 +0,0 @@
// Copyright 2023 The Grim Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use egui::{Response, RichText, Spinner, Ui, Widget};
use crate::gui::colors::COLOR_DARK;
pub struct ProgressLoading {
text: String
}
impl ProgressLoading {
pub fn new(text: String) -> Self {
Self {
text
}
}
}
impl Widget for ProgressLoading {
fn ui(self, ui: &mut Ui) -> Response {
ui.vertical_centered_justified(|ui| {
ui.add_space(10.0);
Spinner::new().size(36.0).color(COLOR_DARK).ui(ui);
ui.add_space(10.0);
ui.label(RichText::new(self.text).size(18.0).color(COLOR_DARK));
}).response
}
}

View file

@ -14,10 +14,11 @@
use egui::epaint::{Color32, FontId, Rounding, Stroke};
use egui::text::{LayoutJob, TextFormat};
use egui::{Button, PointerState, Response, RichText, Sense, Widget};
use egui::{Button, PointerState, Response, RichText, Sense, Vec2, Widget};
use egui::epaint::text::TextWrapping;
use egui_extras::{Size, StripBuilder};
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_LIGHT, COLOR_GRAY_LIGHT, COLOR_GRAY_DARK};
use crate::gui::colors::{COLOR_DARK, COLOR_GRAY, COLOR_LIGHT, COLOR_GRAY_LIGHT, COLOR_GRAY_DARK, COLOR_YELLOW};
pub struct View;
@ -103,7 +104,6 @@ impl View {
false => { Color32::WHITE }
};
let br = Button::new(wt)
.min_size(ui.available_size_before_wrap())
.stroke(stroke)
.fill(color)
.ui(ui).interact(Sense::click_and_drag());
@ -111,16 +111,12 @@ impl View {
Self::on_button_click(ui, br, action);
}
/// Modal button with white background fill color, contains text.
pub fn modal_button(ui: &mut egui::Ui, text: String, action: impl FnOnce()) {
let mut size = ui.available_size_before_wrap();
size.y = 36.0;
/// Draw [`Button`] with specified background fill color.
pub fn button(ui: &mut egui::Ui, text: String, fill_color: Color32, action: impl FnOnce()) {
let wt = RichText::new(text.to_uppercase()).size(18.0).color(COLOR_GRAY_DARK);
let br = Button::new(wt)
.stroke(Self::DEFAULT_STROKE)
.min_size(size)
.fill(Color32::WHITE)
.fill(fill_color)
.ui(ui).interact(Sense::click_and_drag());
Self::on_button_click(ui, br, action);
@ -169,4 +165,18 @@ impl View {
ui.label(RichText::new(label).color(COLOR_GRAY).size(15.0));
});
}
/// Draw content in the center of current layout with specified width and height.
pub fn center_content(ui: &mut egui::Ui, w_h: [f32; 2], content: impl FnOnce(&mut egui::Ui)) {
ui.vertical_centered(|ui| {
let mut rect = ui.available_rect_before_wrap();
let side_margin = (ui.available_width() - w_h[0]) / 2.0;
rect.min += egui::emath::vec2(side_margin, ui.available_height() / 2.0 - w_h[1] / 2.0);
rect.max -= egui::emath::vec2(side_margin, 0.0);
// rect.set_width(w_h[0]);
ui.allocate_ui_at_rect(rect, |ui| {
(content)(ui);
});
});
}
}

View file

@ -30,11 +30,11 @@ use lazy_static::lazy_static;
use log::info;
lazy_static! {
/// Static thread-aware state of [Node] to be updated from another thread.
/// Static thread-aware state of [`Node`] to be updated from another thread.
static ref NODE_STATE: Arc<Node> = Arc::new(Node::default());
}
/// Provides [Server] control, holds current status and statistics.
/// Provides [`Server`] control, holds current status and statistics.
pub struct Node {
/// Statistics data for UI.
stats: Arc<RwLock<Option<ServerStats>>>,
@ -61,12 +61,12 @@ impl Default for Node {
}
impl Node {
/// Stop [Server].
/// Stop the [`Server`].
pub fn stop() {
NODE_STATE.stop_needed.store(true, Ordering::Relaxed);
}
/// Start [Server] with provided chain type.
/// Start [`Server`] with provided chain type.
pub fn start(chain_type: ChainTypes) {
if !Self::is_running() {
let mut w_chain_type = NODE_STATE.chain_type.write().unwrap();
@ -75,7 +75,7 @@ impl Node {
}
}
/// Restart [Server] with provided chain type.
/// Restart [`Server`] with provided chain type.
pub fn restart(chain_type: ChainTypes) {
if Self::is_running() {
let mut w_chain_type = NODE_STATE.chain_type.write().unwrap();
@ -86,40 +86,40 @@ impl Node {
}
}
/// Check if [Server] is starting.
/// Check if [`Server`] is starting.
pub fn is_starting() -> bool {
NODE_STATE.starting.load(Ordering::Relaxed)
}
/// Check if [Server] is running.
/// Check if [`Server`] is running.
pub fn is_running() -> bool {
Self::get_stats().is_some() || Self::is_starting()
Self::get_sync_status().is_some()
}
/// Check if [Server] is stopping.
/// Check if [`Server`] is stopping.
pub fn is_stopping() -> bool {
NODE_STATE.stop_needed.load(Ordering::Relaxed)
}
/// Check if [Server] is restarting.
/// Check if [`Server`] is restarting.
pub fn is_restarting() -> bool {
NODE_STATE.restart_needed.load(Ordering::Relaxed)
}
/// Get [Server] statistics.
/// Get [`Server`] statistics.
pub fn get_stats() -> RwLockReadGuard<'static, Option<ServerStats>> {
NODE_STATE.stats.read().unwrap()
}
/// Get [Server] synchronization status, empty when it is not running.
/// Get [`Server`] synchronization status, empty when Server is not running.
pub fn get_sync_status() -> Option<SyncStatus> {
// Return Shutdown status when node is stopping.
if Self::is_stopping() {
return Some(SyncStatus::Shutdown)
}
// Return Initial status when node is starting.
if Self::is_starting() {
// Return Initial status when node is starting or restarting.
if Self::is_starting() || Self::is_restarting() {
return Some(SyncStatus::Initial)
}
@ -131,16 +131,24 @@ impl Node {
None
}
/// Start a thread to launch [Server] and update [NODE_STATE] with server statistics.
fn start_server_thread() -> JoinHandle<()> {
/// Start a thread to launch [`Server`] and update [`NODE_STATE`] with server statistics.
fn start_server_thread() {
thread::spawn(move || {
NODE_STATE.starting.store(true, Ordering::Relaxed);
// Start the server.
let mut server = start_server(&NODE_STATE.chain_type.read().unwrap());
let mut first_start = true;
loop {
if Self::is_restarting() {
// Clean server stats.
{
let mut w_stats = NODE_STATE.stats.write().unwrap();
*w_stats = None;
}
// Stop the server.
server.stop();
// Create new server with current chain type.
@ -148,10 +156,14 @@ impl Node {
NODE_STATE.restart_needed.store(false, Ordering::Relaxed);
} else if Self::is_stopping() {
server.stop();
// Clean server stats.
{
let mut w_stats = NODE_STATE.stats.write().unwrap();
*w_stats = None;
}
let mut w_stats = NODE_STATE.stats.write().unwrap();
*w_stats = None;
// Stop the server.
server.stop();
NODE_STATE.starting.store(false, Ordering::Relaxed);
NODE_STATE.stop_needed.store(false, Ordering::Relaxed);
@ -159,8 +171,11 @@ impl Node {
} else {
let stats = server.get_server_stats();
if stats.is_ok() {
let mut w_stats = NODE_STATE.stats.write().unwrap();
*w_stats = Some(stats.as_ref().ok().unwrap().clone());
// Update server stats.
{
let mut w_stats = NODE_STATE.stats.write().unwrap();
*w_stats = Some(stats.as_ref().ok().unwrap().clone());
}
if first_start {
NODE_STATE.starting.store(false, Ordering::Relaxed);
@ -170,18 +185,24 @@ impl Node {
}
thread::sleep(Duration::from_millis(250));
}
})
});
}
/// Get synchronization status i18n text.
pub fn get_sync_status_text(sync_status: Option<SyncStatus>) -> String {
pub fn get_sync_status_text() -> String {
if Node::is_starting() {
return t!("sync_status.initial")
};
if Node::is_stopping() {
return t!("sync_status.shutdown")
};
if Node::is_restarting() {
return t!("sync_status.server_restarting")
}
if Node::is_stopping() {
return t!("sync_status.shutdown")
}
let sync_status = Self::get_sync_status();
if sync_status.is_none() {
return t!("sync_status.server_down")
@ -256,7 +277,7 @@ impl Node {
}
/// Start [Server] with provided chain type.
/// Start the [`Server`] with provided chain type.
fn start_server(chain_type: &ChainTypes) -> Server {
// Initialize config
let mut node_config_result = config::initial_setup_server(chain_type);
@ -358,14 +379,13 @@ fn start_server(chain_type: &ChainTypes) -> Server {
#[cfg(target_os = "android")]
#[allow(non_snake_case)]
#[no_mangle]
/// Get sync status text for Android notification from [NODE_STATE] in Java string format.
/// Get sync status text for Android notification from [`NODE_STATE`] in Java string format.
pub extern "C" fn Java_mw_gri_android_BackgroundService_getSyncStatusText(
_env: jni::JNIEnv,
_class: jni::objects::JObject,
_activity: jni::objects::JObject,
) -> jstring {
let sync_status = Node::get_sync_status();
let status_text = Node::get_sync_status_text(sync_status);
let status_text = Node::get_sync_status_text();
let j_text = _env.new_string(status_text);
return j_text.unwrap().into_raw();
}
@ -388,7 +408,7 @@ pub extern "C" fn Java_mw_gri_android_BackgroundService_getSyncTitle(
#[cfg(target_os = "android")]
#[allow(non_snake_case)]
#[no_mangle]
/// Calling on unexpected application termination (removal from recent apps)
/// Calling on unexpected Android application termination (removal from recent apps).
pub extern "C" fn Java_mw_gri_android_MainActivity_onTermination(
_env: jni::JNIEnv,
_class: jni::objects::JObject,