package ui import ( "fmt" "github.com/NicoNex/echotron/v3" ) // PaginationConfig конфигурация для построения навигационного ряда пагинации type PaginationConfig struct { CurrentPage int TotalPages int // Для API пагинации (из page.Pages) TotalItems int // Для локальной пагинации (len(array)) ItemsPerPage int // Для расчета TotalPages из TotalItems PrevCallback string // По умолчанию "prev" NextCallback string // По умолчанию "next" MiddleButtons []echotron.InlineKeyboardButton // Опциональные кнопки в центре (например, "+ Добавить") } // BuildNavigationRow создает навигационный ряд с динамической шириной. // Показывает ряд только если страниц > 1. // Возвращает nil если пагинация не нужна. func BuildNavigationRow(config PaginationConfig) []echotron.InlineKeyboardButton { // Вычисляем TotalPages из TotalItems если не задан totalPages := config.TotalPages if totalPages == 0 && config.TotalItems > 0 && config.ItemsPerPage > 0 { totalPages = CalculatePages(config.TotalItems, config.ItemsPerPage) } // Устанавливаем значения по умолчанию для callbacks prevCallback := config.PrevCallback if prevCallback == "" { prevCallback = "prev" } nextCallback := config.NextCallback if nextCallback == "" { nextCallback = "next" } var row []echotron.InlineKeyboardButton // Левая стрелка (только если есть предыдущая страница) if totalPages > 1 && config.CurrentPage > 0 { row = append(row, echotron.InlineKeyboardButton{ Text: "←", CallbackData: prevCallback, }) } // Средние кнопки (если есть) if len(config.MiddleButtons) > 0 { row = append(row, config.MiddleButtons...) } // Правая стрелка (только если есть следующая страница) if totalPages > 1 && config.CurrentPage+1 < totalPages { row = append(row, echotron.InlineKeyboardButton{ Text: "→", CallbackData: nextCallback, }) } if len(row) == 0 { return nil } return row } // CalculatePages вычисляет количество страниц из общего количества элементов func CalculatePages(totalItems, itemsPerPage int) int { if itemsPerPage <= 0 { return 0 } return (totalItems + itemsPerPage - 1) / itemsPerPage } // GetPageBounds возвращает start/end индексы для текущей страницы. // Автоматически сбрасывает на первую страницу если currentPage выходит за границы. func GetPageBounds(currentPage, itemsPerPage, totalItems int) (start, end int) { start = currentPage * itemsPerPage if start >= totalItems { start = 0 } end = start + itemsPerPage if end > totalItems { end = totalItems } return start, end } // FormatPageInfo форматирует текст индикатора страницы для заголовка func FormatPageInfo(currentPage, totalPages int) string { if totalPages <= 1 { return "" } return fmt.Sprintf(" (стр. %d/%d)", currentPage+1, totalPages) } // ElementLayoutConfig конфигурация для автоматической раскладки элементов с пагинацией type ElementLayoutConfig struct { CurrentPage int // Текущая страница (0-indexed) ItemsPerPage int // Элементов на странице ItemsPerRow int // Элементов в одном ряду EmptyButton *echotron.InlineKeyboardButton // Кнопка-заполнитель (опционально, по умолчанию " ") } // BuildElementRows автоматически раскладывает элементы с пагинацией. // Принимает все элементы, возвращает ряды для текущей страницы с правильной раскладкой. // Автоматически заполняет пустыми кнопками если страниц > 1 (для консистентности высоты). // Возвращает 2D массив кнопок готовый к добавлению в клавиатуру. // // Пример использования: // // config := ui.ElementLayoutConfig{ // CurrentPage: 0, // ItemsPerPage: 6, // ItemsPerRow: 2, // } // rows := ui.BuildElementRows(config, allButtons) // keyboard = append(keyboard, rows...) func BuildElementRows(config ElementLayoutConfig, allItems []echotron.InlineKeyboardButton) [][]echotron.InlineKeyboardButton { if len(allItems) == 0 { return nil } // Параметры по умолчанию if config.ItemsPerPage <= 0 { config.ItemsPerPage = 6 } if config.ItemsPerRow <= 0 { config.ItemsPerRow = 2 } // Кнопка-заполнитель по умолчанию emptyButton := echotron.InlineKeyboardButton{Text: " ", CallbackData: "empty"} if config.EmptyButton != nil { emptyButton = *config.EmptyButton } // Вычисляем границы страницы totalPages := CalculatePages(len(allItems), config.ItemsPerPage) start, end := GetPageBounds(config.CurrentPage, config.ItemsPerPage, len(allItems)) // Получаем элементы текущей страницы pageItems := allItems[start:end] // Если страниц >= 2, заполняем до ItemsPerPage пустыми кнопками // Это обеспечивает одинаковую высоту клавиатуры на всех страницах if totalPages >= 2 { for len(pageItems) < config.ItemsPerPage { pageItems = append(pageItems, emptyButton) } } // Раскладываем элементы по рядам var rows [][]echotron.InlineKeyboardButton for i := 0; i < len(pageItems); i += config.ItemsPerRow { var row []echotron.InlineKeyboardButton // Добавляем элементы в ряд for j := 0; j < config.ItemsPerRow && i+j < len(pageItems); j++ { row = append(row, pageItems[i+j]) } // Если в ряду меньше элементов чем ItemsPerRow, заполняем пустыми for len(row) < config.ItemsPerRow { row = append(row, emptyButton) } rows = append(rows, row) } return rows }