feat(tgbot-front): implement the back button operation
Add functions to handle navigation callback logic Also add function for creating initial user context (pay attention to auth and registration later)
This commit is contained in:
parent
0fdf577612
commit
ccf9722bb7
5 changed files with 145 additions and 44 deletions
|
|
@ -14,6 +14,7 @@ TgBot::InlineKeyboardMarkup::Ptr KeyboardFactory::createMainMenu() {
|
|||
return keyboard;
|
||||
}
|
||||
|
||||
// TODO: Переписать с учетом констант на количество отображаемых тайтлов и нового callback'a
|
||||
TgBot::InlineKeyboardMarkup::Ptr KeyboardFactory::createMyTitles(std::vector<Title> titles) {
|
||||
auto keyboard = std::make_shared<TgBot::InlineKeyboardMarkup>();
|
||||
std::vector<TgBot::InlineKeyboardButton::Ptr> row;
|
||||
|
|
@ -39,13 +40,23 @@ TgBot::InlineKeyboardMarkup::Ptr KeyboardFactory::createMyTitles(std::vector<Tit
|
|||
if(counter % 2 == 1) {
|
||||
auto button = std::make_shared<TgBot::InlineKeyboardButton>();
|
||||
button->text = BotConstants::Button::PREV;
|
||||
button->callbackData = BotConstants::Callback::LIST_PREV + ':' + std::to_string(titles[0].num);
|
||||
if(titles[0].num == 1) {
|
||||
button->callbackData = BotConstants::Callback::NAV_BACK;
|
||||
}
|
||||
else {
|
||||
button->callbackData = BotConstants::Callback::LIST_PREV + ':' + std::to_string(titles[0].num);
|
||||
}
|
||||
layout[counter / 2].push_back(button);
|
||||
}
|
||||
else {
|
||||
auto button_prev = std::make_shared<TgBot::InlineKeyboardButton>();
|
||||
button_prev->text = BotConstants::Button::PREV;
|
||||
button_prev->callbackData = BotConstants::Callback::LIST_PREV + ':' + std::to_string(titles[0].num);
|
||||
if(titles[0].num == 1) {
|
||||
button_prev->callbackData = BotConstants::Callback::NAV_BACK;
|
||||
}
|
||||
else {
|
||||
button_prev->callbackData = BotConstants::Callback::LIST_PREV + ':' + std::to_string(titles[0].num);
|
||||
}
|
||||
auto button_next = std::make_shared<TgBot::InlineKeyboardButton>();
|
||||
button_next->text = BotConstants::Button::NEXT;
|
||||
button_next->callbackData = BotConstants::Callback::LIST_NEXT + ':' + std::to_string(titles[5].num);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ AnimeBot::AnimeBot(const std::string& token)
|
|||
void AnimeBot::setupHandlers() {
|
||||
bot.getEvents().onCommand("start", [this](TgBot::Message::Ptr message) {
|
||||
sendMainMenu(message->chat->id);
|
||||
//TODO: производить инициализацию контекста только после авторизации
|
||||
handler.createInitContext(message->chat->id);
|
||||
});
|
||||
|
||||
bot.getEvents().onCallbackQuery([this](TgBot::CallbackQuery::Ptr query) {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ void BotHandlers::handleCallback(TgBot::CallbackQuery::Ptr query) {
|
|||
processCallbackImpl(query);
|
||||
}
|
||||
|
||||
HandlerResult BotHandlers::returnMyTitles(int64_t userId) {
|
||||
HandlerResult BotHandlers::returnMyTitles(int64_t userId, int64_t payload) {
|
||||
// Здесь должен происходить запрос на сервер
|
||||
std::vector<Title> titles = {{123, "Школа мертвяков", "", 1}, {321, "KissXsis", "", 2}};
|
||||
|
||||
|
|
@ -31,44 +31,6 @@ HandlerResult BotHandlers::returnMyTitles(int64_t userId) {
|
|||
return result;
|
||||
}
|
||||
|
||||
void BotHandlers::handleNavigation(TgBot::CallbackQuery::Ptr query) {
|
||||
int64_t userId = query->from->id;
|
||||
auto it = userContexts.find(userId);
|
||||
if (it == userContexts.end()) {
|
||||
botApi.sendMessage(query->message->chat->id, BotConstants::Text::SAD_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
UserContext& ctx = it->second;
|
||||
const std::string& data = query->data;
|
||||
|
||||
//HandlerResult response;
|
||||
//UserContext newCtx;
|
||||
|
||||
auto [response, newCtx] = newStateNavigation(query, ctx);
|
||||
switch (ctx.state) {
|
||||
case UserState::VIEWING_MY_TITLES:
|
||||
response = BotHandlers::returnMyTitles(ctx.cursor);
|
||||
break;
|
||||
case UserState::VIEWING_REVIEW_LIST:
|
||||
response = BotHandlers::returnReviewList(ctx.cursor);
|
||||
break;
|
||||
default:
|
||||
botApi.sendMessage(query->message->chat->id, BotConstants::Text::SAD_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
botApi.editMessageText(
|
||||
response.message,
|
||||
query->message->chat->id,
|
||||
query->message->messageId,
|
||||
"",
|
||||
"",
|
||||
nullptr,
|
||||
response.keyboard
|
||||
);
|
||||
}
|
||||
|
||||
void BotHandlers::handleMessage(TgBot::Message::Ptr message) {
|
||||
//TODO: просмотр состояния пользователя
|
||||
return;
|
||||
|
|
@ -90,6 +52,7 @@ void BotHandlers::handleNavigation(TgBot::CallbackQuery::Ptr query) {
|
|||
auto it = userContexts.find(userId);
|
||||
if (it == userContexts.end()) {
|
||||
// TODO: log
|
||||
sendError(query, BotConstants::Text::AUTH_ERROR);
|
||||
std::cout << "Error: Не нашел пользователя " << userId;
|
||||
return;
|
||||
}
|
||||
|
|
@ -127,7 +90,7 @@ void BotHandlers::handleNavigation(TgBot::CallbackQuery::Ptr query) {
|
|||
// Обработка back по интерфейсу
|
||||
if (data == BotConstants::Callback::NAV_BACK) {
|
||||
if (!popState(ctx)) {
|
||||
botApi.answerCallbackQuery(query->id, "Некуда возвращаться", true);
|
||||
sendError(query, BotConstants::Text::SAD_ERROR);
|
||||
return;
|
||||
}
|
||||
auto result = renderCurrent(ctx);
|
||||
|
|
@ -138,7 +101,7 @@ void BotHandlers::handleNavigation(TgBot::CallbackQuery::Ptr query) {
|
|||
// Переходы вперёд (push)
|
||||
auto newStepOpt = computeNextStep(query, current);
|
||||
if (!newStepOpt.has_value()) {
|
||||
sendError(query->message->chat->id);
|
||||
sendError(query, BotConstants::Text::SAD_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -181,4 +144,93 @@ void BotHandlers::increasePayload(int64_t& payload, const UserState curState) {
|
|||
payload = BotConstants::NULL_PAYLOAD;
|
||||
std::cerr << "Error: increasePayload" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void BotHandlers::editMessage(TgBot::CallbackQuery::Ptr query, HandlerResult response) {
|
||||
botApi.editMessageText(
|
||||
response.message,
|
||||
query->message->chat->id,
|
||||
query->message->messageId,
|
||||
"",
|
||||
"",
|
||||
nullptr,
|
||||
response.keyboard
|
||||
);
|
||||
}
|
||||
|
||||
HandlerResult BotHandlers::renderCurrent(const UserContext& ctx) {
|
||||
const auto& step = ctx.history.back();
|
||||
switch (step.state) {
|
||||
case UserState::MAIN_MENU:
|
||||
return showMainMenu();
|
||||
case UserState::VIEWING_MY_TITLES:
|
||||
return returnMyTitles(ctx.userId, step.payload); // payload = offset
|
||||
/*
|
||||
case UserState::VIEWING_TITLE_PAGE:
|
||||
return returnTitlePage(step.payload); // payload = titleId
|
||||
case UserState::VIEWING_REVIEW:
|
||||
return returnReview(step.payload); // payload = reviewId
|
||||
case UserState::AWAITING_REVIEW:
|
||||
return HandlerResult{"Пришлите текст отзыва:", nullptr};
|
||||
// ...
|
||||
*/
|
||||
default:
|
||||
return HandlerResult{BotConstants::Text::SAD_ERROR, nullptr};
|
||||
}
|
||||
}
|
||||
|
||||
HandlerResult BotHandlers::showMainMenu() {
|
||||
auto keyboard = KeyboardFactory::createMainMenu();
|
||||
|
||||
return HandlerResult{BotConstants::Text::MAIN_MENU, keyboard};
|
||||
}
|
||||
|
||||
void BotHandlers::sendError(TgBot::CallbackQuery::Ptr query, const std::string& errText) {
|
||||
//TODO: посылать сообщение с кнопкой возврата в главное меню
|
||||
auto keyboard = nullptr;
|
||||
|
||||
editMessage(query, {errText, keyboard});
|
||||
}
|
||||
|
||||
std::optional<NavigationStep> BotHandlers::computeNextStep(
|
||||
const TgBot::CallbackQuery::Ptr& query,
|
||||
const NavigationStep& current
|
||||
) {
|
||||
const std::string& data = query->data;
|
||||
|
||||
switch (current.state) {
|
||||
case UserState::MAIN_MENU:
|
||||
if (data == BotConstants::Callback::MY_TITLES) {
|
||||
return NavigationStep{UserState::VIEWING_MY_TITLES, 0};
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case UserState::VIEWING_MY_TITLES:
|
||||
if (data.starts_with("title_")) {
|
||||
int64_t titleId = parseId(data);
|
||||
return NavigationStep{UserState::VIEWING_TITLE_PAGE, titleId};
|
||||
}
|
||||
break;
|
||||
|
||||
case UserState::VIEWING_TITLE_PAGE:
|
||||
if (data == BotConstants::Callback::ACTION_ADD_REVIEW) {
|
||||
return NavigationStep{UserState::AWAITING_REVIEW, current.payload};
|
||||
}
|
||||
if (data.starts_with("review_")) {
|
||||
int64_t reviewId = parseId(data);
|
||||
return NavigationStep{UserState::VIEWING_REVIEW, reviewId};
|
||||
}
|
||||
break;
|
||||
|
||||
// Добавляйте другие переходы по мере роста функционала
|
||||
*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void BotHandlers::createInitContext(int64_t chatId) {
|
||||
NavigationStep init = {UserState::MAIN_MENU, BotConstants::NULL_PAYLOAD};
|
||||
userContexts[chatId] = {chatId, {init}};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue