|
38 | 38 | // is passed to tea.NewProgram() which accepts tea.Model |
39 | 39 | // Either way type 'model' is not exported, so there is not way main package can |
40 | 40 | // be aware of it, and use it directly |
41 | | -func InitialModel(firstFilePanelDirs []string, firstUseCheck bool) tea.Model { |
42 | | - toggleDotFile, toggleFooter, zClient := initialConfig(firstFilePanelDirs) |
43 | | - return defaultModelConfig(toggleDotFile, toggleFooter, firstUseCheck, firstFilePanelDirs, zClient) |
| 41 | +func InitialModel(firstPanelPaths []string, firstUseCheck bool) tea.Model { |
| 42 | + toggleDotFile, toggleFooter, zClient := initialConfig(firstPanelPaths) |
| 43 | + return defaultModelConfig(toggleDotFile, toggleFooter, firstUseCheck, firstPanelPaths, zClient) |
44 | 44 | } |
45 | 45 |
|
46 | 46 | // Init function to be called by Bubble tea framework, sets windows title, |
@@ -698,50 +698,82 @@ func getMaxW(s string) int { |
698 | 698 | func (m *model) getFilePanelItems() { |
699 | 699 | focusPanel := m.fileModel.filePanels[m.filePanelFocusIndex] |
700 | 700 | for i, filePanel := range m.fileModel.filePanels { |
701 | | - var fileElement []element |
702 | 701 | nowTime := time.Now() |
703 | | - // Check last time each element was updated, if less then 3 seconds ignore |
704 | | - if !filePanel.isFocused && nowTime.Sub(filePanel.lastTimeGetElement) < 3*time.Second { |
705 | | - // TODO : revisit this. This feels like a duct tape solution of an actual |
706 | | - // deep rooted problem. This feels very hacky. |
707 | | - if !m.updatedToggleDotFile { |
708 | | - continue |
709 | | - } |
710 | | - } |
711 | | - |
712 | | - focusPanelReRender := false |
713 | | - |
714 | | - if len(focusPanel.element) > 0 { |
715 | | - if filepath.Dir(focusPanel.element[0].location) != focusPanel.location { |
716 | | - focusPanelReRender = true |
717 | | - } |
718 | | - } else { |
719 | | - focusPanelReRender = true |
720 | | - } |
721 | | - |
722 | | - reRenderTime := int(float64(len(filePanel.element)) / 100) |
723 | | - |
724 | | - if filePanel.isFocused && !focusPanelReRender && |
725 | | - nowTime.Sub(filePanel.lastTimeGetElement) < time.Duration(reRenderTime)*time.Second { |
| 702 | + if m.shouldSkipPanelUpdate(filePanel, focusPanel, nowTime) { |
726 | 703 | continue |
727 | 704 | } |
728 | 705 |
|
729 | | - // Get file names based on search bar filter |
730 | | - if filePanel.searchBar.Value() != "" { |
731 | | - fileElement = returnDirElementBySearchString(filePanel.location, m.toggleDotFile, |
732 | | - filePanel.searchBar.Value(), filePanel.sortOptions.data) |
733 | | - } else { |
734 | | - fileElement = returnDirElement(filePanel.location, m.toggleDotFile, filePanel.sortOptions.data) |
735 | | - } |
| 706 | + // Load elements for this panel (with/without search filter) |
| 707 | + fileElement := m.getElementsForPanel(filePanel) |
| 708 | + |
736 | 709 | // Update file panel list |
737 | | - filePanel.element = fileElement |
738 | 710 | m.fileModel.filePanels[i].element = fileElement |
739 | 711 | m.fileModel.filePanels[i].lastTimeGetElement = nowTime |
| 712 | + |
| 713 | + // Position cursor on target file when provided |
| 714 | + m.applyTargetFileCursor(i, fileElement) |
740 | 715 | } |
741 | 716 |
|
742 | 717 | m.updatedToggleDotFile = false |
743 | 718 | } |
744 | 719 |
|
| 720 | +// Helper to decide whether to skip updating a panel this tick. |
| 721 | +func (m *model) shouldSkipPanelUpdate(filePanel filePanel, focusPanel filePanel, nowTime time.Time) bool { |
| 722 | + // Throttle non-focused panels unless dotfile toggle changed |
| 723 | + if !filePanel.isFocused && nowTime.Sub(filePanel.lastTimeGetElement) < 3*time.Second { |
| 724 | + if !m.updatedToggleDotFile { |
| 725 | + return true |
| 726 | + } |
| 727 | + } |
| 728 | + |
| 729 | + focusPanelReRender := m.focusPanelNeedsReRender(focusPanel) |
| 730 | + reRenderTime := int(float64(len(filePanel.element)) / 100) |
| 731 | + if filePanel.isFocused && !focusPanelReRender && |
| 732 | + nowTime.Sub(filePanel.lastTimeGetElement) < time.Duration(reRenderTime)*time.Second { |
| 733 | + return true |
| 734 | + } |
| 735 | + return false |
| 736 | +} |
| 737 | + |
| 738 | +// Checks whether the focus panel directory changed and forces a re-render. |
| 739 | +func (m *model) focusPanelNeedsReRender(focusPanel filePanel) bool { |
| 740 | + if len(focusPanel.element) > 0 { |
| 741 | + return filepath.Dir(focusPanel.element[0].location) != focusPanel.location |
| 742 | + } |
| 743 | + return true |
| 744 | +} |
| 745 | + |
| 746 | +// Retrieves elements for a panel based on search bar value and sort options. |
| 747 | +func (m *model) getElementsForPanel(filePanel filePanel) []element { |
| 748 | + if filePanel.searchBar.Value() != "" { |
| 749 | + return returnDirElementBySearchString( |
| 750 | + filePanel.location, |
| 751 | + m.toggleDotFile, |
| 752 | + filePanel.searchBar.Value(), |
| 753 | + filePanel.sortOptions.data, |
| 754 | + ) |
| 755 | + } |
| 756 | + return returnDirElement(filePanel.location, m.toggleDotFile, filePanel.sortOptions.data) |
| 757 | +} |
| 758 | + |
| 759 | +// Applies targetFile cursor positioning, if configured for the panel. |
| 760 | +func (m *model) applyTargetFileCursor(panelIndex int, elements []element) { |
| 761 | + if tf := m.fileModel.filePanels[panelIndex].targetFile; tf == "" { |
| 762 | + return |
| 763 | + } else { |
| 764 | + for idx, el := range elements { |
| 765 | + if el.name == tf { |
| 766 | + m.fileModel.filePanels[panelIndex].cursor = idx |
| 767 | + if idx > 0 { |
| 768 | + m.fileModel.filePanels[panelIndex].render = idx - 1 |
| 769 | + } |
| 770 | + break |
| 771 | + } |
| 772 | + } |
| 773 | + m.fileModel.filePanels[panelIndex].targetFile = "" |
| 774 | + } |
| 775 | +} |
| 776 | + |
745 | 777 | // Close superfile application. Cd into the current dir if CdOnQuit on and save |
746 | 778 | // the path in state direcotory |
747 | 779 | func (m *model) quitSuperfile(cdOnQuit bool) { |
|
0 commit comments