MobileMkch/ui/threads_screen.go
2025-08-05 13:45:18 +03:00

196 lines
4.1 KiB
Go

package ui
import (
"fmt"
"log"
"strings"
"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
}
func NewThreadsScreen(uiManager *UIManager, board *models.Board) *ThreadsScreen {
screen := &ThreadsScreen{
uiManager: uiManager,
board: board,
loading: false,
}
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.displayThreads()
})
}()
}
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)
if len(ts.threads) == 0 {
ts.content.Add(widget.NewLabel("Тредов не найдено"))
ts.content.Refresh()
return
}
for i := range ts.threads {
thread := ts.threads[i]
threadCard := ts.createThreadCard(&thread)
ts.content.Add(threadCard)
}
ts.content.Refresh()
}
func (ts *ThreadsScreen) createThreadCard(thread *models.Thread) fyne.CanvasObject {
title := fmt.Sprintf("#%d: %s", thread.ID, thread.Title)
if len(title) > 50 {
title = title[:47] + "..."
}
info := fmt.Sprintf("Автор: %s | %s",
thread.Author,
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 {
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()
}