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;
}
// Track product view
await _activityTracker.TrackActivityAsync(
message.Chat,
ActivityTypes.ViewProduct,
$"Viewing product: {product.Name}",
product
);
// Track product view (non-blocking)
try
{
await _activityTracker.TrackActivityAsync(
message.Chat,
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
session.TempData["current_product"] = productId;
session.TempData["current_quantity"] = 1;
// Use carousel service to send product with image
await _carouselService.SendSingleProductWithImageAsync(bot, message.Chat.Id, product);
// Use carousel service to send product with image, replying to the current message to ensure visibility
await _carouselService.SendSingleProductWithImageAsync(bot, message.Chat.Id, product, message.MessageId);
session.State = SessionState.ViewingProduct;
}

View File

@ -19,7 +19,7 @@ namespace TeleBot.Services
public interface IProductCarouselService
{
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<bool> IsImageUrlValidAsync(string imageUrl);
}
@ -212,7 +212,7 @@ 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
{
@ -225,7 +225,9 @@ namespace TeleBot.Services
image,
caption: FormatProductCaption(product),
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
replyMarkup: _menuBuilder.ProductDetailMenu(product)
replyMarkup: _menuBuilder.ProductDetailMenu(product),
replyToMessageId: replyToMessageId,
allowSendingWithoutReply: true
);
}
else
@ -235,7 +237,9 @@ namespace TeleBot.Services
chatId,
MessageFormatter.FormatProductDetail(product),
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,
MessageFormatter.FormatProductDetail(product),
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
replyMarkup: _menuBuilder.ProductDetailMenu(product)
replyMarkup: _menuBuilder.ProductDetailMenu(product),
replyToMessageId: replyToMessageId,
allowSendingWithoutReply: true
);
}
}