269 lines
5.9 KiB
Go
269 lines
5.9 KiB
Go
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
"time"
|
|
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/container"
|
|
"fyne.io/fyne/v2/widget"
|
|
|
|
"MobileMkch/models"
|
|
)
|
|
|
|
type ThreadsScreen struct {
|
|
uiManager *UIManager
|
|
board *models.Board
|
|
content *fyne.Container
|
|
threads []models.Thread
|
|
loading bool
|
|
debouncer *Debouncer
|
|
currentPage int
|
|
pageSize int
|
|
totalPages int
|
|
pageContainer *fyne.Container
|
|
}
|
|
|
|
func NewThreadsScreen(uiManager *UIManager, board *models.Board) *ThreadsScreen {
|
|
screen := &ThreadsScreen{
|
|
uiManager: uiManager,
|
|
board: board,
|
|
loading: false,
|
|
pageSize: uiManager.GetSettings().PageSize,
|
|
}
|
|
|
|
screen.debouncer = NewDebouncer(100*time.Millisecond, func() {
|
|
screen.displayThreads()
|
|
})
|
|
|
|
screen.setupContent()
|
|
return screen
|
|
}
|
|
|
|
func (ts *ThreadsScreen) setupContent() {
|
|
ts.content = container.NewVBox()
|
|
|
|
header := widget.NewLabel(fmt.Sprintf("/%s/ - %s", ts.board.Code, ts.board.Description))
|
|
header.TextStyle = fyne.TextStyle{Bold: true}
|
|
ts.content.Add(header)
|
|
|
|
ts.content.Add(widget.NewLabel("Загрузка тредов..."))
|
|
}
|
|
|
|
func (ts *ThreadsScreen) GetContent() fyne.CanvasObject {
|
|
return container.NewScroll(ts.content)
|
|
}
|
|
|
|
func (ts *ThreadsScreen) GetTitle() string {
|
|
return fmt.Sprintf("/%s/", ts.board.Code)
|
|
}
|
|
|
|
func (ts *ThreadsScreen) OnShow() {
|
|
if !ts.loading {
|
|
ts.loadThreads()
|
|
}
|
|
}
|
|
|
|
func (ts *ThreadsScreen) OnHide() {
|
|
// Ничего не делаем
|
|
}
|
|
|
|
func (ts *ThreadsScreen) loadThreads() {
|
|
ts.loading = true
|
|
|
|
ts.showLoading()
|
|
|
|
go func() {
|
|
defer func() {
|
|
ts.loading = false
|
|
}()
|
|
|
|
threads, err := ts.uiManager.GetAPIClient().GetThreads(ts.board.Code)
|
|
if err != nil {
|
|
log.Printf("Ошибка загрузки тредов: %v", err)
|
|
|
|
fyne.Do(func() {
|
|
ts.showError(fmt.Sprintf("Ошибка загрузки тредов:\n%v", err))
|
|
})
|
|
return
|
|
}
|
|
|
|
ts.threads = threads
|
|
|
|
fyne.Do(func() {
|
|
ts.debouncer.Trigger()
|
|
})
|
|
}()
|
|
}
|
|
|
|
func (ts *ThreadsScreen) showLoading() {
|
|
ts.content.RemoveAll()
|
|
|
|
header := widget.NewLabel(fmt.Sprintf("/%s/ - %s", ts.board.Code, ts.board.Description))
|
|
header.TextStyle = fyne.TextStyle{Bold: true}
|
|
ts.content.Add(header)
|
|
|
|
progressBar := widget.NewProgressBarInfinite()
|
|
ts.content.Add(progressBar)
|
|
progressBar.Start()
|
|
|
|
ts.content.Add(widget.NewLabel("Загрузка тредов..."))
|
|
|
|
ts.content.Refresh()
|
|
}
|
|
|
|
func (ts *ThreadsScreen) showError(message string) {
|
|
ts.content.RemoveAll()
|
|
|
|
header := widget.NewLabel(fmt.Sprintf("/%s/ - %s", ts.board.Code, ts.board.Description))
|
|
header.TextStyle = fyne.TextStyle{Bold: true}
|
|
ts.content.Add(header)
|
|
|
|
errorLabel := widget.NewLabel("❌ " + message)
|
|
errorLabel.Wrapping = fyne.TextWrapWord
|
|
ts.content.Add(errorLabel)
|
|
|
|
retryButton := widget.NewButton("Повторить", func() {
|
|
ts.loadThreads()
|
|
})
|
|
ts.content.Add(retryButton)
|
|
|
|
ts.content.Refresh()
|
|
}
|
|
|
|
func (ts *ThreadsScreen) displayThreads() {
|
|
ts.content.RemoveAll()
|
|
|
|
header := widget.NewLabel(fmt.Sprintf("/%s/ - %s", ts.board.Code, ts.board.Description))
|
|
header.TextStyle = fyne.TextStyle{Bold: true}
|
|
ts.content.Add(header)
|
|
|
|
buttonsContainer := container.NewHBox()
|
|
|
|
createThreadButton := widget.NewButton("Создать тред", func() {
|
|
createThreadScreen := NewCreateThreadScreen(ts.uiManager, ts.board.Code)
|
|
ts.uiManager.PushScreen(createThreadScreen)
|
|
})
|
|
buttonsContainer.Add(createThreadButton)
|
|
|
|
ts.content.Add(buttonsContainer)
|
|
|
|
if len(ts.threads) == 0 {
|
|
ts.content.Add(widget.NewLabel("Тредов не найдено"))
|
|
ts.content.Refresh()
|
|
return
|
|
}
|
|
|
|
ts.totalPages = (len(ts.threads) + ts.pageSize - 1) / ts.pageSize
|
|
ts.pageContainer = container.NewVBox()
|
|
|
|
start := ts.currentPage * ts.pageSize
|
|
end := start + ts.pageSize
|
|
if end > len(ts.threads) {
|
|
end = len(ts.threads)
|
|
}
|
|
|
|
for i := start; i < end; i++ {
|
|
thread := &ts.threads[i]
|
|
threadCard := ts.createThreadCard(thread)
|
|
ts.pageContainer.Add(threadCard)
|
|
}
|
|
|
|
ts.addPaginationControls()
|
|
|
|
ts.content.Add(ts.pageContainer)
|
|
ts.content.Refresh()
|
|
}
|
|
|
|
func (ts *ThreadsScreen) createThreadCard(thread *models.Thread) fyne.CanvasObject {
|
|
title := fmt.Sprintf("#%d: %s", thread.ID, thread.Title)
|
|
|
|
if len(title) > 20 {
|
|
title = title[:17] + "..."
|
|
}
|
|
|
|
info := fmt.Sprintf("Дата: %s",
|
|
thread.GetCreationTime().Format("02.01.2006 15:04"))
|
|
|
|
if thread.IsPinned() {
|
|
info += " | 📌 Закреплён"
|
|
}
|
|
|
|
if rating := thread.GetRatingValue(); rating != 0 {
|
|
info += fmt.Sprintf(" | ⭐ %d", rating)
|
|
}
|
|
|
|
if len(thread.Files) > 0 && ts.uiManager.GetSettings().ShowFiles {
|
|
info += fmt.Sprintf(" | 📎 %d", len(thread.Files))
|
|
}
|
|
|
|
preview := thread.Text
|
|
|
|
preview = strings.ReplaceAll(preview, "\n", " ")
|
|
preview = strings.ReplaceAll(preview, "\r", " ")
|
|
|
|
if len(preview) > 90 {
|
|
maxLen := 50
|
|
if len(preview) < maxLen {
|
|
maxLen = len(preview)
|
|
}
|
|
preview = preview[:maxLen] + "..."
|
|
}
|
|
|
|
buttonText := fmt.Sprintf("%s\n%s\n%s", title, info, preview)
|
|
|
|
button := widget.NewButton(buttonText, func() {
|
|
ts.uiManager.ShowThreadDetail(ts.board, thread)
|
|
})
|
|
|
|
return button
|
|
}
|
|
|
|
func (ts *ThreadsScreen) RefreshThreads() {
|
|
ts.loadThreads()
|
|
}
|
|
|
|
func (ts *ThreadsScreen) addPaginationControls() {
|
|
if ts.totalPages <= 1 {
|
|
return
|
|
}
|
|
|
|
paginationContainer := container.NewHBox()
|
|
|
|
prevButton := widget.NewButton("←", func() {
|
|
if ts.currentPage > 0 {
|
|
ts.currentPage--
|
|
ts.displayThreads()
|
|
}
|
|
})
|
|
if ts.currentPage == 0 {
|
|
prevButton.Disable()
|
|
}
|
|
paginationContainer.Add(prevButton)
|
|
|
|
pageInfo := widget.NewLabel(fmt.Sprintf("Страница %d из %d", ts.currentPage+1, ts.totalPages))
|
|
paginationContainer.Add(pageInfo)
|
|
|
|
nextButton := widget.NewButton("→", func() {
|
|
if ts.currentPage < ts.totalPages-1 {
|
|
ts.currentPage++
|
|
ts.displayThreads()
|
|
}
|
|
})
|
|
if ts.currentPage >= ts.totalPages-1 {
|
|
nextButton.Disable()
|
|
}
|
|
paginationContainer.Add(nextButton)
|
|
|
|
ts.pageContainer.Add(paginationContainer)
|
|
}
|
|
|
|
func (ts *ThreadsScreen) goToPage(page int) {
|
|
if page >= 0 && page < ts.totalPages {
|
|
ts.currentPage = page
|
|
ts.displayThreads()
|
|
}
|
|
}
|