Skip to content

Commit

Permalink
About dialog, small UI fixes, readme
Browse files Browse the repository at this point in the history
  • Loading branch information
nazar-pc committed Dec 4, 2023
1 parent dfae337 commit 3c1d071
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 11 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "space-acres"
description = ""
description = "Space Acres is an opinionated unofficial GUI application for farming on Subspace Network"
license = "0BSD"
version = "0.0.1"
authors = ["Nazar Mokrynskyi <[email protected]>"]
Expand All @@ -10,7 +10,6 @@ include = [
"/Cargo.toml",
]


[dependencies]
anyhow = "1.0.75"
arc-swap = "1.6.0"
Expand Down
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Space Acres

Space Acres is an opinionated unofficial GUI application for farming on [Subspace Network](https://subspace.network/).

## Current status

Current status of the project is Alpha.

This means that while it should generally work, expect things to not work sometimes, break in unexpected ways and error
handling to be lacking.

Current version supports Gemini 3g chain only and doesn't allow to select anything else.

## Features

Current features:
* Initial configuration
* Node sync with displayed progress
* Farmer plotting/farming with a single farm with displayed plotting/replotting progress

Some of the upcoming features/capabilities (not necessarily in priority order):
* Automatic builds in CI with pre-built executables
* Testing on Windows and macOS
* Welcome screen
* Writing logs to a file
* Displaying of earned farming rewards or at least link to block explorers
* Better status reporting of the node and farmer (piece cache sync, etc.)
* Displaying sync/plotting/replotting speed (UI already supports this, but there is no backend code to calculate the speed)
* Support for multiple farms (backend and config file already support this if you edit config manually, but you will not see them in UI)
* Farmer benchmarking support
* Re-configuration screen with old configuration filled instead of starting from scratch

## Project structure

The project at high level is structured in a few large modules:
* `backend` handles all the backend functionality
* `config` contains configuration data structure with ability to read, write and validate it
* `farmer` contains farmer implementation with a wrapper data structure that abstracts away its internals
* `networking` contains networking stack that is shared between `farmer` and `node` with a wrapper data structure that abstracts away its internals
* `node` contains consensus node with a wrapper data structure that abstracts away its internals
* `utils` contains some low-level utilities
* `main.rs` contains UI and communication with backend, though UI will move into `frontend` in the future
* `res/app.css` contains a few small non-critical tweaks for presentation, it will likely be necessary to ship a GTK4 theme with the app in the future to ensure consistent look

Application supports bare minimum configuration and doesn't support operator functionality (not yet anyway).

## How to build

In order to build this app you'll need to install both dependencies necessary for building
[Subspace](https://github.com/subspace/subspace) and [GTK4](https://github.com/gtk-rs/gtk4-rs), follow their
documentation for details, otherwise `cargo run` will get you where to want to be.

## Contribution
Contributions of various kinds are welcome and appreciated.

## License
Zero-Clause BSD

https://opensource.org/licenses/0BSD

https://tldrlegal.com/license/bsd-0-clause-license
Binary file added screenshots/configuration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/loading.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/plotting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/syncing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 57 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ enum ConfigurationEvent {
enum AppInput {
BackendNotification(BackendNotification),
Configuration(ConfigurationEvent),
ShowAboutDialog,
Ignore,
}

Expand Down Expand Up @@ -155,6 +156,8 @@ struct App {
current_view: View,
backend_action_sender: mpsc::Sender<BackendAction>,
open_dialog: Controller<OpenDialog>,
menu_popover: gtk::Popover,
about_dialog: gtk::AboutDialog,
}

#[relm4::component(async)]
Expand All @@ -176,6 +179,27 @@ impl AsyncComponent for App {
set_orientation: gtk::Orientation::Vertical,

gtk::HeaderBar {
pack_end = &gtk::MenuButton {
set_direction: gtk::ArrowType::None,
set_icon_name: "open-menu-symbolic",
#[wrap(Some)]
set_popover: menu_popover = &gtk::Popover {
set_halign: gtk::Align::End,
set_position: gtk::PositionType::Bottom,

gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 5,

gtk::Button {
set_label: "About",
connect_clicked[sender] => move |_| {
sender.input(AppInput::ShowAboutDialog);
},
},
},
},
},
},

gtk::Box {
Expand Down Expand Up @@ -458,19 +482,20 @@ impl AsyncComponent for App {
gtk::Box {
set_height_request: 100,
set_orientation: gtk::Orientation::Vertical,
set_spacing: 10,

gtk::Label {
add_css_class: "heading",
set_halign: gtk::Align::Start,
set_label: "Consensus node",
set_margin_bottom: 10,
},

// Match only because `if let Some(x) = y` is not yet supported here
// TODO: Match only because `if let Some(x) = y` is not yet supported here: https://github.com/Relm4/Relm4/issues/582
#[transition = "SlideUpDown"]
match &node_state.sync_state {
Some(sync_state) => gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 10,

gtk::Box {
gtk::Label {
Expand Down Expand Up @@ -504,8 +529,6 @@ impl AsyncComponent for App {
gtk::ProgressBar {
#[watch]
set_fraction: node_state.best_block_number as f64 / sync_state.target as f64,
set_margin_bottom: 10,
set_margin_top: 10,
},
},
None => gtk::Box {
Expand All @@ -523,23 +546,25 @@ impl AsyncComponent for App {

gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 10,
set_valign: gtk::Align::Start,

gtk::Label {
add_css_class: "heading",
set_halign: gtk::Align::Start,
set_label: "Farmer",
set_margin_bottom: 10,
},

// TODO: Render all farms, not just the first one
// Match only because `if let Some(x) = y` is not yet supported here
// TODO: Match only because `if let Some(x) = y` is not yet supported here: https://github.com/Relm4/Relm4/issues/582
#[transition = "SlideUpDown"]
match (&farmer_state.plotting_state[0], node_state.sync_state.is_none()) {
(Some(plotting_state), true) => gtk::Box {
set_orientation: gtk::Orientation::Vertical,

gtk::Box {
set_spacing: 10,

gtk::Label {
set_halign: gtk::Align::Start,

Expand Down Expand Up @@ -571,8 +596,6 @@ impl AsyncComponent for App {
gtk::ProgressBar {
#[watch]
set_fraction: plotting_state.progress as f64 / 100.0,
set_margin_bottom: 10,
set_margin_top: 10,
},
},
(None, true) => gtk::Box {
Expand Down Expand Up @@ -653,14 +676,35 @@ impl AsyncComponent for App {
OpenDialogResponse::Cancel => AppInput::Ignore,
});

let model = App {
let about_dialog = gtk::AboutDialog::builder()
.title("About")
.program_name("Space Acres")
.version(env!("CARGO_PKG_VERSION"))
.authors(env!("CARGO_PKG_AUTHORS").split(':').collect::<Vec<_>>())
// TODO: Use https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6643 once available
.license("Zero-Clause BSD: https://opensource.org/license/0bsd/")
.website("https://github.com/nazar-pc/space-acres")
.comments(env!("CARGO_PKG_DESCRIPTION"))
.transient_for(&root)
.build();
about_dialog.connect_close_request(|about_dialog| {
about_dialog.hide();
gtk::glib::Propagation::Stop
});

let mut model = App {
current_view: View::Loading(String::new()),
backend_action_sender: action_sender,
open_dialog,
// Hack to initialize a field before this data structure is used
menu_popover: gtk::Popover::default(),
about_dialog,
};

let widgets = view_output!();

model.menu_popover = widgets.menu_popover.clone();

AsyncComponentParts { model, widgets }
}

Expand All @@ -677,6 +721,10 @@ impl AsyncComponent for App {
AppInput::Configuration(event) => {
self.process_configuration_event(event).await;
}
AppInput::ShowAboutDialog => {
self.menu_popover.hide();
self.about_dialog.show();
}
AppInput::Ignore => {
// Ignore
}
Expand Down

0 comments on commit 3c1d071

Please sign in to comment.