mirror of
https://github.com/ChrisTitusTech/linutil.git
synced 2024-11-22 05:12:27 +00:00
Add per cmd multi-selection
This commit is contained in:
parent
476dbf3a12
commit
8edd12f0b4
|
@ -28,30 +28,18 @@ pub fn get_tabs(validate: bool) -> Vec<Tab> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let tabs: Vec<Tab> = tabs
|
let tabs: Vec<Tab> = tabs
|
||||||
.map(
|
.map(|(TabEntry { name, data }, directory)| {
|
||||||
|(
|
let mut tree = Tree::new(Rc::new(ListNode {
|
||||||
TabEntry {
|
name: "root".to_string(),
|
||||||
name,
|
description: String::new(),
|
||||||
data,
|
command: Command::None,
|
||||||
multi_selectable,
|
task_list: String::new(),
|
||||||
},
|
multi_select: false,
|
||||||
directory,
|
}));
|
||||||
)| {
|
let mut root = tree.root_mut();
|
||||||
let mut tree = Tree::new(Rc::new(ListNode {
|
create_directory(data, &mut root, &directory, validate, true);
|
||||||
name: "root".to_string(),
|
Tab { name, tree }
|
||||||
description: String::new(),
|
})
|
||||||
command: Command::None,
|
|
||||||
task_list: String::new(),
|
|
||||||
}));
|
|
||||||
let mut root = tree.root_mut();
|
|
||||||
create_directory(data, &mut root, &directory, validate);
|
|
||||||
Tab {
|
|
||||||
name,
|
|
||||||
tree,
|
|
||||||
multi_selectable,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if tabs.is_empty() {
|
if tabs.is_empty() {
|
||||||
|
@ -69,12 +57,6 @@ struct TabList {
|
||||||
struct TabEntry {
|
struct TabEntry {
|
||||||
name: String,
|
name: String,
|
||||||
data: Vec<Entry>,
|
data: Vec<Entry>,
|
||||||
#[serde(default = "default_multi_selectable")]
|
|
||||||
multi_selectable: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_multi_selectable() -> bool {
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -89,6 +71,12 @@ struct Entry {
|
||||||
entry_type: EntryType,
|
entry_type: EntryType,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
task_list: String,
|
task_list: String,
|
||||||
|
#[serde(default = "default_true")]
|
||||||
|
multi_select: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_true() -> bool {
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -169,8 +157,11 @@ fn create_directory(
|
||||||
node: &mut NodeMut<Rc<ListNode>>,
|
node: &mut NodeMut<Rc<ListNode>>,
|
||||||
command_dir: &Path,
|
command_dir: &Path,
|
||||||
validate: bool,
|
validate: bool,
|
||||||
|
parent_multi_select: bool,
|
||||||
) {
|
) {
|
||||||
for entry in data {
|
for entry in data {
|
||||||
|
let multi_select = parent_multi_select && entry.multi_select;
|
||||||
|
|
||||||
match entry.entry_type {
|
match entry.entry_type {
|
||||||
EntryType::Entries(entries) => {
|
EntryType::Entries(entries) => {
|
||||||
let mut node = node.append(Rc::new(ListNode {
|
let mut node = node.append(Rc::new(ListNode {
|
||||||
|
@ -178,8 +169,9 @@ fn create_directory(
|
||||||
description: entry.description,
|
description: entry.description,
|
||||||
command: Command::None,
|
command: Command::None,
|
||||||
task_list: String::new(),
|
task_list: String::new(),
|
||||||
|
multi_select,
|
||||||
}));
|
}));
|
||||||
create_directory(entries, &mut node, command_dir, validate);
|
create_directory(entries, &mut node, command_dir, validate, multi_select);
|
||||||
}
|
}
|
||||||
EntryType::Command(command) => {
|
EntryType::Command(command) => {
|
||||||
node.append(Rc::new(ListNode {
|
node.append(Rc::new(ListNode {
|
||||||
|
@ -187,6 +179,7 @@ fn create_directory(
|
||||||
description: entry.description,
|
description: entry.description,
|
||||||
command: Command::Raw(command),
|
command: Command::Raw(command),
|
||||||
task_list: String::new(),
|
task_list: String::new(),
|
||||||
|
multi_select,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
EntryType::Script(script) => {
|
EntryType::Script(script) => {
|
||||||
|
@ -205,6 +198,7 @@ fn create_directory(
|
||||||
file: script,
|
file: script,
|
||||||
},
|
},
|
||||||
task_list: entry.task_list,
|
task_list: entry.task_list,
|
||||||
|
multi_select,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ pub enum Command {
|
||||||
pub struct Tab {
|
pub struct Tab {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub tree: Tree<Rc<ListNode>>,
|
pub tree: Tree<Rc<ListNode>>,
|
||||||
pub multi_selectable: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Hash, Eq, PartialEq)]
|
#[derive(Clone, Hash, Eq, PartialEq)]
|
||||||
|
@ -32,4 +31,5 @@ pub struct ListNode {
|
||||||
pub description: String,
|
pub description: String,
|
||||||
pub command: Command,
|
pub command: Command,
|
||||||
pub task_list: String,
|
pub task_list: String,
|
||||||
|
pub multi_select: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
name = "System Setup"
|
name = "System Setup"
|
||||||
multi_selectable = false
|
|
||||||
|
|
||||||
[[data]]
|
[[data]]
|
||||||
name = "Arch Linux"
|
name = "Arch Linux"
|
||||||
|
@ -14,6 +13,7 @@ name = "Arch Server Setup"
|
||||||
description = "This command installs a minimal arch server setup under 5 minutes."
|
description = "This command installs a minimal arch server setup under 5 minutes."
|
||||||
script = "arch/server-setup.sh"
|
script = "arch/server-setup.sh"
|
||||||
task_list = "SI D"
|
task_list = "SI D"
|
||||||
|
multi_select = false
|
||||||
|
|
||||||
[[data.entries]]
|
[[data.entries]]
|
||||||
name = "Paru AUR Helper"
|
name = "Paru AUR Helper"
|
||||||
|
@ -76,12 +76,14 @@ name = "Full System Cleanup"
|
||||||
description = "This script is designed to remove unnecessary packages, clean old cache files, remove temporary files, and to empty the trash."
|
description = "This script is designed to remove unnecessary packages, clean old cache files, remove temporary files, and to empty the trash."
|
||||||
script = "system-cleanup.sh"
|
script = "system-cleanup.sh"
|
||||||
task_list = "RP PFM"
|
task_list = "RP PFM"
|
||||||
|
multi_select = false
|
||||||
|
|
||||||
[[data]]
|
[[data]]
|
||||||
name = "Full System Update"
|
name = "Full System Update"
|
||||||
description = "This command updates your system to the latest packages available for your distro"
|
description = "This command updates your system to the latest packages available for your distro"
|
||||||
script = "system-update.sh"
|
script = "system-update.sh"
|
||||||
task_list = "PFM"
|
task_list = "PFM"
|
||||||
|
multi_select = false
|
||||||
|
|
||||||
[[data]]
|
[[data]]
|
||||||
name = "Gaming Dependencies"
|
name = "Gaming Dependencies"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
name = "Utilities"
|
name = "Utilities"
|
||||||
multi_selectable = false
|
|
||||||
|
|
||||||
[[data]]
|
[[data]]
|
||||||
name = "Monitor Control"
|
name = "Monitor Control"
|
||||||
|
multi_select = false
|
||||||
|
|
||||||
[[data.preconditions]]
|
[[data.preconditions]]
|
||||||
matches = true
|
matches = true
|
||||||
|
@ -72,6 +72,7 @@ script = "monitor-control/set_primary_monitor.sh"
|
||||||
|
|
||||||
[[data]]
|
[[data]]
|
||||||
name = "User Account Manager"
|
name = "User Account Manager"
|
||||||
|
multi_select = false
|
||||||
|
|
||||||
[[data.entries]]
|
[[data.entries]]
|
||||||
name = "Add User"
|
name = "Add User"
|
||||||
|
@ -98,6 +99,7 @@ name = "Auto Mount Drive"
|
||||||
description = "This utility is designed to help with automating the process of mounting a drive on to your system."
|
description = "This utility is designed to help with automating the process of mounting a drive on to your system."
|
||||||
script = "auto-mount.sh"
|
script = "auto-mount.sh"
|
||||||
task_list = "PFM"
|
task_list = "PFM"
|
||||||
|
multi_select = false
|
||||||
|
|
||||||
[[data]]
|
[[data]]
|
||||||
name = "Auto Login"
|
name = "Auto Login"
|
||||||
|
@ -114,6 +116,7 @@ name = "Bluetooth Manager"
|
||||||
description = "This utility is designed to manage bluetooth in your system"
|
description = "This utility is designed to manage bluetooth in your system"
|
||||||
script = "bluetooth-control.sh"
|
script = "bluetooth-control.sh"
|
||||||
task_list = "I SS"
|
task_list = "I SS"
|
||||||
|
multi_select = false
|
||||||
|
|
||||||
[[data]]
|
[[data]]
|
||||||
name = "Bootable USB Creator"
|
name = "Bootable USB Creator"
|
||||||
|
|
|
@ -140,12 +140,10 @@ impl AppState {
|
||||||
hints.push(Shortcut::new("Select item below", ["j", "Down"]));
|
hints.push(Shortcut::new("Select item below", ["j", "Down"]));
|
||||||
hints.push(Shortcut::new("Next theme", ["t"]));
|
hints.push(Shortcut::new("Next theme", ["t"]));
|
||||||
hints.push(Shortcut::new("Previous theme", ["T"]));
|
hints.push(Shortcut::new("Previous theme", ["T"]));
|
||||||
|
hints.push(Shortcut::new("Multi-selection mode", ["v"]));
|
||||||
if self.is_current_tab_multi_selectable() {
|
if self.multi_select {
|
||||||
hints.push(Shortcut::new("Toggle multi-selection mode", ["v"]));
|
|
||||||
hints.push(Shortcut::new("Select multiple commands", ["Space"]));
|
hints.push(Shortcut::new("Select multiple commands", ["Space"]));
|
||||||
}
|
}
|
||||||
|
|
||||||
hints.push(Shortcut::new("Next tab", ["Tab"]));
|
hints.push(Shortcut::new("Next tab", ["Tab"]));
|
||||||
hints.push(Shortcut::new("Previous tab", ["Shift-Tab"]));
|
hints.push(Shortcut::new("Previous tab", ["Shift-Tab"]));
|
||||||
hints.push(Shortcut::new("Important actions guide", ["g"]));
|
hints.push(Shortcut::new("Important actions guide", ["g"]));
|
||||||
|
@ -462,6 +460,13 @@ impl AppState {
|
||||||
// enabled, need to clear it to prevent state corruption
|
// enabled, need to clear it to prevent state corruption
|
||||||
if !self.multi_select {
|
if !self.multi_select {
|
||||||
self.selected_commands.clear()
|
self.selected_commands.clear()
|
||||||
|
} else {
|
||||||
|
// Prevents non multi_selectable cmd from being pushed into the selected list
|
||||||
|
if let Some(node) = self.get_selected_node() {
|
||||||
|
if !node.multi_select {
|
||||||
|
self.selected_commands.retain(|cmd| cmd.name != node.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConfirmStatus::Confirm => self.handle_confirm_command(),
|
ConfirmStatus::Confirm => self.handle_confirm_command(),
|
||||||
|
@ -519,41 +524,30 @@ impl AppState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_multi_select(&mut self) {
|
fn toggle_multi_select(&mut self) {
|
||||||
if self.is_current_tab_multi_selectable() {
|
self.multi_select = !self.multi_select;
|
||||||
self.multi_select = !self.multi_select;
|
if !self.multi_select {
|
||||||
if !self.multi_select {
|
self.selected_commands.clear();
|
||||||
self.selected_commands.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_selection(&mut self) {
|
fn toggle_selection(&mut self) {
|
||||||
if let Some(command) = self.get_selected_node() {
|
if let Some(node) = self.get_selected_node() {
|
||||||
if self.selected_commands.contains(&command) {
|
if node.multi_select {
|
||||||
self.selected_commands.retain(|c| c != &command);
|
if self.selected_commands.contains(&node) {
|
||||||
} else {
|
self.selected_commands.retain(|c| c != &node);
|
||||||
self.selected_commands.push(command);
|
} else {
|
||||||
|
self.selected_commands.push(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_current_tab_multi_selectable(&self) -> bool {
|
|
||||||
let index = self.current_tab.selected().unwrap_or(0);
|
|
||||||
self.tabs
|
|
||||||
.get(index)
|
|
||||||
.map_or(false, |tab| tab.multi_selectable)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_items(&mut self) {
|
fn update_items(&mut self) {
|
||||||
self.filter.update_items(
|
self.filter.update_items(
|
||||||
&self.tabs,
|
&self.tabs,
|
||||||
self.current_tab.selected().unwrap(),
|
self.current_tab.selected().unwrap(),
|
||||||
*self.visit_stack.last().unwrap(),
|
*self.visit_stack.last().unwrap(),
|
||||||
);
|
);
|
||||||
if !self.is_current_tab_multi_selectable() {
|
|
||||||
self.multi_select = false;
|
|
||||||
self.selected_commands.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks either the current tree node is the root node (can we go up the tree or no)
|
/// Checks either the current tree node is the root node (can we go up the tree or no)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user