This commit is contained in:
Natsu Kagami 2025-02-15 17:46:40 +01:00
parent 83eb92f5a7
commit b13e662569
Signed by: nki
GPG key ID: 55A032EB38B49ADB
3 changed files with 68 additions and 64 deletions

View file

@ -43,7 +43,7 @@ mod scores {
mode: Mode, mode: Mode,
ctx: &Context, ctx: &Context,
guild_id: Option<GuildId>, guild_id: Option<GuildId>,
m: Message, m: impl Editable,
) -> Result<()> { ) -> Result<()> {
match self { match self {
ScoreListStyle::Table => table::display_scores_table(scores, mode, ctx, m).await, ScoreListStyle::Table => table::display_scores_table(scores, mode, ctx, m).await,
@ -56,6 +56,7 @@ mod scores {
mod grid { mod grid {
use pagination::paginate_with_first_message; use pagination::paginate_with_first_message;
use poise::CreateReply;
use serenity::all::GuildId; use serenity::all::GuildId;
use serenity::builder::EditMessage; use serenity::builder::EditMessage;
use serenity::model::channel::Message; use serenity::model::channel::Message;
@ -71,10 +72,10 @@ mod scores {
mode: Mode, mode: Mode,
ctx: &Context, ctx: &Context,
guild_id: Option<GuildId>, guild_id: Option<GuildId>,
mut on: Message, mut on: impl Editable,
) -> Result<()> { ) -> Result<()> {
if scores.is_empty() { if scores.is_empty() {
on.edit(&ctx, EditMessage::new().content("No plays found")) on.edit_msg(CreateReply::default().content("No plays found"))
.await?; .await?;
return Ok(()); return Ok(());
} }
@ -160,7 +161,7 @@ mod scores {
scores: Vec<Score>, scores: Vec<Score>,
mode: Mode, mode: Mode,
ctx: &Context, ctx: &Context,
mut on: Message, mut on: impl Editable,
) -> Result<()> { ) -> Result<()> {
if scores.is_empty() { if scores.is_empty() {
on.edit(&ctx, EditMessage::new().content("No plays found")) on.edit(&ctx, EditMessage::new().content("No plays found"))

View file

@ -5,7 +5,7 @@ use crate::CmdContext;
use core::future::Future; use core::future::Future;
/// Represents an editable message context. /// Represents an editable message context.
pub trait Editable { pub trait Editable: Send {
/// Edits the underlying message. /// Edits the underlying message.
fn edit_msg(&mut self, reply: CreateReply) -> impl Future<Output = anyhow::Result<()>> + Send; fn edit_msg(&mut self, reply: CreateReply) -> impl Future<Output = anyhow::Result<()>> + Send;
} }

View file

@ -1,4 +1,4 @@
use crate::{Context, OkPrint, Result}; use crate::{editable_message, Context, Editable, OkPrint, Result};
use futures_util::{future::Future, StreamExt as _}; use futures_util::{future::Future, StreamExt as _};
use serenity::{ use serenity::{
builder::CreateMessage, builder::CreateMessage,
@ -20,15 +20,15 @@ const FAST_FORWARD: &str = "⏩";
#[async_trait::async_trait] #[async_trait::async_trait]
pub trait Paginate: Send + Sized { pub trait Paginate: Send + Sized {
/// Render the given page. /// Render the given page.
async fn render(&mut self, page: u8, ctx: &Context, m: &mut Message) -> Result<bool>; async fn render(&mut self, page: u8, ctx: &Context, m: &mut impl Editable) -> Result<bool>;
/// Any setting-up before the rendering stage. /// Any setting-up before the rendering stage.
async fn prerender(&mut self, _ctx: &Context, _m: &mut Message) -> Result<()> { async fn prerender(&mut self, _ctx: &Context, _m: &mut impl Editable) -> Result<()> {
Ok(()) Ok(())
} }
/// Cleans up after the pagination has timed out. /// Cleans up after the pagination has timed out.
async fn cleanup(&mut self, _ctx: &Context, _m: &mut Message) -> () {} async fn cleanup(&mut self, _ctx: &Context, _m: &mut impl Editable) -> () {}
/// Handle the incoming reaction. Defaults to calling `handle_pagination_reaction`, but you can do some additional handling /// Handle the incoming reaction. Defaults to calling `handle_pagination_reaction`, but you can do some additional handling
/// before handing the functionality over. /// before handing the functionality over.
@ -38,7 +38,7 @@ pub trait Paginate: Send + Sized {
&mut self, &mut self,
page: u8, page: u8,
ctx: &Context, ctx: &Context,
message: &mut Message, message: &mut impl Editable,
reaction: &Reaction, reaction: &Reaction,
) -> Result<Option<u8>> { ) -> Result<Option<u8>> {
handle_pagination_reaction(page, self, ctx, message, reaction) handle_pagination_reaction(page, self, ctx, message, reaction)
@ -65,16 +65,17 @@ pub trait Paginate: Send + Sized {
} }
} }
pub fn paginate_from_fn( // pub fn paginate_from_fn(
pager: impl for<'m> FnMut( // pager: impl for<'m, M: Editable> FnMut(
u8, // u8,
&'m Context, // &'m Context,
&'m mut Message, // &'m mut M,
) -> std::pin::Pin<Box<dyn Future<Output = Result<bool>> + Send + 'm>> // ) -> std::pin::Pin<
+ Send, // Box<dyn Future<Output = Result<bool>> + Send + 'm>,
) -> impl Paginate { // > + Send,
pager // ) -> impl Paginate {
} // pager
// }
struct WithPageCount<Inner> { struct WithPageCount<Inner> {
inner: Inner, inner: Inner,
@ -83,13 +84,13 @@ struct WithPageCount<Inner> {
#[async_trait::async_trait] #[async_trait::async_trait]
impl<Inner: Paginate> Paginate for WithPageCount<Inner> { impl<Inner: Paginate> Paginate for WithPageCount<Inner> {
async fn render(&mut self, page: u8, ctx: &Context, m: &mut Message) -> Result<bool> { async fn render(&mut self, page: u8, ctx: &Context, m: &mut impl Editable) -> Result<bool> {
if page as usize >= self.page_count { if page as usize >= self.page_count {
return Ok(false); return Ok(false);
} }
self.inner.render(page, ctx, m).await self.inner.render(page, ctx, m).await
} }
async fn prerender(&mut self, ctx: &Context, m: &mut Message) -> Result<()> { async fn prerender(&mut self, ctx: &Context, m: &mut impl Editable) -> Result<()> {
self.inner.prerender(ctx, m).await self.inner.prerender(ctx, m).await
} }
@ -97,7 +98,7 @@ impl<Inner: Paginate> Paginate for WithPageCount<Inner> {
&mut self, &mut self,
page: u8, page: u8,
ctx: &Context, ctx: &Context,
message: &mut Message, message: &mut impl Editable,
reaction: &Reaction, reaction: &Reaction,
) -> Result<Option<u8>> { ) -> Result<Option<u8>> {
// handle normal reactions first, then fallback to the inner one // handle normal reactions first, then fallback to the inner one
@ -120,25 +121,25 @@ impl<Inner: Paginate> Paginate for WithPageCount<Inner> {
Some(self.page_count == 0) Some(self.page_count == 0)
} }
async fn cleanup(&mut self, ctx: &Context, msg: &mut Message) { async fn cleanup(&mut self, ctx: &Context, msg: &mut impl Editable) {
self.inner.cleanup(ctx, msg).await; self.inner.cleanup(ctx, msg).await;
} }
} }
#[async_trait::async_trait] // #[async_trait::async_trait]
impl<T> Paginate for T // impl<T> Paginate for T
where // where
T: for<'m> FnMut( // T: for<'m> FnMut(
u8, // u8,
&'m Context, // &'m Context,
&'m mut Message, // &'m mut Message,
) -> std::pin::Pin<Box<dyn Future<Output = Result<bool>> + Send + 'm>> // ) -> std::pin::Pin<Box<dyn Future<Output = Result<bool>> + Send + 'm>>
+ Send, // + Send,
{ // {
async fn render(&mut self, page: u8, ctx: &Context, m: &mut Message) -> Result<bool> { // async fn render(&mut self, page: u8, ctx: &Context, m: &mut impl Editable) -> Result<bool> {
self(page, ctx, m).await // self(page, ctx, m).await
} // }
} // }
// Paginate! with a pager function, and replying to a message. // Paginate! with a pager function, and replying to a message.
/// If awaited, will block until everything is done. /// If awaited, will block until everything is done.
@ -151,7 +152,8 @@ pub async fn paginate_reply(
let message = reply_to let message = reply_to
.reply(&ctx, "Youmu is loading the first page...") .reply(&ctx, "Youmu is loading the first page...")
.await?; .await?;
paginate_with_first_message(pager, ctx, message, timeout).await let mut edit = editable_message(message, ctx.clone());
paginate_with_first_message(pager, ctx, edit, timeout).await
} }
// Paginate! with a pager function. // Paginate! with a pager function.
@ -168,14 +170,15 @@ pub async fn paginate(
CreateMessage::new().content("Youmu is loading the first page..."), CreateMessage::new().content("Youmu is loading the first page..."),
) )
.await?; .await?;
paginate_with_first_message(pager, ctx, message, timeout).await let mut edit = editable_message(message, ctx.clone());
paginate_with_first_message(pager, ctx, edit, timeout).await
} }
/// Paginate with the first message already created. /// Paginate with the first message already created.
pub async fn paginate_with_first_message( pub async fn paginate_with_first_message(
mut pager: impl Paginate, mut pager: impl Paginate,
ctx: &Context, ctx: &Context,
mut message: Message, message: impl Editable,
timeout: std::time::Duration, timeout: std::time::Duration,
) -> Result<()> { ) -> Result<()> {
pager.prerender(ctx, &mut message).await?; pager.prerender(ctx, &mut message).await?;
@ -188,28 +191,28 @@ pub async fn paginate_with_first_message(
let large_count = pager.len().filter(|&p| p > 10).is_some(); let large_count = pager.len().filter(|&p| p > 10).is_some();
let reactions = { let reactions = {
let mut rs = Vec::<Reaction>::with_capacity(4); let mut rs = Vec::<Reaction>::with_capacity(4);
if large_count { // if large_count {
// add >> and << buttons // // add >> and << buttons
rs.push(message.react(&ctx, ReactionType::try_from(REWIND)?).await?); // rs.push(message.react(&ctx, ReactionType::try_from(REWIND)?).await?);
} // }
rs.push( // rs.push(
message // message
.react(&ctx, ReactionType::try_from(ARROW_LEFT)?) // .react(&ctx, ReactionType::try_from(ARROW_LEFT)?)
.await?, // .await?,
); // );
rs.push( // rs.push(
message // message
.react(&ctx, ReactionType::try_from(ARROW_RIGHT)?) // .react(&ctx, ReactionType::try_from(ARROW_RIGHT)?)
.await?, // .await?,
); // );
if large_count { // if large_count {
// add >> and << buttons // // add >> and << buttons
rs.push( // rs.push(
message // message
.react(&ctx, ReactionType::try_from(FAST_FORWARD)?) // .react(&ctx, ReactionType::try_from(FAST_FORWARD)?)
.await?, // .await?,
); // );
} // }
rs rs
}; };
// Build a reaction collector // Build a reaction collector
@ -264,7 +267,7 @@ pub async fn handle_pagination_reaction(
page: u8, page: u8,
pager: &mut impl Paginate, pager: &mut impl Paginate,
ctx: &Context, ctx: &Context,
message: &mut Message, message: &mut impl Editable,
reaction: &Reaction, reaction: &Reaction,
) -> Result<u8> { ) -> Result<u8> {
let pages = pager.len(); let pages = pager.len();