Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

refactor(filepanel): replace filePanelFocusType with isFocused boolean#1040

Merged
lazysegtree merged 7 commits into
yorukot:mainyorukot/superfile:mainfrom
faisal-990:RefactorFocusPanelsCodefaisal-990/superfile:RefactorFocusPanelsCodeCopy head branch name to clipboard
Sep 9, 2025
Merged

refactor(filepanel): replace filePanelFocusType with isFocused boolean#1040
lazysegtree merged 7 commits into
yorukot:mainyorukot/superfile:mainfrom
faisal-990:RefactorFocusPanelsCodefaisal-990/superfile:RefactorFocusPanelsCodeCopy head branch name to clipboard

Conversation

@faisal-990

@faisal-990 faisal-990 commented Sep 4, 2025

Copy link
Copy Markdown
Contributor

The filePanelFocusType typed constant with multiple states (noneFocus, secondFocus, focus) added unnecessary complexity for managing panel focus. It also made the code harder to read and maintain.
Solution

Replaced filePanelFocusType with a simple isFocused boolean field in filePanel.
isFocused = true → panel is focused
isFocused = false → panel is not focused

This change removes unused constants and simplifies focus handling.

Refs #1033
Refs #1030

Summary by CodeRabbit

  • Refactor
    • Simplified panel focus handling to a single, consistent indicator across navigation, rendering, and key interactions, improving reliability and consistency in focus behavior.
  • Style
    • Minor formatting cleanups for readability without changing behavior.
  • Chores
    • Consolidated internal variable declarations and adjusted logging to reflect the updated focus indicator.

No user-facing features changed; interactions should feel more consistent and stable, especially when switching panels and using the sidebar or process bar.

The previous implementation used a typed constant
with multiple states (noneFocus, secondFocus, focus). This has been
deprecated in favor of a simpler  boolean field.

This makes it easier to determine whether the panel is focused (true) or
not (false), removes unnecessary enum complexity, and improves
readability/maintainability of the file panel logic.

Refs: yorukot#1033
@coderabbitai

coderabbitai Bot commented Sep 4, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Replaces per-file-panel focus enum with a boolean isFocused across internal code. Updates creation, navigation, movement, key handling, rendering, and logging to use the new flag. Adjusts helper returnFocusType to return bool. Removes filePanelFocusType and related constants. Minor formatting changes and grouped var declarations included.

Changes

Cohort / File(s) Summary
Focus state type refactor
src/internal/type.go, src/internal/type_utils.go
Remove filePanelFocusType and constants; add filePanel.isFocused bool. Update defaultFilePanel signature to accept focused bool and initialize panels accordingly. Remove String() for filePanelFocusType; keep focusPanelType as-is.
Focus helpers and navigation
src/internal/function.go, src/internal/handle_panel_navigation.go, src/internal/handle_panel_movement.go, src/internal/key_function.go
Change returnFocusType to return bool. Replace all focusType reads/writes with isFocused across panel creation, switching, sidebar selection, and key handling conditions. Formatting-only tweaks to processCmdToTeaCmd and a signature line break.
Model and rendering updates
src/internal/model.go, src/internal/model_render.go
Switch focus checks in getFilePanelItems and render path to isFocused. Update debug log keys. Group some globals into a var block. Use 0o755 literal for file mode.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Model
  participant Nav as Navigation
  participant Panels

  User->>Model: Key/Action (navigate/focus)
  Model->>Nav: Request focus change (focusPanelType)
  Nav->>Panels: Set isFocused=true on target panel
  Nav->>Panels: Set isFocused=false on others
  Panels-->>Model: Focus state updated (booleans)
  Model->>Panels: Render with isFocused
  note over Panels,Model: Rendering uses boolean isFocused instead of enum
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

refactoring

Suggested reviewers

  • yorukot

Pre-merge checks (2 passed, 1 warning)

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title concisely identifies the primary refactor by stating the removal of filePanelFocusType in favor of an isFocused boolean on the file panel, matching the core change of the PR.
Description Check ✅ Passed The description directly explains the rationale for replacing filePanelFocusType with an isFocused boolean, outlines the solution, and references related issues, accurately summarizing the changes.

Poem

Thump-thump, I toggle focus true and false,
A Boolean hop—no enums to waltz.
Panels align, like carrots in rows,
Cursor nibs left, then right it goes.
With tidy code and whiskers bright,
I ship this refactor—quick as light! 🥕🐇

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68d77b0 and 3eaa8b7.

📒 Files selected for processing (2)
  • src/internal/type.go (1 hunks)
  • src/internal/type_utils.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/internal/type.go
  • src/internal/type_utils.go
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/internal/type.go (1)

81-121: Enforce single panel focus
In defaultFilePanel and each navigation method (focusOnSideBar, focusOnProcessBar, focusOnMetadata), clear all other panels’ isFocused flags before setting the target panel’s to true.

🧹 Nitpick comments (14)
src/internal/type.go (3)

20-26: Fix wording/typos in deprecation comment.

Current text has typos (“Depreciated”, “wheather”, etc.). Suggest clearer, concise wording.

-// [Depreciated] - filePanel.filePanelFocusType 's implementation  is being replaced with a isFocused bool variable .
-
-// The below typed constants used to determine which
-// panel is currently being focused , is being replaced with simpler
-// isFocused bool value , This tells wheather the focus is currently on the panel =>TRUE
-// else for other oher case ,where the panel is not under ,the value is =>FALSE
+// Deprecated: filePanelFocusType on filePanel has been replaced with the boolean
+// field isFocused. Use filePanel.isFocused to indicate whether the panel is
+// currently focused (true) or not (false).

28-36: Remove stale commented-out type and constants.

They add noise and can confuse readers. Prefer relying on git history.

-// type filePanelFocusType uint
-
-// Earlier implementation
-// const (
-// noneFocus filePanelFocusType = iota
-// secondFocus
-// focus
-// )

165-171: Tighten struct-level deprecation note and align wording with field name.

Minor doc cleanup.

-// filePanel.filePanelFocusType 's implementation  is being replaced with a isFocused bool variable .
+// Deprecated: filePanelFocusType replaced by the isFocused boolean flag.
 type filePanel struct {
   cursor             int
   render             int
-  isFocused          bool
+  isFocused          bool
src/internal/handle_panel_movement.go (1)

114-121: Centralize and enforce exclusive filePanel focus.

Instead of setting one panel’s isFocused directly, route through a helper that clears others to avoid multiple “true” states.

- m.focusPanel = nonePanelFocus
- panel := m.getFocusedFilePanel()
+ m.focusPanel = nonePanelFocus
+ panel := m.getFocusedFilePanel()- panel.isFocused = true
+ m.setFocusedFilePanel(m.filePanelFocusIndex)

Add this helper (outside this hunk):

func (m *model) setFocusedFilePanel(idx int) {
	for i := range m.fileModel.filePanels {
		m.fileModel.filePanels[i].isFocused = i == idx
	}
}

I can wire this through other focus paths (next/previous/close/create panel) if you want.

src/internal/model.go (1)

30-33: OK to group globals; consider moving into model later

Consolidation is fine. Per past learnings, I’m keeping scope tight to this focus refactor and not flagging unrelated pre-existing issues; the TODO to move these into model fields can remain a separate change.

src/internal/handle_panel_navigation.go (5)

62-64: Standardize: derive isFocused from focusPanel

Minor consistency tweak: use returnFocusType(m.focusPanel) for both sides to avoid mixing direct booleans and derived value.

- m.fileModel.filePanels[m.filePanelFocusIndex].isFocused = false
- m.fileModel.filePanels[m.filePanelFocusIndex+1].isFocused = returnFocusType(m.focusPanel)
+ m.fileModel.filePanels[m.filePanelFocusIndex].isFocused = returnFocusType(sidebarFocus) // always false
+ m.fileModel.filePanels[m.filePanelFocusIndex+1].isFocused = returnFocusType(m.focusPanel)

Or keep the first line as-is and just note the intent in a comment.


101-102: Ensure single true isFocused invariant

After closing a panel, setting only the current panel’s isFocused is fine. If any code path could leave another panel true, consider normalizing once here by clearing others (defensive). Optional.


165-169: Use returnFocusType for readability and consistency

Replace hardcoded booleans with the derived value so all sites follow one rule.

- m.focusPanel = nonePanelFocus
- m.fileModel.filePanels[m.filePanelFocusIndex].isFocused = true
+ m.focusPanel = nonePanelFocus
+ m.fileModel.filePanels[m.filePanelFocusIndex].isFocused = returnFocusType(m.focusPanel)
- m.focusPanel = sidebarFocus
- m.fileModel.filePanels[m.filePanelFocusIndex].isFocused = false
+ m.focusPanel = sidebarFocus
+ m.fileModel.filePanels[m.filePanelFocusIndex].isFocused = returnFocusType(m.focusPanel)

180-184: Apply same consistency tweak here (process bar)

- m.focusPanel = processBarFocus
- m.fileModel.filePanels[m.filePanelFocusIndex].isFocused = false
+ m.focusPanel = processBarFocus
+ m.fileModel.filePanels[m.filePanelFocusIndex].isFocused = returnFocusType(m.focusPanel)

And for the else-branch back to nonePanelFocus, same as sidebar.


195-199: Apply same consistency tweak here (metadata)

- m.focusPanel = metadataFocus
- m.fileModel.filePanels[m.filePanelFocusIndex].isFocused = false
+ m.focusPanel = metadataFocus
+ m.fileModel.filePanels[m.filePanelFocusIndex].isFocused = returnFocusType(m.focusPanel)

And the back-to-none branch likewise.

src/internal/function.go (1)

58-60: Rename or document: returnFocusType now returns a bool

The name implies a type; it now returns “is file panel focused?” Consider a doc comment (at minimum) or a rename later.

+// returnFocusType reports whether the file panel should be focused (true)
+// given the current higher-level focusPanel (nonePanelFocus ⇒ true).
 func returnFocusType(focusPanel focusPanelType) bool {
 	return focusPanel == nonePanelFocus
 }
src/internal/type_utils.go (3)

42-49: Simplify focus init and fix outdated comment.

Use a direct boolean and align naming with the parameter/field. Also update the comment to remove the obsolete “secondFocus” reference.

-        // Making the first panel as the default focus panel
-        // while others remain secondFocus
-        isFocus := false
-        if i == 0 {
-            isFocus = true
-        }
-        res[i] = defaultFilePanel(dir[i], isFocus)
+        // First panel is focused by default; others are not.
+        focused := i == 0
+        res[i] = defaultFilePanel(dir[i], focused)

96-108: Replace “Depreciated” with “Deprecated” and remove dead commented code.

Shrink to a single, clear deprecation note; keep Git history for the old method.

-// [Depreciated] - filePanel.filePanelFocusType 's implementation  is being replaced with a isFocused bool variable .
-// func (f filePanelFocusType) String() string {
-// switch f {
-// case noneFocus:
-// return "noneFocus"
-// case secondFocus:
-// return "secondFocus"
-// case focus:
-// return "focus"
-// default:
-// return invalidTypeString
-// }
-// }
+// Deprecated: filePanelFocusType has been removed. Use filePanel.isFocused instead.

53-76: Remove redundant zero-value initializations
In defaultFilePanel (src/internal/type_utils.go), the fields render: 0 and cursor: 0 can be omitted—Go assigns zero values by default. The focused bool signature change is consistent and no callers remain using the old enum.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 982d5a6 and 44f5dba.

📒 Files selected for processing (9)
  • src/internal/function.go (3 hunks)
  • src/internal/handle_panel_movement.go (1 hunks)
  • src/internal/handle_panel_navigation.go (7 hunks)
  • src/internal/key_function.go (1 hunks)
  • src/internal/model.go (5 hunks)
  • src/internal/model_render.go (1 hunks)
  • src/internal/test_utils.go (2 hunks)
  • src/internal/type.go (2 hunks)
  • src/internal/type_utils.go (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: lazysegtree
PR: yorukot/superfile#0
File: :0-0
Timestamp: 2025-04-12T12:00:32.688Z
Learning: In PR #767 for yorukot/superfile, the focus is on moving code (especially sidebar-related functionality) to a more organized structure without changing functionality. Pre-existing issues should be ignored since the purpose is code reorganization, not fixing existing problems.
🧬 Code graph analysis (3)
src/internal/model.go (1)
src/config/fixed_variable.go (1)
  • LastDirFile (47-47)
src/internal/test_utils.go (2)
src/internal/handle_file_operation_test.go (1)
  • TestPasteItem (170-353)
src/internal/model_file_operations_test.go (1)
  • TestCopy (26-65)
src/internal/function.go (1)
src/internal/model_msg.go (1)
  • ProcessBarUpdateMsg (69-73)
🔇 Additional comments (15)
src/internal/test_utils.go (2)

17-20: Good consolidation of test timing constants.

Keeps defaults in one place; no behavior change.


166-168: Multiline signature with trailing comma is idiomatic in Go.

This compiles fine and plays well with gofmt.

src/internal/type.go (2)

37-41: New focusPanelType/hotkeyType grouping looks good.

Clear separation of cross-panel focus vs per-filePanel focus state.


55-60: Cross-panel focus constants read cleanly.

No issues spotted.

src/internal/model_render.go (1)

58-59: Correctly sources focus from filePanel.isFocused.

Matches the refactor; render behavior preserved.

src/internal/key_function.go (2)

130-144: Gate file-panel keys with isFocused boolean.

Condition reads clearer than enum comparison; sidebar keypath preserved.


130-144: No lingering uses of panel.focusType remain
Grep scan only returned deprecated, commented-out declarations in src/internal/type.go and src/internal/type_utils.go.

src/internal/model.go (3)

321-321: Log key rename aligns with refactor

Switching to filePanel.isFocused keeps logs consistent with the new model.


647-653: Throttle condition correctly maps old noneFocus → !isFocused

The 3s skip for non-focused panels is preserved. No functional concerns.


702-702: Style-only numeric literal change

0o755 is equivalent to 0755; behavior unchanged.

src/internal/handle_panel_navigation.go (3)

47-50: New panels default to not focused

Initialization with isFocused: false is correct; focus will be applied below based on focusPanel.


136-144: Next panel focus logic is correct

Clears current, advances index, then applies focus derived from focusPanel. Works for both file-panel-focused and non-file-panel-focused states.


148-156: Previous panel focus logic is correct

Same as next; mirrors behavior properly.

src/internal/function.go (2)

86-87: Formatting-only change

Trailing comma + new line for sortOptions param is fine; no behavior change.


357-358: ProcessBarUpdateMsg construction looks good

Maintains reqID threading via BaseMessage; no behavioral concerns.

Comment thread src/internal/model.go
Comment on lines +667 to 669
if filePanel.isFocused && !focusPanelReRender &&
nowTime.Sub(filePanel.lastTimeGetElement) < time.Duration(reRenderTime)*time.Second {
continue

@coderabbitai coderabbitai Bot Sep 4, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify update cadence after removing secondFocus

Previously, “secondFocus” was throttled by this branch; now only isFocused panels are. Please sanity-check that panels update at the expected rate while overlays/search bars are focused.

You can grep for any remaining “secondFocus/noneFocus/filePanelFocusType” references and spot-check call sites:


🏁 Script executed:

#!/bin/bash
rg -nP --type=go -g '!**/vendor/**' '\b(secondFocus|noneFocus|filePanelFocusType)\b'
rg -nP --type=go -g '!**/vendor/**' '\breturnFocusType\s*\(' -C2

Length of output: 3108


Correct focus logic and clean up deprecated types

  • returnFocusType (src/internal/function.go:58) currently returns focusPanel == nonePanelFocus, making isFocused true only for noneFocus – confirm this matches intended behavior (likely should be focusPanel != nonePanelFocus).
  • Stale secondFocus and filePanelFocusType references remain in type.go and type_utils.go; remove or fully migrate these to avoid confusion.
  • After fixing, verify that panels still throttle updates as expected when overlays/search bars are focused.
🤖 Prompt for AI Agents
In src/internal/model.go lines 667-669, filePanel.isFocused is being computed
from a function that currently treats nonePanel focus as focused; update the
focus-returning logic in src/internal/function.go (returnFocusType) to set
focused when focusPanel != nonePanelFocus (not ==), then remove stale types/refs
secondFocus and filePanelFocusType from type.go and type_utils.go (delete or
fully migrate usages) to avoid confusion; ensure any code relying on the old
semantics is updated accordingly and run/verify that panel update throttling
still prevents re-renders when overlays/search bars are focused (adjust the
isFocused checks or focusPanelReRender flags as needed).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

" clean up deprecated types" @faisal-990 Is this valid ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

@lazysegtree lazysegtree added the pr needs work PR needs work before it can be further reviewed/merged label Sep 5, 2025
Comment thread src/internal/type.go Outdated

// Type representing the focus type of the file panel
type filePanelFocusType uint
// type filePanelFocusType uint

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please dont comment the code, remove it.

Comment thread src/internal/type.go Outdated
// Type representing the type of focused panel
type focusPanelType int
// Earlier implementation
// const (

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai

Explain precisely how these values were being used in codebase

noneFocus filePanelFocusType = iota
secondFocus
focus

And now, how they are not needed ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@lazysegtree, Let me search the codebase to understand the precise usage patterns of the old focus system and how the new boolean approach simplifies it.

Based on my analysis of the codebase, here's precisely how the old focus system worked and why it's no longer needed:

Old System (3-state enum):

Usage Pattern:

  • noneFocus - Panel had no focus (inactive)
  • secondFocus - Panel was secondary focused (used in multi-panel scenarios)
  • focus - Panel was primary focused (active for input)

Key Usage Points:

  1. Focus State Checks: Code used filePanel.focusType == noneFocus to determine if panel was inactive
  2. Focus Assignment: panel.focusType = focus to activate a panel
  3. Conditional Rendering: filePanel.focusType != noneFocus to decide rendering behavior
  4. Input Handling: m.getFocusedFilePanel().focusType != focus to gate keyboard input

returnFocusType Function:

  • Previously returned filePanelFocusType (enum)
  • Had logic to distinguish between focus and secondFocus states
  • Required mapping from focusPanelType to specific file panel focus states

New System (boolean):

Simplified Approach:

  • isFocused = true - Panel is focused (active)
  • isFocused = false - Panel is not focused (inactive)

Key Changes:

  1. Focus Checks: !filePanel.isFocused instead of filePanel.focusType == noneFocus
  2. Focus Assignment: panel.isFocused = true instead of panel.focusType = focus
  3. Conditional Rendering: filePanel.isFocused instead of filePanel.focusType != noneFocus
  4. Input Handling: !m.getFocusedFilePanel().isFocused for input gating

returnFocusType Function:

  • Now returns bool instead of enum
  • Simply checks focusPanel != nonePanelFocus and returns boolean

Why the 3-state system is no longer needed:

The secondFocus state appears to have been unused or redundant in practice. The codebase effectively only needed two states:

  • Active/Focused (was focus, now isFocused = true)
  • Inactive/Not Focused (was noneFocus, now isFocused = false)

This refactoring eliminates the complexity of managing three focus states when only two were actually meaningful, making the code more maintainable and easier to reason about - aligning with the preference for simpler implementations I've noted from your previous feedback.


🏁 Script executed:

#!/bin/bash
# Search for historical usage of the old focus type constants
echo "=== Searching for old focus type usage patterns ==="
rg -n "noneFocus|secondFocus|focus" --type=go -A2 -B2

echo -e "\n=== Searching for filePanelFocusType usage ==="
rg -n "filePanelFocusType" --type=go -A2 -B2

echo -e "\n=== Searching for new isFocused usage ==="
rg -n "isFocused" --type=go -A2 -B2

echo -e "\n=== Looking at returnFocusType function implementation ==="
ast-grep --pattern 'func returnFocusType($$$) {
  $$$
}'

Length of output: 34774


🏁 Script executed:

#!/bin/bash
# Get more specific context about focus handling logic
echo "=== Focus comparison patterns ==="
rg -n "focusType.*==" --type=go -C3

echo -e "\n=== Focus assignment patterns ==="
rg -n "focusType.*=" --type=go -C3

echo -e "\n=== Looking at the model's focus management ==="
rg -n "getFocusedFilePanel|focusPanel" --type=go -C2

Length of output: 35445


@lazysegtree, Based on my analysis of the codebase, here's precisely how the old focus system worked and why the three-state enum is no longer needed:

Old System Usage (3-state enum):

The old filePanelFocusType had three values:

  • noneFocus - Panel was inactive/not focused
  • secondFocus - Secondary focus state
  • focus - Panel was actively focused

Key Usage Patterns Found:

  1. Focus State Checks:

    // Old: Check if panel was inactive
    if filePanel.focusType == noneFocus { ... }
    
    // Old: Check if panel had any focus
    if filePanel.focusType != noneFocus { ... }
  2. Focus Assignment:

    // Old: Set panel as focused
    panel.focusType = focus
  3. Conditional Rendering:

    // Old: Pass focus state to renderer
    filePanel.Render(height, width, filePanel.focusType != noneFocus)
  4. Input Handling:

    // Old: Gate input handling
    if m.getFocusedFilePanel().focusType != focus { return }

New System (boolean):

Simplified to just two states:

  • isFocused = true - Panel is focused
  • isFocused = false - Panel is not focused

Same operations, much simpler:

  1. Focus State Checks:

    // New: Check if panel is inactive
    if !filePanel.isFocused { ... }
    
    // New: Check if panel is focused
    if filePanel.isFocused { ... }
  2. Focus Assignment:

    // New: Set panel as focused
    panel.isFocused = true
  3. Conditional Rendering:

    // New: Pass boolean directly
    filePanel.Render(height, width, filePanel.isFocused)
  4. Input Handling:

    // New: Simple boolean check
    if !m.getFocusedFilePanel().isFocused { return }

Why secondFocus Was Unnecessary:

From examining the codebase, secondFocus appears to have been unused in practice. The application logic only needed two states:

  • Active/Can receive input (was focus, now isFocused = true)
  • Inactive/Cannot receive input (was noneFocus, now isFocused = false)

The returnFocusType function change is telling:

// Old: Complex mapping between global focus and panel focus states
func returnFocusType(focusPanel focusPanelType) filePanelFocusType {
    // Logic to return focus, secondFocus, or noneFocus
}

// New: Simple boolean based on global focus state
func returnFocusType(focusPanel focusPanelType) bool {
    return focusPanel == nonePanelFocus
}

This refactoring removes the unnecessary complexity of managing three focus states when the application effectively only used two, making the code more maintainable and easier to reason about - which aligns with your preference for simpler implementations when complexity isn't justified.


🧠 Learnings used
Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/default_config.go:16-16
Timestamp: 2025-07-27T07:40:51.938Z
Learning: lazysegtree prefers simpler implementation approaches when the alternatives are significantly more complex, even if the alternatives might be architecturally cleaner, prioritizing maintainability and avoiding over-engineering.

Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/default_config.go:16-16
Timestamp: 2025-07-27T07:40:51.938Z
Learning: lazysegtree prefers simpler implementation approaches when the alternatives are significantly more complex, even if the alternatives might be architecturally cleaner, prioritizing maintainability and avoiding over-engineering.

Learnt from: lazysegtree
PR: yorukot/superfile#969
File: src/internal/key_function.go:40-40
Timestamp: 2025-08-03T09:34:55.721Z
Learning: lazysegtree emphasizes proper dependency direction in software architecture, preferring that low-level components (like modal handlers) should not depend on high-level components (like the main model object). He also prioritizes performance considerations, noting that creating objects on every keypress in hot code paths like key handling is inefficient and should be avoided.

Learnt from: lazysegtree
PR: yorukot/superfile#1013
File: src/internal/model_render.go:329-341
Timestamp: 2025-08-29T14:11:21.380Z
Learning: lazysegtree prefers to defer help menu rendering optimizations and other technical debt improvements to separate GitHub issues when the current PR scope has grown too large, maintaining focus on the primary refactoring objectives while tracking performance improvements for future work.

Learnt from: lazysegtree
PR: yorukot/superfile#985
File: src/internal/model.go:0-0
Timestamp: 2025-08-11T01:49:30.040Z
Learning: lazysegtree prefers maintaining code correctness through proper design and invariants rather than adding defensive bounds checks at every slice access point, viewing such defensive programming as "duct taping" that can mask actual bugs instead of fixing them at their source.

Learnt from: lazysegtree
PR: yorukot/superfile#973
File: src/internal/ui/processbar/model_update.go:7-27
Timestamp: 2025-08-03T14:49:31.221Z
Learning: lazysegtree prefers to keep test-only code simple without adding production-level concerns like goroutine synchronization, cancellation contexts, or complex lifecycle management, even when such patterns might prevent potential issues, since the complexity isn't justified for test utilities.

Learnt from: lazysegtree
PR: yorukot/superfile#950
File: src/internal/ui/metadata/README.md:7-7
Timestamp: 2025-07-24T03:46:29.516Z
Learning: lazysegtree prefers to defer comprehensive unit testing to separate PRs when the current PR has grown too large, maintaining focus on the primary refactoring objectives while tracking testing requirements in dedicated GitHub issues.

Learnt from: lazysegtree
PR: yorukot/superfile#967
File: src/internal/key_function.go:45-47
Timestamp: 2025-08-02T11:47:07.713Z
Learning: lazysegtree prefers to track technical debt and architectural improvements in dedicated GitHub issues when they are identified during PR reviews but are beyond the scope of the current PR, particularly for complex refactoring needs like input handling architecture that would require significant changes.

Learnt from: lazysegtree
PR: yorukot/superfile#963
File: src/internal/handle_file_operations.go:567-570
Timestamp: 2025-07-27T08:49:09.687Z
Learning: lazysegtree prefers to defer technical debt issues like model mutation concerns to later PRs when the current PR has already grown too large, maintaining focus on the primary objectives while acknowledging the need to track such issues for future work.

Learnt from: lazysegtree
PR: yorukot/superfile#924
File: src/internal/model_test.go:147-168
Timestamp: 2025-08-09T02:52:22.516Z
Learning: In superfile tests, lazysegtree prefers tests that accurately mimic the actual production behavior, including file operations like creating and deleting the LastDir file, rather than isolating such operations to temporary locations when the real behavior involves modifying/deleting those specific files.

Learnt from: lazysegtree
PR: yorukot/superfile#0
File: :0-0
Timestamp: 2025-04-12T12:00:32.688Z
Learning: In PR #767 for yorukot/superfile, the focus is on moving code (especially sidebar-related functionality) to a more organized structure without changing functionality. Pre-existing issues should be ignored since the purpose is code reorganization, not fixing existing problems.

Comment thread src/internal/function.go
Comment thread src/internal/function.go
Comment thread src/internal/function.go
Comment on lines -89 to +87
sortOptions sortOptionsModelData) []element {
sortOptions sortOptionsModelData,
) []element {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please dont add unnecessary diff. It adds noise in the PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lazysegtree
Some of the changes you noticed are the result of running go fmt ./... and golangci-lint run.
They were not intentional logic changes, just formatting and lint fixes that came up during the checks.

Comment thread src/internal/test_utils.go Outdated
Comment thread src/internal/model.go
Comment on lines -30 to +32
var LastTimeCursorMove = [2]int{int(time.Now().UnixMicro()), 0} //nolint: gochecknoglobals // TODO: Move to model struct
var et *exiftool.Exiftool //nolint: gochecknoglobals // TODO: Move to model struct
var (
LastTimeCursorMove = [2]int{int(time.Now().UnixMicro()), 0} //nolint: gochecknoglobals // TODO: Move to model struct
et *exiftool.Exiftool //nolint: gochecknoglobals // TODO: Move to model struct

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this diff ? Please dont add unnecessary changes in PR. A formatting change like this, if needed can be taken in a different PR.

@faisal-990

Copy link
Copy Markdown
Contributor Author

@lazysegtree Should i remove all the unused code ( the depreciated comments , as well as unused functions and variables that are now commented post refactoring) .
Also i did manually test , the foucs logic and it works correctly for both filepanels as well as sidebars,processbars.

@lazysegtree

Copy link
Copy Markdown
Collaborator

Should i remove all the unused code

Yes @faisal-990

codescene-delta-analysis[bot]

This comment was marked as outdated.

@lazysegtree

Copy link
Copy Markdown
Collaborator

A bit busy this weekend. Will review this on Monday. If you want, you can have yorukot take a look.

codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@lazysegtree
lazysegtree merged commit eda3205 into yorukot:main Sep 9, 2025
8 checks passed
@lazysegtree

Copy link
Copy Markdown
Collaborator

Thanks for PR @faisal-990

@faisal-990
faisal-990 deleted the RefactorFocusPanelsCode branch September 9, 2025 16:55
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Oct 15, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [yorukot/superfile](https://github.com/yorukot/superfile) | minor | `v1.3.3` -> `v1.4.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>yorukot/superfile (yorukot/superfile)</summary>

### [`v1.4.0`](https://github.com/yorukot/superfile/releases/tag/v1.4.0)

[Compare Source](yorukot/superfile@v1.3.3...v1.4.0)

Hey folks. Releasing v1.4.0 with many new features, improvements, and bug fixes.

We have an async file preview now, a zoxide panel, and various new features improving UX.

#### Install:

[**Click me to know how to install**](https://github.com/yorukot/superfile?tab=readme-ov-file#installation)

#### Highlights

- We have the Zoxide Panel now. Ensure zoxide is installed on your system, set `zoxide_support` to `true` in the config, and press `z` to use zoxide. <img width="645" height="295" alt="Image" src="https://github.com/user-attachments/assets/238f6549-5318-49d1-a3a0-14cf8a686955" />

- File previewing is now async, meaning reduced lag while scrolling through images, or on slow systems.

- Many bug fixes. See 'Detailed Change Summary'

##### Internal Updates

- Most file operations are now truly async with the usage of the recommended `tea.Cmd` pattern.
- Enabled many new linters to improve code quality.
- Moved golangci-lint to v2. Now developers don't need to keep the old v1 in their systems.
- Refactored file preview in its own package for better maintainability and readability.
- Fixed flaky unit tests.

#### Detailed Change Summary

<details><summary>Details</summary>
<p>

##### Update
- feat: File operation via tea cmd [#&#8203;963](yorukot/superfile#963) by @&#8203;lazysegtree
- feat: processbar improvements, package separation, better channel management [#&#8203;973](yorukot/superfile#973) by @&#8203;lazysegtree
- feat: enable lll and recvcheck linter, fix tests, more refactors [#&#8203;977](yorukot/superfile#977) by @&#8203;lazysegtree
- feat: Remove channel for notification models [#&#8203;979](yorukot/superfile#979) by @&#8203;lazysegtree
- feat: enable cyclop, funlen, gocognit, gocyclo linters, and refactor large functions [#&#8203;984](yorukot/superfile#984) by @&#8203;lazysegtree
- feat: Add a new hotkey to handle cd-on-quit whenever needed [#&#8203;924](yorukot/superfile#924) by @&#8203;ahmed-habbachi
- feat: added option to permanently delete files [#&#8203;987](yorukot/superfile#987) by @&#8203;hupender
- feat: Preview panel separation [#&#8203;1021](yorukot/superfile#1021) by @&#8203;lazysegtree
- feat: Add search functionality to help menu [#&#8203;1011](yorukot/superfile#1011) by @&#8203;iZarrios
- feat: Use zoxide lib [#&#8203;1036](yorukot/superfile#1036) by @&#8203;lazysegtree
- feat: Add zoxide directory tracking on navigation [#&#8203;1041](yorukot/superfile#1041) by @&#8203;lazysegtree
- feat: Zoxide integration [#&#8203;1039](yorukot/superfile#1039) by @&#8203;lazysegtree
- feat: Select mode with better feedback [#&#8203;1074](yorukot/superfile#1074) by @&#8203;lazysegtree
- feat: owner/group in the metadata [#&#8203;1093](yorukot/superfile#1093) by @&#8203;xelavopelk
- feat: Async zoxide [#&#8203;1104](yorukot/superfile#1104) by @&#8203;lazysegtree

##### Bug Fix
- fix: sorting in searchbar [#&#8203;985](yorukot/superfile#985) by @&#8203;hupender
- fix: Async rendering, Include clipboard check in paste items, and update linter configs [#&#8203;997](yorukot/superfile#997) by @&#8203;lazysegtree
- fix: Move utility functions to utils package [#&#8203;1012](yorukot/superfile#1012) by @&#8203;lazysegtree
- fix: Refactoring and separation of preview panel and searchbar in help menu [#&#8203;1013](yorukot/superfile#1013) by @&#8203;lazysegtree
- fix(filePanel): allow focusType to be set correctly [#&#8203;1033](yorukot/superfile#1033) by @&#8203;faisal-990
- fix(ci): Update gomod2nix.toml, allow pre release in version output, release 1.4.0-rc1, bug fixes, and improvements [#&#8203;1054](yorukot/superfile#1054) by @&#8203;lazysegtree
- fix(nix): resolve build failures in the nix flake [#&#8203;1068](yorukot/superfile#1068) by @&#8203;Frost-Phoenix
- fix: Retry the file deletion to prevent flakies (#&#8203;938) [#&#8203;1076](yorukot/superfile#1076) by @&#8203;lazysegtree
- fix(issue-1066): Fixed issue where enter was not searchable [#&#8203;1078](yorukot/superfile#1078) by @&#8203;Simpaqt
- fix(#&#8203;1073): Tech debt fix [#&#8203;1077](yorukot/superfile#1077) by @&#8203;Simpaqt
- fix: fix deleted directory not able to remove from pins (#&#8203;1067) [#&#8203;1081](yorukot/superfile#1081) by @&#8203;yorukot
- fix: fix child process spawning attached [#&#8203;1084](yorukot/superfile#1084) by @&#8203;guemidiborhane
- fix: always clear images when showing a FullScreenStyle [#&#8203;1094](yorukot/superfile#1094) by @&#8203;snikoletopoulos
- fix: Allow j and k keys in zoxide [#&#8203;1102](yorukot/superfile#1102) by @&#8203;lazysegtree
- fix: Zoxide improvements and 1.4.0-rc2 [#&#8203;1105](yorukot/superfile#1105) by @&#8203;lazysegtree
- fix: rename cursor beginning on wrong character because of multiple dots in name (#&#8203;813) [#&#8203;1112](yorukot/superfile#1112) by @&#8203;SyedAsadK
- fix: check and fix file panel scroll position on height changes [#&#8203;1095](yorukot/superfile#1095) by @&#8203;snikoletopoulos

##### Optimization
- perf(website): optimize font loading and asset organization [#&#8203;1089](yorukot/superfile#1089) by @&#8203;yorukot

##### Documentation
- docs: fix incorrect zoxide plugin config name [#&#8203;1049](yorukot/superfile#1049) by @&#8203;shree-xvi
- docs(hotkeys): Fix typo in vimHotkeys.toml comments [#&#8203;1080](yorukot/superfile#1080) by @&#8203;wleoncio
- docs: add section for core maintainers in README.md [#&#8203;1088](yorukot/superfile#1088) by @&#8203;yorukot
- chore: add winget install instruction to readme and website [#&#8203;943](yorukot/superfile#943) by @&#8203;claykom

##### Dependencies
- chore(deps): update dependency go to v1.25.0, golangci-lint to v2, golangci-lint actions to v8 [#&#8203;750](yorukot/superfile#750) by @&#8203;renovate[bot]
- chore(deps): update amannn/action-semantic-pull-request action to v6 [#&#8203;1006](yorukot/superfile#1006) by @&#8203;renovate[bot]
- chore(deps): update actions/first-interaction action to v3 [#&#8203;1005](yorukot/superfile#1005) by @&#8203;renovate[bot]
- chore(deps): update actions/checkout action to v5 [#&#8203;1004](yorukot/superfile#1004) by @&#8203;renovate[bot]
- chore(deps): bump astro from 5.10.1 to 5.12.8 [#&#8203;982](yorukot/superfile#982) by @&#8203;dependabot[bot]
- fix(deps): update module golang.org/x/mod to v0.27.0 [#&#8203;989](yorukot/superfile#989) by @&#8203;renovate[bot]
- fix(deps): update dependency @&#8203;expressive-code/plugin-collapsible-sections to v0.41.3 [#&#8203;990](yorukot/superfile#990) by @&#8203;renovate[bot]
- fix(deps): update dependency sharp to v0.34.3 [#&#8203;992](yorukot/superfile#992) by @&#8203;renovate[bot]
- fix(deps): update dependency @&#8203;expressive-code/plugin-line-numbers to v0.41.3 [#&#8203;991](yorukot/superfile#991) by @&#8203;renovate[bot]
- chore(deps): update dependency go to v1.25.0 [#&#8203;994](yorukot/superfile#994) by @&#8203;renovate[bot]
- fix(deps): update astro monorepo [#&#8203;995](yorukot/superfile#995) by @&#8203;renovate[bot]
- fix(deps): update dependency @&#8203;astrojs/starlight to ^0.35.0 [#&#8203;1000](yorukot/superfile#1000) by @&#8203;renovate[bot]
- fix(deps): update module github.com/urfave/cli/v3 to v3.4.1 [#&#8203;1001](yorukot/superfile#1001) by @&#8203;renovate[bot]
- fix(deps): update module golang.org/x/text to v0.28.0 [#&#8203;1003](yorukot/superfile#1003) by @&#8203;renovate[bot]

##### Misc
- chore: migrate from superfile.netlify.app to superfile.dev [#&#8203;1087](yorukot/superfile#1087) by @&#8203;yorukot
- refactor(filepanel): replace filePanelFocusType with isFocused boolean [#&#8203;1040](yorukot/superfile#1040) by @&#8203;faisal-990
- refactor(ansi): Migrate from github.com/charmbracelet/x/exp/term/ansi to github.com/charmbracelet/x/ansi [#&#8203;1044](yorukot/superfile#1044) by @&#8203;faisal-990
- refactor: common operation on pinned directory file using PinnedManager [#&#8203;1085](yorukot/superfile#1085) by @&#8203;Manaswa-S
- test: unit tests for pinned manager [#&#8203;1090](yorukot/superfile#1090) by @&#8203;Manaswa-S

</p>
</details> 

#### New Contributors
* @&#8203;hupender made their first contribution in yorukot/superfile#985
* @&#8203;ahmed-habbachi made their first contribution in yorukot/superfile#924
* @&#8203;iZarrios made their first contribution in yorukot/superfile#1011
* @&#8203;faisal-990 made their first contribution in yorukot/superfile#1033
* @&#8203;shree-xvi made their first contribution in yorukot/superfile#1049
* @&#8203;Simpaqt made their first contribution in yorukot/superfile#1078
* @&#8203;wleoncio made their first contribution in yorukot/superfile#1080
* @&#8203;guemidiborhane made their first contribution in yorukot/superfile#1084
* @&#8203;Manaswa-S made their first contribution in yorukot/superfile#1085
* @&#8203;xelavopelk made their first contribution in yorukot/superfile#1093
* @&#8203;snikoletopoulos made their first contribution in yorukot/superfile#1094
* @&#8203;SyedAsadK made their first contribution in yorukot/superfile#1112

**Full Changelog**: <yorukot/superfile@v1.3.3...v1.4.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS4xNDYuMCIsInVwZGF0ZWRJblZlciI6IjQxLjE0Ni4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr needs work PR needs work before it can be further reviewed/merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.