diff --git a/CHANGELOG.md b/CHANGELOG.md index fdde4a2..2fd9b68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,12 @@ - Fixed: key_list_tab & snippet_list_tab were dropping last data row (off-by-one in `rows[:len(rows)-1]`) - Fixed: SFTP pane width — lipgloss `Width(n)` renders `n+2` chars (border extra). halfW now `t.width/2-2` to compensate. File names truncate to `…` within inner text area. Filter line also truncated. - Verified: zero overflow at 80, 60, 50 (side-by-side), 40, 30 cols (stacked) + +### SFTP Stacked Mode Fix (Done) +- Stacked mode (<50 cols) now renders only the active pane (Local or Remote) +- Added pane indicator bar: `[Local] Remote` with active pane highlighted +- Side-by-side mode (≥50 cols) unchanged — both panes remain visible +- Tab key now visually switches between panes on narrow terminals - Breakpoints: compact (<60), medium (60–100), wide (≥100) ## v1.0.0 (2025-01-30) diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index 2428294..7904a9a 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -63,22 +63,12 @@ ✅ Fixed bug: key_list_tab.go & snippet_list_tab.go dropped last row (`rows[:len(rows)-1]` excluded real data) ✅ Breakpoints: compact (<60 cols / mobile), medium (60–100 / tablet), wide (≥100 / desktop) -### Next: SFTP Stacked Mode Fix -⏳ **File**: `pkg/tui/sftp_browser_tab.go` -⏳ **Masalah**: Stacked mode (<50 cols) render 2 pane vertikal, masing-masing - `t.height-6` entries. Total 2x tinggi terminal. Pane kedua menutupi pane pertama. - Tab switch bekerja tapi tidak terlihat karena cuma 1 pane visible. -⏳ **Solusi**: - - Stacked mode: render cuma ACTIVE pane (bukan 2 pane) - - Tambah pane indicator bar: `[Local] Remote` (active disorot hijau) - - Side-by-side mode (>=50 cols): TIDAK DIUBAH, tetap 2 pane -⏳ **Detail implementasi**: - 1. Di `View()`, ganti blok `if t.width < 50`: - - Render cuma `t.renderPane(activePane, paneW)` bukan keduanya - - Tambah indicator bar sebelum pane: active pane disorot `StatusBarStyle`, inactive `SubtitleStyle` - 2. `maxDisplay` tidak perlu diubah (cuma 1 pane, full height) - 3. Footer tetap sama (sudah wrapped) -⏳ **Prioritas**: HIGH +### Done: SFTP Stacked Mode Fix +✅ **File**: `pkg/tui/sftp_browser_tab.go` +✅ Stacked mode (<50 cols): render cuma ACTIVE pane (bukan 2 pane) +✅ Pane indicator bar: `[Local] Remote` — active disorot hijau (StatusBarStyle) +✅ Side-by-side mode (>=50 cols): tidak diubah, tetap 2 pane +✅ `maxDisplay` tidak diubah (cuma 1 pane, full height) --- diff --git a/pkg/tui/sftp_browser_tab.go b/pkg/tui/sftp_browser_tab.go index 78fc0e9..47a9bba 100644 --- a/pkg/tui/sftp_browser_tab.go +++ b/pkg/tui/sftp_browser_tab.go @@ -543,14 +543,33 @@ func (t *SFTPBrowserTab) View() string { // Responsive pane layout: stack vertically on narrow terminals // Each pane renders at maxW+2 total (maxW content + 2 border chars) var leftView, rightView string + var indicator string if t.width < 50 { - // Stack vertically — each pane gets full width minus border + // Only show active pane in stacked mode — Tab switches between them paneW := t.width - 2 if paneW < 20 { paneW = 20 } - leftView = t.renderPane(&t.left, paneLocal, paneW) - rightView = t.renderPane(&t.right, paneRemote, paneW) + // Pane indicator: [Local] Remote or Local [Remote] + var indicatorParts []string + for _, name := range []string{"Local", "Remote"} { + pt := paneLocal + if name == "Remote" { + pt = paneRemote + } + if t.active == pt { + indicatorParts = append(indicatorParts, StatusBarStyle.Render(" "+name+" ")) + } else { + indicatorParts = append(indicatorParts, SubtitleStyle.Render(" "+name+" ")) + } + } + indicator = lipgloss.JoinHorizontal(lipgloss.Top, indicatorParts[0], SubtitleStyle.Render(" "), indicatorParts[1]) + + if t.active == paneLocal { + leftView = t.renderPane(&t.left, paneLocal, paneW) + } else { + leftView = t.renderPane(&t.right, paneRemote, paneW) + } } else { // Side by side — reserve 2 chars border per pane halfW := t.width/2 - 2 @@ -568,7 +587,9 @@ func (t *SFTPBrowserTab) View() string { b.WriteString("\n") if t.width < 50 { - b.WriteString(lipgloss.JoinVertical(lipgloss.Left, leftView, rightView)) + b.WriteString(lipgloss.PlaceHorizontal(t.width, lipgloss.Center, indicator)) + b.WriteString("\n") + b.WriteString(leftView) } else { b.WriteString(lipgloss.JoinHorizontal(lipgloss.Top, leftView, rightView)) }