modde_ui/views/
data_tab.rs1use crate::views::selectable_text::text;
2use iced::widget::{checkbox, column, container, row, scrollable, text_input};
3use iced::{Alignment, Element, Length};
4
5use crate::app::Message;
6
7#[derive(Debug, Clone, Default)]
9pub struct DataTabState {
10 pub filter: String,
11 pub show_conflicts_only: bool,
12 pub missing_store_mod_count: usize,
13}
14
15pub fn view<'a>(
17 state: &'a DataTabState,
18 conflict_files: &'a [(String, Vec<String>)],
19) -> Element<'a, Message> {
20 let title_bar = row![
21 text("Data Files").size(20),
22 iced::widget::space::horizontal(),
23 ]
24 .align_y(Alignment::Center);
25
26 let toolbar = row![
27 text_input("Filter files...", &state.filter)
28 .on_input(Message::DataTabFilterChanged)
29 .padding(6)
30 .width(Length::Fill),
31 checkbox(state.show_conflicts_only).on_toggle(Message::DataTabToggleConflicts),
32 text("Conflicts only").size(13),
33 ]
34 .spacing(8)
35 .align_y(Alignment::Center);
36
37 let filter_lower = state.filter.to_lowercase();
38 let filtered: Vec<&(String, Vec<String>)> = conflict_files
39 .iter()
40 .filter(|(file, _)| {
41 if !filter_lower.is_empty() && !file.to_lowercase().contains(&filter_lower) {
42 return false;
43 }
44 if state.show_conflicts_only {
45 return true; }
47 true
48 })
49 .collect();
50
51 let file_count = filtered.len();
52
53 let file_rows: Element<Message> = if filtered.is_empty() && state.missing_store_mod_count > 0 {
54 container(
55 text(format!(
56 "{} enabled mod(s) are missing from the store; conflict data is incomplete.",
57 state.missing_store_mod_count
58 ))
59 .size(14),
60 )
61 .padding(20)
62 .width(Length::Fill)
63 .center_x(Length::Fill)
64 .into()
65 } else if filtered.is_empty() {
66 container(text("No data files to display.").size(14))
67 .padding(20)
68 .width(Length::Fill)
69 .center_x(Length::Fill)
70 .into()
71 } else {
72 let rows = filtered
73 .into_iter()
74 .fold(column![].spacing(4), |col, (file, providers)| {
75 let provider_list = providers.join(", ");
76 let file_row = row![
77 text(file).size(13).width(Length::Fill),
78 text(provider_list).size(12).width(Length::Fixed(300.0)),
79 ]
80 .spacing(8)
81 .padding([4, 8]);
82 col.push(file_row)
83 });
84
85 scrollable(rows).height(Length::Fill).into()
86 };
87
88 let header = row![
89 text("File Path").size(12).width(Length::Fill),
90 text("Providing Mods").size(12).width(Length::Fixed(300.0)),
91 ]
92 .spacing(8)
93 .padding([4, 8]);
94
95 let status = text(format!("{file_count} file(s) shown")).size(12);
96
97 column![
98 title_bar,
99 toolbar,
100 header,
101 iced::widget::rule::horizontal(1),
102 file_rows,
103 status,
104 ]
105 .spacing(8)
106 .padding(16)
107 .width(Length::Fill)
108 .height(Length::Fill)
109 .into()
110}