Fix: Product details now auto-scroll into view when Buy is clicked

Problem: When clicking Buy button, product details message appeared at bottom
but Telegram didn't auto-scroll to show it, leaving users confused.

Solution: Use replyToMessageId parameter to thread product details as a reply
to the user's button click message. This:
- Creates visual thread connection
- Encourages Telegram to show the response prominently
- Makes conversation flow more natural

Also wrapped activity tracking in try-catch to prevent blocking.

Technical Changes:
- ProductCarouselService: Added replyToMessageId optional parameter
- SendPhotoAsync/SendTextMessageAsync: Use replyToMessageId with allowSendingWithoutReply
- HandleProductDetail: Pass message.MessageId to carousel service

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
SysAdmin 2025-10-06 04:08:50 +01:00
parent 6676f010a8
commit 3cc7092967
2 changed files with 29 additions and 16 deletions

View File

@ -402,20 +402,27 @@ namespace TeleBot.Handlers
return; return;
} }
// Track product view // Track product view (non-blocking)
await _activityTracker.TrackActivityAsync( try
message.Chat, {
ActivityTypes.ViewProduct, await _activityTracker.TrackActivityAsync(
$"Viewing product: {product.Name}", message.Chat,
product ActivityTypes.ViewProduct,
); $"Viewing product: {product.Name}",
product
);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Failed to track product view - continuing anyway");
}
// Store current product in temp data for quantity selection // Store current product in temp data for quantity selection
session.TempData["current_product"] = productId; session.TempData["current_product"] = productId;
session.TempData["current_quantity"] = 1; session.TempData["current_quantity"] = 1;
// Use carousel service to send product with image // Use carousel service to send product with image, replying to the current message to ensure visibility
await _carouselService.SendSingleProductWithImageAsync(bot, message.Chat.Id, product); await _carouselService.SendSingleProductWithImageAsync(bot, message.Chat.Id, product, message.MessageId);
session.State = SessionState.ViewingProduct; session.State = SessionState.ViewingProduct;
} }

View File

@ -19,7 +19,7 @@ namespace TeleBot.Services
public interface IProductCarouselService public interface IProductCarouselService
{ {
Task SendProductCarouselAsync(ITelegramBotClient botClient, long chatId, PagedResult<Product> products, string? categoryName = null, int currentPage = 1); Task SendProductCarouselAsync(ITelegramBotClient botClient, long chatId, PagedResult<Product> products, string? categoryName = null, int currentPage = 1);
Task SendSingleProductWithImageAsync(ITelegramBotClient botClient, long chatId, Product product); Task SendSingleProductWithImageAsync(ITelegramBotClient botClient, long chatId, Product product, int? replyToMessageId = null);
Task<InputFile?> GetProductImageAsync(Product product); Task<InputFile?> GetProductImageAsync(Product product);
Task<bool> IsImageUrlValidAsync(string imageUrl); Task<bool> IsImageUrlValidAsync(string imageUrl);
} }
@ -212,12 +212,12 @@ namespace TeleBot.Services
} }
} }
public async Task SendSingleProductWithImageAsync(ITelegramBotClient botClient, long chatId, Product product) public async Task SendSingleProductWithImageAsync(ITelegramBotClient botClient, long chatId, Product product, int? replyToMessageId = null)
{ {
try try
{ {
var image = await GetProductImageAsync(product); var image = await GetProductImageAsync(product);
if (image != null) if (image != null)
{ {
await botClient.SendPhotoAsync( await botClient.SendPhotoAsync(
@ -225,7 +225,9 @@ namespace TeleBot.Services
image, image,
caption: FormatProductCaption(product), caption: FormatProductCaption(product),
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown, parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
replyMarkup: _menuBuilder.ProductDetailMenu(product) replyMarkup: _menuBuilder.ProductDetailMenu(product),
replyToMessageId: replyToMessageId,
allowSendingWithoutReply: true
); );
} }
else else
@ -235,7 +237,9 @@ namespace TeleBot.Services
chatId, chatId,
MessageFormatter.FormatProductDetail(product), MessageFormatter.FormatProductDetail(product),
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown, parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
replyMarkup: _menuBuilder.ProductDetailMenu(product) replyMarkup: _menuBuilder.ProductDetailMenu(product),
replyToMessageId: replyToMessageId,
allowSendingWithoutReply: true
); );
} }
} }
@ -248,7 +252,9 @@ namespace TeleBot.Services
chatId, chatId,
MessageFormatter.FormatProductDetail(product), MessageFormatter.FormatProductDetail(product),
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown, parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
replyMarkup: _menuBuilder.ProductDetailMenu(product) replyMarkup: _menuBuilder.ProductDetailMenu(product),
replyToMessageId: replyToMessageId,
allowSendingWithoutReply: true
); );
} }
} }