parent
6cf660c7ee
commit
9b54fba5e5
@ -8,16 +8,12 @@ use chrono::NaiveDateTime;
|
|||||||
use chrono_tz::Tz;
|
use chrono_tz::Tz;
|
||||||
use num_integer::Integer;
|
use num_integer::Integer;
|
||||||
use regex_command_attr::command;
|
use regex_command_attr::command;
|
||||||
use serenity::{
|
use serenity::{builder::CreateEmbed, client::Context, model::channel::Channel};
|
||||||
builder::CreateEmbed,
|
|
||||||
client::Context,
|
|
||||||
model::{channel::Channel, id::UserId},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
check_subscription_on_message,
|
check_subscription_on_message,
|
||||||
component_models::{
|
component_models::{
|
||||||
pager::{DelData, LookData, Pager},
|
pager::{DelPager, LookPager, Pager},
|
||||||
ComponentDataModel, DelSelector,
|
ComponentDataModel, DelSelector,
|
||||||
},
|
},
|
||||||
consts::{
|
consts::{
|
||||||
@ -333,7 +329,7 @@ async fn look(ctx: &Context, invoke: &mut CommandInvoke, args: CommandOptions) {
|
|||||||
.fold(0, |t, r| t + r.len())
|
.fold(0, |t, r| t + r.len())
|
||||||
.div_ceil(EMBED_DESCRIPTION_MAX_LENGTH);
|
.div_ceil(EMBED_DESCRIPTION_MAX_LENGTH);
|
||||||
|
|
||||||
let pager = Pager::new(0, LookData { flags, timezone });
|
let pager = LookPager::new(flags, timezone);
|
||||||
|
|
||||||
invoke
|
invoke
|
||||||
.respond(
|
.respond(
|
||||||
@ -367,7 +363,7 @@ async fn delete(ctx: &Context, invoke: &mut CommandInvoke, _args: CommandOptions
|
|||||||
|
|
||||||
let reminders = Reminder::from_guild(ctx, invoke.guild_id(), invoke.author_id()).await;
|
let reminders = Reminder::from_guild(ctx, invoke.guild_id(), invoke.author_id()).await;
|
||||||
|
|
||||||
let resp = show_delete_page(&reminders, 0, timezone, invoke.author_id());
|
let resp = show_delete_page(&reminders, 0, timezone);
|
||||||
|
|
||||||
let _ = invoke.respond(&ctx, resp).await;
|
let _ = invoke.respond(&ctx, resp).await;
|
||||||
}
|
}
|
||||||
@ -398,9 +394,8 @@ pub fn show_delete_page(
|
|||||||
reminders: &[Reminder],
|
reminders: &[Reminder],
|
||||||
page: usize,
|
page: usize,
|
||||||
timezone: Tz,
|
timezone: Tz,
|
||||||
author_id: UserId,
|
|
||||||
) -> CreateGenericResponse {
|
) -> CreateGenericResponse {
|
||||||
let pager = Pager::new(page, DelData { author_id, timezone });
|
let pager = DelPager::new(page, timezone);
|
||||||
|
|
||||||
if reminders.is_empty() {
|
if reminders.is_empty() {
|
||||||
return CreateGenericResponse::new()
|
return CreateGenericResponse::new()
|
||||||
@ -455,7 +450,7 @@ pub fn show_delete_page(
|
|||||||
|
|
||||||
let display = display_vec.join("\n");
|
let display = display_vec.join("\n");
|
||||||
|
|
||||||
let del_selector = ComponentDataModel::DelSelector(DelSelector { page, timezone, author_id });
|
let del_selector = ComponentDataModel::DelSelector(DelSelector { page, timezone });
|
||||||
|
|
||||||
CreateGenericResponse::new()
|
CreateGenericResponse::new()
|
||||||
.embed(|e| {
|
.embed(|e| {
|
||||||
|
@ -3,7 +3,7 @@ use serenity::client::Context;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
component_models::{
|
component_models::{
|
||||||
pager::{Pager, TodoData},
|
pager::{Pager, TodoPager},
|
||||||
ComponentDataModel, TodoSelector,
|
ComponentDataModel, TodoSelector,
|
||||||
},
|
},
|
||||||
consts::{EMBED_DESCRIPTION_MAX_LENGTH, SELECT_MAX_ENTRIES, THEME_COLOR},
|
consts::{EMBED_DESCRIPTION_MAX_LENGTH, SELECT_MAX_ENTRIES, THEME_COLOR},
|
||||||
@ -136,7 +136,7 @@ pub fn show_todo_page(
|
|||||||
channel_id: Option<u64>,
|
channel_id: Option<u64>,
|
||||||
guild_id: Option<u64>,
|
guild_id: Option<u64>,
|
||||||
) -> CreateGenericResponse {
|
) -> CreateGenericResponse {
|
||||||
let pager = Pager::new(page, TodoData { user_id, channel_id, guild_id });
|
let pager = TodoPager::new(page, user_id, channel_id, guild_id);
|
||||||
|
|
||||||
let pages = max_todo_page(todo_values);
|
let pages = max_todo_page(todo_values);
|
||||||
let mut page = page;
|
let mut page = page;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub mod pager;
|
pub(crate) mod pager;
|
||||||
|
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ use crate::{
|
|||||||
reminder_cmds::{max_delete_page, show_delete_page},
|
reminder_cmds::{max_delete_page, show_delete_page},
|
||||||
todo_cmds::{max_todo_page, show_todo_page},
|
todo_cmds::{max_todo_page, show_todo_page},
|
||||||
},
|
},
|
||||||
component_models::pager::{DelData, LookData, Pager, TodoData},
|
component_models::pager::{DelPager, LookPager, Pager, TodoPager},
|
||||||
consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR},
|
consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR},
|
||||||
framework::CommandInvoke,
|
framework::CommandInvoke,
|
||||||
models::reminder::Reminder,
|
models::reminder::Reminder,
|
||||||
@ -29,15 +29,15 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
#[serde(untagged)]
|
#[serde(tag = "type")]
|
||||||
|
#[repr(u8)]
|
||||||
pub enum ComponentDataModel {
|
pub enum ComponentDataModel {
|
||||||
Restrict(Restrict),
|
Restrict(Restrict),
|
||||||
|
LookPager(LookPager),
|
||||||
|
DelPager(DelPager),
|
||||||
|
TodoPager(TodoPager),
|
||||||
DelSelector(DelSelector),
|
DelSelector(DelSelector),
|
||||||
TodoSelector(TodoSelector),
|
TodoSelector(TodoSelector),
|
||||||
LookPager(Pager<LookData>),
|
|
||||||
DelPager(Pager<DelData>),
|
|
||||||
TodoPager(Pager<TodoData>),
|
|
||||||
MacroPager(Pager<GuildId>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComponentDataModel {
|
impl ComponentDataModel {
|
||||||
@ -90,20 +90,11 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
component
|
// tell them they cant do this
|
||||||
.create_interaction_response(&ctx, |r| {
|
|
||||||
r.kind(InteractionResponseType::ChannelMessageWithSource)
|
|
||||||
.interaction_response_data(|response| response
|
|
||||||
.flags(InteractionApplicationCommandCallbackDataFlags::EPHEMERAL)
|
|
||||||
.content("Only the original command user can interact with this message")
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ComponentDataModel::LookPager(pager) => {
|
ComponentDataModel::LookPager(pager) => {
|
||||||
let flags = pager.data.flags;
|
let flags = pager.flags;
|
||||||
|
|
||||||
let channel_opt = component.channel_id.to_channel_cached(&ctx);
|
let channel_opt = component.channel_id.to_channel_cached(&ctx);
|
||||||
|
|
||||||
@ -121,7 +112,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id
|
|||||||
|
|
||||||
let pages = reminders
|
let pages = reminders
|
||||||
.iter()
|
.iter()
|
||||||
.map(|reminder| reminder.display(&flags, &pager.data.timezone))
|
.map(|reminder| reminder.display(&flags, &pager.timezone))
|
||||||
.fold(0, |t, r| t + r.len())
|
.fold(0, |t, r| t + r.len())
|
||||||
.div_ceil(EMBED_DESCRIPTION_MAX_LENGTH);
|
.div_ceil(EMBED_DESCRIPTION_MAX_LENGTH);
|
||||||
|
|
||||||
@ -139,7 +130,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id
|
|||||||
|
|
||||||
let display = reminders
|
let display = reminders
|
||||||
.iter()
|
.iter()
|
||||||
.map(|reminder| reminder.display(&flags, &pager.data.timezone))
|
.map(|reminder| reminder.display(&flags, &pager.timezone))
|
||||||
.skip_while(|p| {
|
.skip_while(|p| {
|
||||||
skip_char_count += p.len();
|
skip_char_count += p.len();
|
||||||
|
|
||||||
@ -178,33 +169,15 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
ComponentDataModel::DelPager(pager) => {
|
ComponentDataModel::DelPager(pager) => {
|
||||||
if component.user.id == pager.data.author_id {
|
let reminders =
|
||||||
let reminders =
|
Reminder::from_guild(ctx, component.guild_id, component.user.id).await;
|
||||||
Reminder::from_guild(ctx, component.guild_id, component.user.id).await;
|
|
||||||
|
|
||||||
let max_pages = max_delete_page(&reminders, &pager.data.timezone);
|
let max_pages = max_delete_page(&reminders, &pager.timezone);
|
||||||
|
|
||||||
let resp = show_delete_page(
|
let resp = show_delete_page(&reminders, pager.next_page(max_pages), pager.timezone);
|
||||||
&reminders,
|
|
||||||
pager.next_page(max_pages),
|
|
||||||
pager.data.timezone,
|
|
||||||
pager.data.author_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut invoke = CommandInvoke::component(component);
|
let mut invoke = CommandInvoke::component(component);
|
||||||
let _ = invoke.respond(&ctx, resp).await;
|
let _ = invoke.respond(&ctx, resp).await;
|
||||||
} else {
|
|
||||||
component
|
|
||||||
.create_interaction_response(&ctx, |r| {
|
|
||||||
r.kind(InteractionResponseType::ChannelMessageWithSource)
|
|
||||||
.interaction_response_data(|response| response
|
|
||||||
.flags(InteractionApplicationCommandCallbackDataFlags::EPHEMERAL)
|
|
||||||
.content("Only the original command user can interact with this message")
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ComponentDataModel::DelSelector(selector) => {
|
ComponentDataModel::DelSelector(selector) => {
|
||||||
let pool = ctx.data.read().await.get::<SQLPool>().cloned().unwrap();
|
let pool = ctx.data.read().await.get::<SQLPool>().cloned().unwrap();
|
||||||
@ -218,12 +191,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id
|
|||||||
let reminders =
|
let reminders =
|
||||||
Reminder::from_guild(ctx, component.guild_id, component.user.id).await;
|
Reminder::from_guild(ctx, component.guild_id, component.user.id).await;
|
||||||
|
|
||||||
let resp = show_delete_page(
|
let resp = show_delete_page(&reminders, selector.page, selector.timezone);
|
||||||
&reminders,
|
|
||||||
selector.page,
|
|
||||||
selector.timezone,
|
|
||||||
selector.author_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut invoke = CommandInvoke::component(component);
|
let mut invoke = CommandInvoke::component(component);
|
||||||
let _ = invoke.respond(&ctx, resp).await;
|
let _ = invoke.respond(&ctx, resp).await;
|
||||||
@ -234,9 +202,9 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id
|
|||||||
let values = sqlx::query!(
|
let values = sqlx::query!(
|
||||||
// fucking braindead mysql use <=> instead of = for null comparison
|
// fucking braindead mysql use <=> instead of = for null comparison
|
||||||
"SELECT id, value FROM todos WHERE user_id <=> ? AND channel_id <=> ? AND guild_id <=> ?",
|
"SELECT id, value FROM todos WHERE user_id <=> ? AND channel_id <=> ? AND guild_id <=> ?",
|
||||||
pager.data.user_id,
|
pager.user_id,
|
||||||
pager.data.channel_id,
|
pager.channel_id,
|
||||||
pager.data.guild_id,
|
pager.guild_id,
|
||||||
)
|
)
|
||||||
.fetch_all(&pool)
|
.fetch_all(&pool)
|
||||||
.await
|
.await
|
||||||
@ -250,9 +218,9 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id
|
|||||||
let resp = show_todo_page(
|
let resp = show_todo_page(
|
||||||
&values,
|
&values,
|
||||||
pager.next_page(max_pages),
|
pager.next_page(max_pages),
|
||||||
pager.data.user_id,
|
pager.user_id,
|
||||||
pager.data.channel_id,
|
pager.channel_id,
|
||||||
pager.data.guild_id,
|
pager.guild_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut invoke = CommandInvoke::component(component);
|
let mut invoke = CommandInvoke::component(component);
|
||||||
@ -292,7 +260,6 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id
|
|||||||
let mut invoke = CommandInvoke::component(component);
|
let mut invoke = CommandInvoke::component(component);
|
||||||
let _ = invoke.respond(&ctx, resp).await;
|
let _ = invoke.respond(&ctx, resp).await;
|
||||||
}
|
}
|
||||||
ComponentDataModel::MacroPager(pager) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,7 +275,6 @@ pub struct Restrict {
|
|||||||
pub struct DelSelector {
|
pub struct DelSelector {
|
||||||
pub page: usize,
|
pub page: usize,
|
||||||
pub timezone: Tz,
|
pub timezone: Tz,
|
||||||
pub author_id: UserId,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
@ -1,30 +1,37 @@
|
|||||||
|
// todo split pager out into a single struct
|
||||||
use chrono_tz::Tz;
|
use chrono_tz::Tz;
|
||||||
use rmp_serde::Serializer;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_repr::*;
|
use serde_repr::*;
|
||||||
use serenity::{
|
use serenity::{builder::CreateComponents, model::interactions::message_component::ButtonStyle};
|
||||||
builder::CreateComponents,
|
|
||||||
model::{id::UserId, interactions::message_component::ButtonStyle},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{component_models::ComponentDataModel, models::reminder::look_flags::LookFlags};
|
use crate::{component_models::ComponentDataModel, models::reminder::look_flags::LookFlags};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
pub trait Pager {
|
||||||
pub struct Pager<D> {
|
fn next_page(&self, max_pages: usize) -> usize;
|
||||||
pub page: usize,
|
|
||||||
action: PageAction,
|
fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents);
|
||||||
pub data: D,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> Pager<D>
|
#[derive(Serialize_repr, Deserialize_repr)]
|
||||||
where
|
#[repr(u8)]
|
||||||
D: Serialize + Clone,
|
enum PageAction {
|
||||||
{
|
First = 0,
|
||||||
pub fn new(page: usize, data: D) -> Self {
|
Previous = 1,
|
||||||
Self { page, action: PageAction::Refresh, data }
|
Refresh = 2,
|
||||||
}
|
Next = 3,
|
||||||
|
Last = 4,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn next_page(&self, max_pages: usize) -> usize {
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct LookPager {
|
||||||
|
pub flags: LookFlags,
|
||||||
|
pub page: usize,
|
||||||
|
action: PageAction,
|
||||||
|
pub timezone: Tz,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pager for LookPager {
|
||||||
|
fn next_page(&self, max_pages: usize) -> usize {
|
||||||
match self.action {
|
match self.action {
|
||||||
PageAction::First => 0,
|
PageAction::First => 0,
|
||||||
PageAction::Previous => 0.max(self.page - 1),
|
PageAction::Previous => 0.max(self.page - 1),
|
||||||
@ -34,26 +41,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_custom_id(&self) -> String {
|
fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) {
|
||||||
let mut buf = Vec::new();
|
|
||||||
self.serialize(&mut Serializer::new(&mut buf)).unwrap();
|
|
||||||
base64::encode(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn buttons(&self, page: usize) -> (Pager<D>, Pager<D>, Pager<D>, Pager<D>, Pager<D>) {
|
|
||||||
(
|
|
||||||
Pager { page, action: PageAction::First, data: self.data.clone() },
|
|
||||||
Pager { page, action: PageAction::Previous, data: self.data.clone() },
|
|
||||||
Pager { page, action: PageAction::Refresh, data: self.data.clone() },
|
|
||||||
Pager { page, action: PageAction::Next, data: self.data.clone() },
|
|
||||||
Pager { page, action: PageAction::Last, data: self.data.clone() },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) {
|
|
||||||
let next_page = self.next_page(max_pages);
|
let next_page = self.next_page(max_pages);
|
||||||
|
|
||||||
let (page_first, page_prev, page_refresh, page_next, page_last) = self.buttons(next_page);
|
let (page_first, page_prev, page_refresh, page_next, page_last) =
|
||||||
|
LookPager::buttons(self.flags, next_page, self.timezone);
|
||||||
|
|
||||||
comp.create_action_row(|row| {
|
comp.create_action_row(|row| {
|
||||||
row.create_button(|b| {
|
row.create_button(|b| {
|
||||||
@ -87,31 +79,254 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize_repr, Deserialize_repr)]
|
impl LookPager {
|
||||||
#[repr(u8)]
|
pub fn new(flags: LookFlags, timezone: Tz) -> Self {
|
||||||
enum PageAction {
|
Self { flags, page: 0, action: PageAction::First, timezone }
|
||||||
First = 0,
|
}
|
||||||
Previous = 1,
|
|
||||||
Refresh = 2,
|
pub fn buttons(
|
||||||
Next = 3,
|
flags: LookFlags,
|
||||||
Last = 4,
|
page: usize,
|
||||||
|
timezone: Tz,
|
||||||
|
) -> (
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
ComponentDataModel::LookPager(LookPager {
|
||||||
|
flags,
|
||||||
|
page,
|
||||||
|
action: PageAction::First,
|
||||||
|
timezone,
|
||||||
|
}),
|
||||||
|
ComponentDataModel::LookPager(LookPager {
|
||||||
|
flags,
|
||||||
|
page,
|
||||||
|
action: PageAction::Previous,
|
||||||
|
timezone,
|
||||||
|
}),
|
||||||
|
ComponentDataModel::LookPager(LookPager {
|
||||||
|
flags,
|
||||||
|
page,
|
||||||
|
action: PageAction::Refresh,
|
||||||
|
timezone,
|
||||||
|
}),
|
||||||
|
ComponentDataModel::LookPager(LookPager {
|
||||||
|
flags,
|
||||||
|
page,
|
||||||
|
action: PageAction::Next,
|
||||||
|
timezone,
|
||||||
|
}),
|
||||||
|
ComponentDataModel::LookPager(LookPager {
|
||||||
|
flags,
|
||||||
|
page,
|
||||||
|
action: PageAction::Last,
|
||||||
|
timezone,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct LookData {
|
pub struct DelPager {
|
||||||
pub flags: LookFlags,
|
pub page: usize,
|
||||||
|
action: PageAction,
|
||||||
pub timezone: Tz,
|
pub timezone: Tz,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone)]
|
impl Pager for DelPager {
|
||||||
pub struct DelData {
|
fn next_page(&self, max_pages: usize) -> usize {
|
||||||
pub author_id: UserId,
|
match self.action {
|
||||||
pub timezone: Tz,
|
PageAction::First => 0,
|
||||||
|
PageAction::Previous => 0.max(self.page - 1),
|
||||||
|
PageAction::Refresh => self.page,
|
||||||
|
PageAction::Next => (max_pages - 1).min(self.page + 1),
|
||||||
|
PageAction::Last => max_pages - 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) {
|
||||||
|
let next_page = self.next_page(max_pages);
|
||||||
|
|
||||||
|
let (page_first, page_prev, page_refresh, page_next, page_last) =
|
||||||
|
DelPager::buttons(next_page, self.timezone);
|
||||||
|
|
||||||
|
comp.create_action_row(|row| {
|
||||||
|
row.create_button(|b| {
|
||||||
|
b.label("⏮️")
|
||||||
|
.style(ButtonStyle::Primary)
|
||||||
|
.custom_id(page_first.to_custom_id())
|
||||||
|
.disabled(next_page == 0)
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.label("◀️")
|
||||||
|
.style(ButtonStyle::Secondary)
|
||||||
|
.custom_id(page_prev.to_custom_id())
|
||||||
|
.disabled(next_page == 0)
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.label("🔁").style(ButtonStyle::Secondary).custom_id(page_refresh.to_custom_id())
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.label("▶️")
|
||||||
|
.style(ButtonStyle::Secondary)
|
||||||
|
.custom_id(page_next.to_custom_id())
|
||||||
|
.disabled(next_page + 1 == max_pages)
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.label("⏭️")
|
||||||
|
.style(ButtonStyle::Primary)
|
||||||
|
.custom_id(page_last.to_custom_id())
|
||||||
|
.disabled(next_page + 1 == max_pages)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone)]
|
impl DelPager {
|
||||||
pub struct TodoData {
|
pub fn new(page: usize, timezone: Tz) -> Self {
|
||||||
|
Self { page, action: PageAction::Refresh, timezone }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buttons(
|
||||||
|
page: usize,
|
||||||
|
timezone: Tz,
|
||||||
|
) -> (
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
ComponentDataModel::DelPager(DelPager { page, action: PageAction::First, timezone }),
|
||||||
|
ComponentDataModel::DelPager(DelPager { page, action: PageAction::Previous, timezone }),
|
||||||
|
ComponentDataModel::DelPager(DelPager { page, action: PageAction::Refresh, timezone }),
|
||||||
|
ComponentDataModel::DelPager(DelPager { page, action: PageAction::Next, timezone }),
|
||||||
|
ComponentDataModel::DelPager(DelPager { page, action: PageAction::Last, timezone }),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct TodoPager {
|
||||||
|
pub page: usize,
|
||||||
|
action: PageAction,
|
||||||
pub user_id: Option<u64>,
|
pub user_id: Option<u64>,
|
||||||
pub channel_id: Option<u64>,
|
pub channel_id: Option<u64>,
|
||||||
pub guild_id: Option<u64>,
|
pub guild_id: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Pager for TodoPager {
|
||||||
|
fn next_page(&self, max_pages: usize) -> usize {
|
||||||
|
match self.action {
|
||||||
|
PageAction::First => 0,
|
||||||
|
PageAction::Previous => 0.max(self.page - 1),
|
||||||
|
PageAction::Refresh => self.page,
|
||||||
|
PageAction::Next => (max_pages - 1).min(self.page + 1),
|
||||||
|
PageAction::Last => max_pages - 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) {
|
||||||
|
let next_page = self.next_page(max_pages);
|
||||||
|
|
||||||
|
let (page_first, page_prev, page_refresh, page_next, page_last) =
|
||||||
|
TodoPager::buttons(next_page, self.user_id, self.channel_id, self.guild_id);
|
||||||
|
|
||||||
|
comp.create_action_row(|row| {
|
||||||
|
row.create_button(|b| {
|
||||||
|
b.label("⏮️")
|
||||||
|
.style(ButtonStyle::Primary)
|
||||||
|
.custom_id(page_first.to_custom_id())
|
||||||
|
.disabled(next_page == 0)
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.label("◀️")
|
||||||
|
.style(ButtonStyle::Secondary)
|
||||||
|
.custom_id(page_prev.to_custom_id())
|
||||||
|
.disabled(next_page == 0)
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.label("🔁").style(ButtonStyle::Secondary).custom_id(page_refresh.to_custom_id())
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.label("▶️")
|
||||||
|
.style(ButtonStyle::Secondary)
|
||||||
|
.custom_id(page_next.to_custom_id())
|
||||||
|
.disabled(next_page + 1 == max_pages)
|
||||||
|
})
|
||||||
|
.create_button(|b| {
|
||||||
|
b.label("⏭️")
|
||||||
|
.style(ButtonStyle::Primary)
|
||||||
|
.custom_id(page_last.to_custom_id())
|
||||||
|
.disabled(next_page + 1 == max_pages)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TodoPager {
|
||||||
|
pub fn new(
|
||||||
|
page: usize,
|
||||||
|
user_id: Option<u64>,
|
||||||
|
channel_id: Option<u64>,
|
||||||
|
guild_id: Option<u64>,
|
||||||
|
) -> Self {
|
||||||
|
Self { page, action: PageAction::Refresh, user_id, channel_id, guild_id }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buttons(
|
||||||
|
page: usize,
|
||||||
|
user_id: Option<u64>,
|
||||||
|
channel_id: Option<u64>,
|
||||||
|
guild_id: Option<u64>,
|
||||||
|
) -> (
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
ComponentDataModel,
|
||||||
|
) {
|
||||||
|
(
|
||||||
|
ComponentDataModel::TodoPager(TodoPager {
|
||||||
|
page,
|
||||||
|
action: PageAction::First,
|
||||||
|
user_id,
|
||||||
|
channel_id,
|
||||||
|
guild_id,
|
||||||
|
}),
|
||||||
|
ComponentDataModel::TodoPager(TodoPager {
|
||||||
|
page,
|
||||||
|
action: PageAction::Previous,
|
||||||
|
user_id,
|
||||||
|
channel_id,
|
||||||
|
guild_id,
|
||||||
|
}),
|
||||||
|
ComponentDataModel::TodoPager(TodoPager {
|
||||||
|
page,
|
||||||
|
action: PageAction::Refresh,
|
||||||
|
user_id,
|
||||||
|
channel_id,
|
||||||
|
guild_id,
|
||||||
|
}),
|
||||||
|
ComponentDataModel::TodoPager(TodoPager {
|
||||||
|
page,
|
||||||
|
action: PageAction::Next,
|
||||||
|
user_id,
|
||||||
|
channel_id,
|
||||||
|
guild_id,
|
||||||
|
}),
|
||||||
|
ComponentDataModel::TodoPager(TodoPager {
|
||||||
|
page,
|
||||||
|
action: PageAction::Last,
|
||||||
|
user_id,
|
||||||
|
channel_id,
|
||||||
|
guild_id,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user