Indicate when a deployment is necessary #49

Merged
lucas merged 3 commits from issue/32 into master 2023-03-06 16:04:25 +01:00
4 changed files with 38 additions and 14 deletions
Showing only changes of commit 3252e66a3f - Show all commits

View file

@ -78,6 +78,7 @@ pub(crate) struct State {
pub current_view: View, pub current_view: View,
pub mods: Vector<ModInfo>, pub mods: Vector<ModInfo>,
pub selected_mod_index: Option<usize>, pub selected_mod_index: Option<usize>,
pub dirty: bool,
pub is_deployment_in_progress: bool, pub is_deployment_in_progress: bool,
pub is_reset_in_progress: bool, pub is_reset_in_progress: bool,
pub is_save_in_progress: bool, pub is_save_in_progress: bool,
@ -106,6 +107,7 @@ impl State {
current_view: View::default(), current_view: View::default(),
mods: Vector::new(), mods: Vector::new(),
selected_mod_index: None, selected_mod_index: None,
dirty: false,
is_deployment_in_progress: false, is_deployment_in_progress: false,
is_reset_in_progress: false, is_reset_in_progress: false,
is_save_in_progress: false, is_save_in_progress: false,

View file

@ -33,6 +33,8 @@ pub(crate) const ACTION_START_SAVE_SETTINGS: Selector =
pub(crate) const ACTION_FINISH_SAVE_SETTINGS: Selector = pub(crate) const ACTION_FINISH_SAVE_SETTINGS: Selector =
Selector::new("dtmm.action.finish-save-settings"); Selector::new("dtmm.action.finish-save-settings");
pub(crate) const ACTION_SET_DIRTY: Selector = Selector::new("dtmm.action.set-dirty");
pub(crate) enum AsyncAction { pub(crate) enum AsyncAction {
DeployMods(State), DeployMods(State),
ResetDeployment(State), ResetDeployment(State),
@ -81,6 +83,7 @@ impl AppDelegate<State> for Delegate {
} }
cmd if cmd.is(ACTION_FINISH_DEPLOY) => { cmd if cmd.is(ACTION_FINISH_DEPLOY) => {
state.is_deployment_in_progress = false; state.is_deployment_in_progress = false;
state.dirty = false;
Handled::Yes Handled::Yes
} }
cmd if cmd.is(ACTION_START_RESET_DEPLOYMENT) => { cmd if cmd.is(ACTION_START_RESET_DEPLOYMENT) => {
@ -226,6 +229,10 @@ impl AppDelegate<State> for Delegate {
Handled::Yes Handled::Yes
} }
cmd if cmd.is(ACTION_SET_DIRTY) => {
state.dirty = true;
Handled::Yes
}
cmd => { cmd => {
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
tracing::warn!("Unknown command: {:?}", cmd); tracing::warn!("Unknown command: {:?}", cmd);

View file

@ -1,7 +1,7 @@
use druid::widget::{Button, Controller, Scroll}; use druid::widget::{Button, Controller, Scroll};
use druid::{Data, Env, Event, EventCtx, Rect, UpdateCtx, Widget}; use druid::{Data, Env, Event, EventCtx, Rect, UpdateCtx, Widget};
use crate::state::{State, ACTION_START_SAVE_SETTINGS}; use crate::state::{State, ACTION_SET_DIRTY, ACTION_START_SAVE_SETTINGS};
pub struct DisabledButtonController; pub struct DisabledButtonController;
@ -57,11 +57,16 @@ impl<T: Data, W: Widget<T>> Controller<T, Scroll<T, W>> for AutoScrollController
} }
} }
/// A controller that submits the command to save settings every time its widget's macro_rules! compare_state_fields {
/// data changes. ($old:ident, $new:ident, $($field:ident),+) => {
pub struct SaveSettingsController; $($old.$field != $new.$field) || +
}
}
impl<W: Widget<State>> Controller<State, W> for SaveSettingsController { /// A controller that tracks state changes for certain fields and submits commands to handle them.
pub struct DirtyStateController;
impl<W: Widget<State>> Controller<State, W> for DirtyStateController {
fn update( fn update(
&mut self, &mut self,
child: &mut W, child: &mut W,
@ -70,13 +75,14 @@ impl<W: Widget<State>> Controller<State, W> for SaveSettingsController {
data: &State, data: &State,
env: &Env, env: &Env,
) { ) {
// Only filter for the values that actually go into the settings file. if compare_state_fields!(old_data, data, mods, game_dir, data_dir) {
if old_data.mods != data.mods
|| old_data.game_dir != data.game_dir
|| old_data.data_dir != data.data_dir
{
ctx.submit_command(ACTION_START_SAVE_SETTINGS); ctx.submit_command(ACTION_START_SAVE_SETTINGS);
} }
if compare_state_fields!(old_data, data, mods, game_dir) {
ctx.submit_command(ACTION_SET_DIRTY);
}
child.update(ctx, old_data, data, env) child.update(ctx, old_data, data, env)
} }
} }

View file

@ -15,7 +15,7 @@ use crate::state::{
ACTION_START_RESET_DEPLOYMENT, ACTION_START_RESET_DEPLOYMENT,
}; };
use crate::ui::theme; use crate::ui::theme;
use crate::ui::widget::controller::{AutoScrollController, SaveSettingsController}; use crate::ui::widget::controller::{AutoScrollController, DirtyStateController};
use crate::ui::widget::PathBufFormatter; use crate::ui::widget::PathBufFormatter;
const TITLE: &str = "Darktide Mod Manager"; const TITLE: &str = "Darktide Mod Manager";
@ -38,11 +38,20 @@ fn build_top_bar() -> impl Widget<State> {
state.current_view = View::Settings; state.current_view = View::Settings;
}); });
let deploy_button = Button::new("Deploy Mods") let deploy_button = {
Button::dynamic(|state: &State, _| {
let mut s = String::new();
if state.dirty {
s.push_str("! ");
}
s.push_str("Deploy Mods");
s
})
.on_click(|ctx, _state: &mut State, _env| { .on_click(|ctx, _state: &mut State, _env| {
ctx.submit_command(ACTION_START_DEPLOY); ctx.submit_command(ACTION_START_DEPLOY);
}) })
.disabled_if(|data, _| data.is_deployment_in_progress || data.is_reset_in_progress); .disabled_if(|data, _| data.is_deployment_in_progress || data.is_reset_in_progress)
};
let reset_button = Button::new("Reset Game") let reset_button = Button::new("Reset Game")
.on_click(|ctx, _state: &mut State, _env| { .on_click(|ctx, _state: &mut State, _env| {
@ -308,5 +317,5 @@ fn build_window() -> impl Widget<State> {
.with_child(build_top_bar()) .with_child(build_top_bar())
.with_flex_child(build_main(), 1.0) .with_flex_child(build_main(), 1.0)
.with_child(build_log_view()) .with_child(build_log_view())
.controller(SaveSettingsController) .controller(DirtyStateController)
} }