tui_dispatch_core/
action.rs

1//! Action trait for type-safe state mutations
2
3use std::fmt::Debug;
4use std::hash::Hash;
5
6/// Marker trait for actions that can be dispatched to the store
7///
8/// Actions represent intents to change state. They should be:
9/// - Clone: Actions may be logged, replayed, or sent to multiple handlers
10/// - Debug: For debugging and logging
11/// - Send + 'static: For async dispatch across threads
12///
13/// Use `#[derive(Action)]` from `tui-dispatch-macros` to auto-implement this trait.
14pub trait Action: Clone + Debug + Send + 'static {
15    /// Get the action name for logging and filtering
16    fn name(&self) -> &'static str;
17}
18
19/// Extension trait for actions with category support
20///
21/// This trait is auto-implemented when using `#[derive(Action)]` with
22/// `#[action(infer_categories)]`. It provides methods to query an action's
23/// category for routing and filtering.
24///
25/// # Example
26///
27/// ```ignore
28/// use tui_dispatch::ActionCategory;
29///
30/// #[derive(Action, Clone, Debug)]
31/// #[action(infer_categories)]
32/// enum MyAction {
33///     SearchStart,
34///     SearchClear,
35///     ConnectionFormOpen,
36/// }
37///
38/// let action = MyAction::SearchStart;
39/// assert_eq!(action.category(), Some("search"));
40/// assert!(matches!(action.category_enum(), MyActionCategory::Search));
41/// ```
42pub trait ActionCategory: Action {
43    /// The category enum type generated by the derive macro
44    type Category: Copy + Eq + Hash + Debug;
45
46    /// Get the action's category as a string (if categorized)
47    fn category(&self) -> Option<&'static str>;
48
49    /// Get the action's category as an enum value
50    fn category_enum(&self) -> Self::Category;
51}
52
53/// Trait for getting action parameters without the variant name.
54///
55/// Auto-implemented by `#[derive(Action)]`. Returns just the field values
56/// as a string, suitable for display in action logs where the action name
57/// is already shown separately.
58///
59/// # Example
60///
61/// ```ignore
62/// #[derive(Action, Clone, Debug)]
63/// enum MyAction {
64///     SetFilter { query: String, limit: usize },
65///     Tick,
66/// }
67///
68/// let action = MyAction::SetFilter { query: "foo".into(), limit: 10 };
69/// assert_eq!(action.name(), "SetFilter");
70/// assert_eq!(action.params(), r#""foo", 10"#);
71///
72/// let tick = MyAction::Tick;
73/// assert_eq!(tick.params(), "");
74/// ```
75pub trait ActionParams: Action {
76    /// Get just the action parameters as a string (no variant name)
77    fn params(&self) -> String;
78}
79
80/// Trait for actions that provide a summary representation for logging
81///
82/// The default implementation uses the Debug representation. Override
83/// `summary()` to provide concise summaries for actions with large payloads
84/// (e.g., showing byte counts instead of full data).
85///
86/// # Example
87///
88/// ```ignore
89/// impl ActionSummary for MyAction {
90///     fn summary(&self) -> String {
91///         match self {
92///             MyAction::DidLoadData { data } => {
93///                 format!("DidLoadData {{ bytes: {} }}", data.len())
94///             }
95///             _ => format!("{:?}", self)
96///         }
97///     }
98/// }
99/// ```
100#[deprecated(since = "0.3.0", note = "use ActionParams::params() instead")]
101pub trait ActionSummary: Action {
102    /// Get a summary representation of this action for logging
103    ///
104    /// Should return a concise string, ideally one line, suitable for
105    /// display in a scrolling action log. For actions with large data payloads,
106    /// show size/count summaries instead of full content.
107    ///
108    /// Default implementation uses `Debug` formatting.
109    fn summary(&self) -> String {
110        format!("{:?}", self)
111    }
112}