Skip to content

Commit

Permalink
Add built-in help window (#76)
Browse files Browse the repository at this point in the history
  • Loading branch information
TicClick authored Jan 26, 2024
1 parent 67bbda7 commit 261e4a5
Show file tree
Hide file tree
Showing 13 changed files with 215 additions and 17 deletions.
6 changes: 6 additions & 0 deletions crates/steel_core/src/ipc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,10 @@ impl CoreClient {
))
.unwrap();
}

pub fn usage_window_requested(&self) {
self.server
.blocking_send(AppMessageIn::UIUsageWindowRequested)
.unwrap();
}
}
1 change: 1 addition & 0 deletions crates/steel_core/src/ipc/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub enum AppMessageIn {
UIChatActionSent { target: String, text: String },
UISettingsRequested,
UISettingsUpdated(Settings),
UIUsageWindowRequested,

ChatModeratorAdded(String),
}
1 change: 1 addition & 0 deletions crates/steel_core/src/ipc/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ pub enum UIMessageIn {
ChatClosed(String),
ChatCleared(String),
ChatModeratorAdded(String),
UsageWindowRequested,
}
9 changes: 9 additions & 0 deletions src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ impl Application {
AppMessageIn::UISettingsUpdated(settings) => {
self.ui_handle_settings_updated(settings);
}
AppMessageIn::UIUsageWindowRequested => {
self.ui_request_usage_window();
}
}
}
}
Expand Down Expand Up @@ -146,6 +149,12 @@ impl Application {
self.state.settings.save();
}

pub fn ui_request_usage_window(&mut self) {
self.ui_queue
.blocking_send(UIMessageIn::UsageWindowRequested)
.unwrap();
}

pub fn handle_connection_status(&mut self, status: ConnectionStatus) {
self.state.connection = status;
self.ui_queue
Expand Down
12 changes: 9 additions & 3 deletions src/gui/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,15 @@ impl ChatWindow {
if let Some(ch) = state.active_chat() {
if response.lost_focus()
&& ui.input(|i| i.key_pressed(egui::Key::Enter))
&& !self
.command_helper
.detect_and_run(state, &mut self.chat_input)
&& !{
let result = self
.command_helper
.detect_and_run(state, &mut self.chat_input);
if result {
self.return_focus(ctx, state);
}
result
}
{
state.core.chat_message_sent(&ch.name, &self.chat_input);
self.chat_input.clear();
Expand Down
31 changes: 31 additions & 0 deletions src/gui/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,36 @@ impl Command for ClearChat {
}
}

struct ShowUsage {
pub aliases: Vec<String>,
}

impl Command for ShowUsage {
fn new() -> Self {
Self {
aliases: ["/help".into(), "/usage".into()].to_vec(),
}
}
fn description(&self) -> &str {
"show a guide around the application"
}
fn example(&self) -> &str {
self.preferred_alias()
}
fn aliases(&self) -> &Vec<String> {
&self.aliases
}
fn argcount(&self) -> usize {
0
}
fn ui_title(&self) -> egui::RichText {
egui::RichText::new(self.preferred_alias())
}
fn action(&self, state: &UIState, _args: Vec<String>) {
state.core.usage_window_requested();
}
}

pub struct CommandHelper {
commands: Vec<Box<dyn Command>>,
}
Expand All @@ -187,6 +217,7 @@ impl Default for CommandHelper {
Box::new(OpenChat::new()),
Box::new(CloseChat::new()),
Box::new(ClearChat::new()),
Box::new(ShowUsage::new()),
],
};
s.commands
Expand Down
30 changes: 25 additions & 5 deletions src/gui/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub struct Menu {
pub show_settings: bool,
pub show_about: bool,
pub show_update: bool,
pub show_usage: bool,

pin_window: bool,
}
Expand All @@ -20,7 +21,7 @@ impl Menu {
}

pub fn dialogs_visible(&self) -> bool {
self.show_settings || self.show_about || self.show_update
self.show_settings || self.show_about || self.show_update || self.show_usage
}

pub fn show(
Expand Down Expand Up @@ -136,17 +137,36 @@ impl Menu {
});
}

fn show_help_menu(&mut self, ui: &mut egui::Ui, _ctx: &egui::Context, _state: &mut UIState) {
fn show_help_menu(&mut self, ui: &mut egui::Ui, _ctx: &egui::Context, state: &mut UIState) {
ui.menu_button("help", |ui| {
if ui.button("open diagnostic log").clicked() {
if ui.button("open diagnostic log").on_hover_text_at_pointer(
"open the text journal with debug messages and errors -- may or may not help with debugging"
).clicked() {
crate::core::os::open_runtime_log();
ui.close_menu();
}
if ui.button("check for updates").clicked() {

let autoupdate_status = format!("automated updates: {}", match state.settings.application.autoupdate.enabled {
true => "enabled",
false => "disabled",
});

if ui.button("check for updates").on_hover_text_at_pointer(autoupdate_status).clicked() {
self.show_update = !self.show_update;
ui.close_menu();
}
if ui.button("about").clicked() {

ui.separator();

if ui.button("usage guide").on_hover_text_at_pointer(
"show the help window with bits about interface, features, and all things related"
).clicked() {
self.show_usage = !self.show_usage;
ui.close_menu();
}
if ui.button("about").on_hover_text_at_pointer(
"show application info"
).clicked() {
self.show_about = !self.show_about;
ui.close_menu();
}
Expand Down
1 change: 1 addition & 0 deletions src/gui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod menu;
pub mod settings;
pub mod state;
pub mod update_window;
pub mod usage;
pub mod window;

const HIGHLIGHTS_TAB_NAME: &str = "$highlights";
Expand Down
8 changes: 6 additions & 2 deletions src/gui/settings/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,16 @@ impl SettingsWindow {
.hint_text("should point to release metadata");
ui.add(url);
ui.horizontal(|ui| {
if ui.button("test").clicked() {
if ui.button("test").on_hover_text_at_pointer(
"validate the URL -- it will be used for the next update cycle if it contains correctly structured data"
).clicked() {
state
.updater
.change_url(&state.settings.application.autoupdate.url);
}
if ui.button("revert").clicked() {
if ui.button("revert").on_hover_text_at_pointer(
"roll back the URL to its default value"
).clicked() {
state.settings.application.autoupdate.url = updater::default_update_url();
state
.updater
Expand Down
4 changes: 3 additions & 1 deletion src/gui/settings/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ impl AutojoinSection {
let validation_result = crate::gui::validate_channel_name(&self.autojoin_channel_input);

ui.vertical(|ui| {
ui.heading("auto-join channels");
ui.heading("auto-join channels").on_hover_text_at_pointer(
"these channels will be open automatically when you connect to the server -- think of them as favourites"
);
ui.horizontal(|ui| {
let add_autojoin_channel = ui.button("+").on_hover_text_at_pointer("<Enter> = add");
let response = ui.add(
Expand Down
4 changes: 3 additions & 1 deletion src/gui/settings/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ impl SettingsWindow {
.on_hover_text_at_pointer("default colour of all moderators (GMT, NAT, DEV)");
});

ui.heading(format!("custom user colours ({suffix})"));
ui.heading(format!("custom user colours ({suffix})")).on_hover_text_at_pointer(
"works for all the folks out there: exquisite, boring, dangerous, ~ s p e c i a l ~"
);

ui.horizontal(|ui| {
let response = ui.add(
Expand Down
107 changes: 107 additions & 0 deletions src/gui/usage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use super::state::UIState;
use steel_core::settings::ThemeMode;

use eframe::egui;

#[derive(PartialEq)]
enum Section {
Overview,
ChatTabs,
Chat,
}

impl Default for Section {
fn default() -> Self {
Self::Overview
}
}

#[derive(Default)]
pub struct UsageWindow {
active_tab: Section,
}

impl UsageWindow {
pub fn show(&mut self, ctx: &egui::Context, state: &mut UIState, is_open: &mut bool) {
egui::Window::new("help").open(is_open).show(ctx, |ui| {
ui.horizontal(|ui| {
ui.vertical(|ui| {
ui.selectable_value(&mut self.active_tab, Section::Overview, "overview");
ui.selectable_value(&mut self.active_tab, Section::ChatTabs, "chat tabs");
ui.selectable_value(&mut self.active_tab, Section::Chat, "chat");
});
ui.separator();
match self.active_tab {
Section::Overview => self.show_overview_usage(ctx, ui, state),
Section::ChatTabs => self.show_chat_tabs_usage(ui),
Section::Chat => self.show_chat_usage(ui),
}
});
});
}
}

impl UsageWindow {
fn show_overview_usage(&mut self, ctx: &egui::Context, ui: &mut egui::Ui, state: &mut UIState) {
ui.vertical(|ui| {
ui.heading("overview");
ui.horizontal_wrapped(|ui| {
ui.spacing_mut().item_spacing.x = 0.0;
ui.label(
"most of the UI elements are self-explanatory -- hover over menu items, buttons, \
input fields, and other controls to see what they do. example: "
);
if let Some(theme) = ctx.style().visuals.light_dark_small_toggle_button(ui) {
state.settings.ui.theme = if theme.dark_mode {
ThemeMode::Dark
} else {
ThemeMode::Light
};
}
});

ui.label(
"\noverall, steel mostly behaves like you would expect from a regular chat client -- \
it hauls messages back and forth across the network, reconnects automatically with 15 second retries, \
draws your attention to missed messages, etc, etc.\n\
\n\
if something unexpected happens, make sure to check the log file, and tell me about the issue."
);
});
}

fn show_chat_tabs_usage(&mut self, ui: &mut egui::Ui) {
ui.vertical(|ui| {
ui.heading("chat tabs");
ui.label(
"tabs can be closed by middle clicking them. right click brings up a context menu with extra actions. \
to reorder the tabs, drag them around while holding shift."
);

ui.heading("system tabs");
ui.label(
"- \"highlights\": all your mentions -- click the chat name to find out the context\n\
- \"system\": messages from the chat server. most of the time it's just Echo's rad ASCII art, \
but occasionally a stray error might show up (for example, in case of incorrect password)"
);
});
}

fn show_chat_usage(&mut self, ui: &mut egui::Ui) {
ui.vertical(|ui| {
ui.heading("chat");
ui.label(
"type / to see available chat commands. these without input parameters are instant, so take heed.\n\
\n\
hover over a timestamp to see its date and UTC time. the messages are stamped on delivery \
to your device, so unless the network is terribly laggy, 99.9% of the time it's accurate enough.\n\
\n\
some more UX wisdom:\n\
- left clicking a user's name will insert it into the chat input\n\
- right clicking them will bring out the context menu\n\
- chat links are clickable and can be copied\n\
- \"mIRC colours\" aren't supported. AOL has died, and so has MSN -- sorry! we'll all be there."
)
});
}
}
18 changes: 13 additions & 5 deletions src/gui/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ pub struct ApplicationWindow {
settings: gui::settings::SettingsWindow,
about: gui::about::About,
update_window: gui::update_window::UpdateWindow,
usage_window: gui::usage::UsageWindow,

ui_queue: Receiver<UIMessageIn>,
s: UIState,
Expand All @@ -152,6 +153,7 @@ impl ApplicationWindow {
settings: gui::settings::SettingsWindow::new(),
about: gui::about::About::default(),
update_window: gui::update_window::UpdateWindow::default(),
usage_window: gui::usage::UsageWindow::default(),
ui_queue,
s: UIState::new(app_queue_handle),
date_announcer: DateAnnouncer::default(),
Expand Down Expand Up @@ -274,6 +276,10 @@ impl ApplicationWindow {
mods.insert(name.to_lowercase().replace(' ', "_"));
}
}

UIMessageIn::UsageWindowRequested => {
self.menu.show_usage = true;
}
}
}
}
Expand Down Expand Up @@ -308,11 +314,8 @@ impl eframe::App for ApplicationWindow {

self.set_theme(ctx);

self.menu
.show(ctx, frame, &mut self.s, &mut self.chat.response_widget_id);
self.chat_tabs.show(ctx, &mut self.s);
self.chat.show(ctx, &self.s);

self.usage_window
.show(ctx, &mut self.s, &mut self.menu.show_usage);
self.settings
.show(ctx, &mut self.s, &mut self.menu.show_settings);

Expand All @@ -321,6 +324,11 @@ impl eframe::App for ApplicationWindow {
self.update_window
.show(ctx, &mut self.s, &mut self.menu.show_update);

self.menu
.show(ctx, frame, &mut self.s, &mut self.chat.response_widget_id);
self.chat_tabs.show(ctx, &mut self.s);
self.chat.show(ctx, &self.s);

if !self.menu.dialogs_visible() {
self.chat.return_focus(ctx, &self.s);
}
Expand Down

0 comments on commit 261e4a5

Please sign in to comment.