wip bump versions
This commit is contained in:
parent
e7803b98e8
commit
cce0de7c75
1059
Cargo.lock
generated
1059
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -7,12 +7,12 @@ license = "AGPL-3.0 only"
|
|||||||
description = "Reminder Bot for Discord, now in Rust"
|
description = "Reminder Bot for Discord, now in Rust"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
poise = "0.5"
|
poise = "0.6.1-rc1"
|
||||||
dotenv = "0.15"
|
dotenv = "0.15"
|
||||||
tokio = { version = "1", features = ["process", "full"] }
|
tokio = { version = "1", features = ["process", "full"] }
|
||||||
reqwest = "0.11"
|
reqwest = "0.11"
|
||||||
lazy-regex = "3.0.2"
|
lazy-regex = "3.1"
|
||||||
regex = "1.9"
|
regex = "1.10"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
|
@ -405,7 +405,6 @@ WHERE
|
|||||||
|
|
||||||
if fail_count >= 4 {
|
if fail_count >= 4 {
|
||||||
self.log_error(
|
self.log_error(
|
||||||
pool,
|
|
||||||
"Failed to update 4 times and so is being deleted",
|
"Failed to update 4 times and so is being deleted",
|
||||||
None::<&'static str>,
|
None::<&'static str>,
|
||||||
)
|
)
|
||||||
@ -428,12 +427,7 @@ WHERE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn log_error(
|
async fn log_error(&self, error: &'static str, debug_info: Option<impl std::fmt::Debug>) {
|
||||||
&self,
|
|
||||||
pool: impl Executor<'_, Database = Database> + Copy,
|
|
||||||
error: &'static str,
|
|
||||||
debug_info: Option<impl std::fmt::Debug>,
|
|
||||||
) {
|
|
||||||
let message = match debug_info {
|
let message = match debug_info {
|
||||||
Some(info) => format!(
|
Some(info) => format!(
|
||||||
"{}
|
"{}
|
||||||
@ -447,7 +441,7 @@ WHERE
|
|||||||
error!("[Reminder {}] {}", self.id, message);
|
error!("[Reminder {}] {}", self.id, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn log_success(&self, pool: impl Executor<'_, Database = Database> + Copy) {}
|
async fn log_success(&self) {}
|
||||||
|
|
||||||
async fn set_sent(&self, pool: impl Executor<'_, Database = Database> + Copy) {
|
async fn set_sent(&self, pool: impl Executor<'_, Database = Database> + Copy) {
|
||||||
sqlx::query!("UPDATE reminders SET `status` = 'sent' WHERE `id` = ?", self.id)
|
sqlx::query!("UPDATE reminders SET `status` = 'sent' WHERE `id` = ?", self.id)
|
||||||
@ -640,7 +634,6 @@ WHERE
|
|||||||
match http_error.error.code {
|
match http_error.error.code {
|
||||||
10003 => {
|
10003 => {
|
||||||
self.log_error(
|
self.log_error(
|
||||||
pool,
|
|
||||||
"Could not be sent as channel does not exist",
|
"Could not be sent as channel does not exist",
|
||||||
None::<&'static str>,
|
None::<&'static str>,
|
||||||
)
|
)
|
||||||
@ -653,7 +646,6 @@ WHERE
|
|||||||
}
|
}
|
||||||
10004 => {
|
10004 => {
|
||||||
self.log_error(
|
self.log_error(
|
||||||
pool,
|
|
||||||
"Could not be sent as guild does not exist",
|
"Could not be sent as guild does not exist",
|
||||||
None::<&'static str>,
|
None::<&'static str>,
|
||||||
)
|
)
|
||||||
@ -663,7 +655,6 @@ WHERE
|
|||||||
}
|
}
|
||||||
50001 => {
|
50001 => {
|
||||||
self.log_error(
|
self.log_error(
|
||||||
pool,
|
|
||||||
"Could not be sent as missing access",
|
"Could not be sent as missing access",
|
||||||
None::<&'static str>,
|
None::<&'static str>,
|
||||||
)
|
)
|
||||||
@ -672,7 +663,6 @@ WHERE
|
|||||||
}
|
}
|
||||||
50007 => {
|
50007 => {
|
||||||
self.log_error(
|
self.log_error(
|
||||||
pool,
|
|
||||||
"Could not be sent as user has DMs disabled",
|
"Could not be sent as user has DMs disabled",
|
||||||
None::<&'static str>,
|
None::<&'static str>,
|
||||||
)
|
)
|
||||||
@ -682,7 +672,6 @@ WHERE
|
|||||||
}
|
}
|
||||||
50013 => {
|
50013 => {
|
||||||
self.log_error(
|
self.log_error(
|
||||||
pool,
|
|
||||||
"Could not be sent as permissions are invalid",
|
"Could not be sent as permissions are invalid",
|
||||||
None::<&'static str>,
|
None::<&'static str>,
|
||||||
)
|
)
|
||||||
@ -694,25 +683,21 @@ WHERE
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.log_error(
|
self.log_error("HTTP error sending reminder", Some(http_error))
|
||||||
pool,
|
.await;
|
||||||
"HTTP error sending reminder",
|
|
||||||
Some(http_error),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
self.refresh(pool).await;
|
self.refresh(pool).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.log_error(pool, "(Likely) a parsing error", Some(error)).await;
|
self.log_error("(Likely) a parsing error", Some(error)).await;
|
||||||
self.refresh(pool).await;
|
self.refresh(pool).await;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.log_error(pool, "Non-HTTP error", Some(e)).await;
|
self.log_error("Non-HTTP error", Some(e)).await;
|
||||||
self.refresh(pool).await;
|
self.refresh(pool).await;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.log_success(pool).await;
|
self.log_success().await;
|
||||||
self.refresh(pool).await;
|
self.refresh(pool).await;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
use chrono_tz::TZ_VARIANTS;
|
use chrono_tz::TZ_VARIANTS;
|
||||||
use poise::AutocompleteChoice;
|
use poise::serenity_prelude::AutocompleteChoice;
|
||||||
|
|
||||||
use crate::{models::CtxData, time_parser::natural_parser, Context};
|
use crate::{models::CtxData, time_parser::natural_parser, Context};
|
||||||
|
|
||||||
@ -37,15 +37,9 @@ WHERE
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn time_hint_autocomplete(
|
pub async fn time_hint_autocomplete(ctx: Context<'_>, partial: &str) -> Vec<AutocompleteChoice> {
|
||||||
ctx: Context<'_>,
|
|
||||||
partial: &str,
|
|
||||||
) -> Vec<AutocompleteChoice<String>> {
|
|
||||||
if partial.is_empty() {
|
if partial.is_empty() {
|
||||||
vec![AutocompleteChoice {
|
vec![AutocompleteChoice::new("Start typing a time...".to_string(), "now".to_string())]
|
||||||
name: "Start typing a time...".to_string(),
|
|
||||||
value: "now".to_string(),
|
|
||||||
}]
|
|
||||||
} else {
|
} else {
|
||||||
match natural_parser(partial, &ctx.timezone().await.to_string()).await {
|
match natural_parser(partial, &ctx.timezone().await.to_string()).await {
|
||||||
Some(timestamp) => match SystemTime::now().duration_since(UNIX_EPOCH) {
|
Some(timestamp) => match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||||
@ -53,64 +47,49 @@ pub async fn time_hint_autocomplete(
|
|||||||
let diff = timestamp - now.as_secs() as i64;
|
let diff = timestamp - now.as_secs() as i64;
|
||||||
|
|
||||||
if diff < 0 {
|
if diff < 0 {
|
||||||
vec![AutocompleteChoice {
|
vec![AutocompleteChoice::new(
|
||||||
name: "Time is in the past".to_string(),
|
"Time is in the past".to_string(),
|
||||||
value: "1 year ago".to_string(),
|
"1 year ago".to_string(),
|
||||||
}]
|
)]
|
||||||
} else {
|
} else {
|
||||||
if diff > 86400 {
|
if diff > 86400 {
|
||||||
vec![
|
vec![
|
||||||
AutocompleteChoice {
|
AutocompleteChoice::new(partial.to_string(), partial.to_string()),
|
||||||
name: partial.to_string(),
|
AutocompleteChoice::new(
|
||||||
value: partial.to_string(),
|
format!(
|
||||||
},
|
|
||||||
AutocompleteChoice {
|
|
||||||
name: format!(
|
|
||||||
"In approximately {} days, {} hours",
|
"In approximately {} days, {} hours",
|
||||||
diff / 86400,
|
diff / 86400,
|
||||||
(diff % 86400) / 3600
|
(diff % 86400) / 3600
|
||||||
),
|
),
|
||||||
value: partial.to_string(),
|
partial.to_string(),
|
||||||
},
|
),
|
||||||
]
|
]
|
||||||
} else if diff > 3600 {
|
} else if diff > 3600 {
|
||||||
vec![
|
vec![
|
||||||
AutocompleteChoice {
|
AutocompleteChoice::new(partial.to_string(), partial.to_string()),
|
||||||
name: partial.to_string(),
|
AutocompleteChoice::new(
|
||||||
value: partial.to_string(),
|
format!("In approximately {} hours", diff / 3600),
|
||||||
},
|
partial.to_string(),
|
||||||
AutocompleteChoice {
|
),
|
||||||
name: format!("In approximately {} hours", diff / 3600),
|
|
||||||
value: partial.to_string(),
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
vec![
|
vec![
|
||||||
AutocompleteChoice {
|
AutocompleteChoice::new(partial.to_string(), partial.to_string()),
|
||||||
name: partial.to_string(),
|
AutocompleteChoice::new(
|
||||||
value: partial.to_string(),
|
format!("In approximately {} minutes", diff / 60),
|
||||||
},
|
partial.to_string(),
|
||||||
AutocompleteChoice {
|
),
|
||||||
name: format!("In approximately {} minutes", diff / 60),
|
|
||||||
value: partial.to_string(),
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
vec![AutocompleteChoice {
|
vec![AutocompleteChoice::new(partial.to_string(), partial.to_string())]
|
||||||
name: partial.to_string(),
|
|
||||||
value: partial.to_string(),
|
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
vec![AutocompleteChoice {
|
vec![AutocompleteChoice::new("Time not recognised".to_string(), "now".to_string())]
|
||||||
name: "Time not recognised".to_string(),
|
|
||||||
value: "now".to_string(),
|
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use lazy_regex::regex;
|
use lazy_regex::regex;
|
||||||
use poise::serenity_prelude::command::CommandOptionType;
|
use poise::serenity_prelude::CommandOptionType;
|
||||||
use regex::Captures;
|
use regex::Captures;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
|
@ -5,9 +5,7 @@ use chrono_tz::Tz;
|
|||||||
use log::warn;
|
use log::warn;
|
||||||
use num_integer::Integer;
|
use num_integer::Integer;
|
||||||
use poise::{
|
use poise::{
|
||||||
serenity_prelude::{
|
serenity_prelude::{builder::CreateEmbed, model::channel::Channel, ButtonStyle, ReactionType},
|
||||||
builder::CreateEmbed, component::ButtonStyle, model::channel::Channel, ReactionType,
|
|
||||||
},
|
|
||||||
CreateReply, Modal,
|
CreateReply, Modal,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
// todo split pager out into a single struct
|
// todo split pager out into a single struct
|
||||||
use chrono_tz::Tz;
|
use chrono_tz::Tz;
|
||||||
use poise::serenity_prelude::{
|
use poise::serenity_prelude::{ButtonStyle, CreateActionRow, CreateButton};
|
||||||
builder::CreateComponents, model::application::component::ButtonStyle,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_repr::*;
|
use serde_repr::*;
|
||||||
|
|
||||||
@ -11,7 +9,7 @@ use crate::{component_models::ComponentDataModel, models::reminder::look_flags::
|
|||||||
pub trait Pager {
|
pub trait Pager {
|
||||||
fn next_page(&self, max_pages: usize) -> usize;
|
fn next_page(&self, max_pages: usize) -> usize;
|
||||||
|
|
||||||
fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents);
|
fn create_button_row(&self, max_pages: usize) -> CreateActionRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize_repr, Deserialize_repr)]
|
#[derive(Serialize_repr, Deserialize_repr)]
|
||||||
@ -43,41 +41,33 @@ impl Pager for LookPager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) {
|
fn create_button_row(&self, max_pages: usize) -> CreateActionRow {
|
||||||
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) =
|
let (page_first, page_prev, page_refresh, page_next, page_last) =
|
||||||
LookPager::buttons(self.flags, next_page, self.timezone);
|
LookPager::buttons(self.flags, next_page, self.timezone);
|
||||||
|
|
||||||
comp.create_action_row(|row| {
|
CreateActionRow::Buttons(vec![
|
||||||
row.create_button(|b| {
|
CreateButton::new(page_first.to_custom_id())
|
||||||
b.label("⏮️")
|
.label("⏮️")
|
||||||
.style(ButtonStyle::Primary)
|
.style(ButtonStyle::Primary)
|
||||||
.custom_id(page_first.to_custom_id())
|
.disabled(next_page == 0),
|
||||||
.disabled(next_page == 0)
|
CreateButton::new(page_prev.to_custom_id())
|
||||||
})
|
.label("◀️")
|
||||||
.create_button(|b| {
|
.style(ButtonStyle::Secondary)
|
||||||
b.label("◀️")
|
.disabled(next_page == 0),
|
||||||
.style(ButtonStyle::Secondary)
|
CreateButton::new(page_refresh.to_custom_id())
|
||||||
.custom_id(page_prev.to_custom_id())
|
.label("🔁")
|
||||||
.disabled(next_page == 0)
|
.style(ButtonStyle::Secondary),
|
||||||
})
|
CreateButton::new(page_next.to_custom_id())
|
||||||
.create_button(|b| {
|
.label("▶️")
|
||||||
b.label("🔁").style(ButtonStyle::Secondary).custom_id(page_refresh.to_custom_id())
|
.style(ButtonStyle::Secondary)
|
||||||
})
|
.disabled(next_page + 1 == max_pages),
|
||||||
.create_button(|b| {
|
CreateButton::new(page_last.to_custom_id())
|
||||||
b.label("▶️")
|
.label("⏭️")
|
||||||
.style(ButtonStyle::Secondary)
|
.style(ButtonStyle::Primary)
|
||||||
.custom_id(page_next.to_custom_id())
|
.disabled(next_page + 1 == max_pages),
|
||||||
.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)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,41 +140,33 @@ impl Pager for DelPager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) {
|
fn create_button_row(&self, max_pages: usize) -> CreateActionRow {
|
||||||
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) =
|
let (page_first, page_prev, page_refresh, page_next, page_last) =
|
||||||
DelPager::buttons(next_page, self.timezone);
|
DelPager::buttons(next_page, self.timezone);
|
||||||
|
|
||||||
comp.create_action_row(|row| {
|
CreateActionRow::Buttons(vec![
|
||||||
row.create_button(|b| {
|
CreateButton::new(page_first.to_custom_id())
|
||||||
b.label("⏮️")
|
.label("⏮️")
|
||||||
.style(ButtonStyle::Primary)
|
.style(ButtonStyle::Primary)
|
||||||
.custom_id(page_first.to_custom_id())
|
.disabled(next_page == 0),
|
||||||
.disabled(next_page == 0)
|
CreateButton::new(page_prev.to_custom_id())
|
||||||
})
|
.label("◀️")
|
||||||
.create_button(|b| {
|
.style(ButtonStyle::Secondary)
|
||||||
b.label("◀️")
|
.disabled(next_page == 0),
|
||||||
.style(ButtonStyle::Secondary)
|
CreateButton::new(page_refresh.to_custom_id())
|
||||||
.custom_id(page_prev.to_custom_id())
|
.label("🔁")
|
||||||
.disabled(next_page == 0)
|
.style(ButtonStyle::Secondary),
|
||||||
})
|
CreateButton::new(page_next.to_custom_id())
|
||||||
.create_button(|b| {
|
.label("▶️")
|
||||||
b.label("🔁").style(ButtonStyle::Secondary).custom_id(page_refresh.to_custom_id())
|
.style(ButtonStyle::Secondary)
|
||||||
})
|
.disabled(next_page + 1 == max_pages),
|
||||||
.create_button(|b| {
|
CreateButton::new(page_last.to_custom_id())
|
||||||
b.label("▶️")
|
.label("⏭️")
|
||||||
.style(ButtonStyle::Secondary)
|
.style(ButtonStyle::Primary)
|
||||||
.custom_id(page_next.to_custom_id())
|
.disabled(next_page + 1 == max_pages),
|
||||||
.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)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,41 +215,33 @@ impl Pager for TodoPager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) {
|
fn create_button_row(&self, max_pages: usize) -> CreateActionRow {
|
||||||
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) =
|
let (page_first, page_prev, page_refresh, page_next, page_last) =
|
||||||
TodoPager::buttons(next_page, self.user_id, self.channel_id, self.guild_id);
|
TodoPager::buttons(next_page, self.user_id, self.channel_id, self.guild_id);
|
||||||
|
|
||||||
comp.create_action_row(|row| {
|
CreateActionRow::Buttons(vec![
|
||||||
row.create_button(|b| {
|
CreateButton::new(page_first.to_custom_id())
|
||||||
b.label("⏮️")
|
.label("⏮️")
|
||||||
.style(ButtonStyle::Primary)
|
.style(ButtonStyle::Primary)
|
||||||
.custom_id(page_first.to_custom_id())
|
.disabled(next_page == 0),
|
||||||
.disabled(next_page == 0)
|
CreateButton::new(page_prev.to_custom_id())
|
||||||
})
|
.label("◀️")
|
||||||
.create_button(|b| {
|
.style(ButtonStyle::Secondary)
|
||||||
b.label("◀️")
|
.disabled(next_page == 0),
|
||||||
.style(ButtonStyle::Secondary)
|
CreateButton::new(page_refresh.to_custom_id())
|
||||||
.custom_id(page_prev.to_custom_id())
|
.label("🔁")
|
||||||
.disabled(next_page == 0)
|
.style(ButtonStyle::Secondary),
|
||||||
})
|
CreateButton::new(page_next.to_custom_id())
|
||||||
.create_button(|b| {
|
.label("▶️")
|
||||||
b.label("🔁").style(ButtonStyle::Secondary).custom_id(page_refresh.to_custom_id())
|
.style(ButtonStyle::Secondary)
|
||||||
})
|
.disabled(next_page + 1 == max_pages),
|
||||||
.create_button(|b| {
|
CreateButton::new(page_last.to_custom_id())
|
||||||
b.label("▶️")
|
.label("⏭️")
|
||||||
.style(ButtonStyle::Secondary)
|
.style(ButtonStyle::Primary)
|
||||||
.custom_id(page_next.to_custom_id())
|
.disabled(next_page + 1 == max_pages),
|
||||||
.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)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,41 +324,33 @@ impl Pager for MacroPager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) {
|
fn create_button_row(&self, max_pages: usize) -> CreateActionRow {
|
||||||
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) =
|
let (page_first, page_prev, page_refresh, page_next, page_last) =
|
||||||
MacroPager::buttons(next_page);
|
MacroPager::buttons(next_page);
|
||||||
|
|
||||||
comp.create_action_row(|row| {
|
CreateActionRow::Buttons(vec![
|
||||||
row.create_button(|b| {
|
CreateButton::new(page_first.to_custom_id())
|
||||||
b.label("⏮️")
|
.label("⏮️")
|
||||||
.style(ButtonStyle::Primary)
|
.style(ButtonStyle::Primary)
|
||||||
.custom_id(page_first.to_custom_id())
|
.disabled(next_page == 0),
|
||||||
.disabled(next_page == 0)
|
CreateButton::new(page_prev.to_custom_id())
|
||||||
})
|
.label("◀️")
|
||||||
.create_button(|b| {
|
.style(ButtonStyle::Secondary)
|
||||||
b.label("◀️")
|
.disabled(next_page == 0),
|
||||||
.style(ButtonStyle::Secondary)
|
CreateButton::new(page_refresh.to_custom_id())
|
||||||
.custom_id(page_prev.to_custom_id())
|
.label("🔁")
|
||||||
.disabled(next_page == 0)
|
.style(ButtonStyle::Secondary),
|
||||||
})
|
CreateButton::new(page_next.to_custom_id())
|
||||||
.create_button(|b| {
|
.label("▶️")
|
||||||
b.label("🔁").style(ButtonStyle::Secondary).custom_id(page_refresh.to_custom_id())
|
.style(ButtonStyle::Secondary)
|
||||||
})
|
.disabled(next_page + 1 == max_pages),
|
||||||
.create_button(|b| {
|
CreateButton::new(page_last.to_custom_id())
|
||||||
b.label("▶️")
|
.label("⏭️")
|
||||||
.style(ButtonStyle::Secondary)
|
.style(ButtonStyle::Primary)
|
||||||
.custom_id(page_next.to_custom_id())
|
.disabled(next_page + 1 == max_pages),
|
||||||
.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)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
web/static/assets
Symbolic link
1
web/static/assets
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
/home/jude/reminder-bot/reminder-dashboard/dist/static/assets
|
1
web/static/index.html
Symbolic link
1
web/static/index.html
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
/home/jude/reminder-bot/reminder-dashboard/dist/index.html
|
Loading…
Reference in New Issue
Block a user