Files
go-onlyoffice/cmd/office/model/item.go
T
eSliderandCursor cad68f64c6 feat(office): scrollable panes, nav tree drill-down, and item actions
Add viewports to all three columns with cursor sync scrolling. Support
Shift+Tab reverse pane focus. Replace flat menu with hierarchical NavTree
(list loads only on leaf nodes; dynamic project subnodes with Tasks/Files).
Enter or a opens per-item action menu (view, delete, download) wired to
the OnlyOffice API.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-24 16:43:06 +01:00

127 lines
3.0 KiB
Go

package model
// Kind identifies the OnlyOffice entity type for list items and preview routing.
type Kind string
const (
KindProject Kind = "project"
KindTask Kind = "task"
KindContact Kind = "contact"
KindOpportunity Kind = "opportunity"
KindCase Kind = "case"
KindCRMTask Kind = "crm_task"
KindMail Kind = "mail"
KindEvent Kind = "event"
KindCalendar Kind = "calendar"
KindFile Kind = "file"
KindUser Kind = "user"
)
// Subject identifies a menu leaf / list source.
type Subject string
const (
SubjectProjects Subject = "projects"
SubjectTasks Subject = "tasks"
SubjectCalendars Subject = "calendars"
SubjectEvents Subject = "events"
SubjectContacts Subject = "contacts"
SubjectPersons Subject = "persons"
SubjectCompanies Subject = "companies"
SubjectOpportunities Subject = "opportunities"
SubjectCases Subject = "cases"
SubjectCRMTasks Subject = "crm_tasks"
SubjectMailInbox Subject = "mail_inbox"
SubjectMailSent Subject = "mail_sent"
SubjectMailDrafts Subject = "mail_drafts"
SubjectMailTrash Subject = "mail_trash"
SubjectMailSpam Subject = "mail_spam"
SubjectProjectFiles Subject = "project_files"
SubjectTaskFiles Subject = "task_files"
SubjectUsers Subject = "users"
)
// FocusPane is which column has keyboard focus.
type FocusPane int
const (
FocusMenu FocusPane = iota
FocusList
FocusPreview
)
// PrevFocusPane cycles preview → list → menu → preview.
func PrevFocusPane(p FocusPane) FocusPane {
switch p {
case FocusMenu:
return FocusPreview
case FocusList:
return FocusMenu
default:
return FocusList
}
}
// NextFocusPane cycles menu → list → preview → menu.
func NextFocusPane(p FocusPane) FocusPane {
switch p {
case FocusMenu:
return FocusList
case FocusList:
return FocusPreview
default:
return FocusMenu
}
}
// Item is one row in the center list pane.
type Item struct {
ID, Title, Subtitle string
Kind Kind
Raw map[string]any
Selected bool
}
// Selection tracks multi-selected item IDs within the current subject.
type Selection struct {
ids map[string]struct{}
}
// NewSelection returns an empty selection set.
func NewSelection() *Selection {
return &Selection{ids: make(map[string]struct{})}
}
// Toggle flips selection on items[idx] and updates the ID set.
func (s *Selection) Toggle(items *[]Item, idx int) {
if idx < 0 || idx >= len(*items) {
return
}
it := &(*items)[idx]
it.Selected = !it.Selected
if it.Selected {
s.ids[it.ID] = struct{}{}
} else {
delete(s.ids, it.ID)
}
}
// Count returns the number of selected items.
func (s *Selection) Count() int {
return len(s.ids)
}
// Clear removes all selections.
func (s *Selection) Clear() {
s.ids = make(map[string]struct{})
}
// IDs returns selected item IDs in stable order (map iteration order is fine for display).
func (s *Selection) IDs() []string {
out := make([]string, 0, len(s.ids))
for id := range s.ids {
out = append(out, id)
}
return out
}