fix: fs tree min width to be enough to not have line splits

This commit is contained in:
2026-01-27 03:18:39 +00:00
parent e7f450867b
commit e555d74b51
3 changed files with 52 additions and 20 deletions
+21 -1
View File
@@ -85,6 +85,11 @@ type FsTree struct {
totalLines int
oldSelected *FsNode
startOffset int
maxContentWidth int
}
func (t *FsTree) ContentWidth() int {
return t.maxContentWidth
}
// ==================== Bubble Tea Interface Implementation ====================
@@ -92,13 +97,18 @@ func (t *FsTree) Init() tea.Cmd {
return nil
}
type ContentSizeChangeMsg struct{}
func (t *FsTree) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch m := msg.(type) {
case PerformActionMsg:
err := t.PerformAction(m.Action, m.Name)
if err != nil {
t.ErrMsg = err.Error()
return t, nil
}
// todo: standardise these messages
return t, func() tea.Msg { return ContentSizeChangeMsg{} }
case tea.WindowSizeMsg:
t.width = m.Width
t.height = m.Height
@@ -446,6 +456,7 @@ func (t *FsTree) renderNode(node *FsNode, depth int, builder *strings.Builder) {
// builds a cache of line num to rendered node in view
func (t *FsTree) BuildLines() {
t.maxContentWidth = 0
t.lines = make(map[int]*FsNode)
line := -1
flatTree := make([]*FsNode, 0)
@@ -461,7 +472,7 @@ func (t *FsTree) BuildLines() {
}
}
// Deprecated: isn't meant to be used directly
// isn't meant to be used directly
func (t *FsTree) buildLinesRec(node *FsNode, depth int, currentLine *int, flatTree *[]*FsNode) {
if node == nil {
return
@@ -475,6 +486,14 @@ func (t *FsTree) buildLinesRec(node *FsNode, depth int, currentLine *int, flatTr
*flatTree = append(*flatTree, node)
(*currentLine)++
// update max width
if depth > 0 {
w := depth + 2 + len(node.FileName())
if w > t.maxContentWidth {
t.maxContentWidth = w
}
}
if node.Expanded {
for _, child := range node.Children {
t.buildLinesRec(child, depth+1, currentLine, flatTree)
@@ -539,6 +558,7 @@ func (t *FsTree) CreateNode(folder *FsNode, name string, nodeType FsNodeType) er
}
t.SelectedNode = newNode
t.BuildLines()
return nil
}
+5 -5
View File
@@ -2,7 +2,6 @@ package main
// layout constants
const (
minFsTreeWidth = 5
minNoteViewWidth = 10
dividerWidth = 1
dragHitArea = 2 // +/- chars around divider
@@ -11,9 +10,9 @@ const (
fsTreeWidthPercent = 15
)
// calculateLayout computes the widths for the file tree and note view
// getUpdatedWindowSizes computes the widths for the file tree and note view
// based on the terminal dimensions and the desired tree width.
func calculateLayout(totalWidth, requestedTreeWidth int) (treeWidth, noteWidth int) {
func getUpdatedWindowSizes(totalWidth, requestedTreeWidth, minTreeWidth int) (treeWidth, noteWidth int) {
treeWidth = requestedTreeWidth
if treeWidth == 0 {
@@ -26,8 +25,9 @@ func calculateLayout(totalWidth, requestedTreeWidth int) (treeWidth, noteWidth i
if treeWidth > maxTreeWidth {
treeWidth = maxTreeWidth
}
if treeWidth < minFsTreeWidth {
treeWidth = minFsTreeWidth
if treeWidth < minTreeWidth {
treeWidth = minTreeWidth
}
noteWidth = max(0, totalWidth-treeWidth-dividerWidth)
+14 -2
View File
@@ -79,7 +79,11 @@ func (m *model) loadTreeCmd(path string) tea.Cmd {
func (m *model) layout(width, height int) {
m.terminalWidth = width
m.terminalHeight = height
m.fsTreeWidth, m.noteViewWidth = calculateLayout(width, m.fsTreeWidth)
minW := 0
if m.tree != nil {
minW = m.tree.ContentWidth()
}
m.fsTreeWidth, m.noteViewWidth = getUpdatedWindowSizes(width, m.fsTreeWidth, minW)
h := height
if m.showStatusBar || m.inputMode {
@@ -120,6 +124,8 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case treeLoadedMsg:
m.tree = msg.tree
m.loading = false
m.fsTreeWidth = m.tree.ContentWidth()
m.fsTreeWidth, m.noteViewWidth = getUpdatedWindowSizes(m.terminalWidth, m.fsTreeWidth, m.tree.ContentWidth())
_, cmd := m.tree.Update(tea.WindowSizeMsg{
Height: m.contentHeight,
Width: m.fsTreeWidth,
@@ -149,6 +155,12 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, cmd
}
case fstree.ContentSizeChangeMsg:
// layout update needed, sent when a new note is created
m.fsTreeWidth, m.noteViewWidth = getUpdatedWindowSizes(m.terminalWidth, m.tree.ContentWidth(), m.tree.ContentWidth())
// TODO: this can be simplified a lot
return m, m.resizeChildren() // batches two updates
case fstree.RequestInputMsg:
m.inputMode = true
m.pendingAction = msg.Action
@@ -250,7 +262,7 @@ func (m *model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.isHoveringDivider = isHoveringDivider(msg.X, m.fsTreeWidth)
if m.isDragging {
m.fsTreeWidth, m.noteViewWidth = calculateLayout(m.terminalWidth, msg.X)
m.fsTreeWidth, m.noteViewWidth = getUpdatedWindowSizes(m.terminalWidth, msg.X, m.tree.ContentWidth())
// Update children with new sizes
return m, m.resizeChildren()