106 lines
2.7 KiB
Go
106 lines
2.7 KiB
Go
package tui
|
|
|
|
import (
|
|
"filepass/internal/pages"
|
|
"filepass/internal/services"
|
|
|
|
"charm.land/bubbles/v2/textinput"
|
|
)
|
|
|
|
type page int
|
|
|
|
const (
|
|
pageHome page = iota
|
|
pageConfig
|
|
pageAddServer
|
|
pageSelectServer
|
|
pageServerActions
|
|
pageFileAction
|
|
pageSend
|
|
pageCleanAll
|
|
pageRemoveServer
|
|
pageSelectEditServer
|
|
pageEditServer
|
|
)
|
|
|
|
type TUIInterface struct {
|
|
Services *services.ServicesStore
|
|
Page page
|
|
MenuItems []pages.MenuItem
|
|
Selected int
|
|
Servers map[string]services.Server
|
|
ServerNames []string // sorted, stable order for list rendering
|
|
NoServers bool
|
|
InitErr error
|
|
FlashMsg string
|
|
Form addServerForm
|
|
FormErr string // inline field error (e.g. duplicate name)
|
|
Quitting bool
|
|
WindowWidth int
|
|
WindowHeight int
|
|
// server actions page
|
|
ActiveServer string
|
|
LocalDir string // user's cwd, destination for received files
|
|
StorageFiles []string
|
|
StorageLoading bool
|
|
StorageErr error
|
|
FileSelected int // cursor within StorageFiles
|
|
FileFocused bool // true = ↑↓ drives file list, false = action menu
|
|
FileScrollOff int // first visible row in StorageFiles list
|
|
FileViewHeight int // available visible rows for StorageFiles list
|
|
FileMultiSelect map[int]bool // selected rows in StorageFiles
|
|
// file action page
|
|
ActiveFile string
|
|
ActiveFiles []string
|
|
FileOpLoading bool
|
|
FileOpErr error
|
|
FileOpSuccess string
|
|
// edit server page
|
|
EditingServer string // original name of server being edited
|
|
// clean all confirmation page
|
|
CleanInput textinput.Model
|
|
CleanOpLoading bool
|
|
CleanOpErr error
|
|
// send / file picker page
|
|
Picker picker
|
|
}
|
|
|
|
func NewTUIInterface(store *services.ServicesStore, localDir string) TUIInterface {
|
|
return TUIInterface{
|
|
Services: store,
|
|
Page: pageHome,
|
|
MenuItems: pages.HomeMenuItems(),
|
|
LocalDir: localDir,
|
|
FileMultiSelect: make(map[int]bool),
|
|
}
|
|
}
|
|
|
|
// fileListHeight calculates how many rows can fit in the server storage file list.
|
|
func (m TUIInterface) fileListHeight() int {
|
|
h := m.WindowHeight
|
|
if h == 0 {
|
|
return 0 // unconstrained until first WindowSizeMsg
|
|
}
|
|
|
|
// Card chrome overhead (rounded border + compact inner vertical padding)
|
|
const cardOverhead = 2
|
|
// Header (title + subtitle)
|
|
const headerLines = 2
|
|
// Footer (top border + content)
|
|
const footerLines = 2
|
|
// Server actions menu rows (Send / Clean All)
|
|
actionLines := len(m.MenuItems)
|
|
if actionLines < 1 {
|
|
actionLines = 2
|
|
}
|
|
// File section chrome: top border + local-dir label
|
|
const fileSectionOverhead = 2
|
|
|
|
used := cardOverhead + headerLines + footerLines + actionLines + fileSectionOverhead
|
|
available := h - used
|
|
if available < 1 {
|
|
available = 1
|
|
}
|
|
return available
|
|
}
|