use super::ResourceTab;
impl super::App {
#[must_use]
pub const fn tab_count(&self, tab: ResourceTab) -> usize {
match tab {
ResourceTab::Servers => self.servers.len(),
ResourceTab::Databases => self.databases.len(),
ResourceTab::S3 => self.s3_storages.len(),
ResourceTab::Kubernetes => self.k8s_clusters.len(),
ResourceTab::Projects => self.projects.len(),
ResourceTab::Balancers => self.balancers.len(),
ResourceTab::Registry => self.registries.len(),
ResourceTab::Domains => self.domains.len(),
ResourceTab::Firewall => self.firewalls.len(),
ResourceTab::FloatingIps => self.floating_ips.len(),
ResourceTab::Images => self.images.len(),
ResourceTab::NetworkDrives => self.network_drives.len(),
ResourceTab::Vpc => self.vpcs.len(),
ResourceTab::DedicatedServers => self.dedicated_servers.len(),
ResourceTab::Mail => self.mails.len(),
ResourceTab::Apps => self.apps.len(),
ResourceTab::AiAgents => self.ai_agents.len(),
ResourceTab::KnowledgeBases => self.knowledge_bases.len(),
ResourceTab::SshKeys => self.ssh_keys.len(),
ResourceTab::Finances => self.finances.len()
}
}
#[must_use]
pub fn visible_tabs(&self) -> Vec<ResourceTab> {
if !self.hide_empty_tabs {
return ResourceTab::ALL.to_vec();
}
let mut tabs: Vec<ResourceTab> = ResourceTab::ALL
.into_iter()
.filter(|t| self.tab_count(*t) > 0 || *t == self.active_tab)
.collect();
if tabs.is_empty() {
tabs.push(self.active_tab);
}
tabs
}
pub const fn toggle_hide_empty_tabs(&mut self) {
self.hide_empty_tabs = !self.hide_empty_tabs;
self.prefs_dirty = true;
}
#[must_use]
pub fn current_item_names(&self) -> Vec<String> {
match self.active_tab {
ResourceTab::Servers => self.servers.iter().map(|s| s.name.clone()).collect(),
ResourceTab::Databases => self.databases.iter().map(|d| d.name.clone()).collect(),
ResourceTab::S3 => self.s3_storages.iter().map(|s| s.name.clone()).collect(),
ResourceTab::Kubernetes => self.k8s_clusters.iter().map(|c| c.name.clone()).collect(),
ResourceTab::Projects => self.projects.iter().map(|p| p.name.clone()).collect(),
ResourceTab::Balancers => self.balancers.iter().map(|b| b.name.clone()).collect(),
ResourceTab::Registry => self.registries.iter().map(|r| r.name.clone()).collect(),
ResourceTab::Domains => self.domains.iter().map(|d| d.name.clone()).collect(),
ResourceTab::Firewall => self.firewalls.iter().map(|f| f.name.clone()).collect(),
ResourceTab::FloatingIps => self.floating_ips.iter().map(|f| f.ip.clone()).collect(),
ResourceTab::Images => self.images.iter().map(|i| i.name.clone()).collect(),
ResourceTab::NetworkDrives => {
self.network_drives.iter().map(|n| n.name.clone()).collect()
}
ResourceTab::Vpc => self.vpcs.iter().map(|v| v.name.clone()).collect(),
ResourceTab::DedicatedServers => self
.dedicated_servers
.iter()
.map(|d| d.name.clone())
.collect(),
ResourceTab::Mail => self.mails.iter().map(|m| m.name.clone()).collect(),
ResourceTab::Apps => self.apps.iter().map(|a| a.name.clone()).collect(),
ResourceTab::AiAgents => self.ai_agents.iter().map(|a| a.name.clone()).collect(),
ResourceTab::KnowledgeBases => self
.knowledge_bases
.iter()
.map(|k| k.name.clone())
.collect(),
ResourceTab::SshKeys => self.ssh_keys.clone(),
ResourceTab::Finances => self.finances.clone()
}
}
#[must_use]
pub fn filtered_indices(&self) -> Vec<usize> {
let names = self.current_item_names();
if self.filter.is_empty() {
return (0..names.len()).collect();
}
let needle = self.filter.to_lowercase();
names
.iter()
.enumerate()
.filter(|(_, name)| name.to_lowercase().contains(&needle))
.map(|(i, _)| i)
.collect()
}
pub const fn start_filter(&mut self) {
self.filter_editing = true;
self.selected = 0;
}
pub fn filter_push(&mut self, c: char) {
self.filter.push(c);
self.selected = 0;
}
pub fn filter_backspace(&mut self) {
self.filter.pop();
self.selected = 0;
}
pub const fn filter_apply(&mut self) {
self.filter_editing = false;
}
pub fn filter_clear(&mut self) {
self.filter.clear();
self.filter_editing = false;
self.selected = 0;
}
#[must_use]
pub const fn filter_active(&self) -> bool {
self.filter_editing || !self.filter.is_empty()
}
#[must_use]
pub fn selected_real_index(&self) -> usize {
self.filtered_indices()
.get(self.selected)
.copied()
.unwrap_or(0)
}
#[must_use]
pub fn current_list_len(&self) -> usize {
self.filtered_indices().len()
}
pub const fn select_previous(&mut self) {
if self.selected > 0 {
self.selected -= 1;
}
}
pub fn select_next(&mut self) {
if self.selected + 1 < self.current_list_len() {
self.selected += 1;
}
}
pub fn next_tab(&mut self) {
let tabs = self.visible_tabs();
let pos = tabs.iter().position(|t| *t == self.active_tab).unwrap_or(0);
self.active_tab = tabs[(pos + 1) % tabs.len()];
self.reset_after_tab_change();
}
pub fn previous_tab(&mut self) {
let tabs = self.visible_tabs();
let pos = tabs.iter().position(|t| *t == self.active_tab).unwrap_or(0);
self.active_tab = tabs[(pos + tabs.len() - 1) % tabs.len()];
self.reset_after_tab_change();
}
fn reset_after_tab_change(&mut self) {
self.selected = 0;
self.filter.clear();
self.filter_editing = false;
}
pub(super) fn clamp_selection(&mut self) {
let len = self.current_list_len();
if len == 0 {
self.selected = 0;
} else if self.selected >= len {
self.selected = len - 1;
}
}
#[must_use]
pub fn selected_resource(&self) -> Option<(String, String)> {
let real = *self.filtered_indices().get(self.selected)?;
match self.active_tab {
ResourceTab::Servers => self
.servers
.get(real)
.map(|s| (s.id.to_string(), s.name.clone())),
ResourceTab::Databases => self
.databases
.get(real)
.map(|d| (d.id.to_string(), d.name.clone())),
ResourceTab::S3 => self
.s3_storages
.get(real)
.map(|s| (s.id.to_string(), s.name.clone())),
ResourceTab::Kubernetes => self
.k8s_clusters
.get(real)
.map(|c| (c.id.to_string(), c.name.clone())),
ResourceTab::Balancers => self
.balancers
.get(real)
.map(|b| (b.id.to_string(), b.name.clone())),
ResourceTab::Registry => self
.registries
.get(real)
.map(|r| (r.id.to_string(), r.name.clone())),
ResourceTab::Projects => self
.projects
.get(real)
.map(|p| (p.id.to_string(), p.name.clone())),
ResourceTab::DedicatedServers => self
.dedicated_servers
.get(real)
.map(|d| (d.id.to_string(), d.name.clone())),
ResourceTab::AiAgents => self
.ai_agents
.get(real)
.map(|a| (a.id.to_string(), a.name.clone())),
ResourceTab::Apps => self
.apps
.get(real)
.map(|a| (a.id.to_string(), a.name.clone())),
ResourceTab::KnowledgeBases => self
.knowledge_bases
.get(real)
.map(|k| (k.id.to_string(), k.name.clone())),
ResourceTab::Domains => self
.domains
.get(real)
.map(|d| (d.id.to_string(), d.name.clone())),
ResourceTab::Firewall => self
.firewalls
.get(real)
.map(|f| (f.id.clone(), f.name.clone())),
ResourceTab::FloatingIps => self
.floating_ips
.get(real)
.map(|f| (f.id.clone(), f.ip.clone())),
ResourceTab::Images => self
.images
.get(real)
.map(|i| (i.id.clone(), i.name.clone())),
ResourceTab::NetworkDrives => self
.network_drives
.get(real)
.map(|n| (n.id.clone(), n.name.clone())),
ResourceTab::Vpc => self.vpcs.get(real).map(|v| (v.id.clone(), v.name.clone())),
_ => None
}
}
}