rusticity_term/s3/
actions.rs1use crate::app::App;
2use crate::common::{CyclicEnum, InputFocus, PageSize};
3use crate::ui::s3::{calculate_filtered_bucket_rows, BucketType as S3BucketType};
4
5const FILTER_CONTROLS: [InputFocus; 2] = [InputFocus::Filter, InputFocus::Pagination];
6
7pub fn apply_filter_reset(app: &mut App) {
10 if app.s3_state.current_bucket.is_some() {
11 app.s3_state.selected_object = 0;
12 } else {
13 app.s3_state.buckets.reset();
14 app.s3_state.selected_row = 0;
15 app.s3_state.bucket_scroll_offset = 0;
16 }
17}
18
19pub fn reset_on_service_select(app: &mut App) {
20 app.s3_state.selected_row = 0;
21 app.s3_state.selected_object = 0;
22}
23
24pub fn start_filter(app: &mut App) {
25 app.s3_state.input_focus = InputFocus::Filter;
26}
27
28pub fn next_filter_focus(app: &mut App) {
29 app.s3_state.input_focus = app.s3_state.input_focus.next(&FILTER_CONTROLS);
30}
31
32pub fn prev_filter_focus(app: &mut App) {
33 app.s3_state.input_focus = app.s3_state.input_focus.prev(&FILTER_CONTROLS);
34}
35
36pub fn is_pagination_focused(app: &App) -> bool {
37 app.s3_state.input_focus == InputFocus::Pagination
38}
39
40pub fn page_down_filter_input(app: &mut App) {
43 if app.s3_state.input_focus == InputFocus::Pagination {
44 let page_size = app.s3_state.buckets.page_size.value();
45 let total_rows = calculate_filtered_bucket_rows(app);
46 let last_page = if total_rows > page_size {
47 ((total_rows - 1) / page_size) * page_size
48 } else {
49 0
50 };
51 app.s3_state.selected_row = (app.s3_state.selected_row + page_size).min(last_page);
52 app.s3_state.bucket_scroll_offset = app.s3_state.selected_row;
53 }
54}
55
56pub fn page_up_filter_input(app: &mut App) {
57 if app.s3_state.input_focus == InputFocus::Pagination {
58 let page_size = app.s3_state.buckets.page_size.value();
59 app.s3_state.selected_row = app.s3_state.selected_row.saturating_sub(page_size);
60 app.s3_state.bucket_scroll_offset = app.s3_state.selected_row;
61 }
62}
63
64pub fn go_back(app: &mut App) {
67 if !app.s3_state.prefix_stack.is_empty() {
68 app.s3_state.prefix_stack.pop();
69 app.s3_state.buckets.loading = true;
70 } else {
71 app.s3_state.current_bucket = None;
72 app.s3_state.objects.clear();
73 }
74}
75
76pub fn next_detail_tab(app: &mut App) {
77 if app.s3_state.current_bucket.is_some() {
78 app.s3_state.object_tab = app.s3_state.object_tab.next();
79 } else {
80 app.s3_state.bucket_type = match app.s3_state.bucket_type {
81 S3BucketType::GeneralPurpose => S3BucketType::Directory,
82 S3BucketType::Directory => S3BucketType::GeneralPurpose,
83 };
84 app.s3_state.buckets.reset();
85 }
86}
87
88pub fn prev_detail_tab(app: &mut App) {
89 if app.s3_state.current_bucket.is_some() {
90 app.s3_state.object_tab = app.s3_state.object_tab.prev();
91 }
92}
93
94pub fn toggle_column(app: &mut App) {
97 let idx = app.column_selector_index;
98 if idx > 0 && idx <= app.s3_bucket_column_ids.len() {
99 if let Some(col) = app.s3_bucket_column_ids.get(idx - 1) {
100 App::toggle_column_visibility(
101 &mut app.s3_bucket_visible_column_ids,
102 &app.s3_bucket_column_ids,
103 *col,
104 );
105 }
106 } else if idx == app.s3_bucket_column_ids.len() + 3 {
107 app.s3_state.buckets.page_size = PageSize::Ten;
108 } else if idx == app.s3_bucket_column_ids.len() + 4 {
109 app.s3_state.buckets.page_size = PageSize::TwentyFive;
110 } else if idx == app.s3_bucket_column_ids.len() + 5 {
111 app.s3_state.buckets.page_size = PageSize::Fifty;
112 } else if idx == app.s3_bucket_column_ids.len() + 6 {
113 app.s3_state.buckets.page_size = PageSize::OneHundred;
114 }
115}
116
117pub fn next_preferences(app: &mut App) {
118 let page_size_idx = app.s3_bucket_column_ids.len() + 2;
119 if app.column_selector_index < page_size_idx {
120 app.column_selector_index = page_size_idx;
121 } else {
122 app.column_selector_index = 0;
123 }
124}
125
126pub fn prev_preferences(app: &mut App) {
127 let page_size_idx = app.s3_bucket_column_ids.len() + 2;
128 if app.column_selector_index >= page_size_idx {
129 app.column_selector_index = 0;
130 } else {
131 app.column_selector_index = page_size_idx;
132 }
133}
134
135pub fn column_selector_max(app: &App) -> usize {
136 app.s3_bucket_column_ids.len() + 6
137}
138
139pub fn column_count(app: &App) -> usize {
140 app.s3_bucket_column_ids.len()
141}
142
143pub fn breadcrumb(app: &App) -> Vec<String> {
146 let mut parts = vec!["S3".to_string()];
147 if let Some(bucket) = &app.s3_state.current_bucket {
148 parts.push(bucket.clone());
149 if let Some(prefix) = app.s3_state.prefix_stack.last() {
150 parts.push(prefix.trim_end_matches('/').to_string());
151 }
152 } else {
153 parts.push("Buckets".to_string());
154 }
155 parts
156}
157
158pub fn console_url(app: &App) -> String {
159 use crate::s3;
160 if let Some(bucket_name) = &app.s3_state.current_bucket {
161 let prefix = app.s3_state.prefix_stack.join("");
162 s3::console_url_bucket(&app.config.region, bucket_name, &prefix)
163 } else {
164 s3::console_url_buckets(&app.config.region)
165 }
166}