From 4490f19c04eabda5d40f3f9438519e8002a26607 Mon Sep 17 00:00:00 2001 From: jellywx Date: Wed, 13 Oct 2021 17:23:50 +0100 Subject: [PATCH] turned pager into a single type --- src/commands/reminder_cmds.rs | 6 +- src/commands/todo_cmds.rs | 4 +- src/component_models/mod.rs | 36 ++-- src/component_models/pager.rs | 383 ++++++++-------------------------- 4 files changed, 105 insertions(+), 324 deletions(-) diff --git a/src/commands/reminder_cmds.rs b/src/commands/reminder_cmds.rs index b046011..de1b3f8 100644 --- a/src/commands/reminder_cmds.rs +++ b/src/commands/reminder_cmds.rs @@ -13,7 +13,7 @@ use serenity::{builder::CreateEmbed, client::Context, model::channel::Channel}; use crate::{ check_subscription_on_message, component_models::{ - pager::{DelPager, LookPager, Pager}, + pager::{DelData, LookData, Pager}, ComponentDataModel, DelSelector, }, consts::{ @@ -329,7 +329,7 @@ async fn look(ctx: &Context, invoke: &mut CommandInvoke, args: CommandOptions) { .fold(0, |t, r| t + r.len()) .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); - let pager = LookPager::new(flags, timezone); + let pager = Pager::new(0, LookData { flags, timezone }); invoke .respond( @@ -395,7 +395,7 @@ pub fn show_delete_page( page: usize, timezone: Tz, ) -> CreateGenericResponse { - let pager = DelPager::new(page, timezone); + let pager = Pager::new(page, DelData { timezone }); if reminders.is_empty() { return CreateGenericResponse::new() diff --git a/src/commands/todo_cmds.rs b/src/commands/todo_cmds.rs index 789ee69..abde1c4 100644 --- a/src/commands/todo_cmds.rs +++ b/src/commands/todo_cmds.rs @@ -3,7 +3,7 @@ use serenity::client::Context; use crate::{ component_models::{ - pager::{Pager, TodoPager}, + pager::{Pager, TodoData}, ComponentDataModel, TodoSelector, }, consts::{EMBED_DESCRIPTION_MAX_LENGTH, SELECT_MAX_ENTRIES, THEME_COLOR}, @@ -136,7 +136,7 @@ pub fn show_todo_page( channel_id: Option, guild_id: Option, ) -> CreateGenericResponse { - let pager = TodoPager::new(page, user_id, channel_id, guild_id); + let pager = Pager::new(page, TodoData { user_id, channel_id, guild_id }); let pages = max_todo_page(todo_values); let mut page = page; diff --git a/src/component_models/mod.rs b/src/component_models/mod.rs index d0ba9d9..4ca64ab 100644 --- a/src/component_models/mod.rs +++ b/src/component_models/mod.rs @@ -1,4 +1,4 @@ -pub(crate) mod pager; +pub mod pager; use std::io::Cursor; @@ -21,7 +21,7 @@ use crate::{ reminder_cmds::{max_delete_page, show_delete_page}, todo_cmds::{max_todo_page, show_todo_page}, }, - component_models::pager::{DelPager, LookPager, Pager, TodoPager}, + component_models::pager::{DelData, LookData, Pager, TodoData}, consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR}, framework::CommandInvoke, models::reminder::Reminder, @@ -29,15 +29,14 @@ use crate::{ }; #[derive(Deserialize, Serialize)] -#[serde(tag = "type")] -#[repr(u8)] +#[serde(untagged)] pub enum ComponentDataModel { Restrict(Restrict), - LookPager(LookPager), - DelPager(DelPager), - TodoPager(TodoPager), DelSelector(DelSelector), TodoSelector(TodoSelector), + LookPager(Pager), + DelPager(Pager), + TodoPager(Pager), } impl ComponentDataModel { @@ -94,7 +93,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id } } ComponentDataModel::LookPager(pager) => { - let flags = pager.flags; + let flags = pager.data.flags; let channel_opt = component.channel_id.to_channel_cached(&ctx); @@ -112,7 +111,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let pages = reminders .iter() - .map(|reminder| reminder.display(&flags, &pager.timezone)) + .map(|reminder| reminder.display(&flags, &pager.data.timezone)) .fold(0, |t, r| t + r.len()) .div_ceil(EMBED_DESCRIPTION_MAX_LENGTH); @@ -130,7 +129,7 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let display = reminders .iter() - .map(|reminder| reminder.display(&flags, &pager.timezone)) + .map(|reminder| reminder.display(&flags, &pager.data.timezone)) .skip_while(|p| { skip_char_count += p.len(); @@ -172,9 +171,10 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let reminders = Reminder::from_guild(ctx, component.guild_id, component.user.id).await; - let max_pages = max_delete_page(&reminders, &pager.timezone); + let max_pages = max_delete_page(&reminders, &pager.data.timezone); - let resp = show_delete_page(&reminders, pager.next_page(max_pages), pager.timezone); + let resp = + show_delete_page(&reminders, pager.next_page(max_pages), pager.data.timezone); let mut invoke = CommandInvoke::component(component); let _ = invoke.respond(&ctx, resp).await; @@ -202,9 +202,9 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let values = sqlx::query!( // fucking braindead mysql use <=> instead of = for null comparison "SELECT id, value FROM todos WHERE user_id <=> ? AND channel_id <=> ? AND guild_id <=> ?", - pager.user_id, - pager.channel_id, - pager.guild_id, + pager.data.user_id, + pager.data.channel_id, + pager.data.guild_id, ) .fetch_all(&pool) .await @@ -218,9 +218,9 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id let resp = show_todo_page( &values, pager.next_page(max_pages), - pager.user_id, - pager.channel_id, - pager.guild_id, + pager.data.user_id, + pager.data.channel_id, + pager.data.guild_id, ); let mut invoke = CommandInvoke::component(component); diff --git a/src/component_models/pager.rs b/src/component_models/pager.rs index 0d41ab0..611452b 100644 --- a/src/component_models/pager.rs +++ b/src/component_models/pager.rs @@ -1,15 +1,87 @@ -// todo split pager out into a single struct use chrono_tz::Tz; +use rmp_serde::Serializer; use serde::{Deserialize, Serialize}; use serde_repr::*; use serenity::{builder::CreateComponents, model::interactions::message_component::ButtonStyle}; use crate::{component_models::ComponentDataModel, models::reminder::look_flags::LookFlags}; -pub trait Pager { - fn next_page(&self, max_pages: usize) -> usize; +#[derive(Serialize, Deserialize)] +pub struct Pager { + pub page: usize, + action: PageAction, + pub data: D, +} - fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents); +impl Pager +where + D: Serialize + Clone, +{ + pub fn new(page: usize, data: D) -> Self { + Self { page, action: PageAction::Refresh, data } + } + + pub 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, + } + } + + pub fn to_custom_id(&self) -> String { + let mut buf = Vec::new(); + self.serialize(&mut Serializer::new(&mut buf)).unwrap(); + base64::encode(buf) + } + + fn buttons(&self, page: usize) -> (Pager, Pager, Pager, Pager, Pager) { + ( + 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 (page_first, page_prev, page_refresh, page_next, page_last) = self.buttons(next_page); + + 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(Serialize_repr, Deserialize_repr)] @@ -22,311 +94,20 @@ enum PageAction { Last = 4, } -#[derive(Serialize, Deserialize)] -pub struct LookPager { +#[derive(Deserialize, Serialize, Clone)] +pub struct LookData { 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 { - 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) = - LookPager::buttons(self.flags, 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) - }) - }); - } -} - -impl LookPager { - pub fn new(flags: LookFlags, timezone: Tz) -> Self { - Self { flags, page: 0, action: PageAction::First, timezone } - } - - pub fn buttons( - flags: LookFlags, - 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(Serialize, Deserialize)] -pub struct DelPager { - pub page: usize, - action: PageAction, +#[derive(Deserialize, Serialize, Clone)] +pub struct DelData { pub timezone: Tz, } -impl Pager for DelPager { - 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) = - 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) - }) - }); - } -} - -impl DelPager { - 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, +#[derive(Deserialize, Serialize, Clone)] +pub struct TodoData { pub user_id: Option, pub channel_id: Option, pub guild_id: Option, } - -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, - channel_id: Option, - guild_id: Option, - ) -> Self { - Self { page, action: PageAction::Refresh, user_id, channel_id, guild_id } - } - - pub fn buttons( - page: usize, - user_id: Option, - channel_id: Option, - guild_id: Option, - ) -> ( - 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, - }), - ) - } -}