Skip to content

Commit 11b316d

Browse files
authored
Update view.go
1 parent 5c5a80c commit 11b316d

1 file changed

Lines changed: 151 additions & 43 deletions

File tree

source-code/src/view.go

Lines changed: 151 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,176 @@
11
package src
22

33
import (
4+
"fmt"
45
"strings"
56

67
"github.com/charmbracelet/lipgloss"
78
)
89

910
func (m Model) View() string {
1011
if m.quitting {
11-
return "Goodbye!\n"
12+
return lipgloss.NewStyle().Foreground(lipgloss.Color(colorMuted)).Render("Goodbye from ngt.\n")
1213
}
1314
if m.subShell {
1415
return ""
1516
}
16-
title := titleStyle.Render(appName + " " + version)
17-
help := subtitleStyle.Render(strings.Join([]string{
18-
helpString(m.keys.quit),
19-
helpString(m.keys.execute),
20-
helpString(m.keys.refresh),
21-
helpString(m.keys.back),
22-
helpString(m.keys.selectIt),
23-
helpString(m.keys.filter),
24-
helpString(m.keys.tab),
25-
helpString(m.keys.copy),
26-
helpString(m.keys.move),
27-
helpString(m.keys.delete),
28-
helpString(m.keys.fuzzy),
29-
helpString(m.keys.bulkRename),
30-
helpString(m.keys.suspend),
31-
helpString(m.keys.subshell),
32-
helpString(m.keys.help),
33-
}, " • "))
34-
fBar := fBarStyle.Render(fBarContent)
17+
18+
w := m.termW
19+
if w < 40 {
20+
w = 80
21+
}
22+
23+
// ── Title bar ──────────────────────────────────────────────────────────────
24+
titleBar := titleBarStyle.Width(w).Render(
25+
appNameStyle.Render(" ngt ") +
26+
versionStyle.Render(version) +
27+
lipgloss.NewStyle().Foreground(lipgloss.Color(colorDim)).Render(" │ HackerOS file manager"),
28+
)
29+
30+
// ── Function bar ──────────────────────────────────────────────────────────
31+
fBar := renderFBar(w)
32+
33+
// ── Progress mode ─────────────────────────────────────────────────────────
3534
if m.mode == progressMode {
36-
return lipgloss.JoinVertical(lipgloss.Left, title, m.progress.View(), m.statusMsg, fBar, help)
35+
prog := lipgloss.NewStyle().Padding(1, 2).Width(w).Render(m.progress.View())
36+
status := statusBarStyle.Width(w).Render(m.statusMsg)
37+
return lipgloss.JoinVertical(lipgloss.Left, titleBar, prog, status, fBar)
3738
}
39+
40+
// ── Editor mode ───────────────────────────────────────────────────────────
3841
if m.mode == editorMode {
39-
help = subtitleStyle.Render(helpString(m.keys.save) + " • " + helpString(m.keys.cancel))
40-
editorView := editorStyle.Render(m.editor.View())
41-
status := m.statusMsg
42-
return lipgloss.JoinVertical(lipgloss.Left, title, subtitleStyle.Render("Editing: "+m.editorFile), editorView, status, fBar, help)
42+
editorBar := titleBarStyle.Width(w).Render(
43+
" ✎ Editing: " + lipgloss.NewStyle().Foreground(lipgloss.Color(colorAccent)).Render(m.editorFile) +
44+
lipgloss.NewStyle().Foreground(lipgloss.Color(colorMuted)).Render(" Ctrl+S save • Esc cancel"),
45+
)
46+
editorView := editorStyle.Width(w - 2).Render(m.editor.View())
47+
status := statusBarStyle.Width(w).Render(m.statusMsg)
48+
return lipgloss.JoinVertical(lipgloss.Left, titleBar, editorBar, editorView, status, fBar)
4349
}
50+
51+
// ── Fuzzy mode ────────────────────────────────────────────────────────────
4452
if m.mode == fuzzyMode {
45-
fuzzyView := inputStyle.Render(m.fuzzyInput.View())
46-
listView := listStyle.Render(m.panels[m.activePanel].fileList.View())
47-
return lipgloss.JoinVertical(lipgloss.Left, title, fuzzyView, listView, m.statusMsg, fBar, help)
53+
searchBar := inputStyle.Width(w - 2).Render(" 🔍 " + m.fuzzyInput.View())
54+
listView := inactivePanelBorder.Width(w - 2).Render(m.panels[m.activePanel].fileList.View())
55+
status := statusBarStyle.Width(w).Render(
56+
m.statusMsg + lipgloss.NewStyle().Foreground(lipgloss.Color(colorMuted)).Render(
57+
fmt.Sprintf(" %d results • Enter: navigate • Esc: cancel", len(m.fuzzyResults)),
58+
),
59+
)
60+
return lipgloss.JoinVertical(lipgloss.Left, titleBar, searchBar, listView, status, fBar)
4861
}
62+
63+
// ── Bulk rename mode ──────────────────────────────────────────────────────
4964
if m.mode == bulkRenameMode {
50-
inputView := inputStyle.Render(m.commandInput.View())
51-
return lipgloss.JoinVertical(lipgloss.Left, title, "Bulk Rename", inputView, m.statusMsg, fBar, help)
65+
step := "Step 1/2: regex pattern"
66+
if m.bulkRenameFrom != "" {
67+
step = "Step 2/2: replacement string"
68+
}
69+
header := titleBarStyle.Width(w).Render(" ✎ Bulk Rename " +
70+
lipgloss.NewStyle().Foreground(lipgloss.Color(colorMuted)).Render(step))
71+
inputView := inputStyle.Width(w - 2).Render(m.commandInput.View())
72+
status := statusBarStyle.Width(w).Render(m.statusMsg)
73+
return lipgloss.JoinVertical(lipgloss.Left, titleBar, header, inputView, status, fBar)
74+
}
75+
76+
// ── Confirmation mode ─────────────────────────────────────────────────────
77+
if m.mode == confirmMode {
78+
dialog := dialogStyle.Width(50).Render(
79+
errorStyle.Render("⚠ Confirm Action") + "\n\n" +
80+
m.confirmMsg + "\n\n" +
81+
lipgloss.NewStyle().Foreground(lipgloss.Color(colorMuted)).Render("Press y to confirm, n to cancel"),
82+
)
83+
centered := lipgloss.Place(w, 10, lipgloss.Center, lipgloss.Center, dialog)
84+
return lipgloss.JoinVertical(lipgloss.Left, titleBar, centered, fBar)
5285
}
53-
leftList := listStyle.Width(m.panels[0].fileList.Width()).Render(m.panels[0].fileList.View())
54-
rightList := listStyle.Width(m.panels[1].fileList.Width()).Render(m.panels[1].fileList.View())
55-
content := lipgloss.JoinHorizontal(lipgloss.Top, leftList, rightList)
56-
leftPwd := subtitleStyle.Render("Left: " + m.panels[0].currentDir)
57-
if m.panels[0].gitBranch != "" {
58-
leftPwd += " [Branch: " + m.panels[0].gitBranch + "]"
86+
87+
// ── Podman browser mode ───────────────────────────────────────────────────
88+
if m.mode == podmanMode {
89+
header := podmanStyle.Render(" 🐳 Podman Containers ") +
90+
lipgloss.NewStyle().Foreground(lipgloss.Color(colorMuted)).Render(" Enter: connect • Esc: cancel")
91+
var rows []string
92+
for i, c := range m.podmanContainers {
93+
prefix := " "
94+
if i == 0 {
95+
prefix = lipgloss.NewStyle().Foreground(lipgloss.Color(colorAccent)).Render("▶ ")
96+
}
97+
rows = append(rows, prefix+c)
98+
}
99+
if len(rows) == 0 {
100+
rows = []string{lipgloss.NewStyle().Foreground(lipgloss.Color(colorMuted)).Render(" No running containers found")}
101+
}
102+
box := inactivePanelBorder.Width(w - 2).Render(strings.Join(rows, "\n"))
103+
return lipgloss.JoinVertical(lipgloss.Left, titleBar, header, box, fBar)
59104
}
60-
rightPwd := subtitleStyle.Render("Right: " + m.panels[1].currentDir)
61-
if m.panels[1].gitBranch != "" {
62-
rightPwd += " [Branch: " + m.panels[1].gitBranch + "]"
105+
106+
// ── Explorer mode (main) ──────────────────────────────────────────────────
107+
halfW := (w / 2) - 3
108+
109+
// Path bars
110+
leftPath := m.renderPathBar(0, halfW)
111+
rightPath := m.renderPathBar(1, halfW)
112+
pathRow := lipgloss.JoinHorizontal(lipgloss.Top, leftPath, rightPath)
113+
114+
// File panels
115+
leftPanel := m.renderPanel(0, halfW)
116+
rightPanel := m.renderPanel(1, halfW)
117+
panels := lipgloss.JoinHorizontal(lipgloss.Top, leftPanel, rightPanel)
118+
119+
// Command input
120+
cmdLabel := inputLabelStyle.Render("›")
121+
inputView := inputStyle.Width(w - 6).Render(m.commandInput.View())
122+
cmdRow := lipgloss.JoinHorizontal(lipgloss.Left, cmdLabel, inputView)
123+
124+
// Status
125+
status := statusBarStyle.Width(w).Render(m.statusMsg)
126+
127+
return lipgloss.JoinVertical(lipgloss.Left,
128+
titleBar,
129+
pathRow,
130+
panels,
131+
cmdRow,
132+
status,
133+
fBar,
134+
)
135+
}
136+
137+
func (m *Model) renderPathBar(idx, w int) string {
138+
p := &m.panels[idx]
139+
vfsTag := vfsTagStyle.Render(p.vfs.VFSName())
140+
dir := pathStyle.Render(truncatePath(p.currentDir, w-20))
141+
branch := ""
142+
if p.gitBranch != "" {
143+
branch = " " + branchStyle.Render(" "+p.gitBranch+" ")
144+
}
145+
sort := sortTagStyle.Render(p.sortMode.String())
146+
return lipgloss.NewStyle().Width(w + 2).Render(
147+
lipgloss.JoinHorizontal(lipgloss.Top, vfsTag, " ", dir, branch, " ", sort),
148+
)
149+
}
150+
151+
func (m *Model) renderPanel(idx, w int) string {
152+
p := &m.panels[idx]
153+
listView := p.fileList.View()
154+
sel := 0
155+
for _, v := range p.selectedFiles {
156+
if v {
157+
sel++
158+
}
159+
}
160+
footer := ""
161+
if sel > 0 {
162+
footer = "\n" + warnStyle.Render(fmt.Sprintf(" %d selected", sel))
163+
}
164+
content := listView + footer
165+
if idx == m.activePanel {
166+
return activePanelBorder.Width(w).Render(content)
167+
}
168+
return inactivePanelBorder.Width(w).Render(content)
169+
}
170+
171+
func truncatePath(path string, maxLen int) string {
172+
if len(path) <= maxLen {
173+
return path
63174
}
64-
pwds := lipgloss.JoinHorizontal(lipgloss.Top, leftPwd, rightPwd)
65-
inputView := inputStyle.Render(m.commandInput.View())
66-
status := m.statusMsg
67-
return lipgloss.JoinVertical(lipgloss.Left, title, pwds, content, inputView, status, fBar, help)
175+
return "…" + path[len(path)-maxLen+1:]
68176
}

0 commit comments

Comments
 (0)