158 lines
4.7 KiB
Rust
158 lines
4.7 KiB
Rust
use poise::{
|
|
serenity_prelude::{
|
|
CreateActionRow, CreateEmbed, CreateEmbedFooter, CreateSelectMenu, CreateSelectMenuKind,
|
|
CreateSelectMenuOption,
|
|
},
|
|
CreateReply,
|
|
};
|
|
|
|
use crate::{
|
|
component_models::{
|
|
pager::{Pager, TodoPager},
|
|
ComponentDataModel, TodoSelector,
|
|
},
|
|
consts::{EMBED_DESCRIPTION_MAX_LENGTH, SELECT_MAX_ENTRIES, THEME_COLOR},
|
|
Context, Error,
|
|
};
|
|
|
|
pub mod channel;
|
|
pub mod guild;
|
|
pub mod user;
|
|
|
|
/// Manage todo lists
|
|
#[poise::command(slash_command, default_member_permissions = "MANAGE_GUILD")]
|
|
pub async fn todo(_ctx: Context<'_>) -> Result<(), Error> {
|
|
Ok(())
|
|
}
|
|
|
|
pub fn max_todo_page(todo_values: &[(usize, String)]) -> usize {
|
|
let mut rows = 0;
|
|
let mut char_count = 0;
|
|
|
|
todo_values.iter().enumerate().map(|(c, (_, v))| format!("{}: {}", c, v)).fold(
|
|
1,
|
|
|mut pages, text| {
|
|
rows += 1;
|
|
char_count += text.len();
|
|
|
|
if char_count > EMBED_DESCRIPTION_MAX_LENGTH || rows > SELECT_MAX_ENTRIES {
|
|
rows = 1;
|
|
char_count = text.len();
|
|
pages += 1;
|
|
}
|
|
|
|
pages
|
|
},
|
|
)
|
|
}
|
|
|
|
pub fn show_todo_page(
|
|
todo_values: &[(usize, String)],
|
|
page: usize,
|
|
user_id: Option<u64>,
|
|
channel_id: Option<u64>,
|
|
guild_id: Option<u64>,
|
|
) -> CreateReply {
|
|
let pager = TodoPager::new(page, user_id, channel_id, guild_id);
|
|
|
|
let pages = max_todo_page(todo_values);
|
|
let mut page = page;
|
|
if page >= pages {
|
|
page = pages - 1;
|
|
}
|
|
|
|
let mut char_count = 0;
|
|
let mut rows = 0;
|
|
let mut skipped_rows = 0;
|
|
let mut skipped_char_count = 0;
|
|
let mut first_num = 0;
|
|
|
|
let mut skipped_pages = 0;
|
|
|
|
let (todo_ids, display_vec): (Vec<usize>, Vec<String>) = todo_values
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(c, (i, v))| (i, format!("`{}`: {}", c + 1, v)))
|
|
.skip_while(|(_, p)| {
|
|
first_num += 1;
|
|
skipped_rows += 1;
|
|
skipped_char_count += p.len();
|
|
|
|
if skipped_char_count > EMBED_DESCRIPTION_MAX_LENGTH
|
|
|| skipped_rows > SELECT_MAX_ENTRIES
|
|
{
|
|
skipped_rows = 1;
|
|
skipped_char_count = p.len();
|
|
skipped_pages += 1;
|
|
}
|
|
|
|
skipped_pages < page
|
|
})
|
|
.take_while(|(_, p)| {
|
|
rows += 1;
|
|
char_count += p.len();
|
|
|
|
char_count < EMBED_DESCRIPTION_MAX_LENGTH && rows <= SELECT_MAX_ENTRIES
|
|
})
|
|
.unzip();
|
|
|
|
let display = display_vec.join("\n");
|
|
|
|
let title = if user_id.is_some() {
|
|
"Your"
|
|
} else if channel_id.is_some() {
|
|
"Channel"
|
|
} else {
|
|
"Server"
|
|
};
|
|
|
|
if todo_ids.is_empty() {
|
|
CreateReply::default().embed(
|
|
CreateEmbed::new()
|
|
.title(format!("{} Todo List", title))
|
|
.description("Todo List Empty!")
|
|
.color(*THEME_COLOR)
|
|
.footer(CreateEmbedFooter::new(format!("Page {} of {}", page + 1, pages))),
|
|
)
|
|
} else {
|
|
let todo_selector =
|
|
ComponentDataModel::TodoSelector(TodoSelector { page, user_id, channel_id, guild_id });
|
|
|
|
CreateReply::default()
|
|
.embed(
|
|
CreateEmbed::new()
|
|
.title(format!("{} Todo List", title))
|
|
.description(display)
|
|
.color(*THEME_COLOR)
|
|
.footer(CreateEmbedFooter::new(format!("Page {} of {}", page + 1, pages))),
|
|
)
|
|
.components(vec![
|
|
pager.create_button_row(pages),
|
|
CreateActionRow::SelectMenu(CreateSelectMenu::new(
|
|
todo_selector.to_custom_id(),
|
|
CreateSelectMenuKind::String {
|
|
options: todo_ids
|
|
.iter()
|
|
.zip(&display_vec)
|
|
.enumerate()
|
|
.map(|(count, (id, disp))| {
|
|
let c = disp.split_once(' ').unwrap_or(("", "")).1;
|
|
let description = if c.len() > 100 {
|
|
format!("{}...", c.chars().take(97).collect::<String>())
|
|
} else {
|
|
c.to_string()
|
|
};
|
|
|
|
CreateSelectMenuOption::new(
|
|
format!("Mark {} complete", count + first_num),
|
|
id.to_string(),
|
|
)
|
|
.description(description)
|
|
})
|
|
.collect(),
|
|
},
|
|
)),
|
|
])
|
|
}
|
|
}
|