Skip to content

feat: Metadata panel into separate package, UI bug fixes, Code improvements #950

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jul 24, 2025

Conversation

lazysegtree
Copy link
Collaborator

@lazysegtree lazysegtree commented Jul 20, 2025

Also fixes

Related issues

Summary by CodeRabbit

  • New Features

    • Introduced a dedicated metadata panel with enhanced file information display and cyclic navigation.
    • Added extended metadata extraction including symbolic link status, directory size, and MD5 checksums.
  • Refactor

    • Centralized metadata management and rendering into a new metadata module for improved maintainability.
    • Updated metadata panel resizing and navigation for consistent user interaction.
    • Removed legacy metadata utilities and replaced with new structured metadata handling.
  • Bug Fixes

    • Improved error messages and handling during metadata extraction and display.
  • Documentation

    • Added comprehensive README for the metadata module with usage and testing guidance.
  • Tests

    • Added tests verifying metadata navigation behavior and metadata extraction correctness.
  • Chores

    • Updated CI workflow to install exiftool on Linux runners for metadata extraction support.

Copy link
Contributor

coderabbitai bot commented Jul 20, 2025

Warning

Rate limit exceeded

@lazysegtree has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 20 minutes and 54 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 829dc6a and 98b2dbe.

📒 Files selected for processing (2)
  • src/internal/ui/metadata/metadata.go (1 hunks)
  • src/internal/ui/metadata/utils.go (1 hunks)

Walkthrough

This change refactors file metadata handling by removing internal metadata utility functions and types, and introducing a new metadata package with its own Model and supporting utilities. The main application now delegates metadata extraction, navigation, and rendering to this externalized package, updating method calls and struct fields accordingly. Associated tests and documentation are updated or added.

Changes

Files / Groups Change Summary
src/internal/default_config.go Imports new metadata package and initializes fileMetaData using metadata.New() in the model config.
src/internal/function.go Removes all internal metadata utility functions and related imports.
src/internal/handle_panel_up_down.go, src/internal/handle_panel_up_down_test.go Removes fileMetadata navigation methods and their tests.
src/internal/key_function.go, src/internal/wheel_function.go Updates method calls to new ListUp/ListDown and removes direct render index resets.
src/internal/model.go Refactors to use new metadata.Metadata and metadata.Model, updates metadata handling and rendering logic.
src/internal/model_render.go Removes old metadata rendering logic and helper functions.
src/internal/type.go Removes internal fileMetadata type and related fields; updates model struct to use metadata.Model.
src/internal/ui/metadata/README.md Adds documentation for the new metadata package.
src/internal/ui/metadata/metadata.go Introduces new metadata extraction logic and data structures.
src/internal/ui/metadata/model.go Adds new Model type for metadata panel state and rendering.
src/internal/ui/metadata/model_test.go Adds tests for Model navigation methods.
src/internal/ui/metadata/utils.go Adds utility functions for formatting and rendering metadata.
src/internal/utils/file_utils.go Adds new file system utility functions for directory size and MD5 checksum calculation.
.github/workflows/superfile-build-test.yml Adds exiftool installation step on Linux runners in CI workflow.
src/internal/ui/metadata/const.go Adds constants for metadata keys, error messages, and sorting priorities.
src/internal/ui/metadata/metadata_test.go Adds tests for metadata extraction function.
src/internal/ui/metadata/testdata/file1.txt Adds test data file for metadata tests.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MainModel
    participant MetadataModel
    participant MetadataPkg

    User->>MainModel: Selects file / requests metadata
    MainModel->>MetadataPkg: GetMetadata(filePath, ...)
    MetadataPkg->>MetadataPkg: Extract & sort metadata
    MetadataPkg-->>MainModel: Return Metadata struct
    MainModel->>MetadataModel: SetMetadata(Metadata)
    User->>MainModel: Navigates metadata panel (up/down)
    MainModel->>MetadataModel: ListUp() / ListDown()
    MainModel->>MetadataModel: Render(focused)
    MetadataModel-->>MainModel: Rendered string
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~90 minutes

Suggested labels

refactoring, new feature

Suggested reviewers

  • yorukot

Poem

A hop and a skip, the metadata's new,
Old code is gone, replaced with a view!
With panels that scroll and info that shines,
Now handled by models with orderly lines.
From symlinks to checksums, all neat in a row,
This bunny approves—let the metadata flow!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch metadata_separation

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@lazysegtree lazysegtree marked this pull request as draft July 20, 2025 02:23
@lazysegtree lazysegtree changed the base branch from async-rendering to main July 21, 2025 03:08
@lazysegtree lazysegtree force-pushed the metadata_separation branch from a9d08ec to c20f5e6 Compare July 23, 2025 17:29
@lazysegtree lazysegtree mentioned this pull request Jul 23, 2025
@lazysegtree lazysegtree marked this pull request as ready for review July 23, 2025 17:32
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (9)
src/internal/ui/metadata/README.md (1)

16-19: Fix the placeholder path and incomplete coverage information.

The coverage section contains a placeholder path and incomplete coverage information.

Apply this diff to fix the issues:

-cd /path/to/ui/metadata
+cd src/internal/ui/metadata
 go test -cover
-```
-Current coverage is .
+```
+
+Current coverage: Run `go test -cover` to see current coverage.
src/internal/ui/metadata/model_test.go (1)

17-17: Fix typo in test struct field name.

There's a typo in the struct field name expectedRendeIndex - it should be expectedRenderIndex to match the actual field name in the Model struct.

Apply this diff to fix the typo:

-		expectedRendeIndex int
+		expectedRenderIndex int

And update all references:

-			expectedRendeIndex: 1,
+			expectedRenderIndex: 1,
-			expectedRendeIndex: 0,
+			expectedRenderIndex: 0,
-			expectedRendeIndex: 3,
+			expectedRenderIndex: 3,
-			expectedRendeIndex: 4,
+			expectedRenderIndex: 4,
-			assert.Equal(t, tt.expectedRendeIndex, tt.m.renderIndex)
+			assert.Equal(t, tt.expectedRenderIndex, tt.m.renderIndex)

Also applies to: 26-26, 35-35, 44-44, 53-53, 64-64

src/internal/utils/file_utils.go (2)

205-226: LGTM! Well-implemented directory size calculation.

The function properly:

  • Uses filepath.WalkDir for efficient directory traversal
  • Handles errors gracefully with logging
  • Accumulates file sizes correctly
  • Continues processing despite individual file errors

The TODO comment indicates unit tests are needed - consider prioritizing this for such a utility function.


228-243: LGTM! Solid MD5 checksum implementation.

The function demonstrates good practices:

  • Proper error handling with wrapped errors
  • Correct use of defer for file cleanup
  • Standard library usage for hash calculation
  • Clear and readable implementation

The TODO comment indicates unit tests are needed - this would be valuable for ensuring correctness across different file types and edge cases.

src/internal/ui/metadata/model.go (2)

25-30: Consider implementing dimension validation as indicated by TODO.

The TODO comment suggests validating that dimensions are at least 2x2, which would prevent potential rendering issues with border and content display.

Consider adding the validation:

 func (m *Model) SetDimensions(width int, height int) {
+	if width < 2 || height < 2 {
+		// Log warning or set minimum dimensions
+		return
+	}
 	m.width = width
 	m.height = height
 }

32-37: Fix typo in method name.

Method name SetMedatada should be SetMetadata (missing 't').

-func (m *Model) SetMedatada(metadata Metadata) {
+func (m *Model) SetMetadata(metadata Metadata) {

The logic for updating metadata and resetting render index when invalid is correct.

src/internal/model.go (3)

61-65: Update the outdated comment to reflect the new structure.

The comment "Path of the file whose metadata is this" is no longer accurate since the path is now encapsulated within the metadata.Metadata type.

 type MetadataMsg struct {
-	// Path of the file whose metadata is this
 	metadata metadata.Metadata
 	reqID    int
 }

147-150: Consider implementing the metadata fetch optimization mentioned in TODOs.

The TODO comments raise valid performance concerns about unnecessary metadata fetches during scrolling. This could impact user experience with frequent metadata updates.

Would you like me to open an issue to track implementing a smarter metadata fetch strategy that avoids updates during rapid scrolling?


118-121: Consider moving this logic as suggested by the TODO.

The metadata render reset logic is functional but could be better organized in a utility function for cleaner separation of concerns.

Would you like me to suggest a utility function structure for managing panel focus state changes?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 29dc4d0 and c20f5e6.

📒 Files selected for processing (15)
  • src/internal/default_config.go (2 hunks)
  • src/internal/function.go (0 hunks)
  • src/internal/handle_panel_up_down.go (0 hunks)
  • src/internal/handle_panel_up_down_test.go (0 hunks)
  • src/internal/key_function.go (2 hunks)
  • src/internal/model.go (8 hunks)
  • src/internal/model_render.go (0 hunks)
  • src/internal/type.go (2 hunks)
  • src/internal/ui/metadata/README.md (1 hunks)
  • src/internal/ui/metadata/metadata.go (1 hunks)
  • src/internal/ui/metadata/model.go (1 hunks)
  • src/internal/ui/metadata/model_test.go (1 hunks)
  • src/internal/ui/metadata/utils.go (1 hunks)
  • src/internal/utils/file_utils.go (2 hunks)
  • src/internal/wheel_function.go (2 hunks)
🧠 Learnings (10)
📓 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.
Learnt from: lazysegtree
PR: yorukot/superfile#0
File: :0-0
Timestamp: 2025-04-12T12:25:06.352Z
Learning: PR #770 "Sidebar code separation" is a refactoring and code reorganization effort with no new features. It involves moving code, updating import paths, renaming functions to follow PascalCase convention, and consolidating sidebar-related functionality into a dedicated package.
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/ui/sidebar/render.go:46-48
Timestamp: 2025-04-28T03:48:46.327Z
Learning: The user (lazysegtree) prefers to keep PRs focused and manageable in size, sometimes intentionally leaving TODO comments to track minor issues for later PRs rather than addressing everything at once.
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/model_render.go:254-256
Timestamp: 2025-04-28T04:27:33.074Z
Learning: When race conditions or other issues that are unrelated to the current PR's focus are identified during review, lazysegtree prefers creating separate GitHub issues to track them rather than addressing them in the current PR. This helps maintain PR focus and scope.
Learnt from: lazysegtree
PR: yorukot/superfile#906
File: src/internal/file_panel.go:11-14
Timestamp: 2025-07-12T05:32:53.131Z
Learning: lazysegtree is concerned about the efficiency impact of adding bounds checking to frequently called methods like getSelectedItem() in file panels, preferring to defer such changes to consider performance implications.
Learnt from: lazysegtree
PR: yorukot/superfile#935
File: website/src/content/docs/changelog.md:17-26
Timestamp: 2025-07-15T10:32:28.063Z
Learning: In the superfile changelog (website/src/content/docs/changelog.md), lazysegtree prefers to maintain the existing heading format with main version headings using # and sub-sections using #### (Update, Bug fix, Optimization, etc.) consistently throughout all releases, prioritizing established format consistency over strict markdown heading hierarchy compliance.
Learnt from: lazysegtree
PR: yorukot/superfile#953
File: website/public/install.ps1:25-25
Timestamp: 2025-07-21T08:49:13.041Z
Learning: In the superfile PowerShell installer (website/public/install.ps1), lazysegtree prefers that users supply correct environment variable values (like SPF_INSTALL_VERSION without leading 'v') rather than adding validation code to handle malformed input, following the principle that users should provide properly formatted values.
Learnt from: lazysegtree
PR: yorukot/superfile#953
File: website/public/install.sh:42-42
Timestamp: 2025-07-21T08:49:44.603Z
Learning: In the superfile bash installer (website/public/install.sh), lazysegtree maintains the same principle as the PowerShell installer - users should supply correct environment variable values (SPF_INSTALL_VERSION without leading 'v') rather than adding validation code to handle malformed input, following the philosophy that users should provide properly formatted values.
Learnt from: lazysegtree
PR: yorukot/superfile#775
File: src/internal/common/style_function.go:240-243
Timestamp: 2025-04-27T17:04:47.888Z
Learning: lazysegtree plans to refactor textinput.Model creation in the future to fix the code duplication issue that caused a bug where the sidebar search model was created without setting the Width property.
src/internal/wheel_function.go (3)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/consts.go:16-16
Timestamp: 2025-04-12T14:02:46.575Z
Learning: In Go packages, constants and variables should only be exported (capitalized) if they need to be accessed from outside their package. In the sidebar package, constants like sideBarInitialHeight should remain unexported as they're only used within the package.

src/internal/key_function.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/utils/file_utils.go (1)

Learnt from: lazysegtree
PR: #887
File: src/internal/handle_file_operations.go:53-53
Timestamp: 2025-06-21T15:17:49.464Z
Learning: In Go, filepath.Abs() internally calls filepath.Clean() on the result, so calling filepath.Clean() after filepath.Abs() is redundant and should be avoided.

src/internal/type.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/ui/metadata/model_test.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/default_config.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/ui/metadata/utils.go (4)

Learnt from: lazysegtree
PR: #781
File: src/internal/ui/rendering/border.go:104-114
Timestamp: 2025-04-28T04:02:28.747Z
Learning: The BorderConfig.GetBorder method in src/internal/ui/rendering/border.go already protects against negative availWidth values through the condition actualWidth >= cnt*4 which ensures that availWidth is at least 1.

Learnt from: lazysegtree
PR: #825
File: src/internal/ui/rendering/renderer_core.go:95-108
Timestamp: 2025-05-22T04:42:07.369Z
Learning: In src/internal/ui/rendering/renderer_core.go, when truncating rendered output that exceeds the maximum height, we should drop all remaining lines after reaching totalHeight without adding an ellipsis or other truncation indicator, as the goal is to have exactly totalHeight lines.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/ui/metadata/model.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/model.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

🧬 Code Graph Analysis (6)
src/internal/type.go (1)
src/internal/ui/metadata/model.go (1)
  • Model (9-19)
src/internal/ui/metadata/model_test.go (2)
src/internal/ui/metadata/metadata.go (1)
  • Metadata (15-20)
src/internal/ui/metadata/model.go (1)
  • Model (9-19)
src/internal/default_config.go (2)
src/internal/ui/metadata/model.go (1)
  • New (21-23)
src/internal/ui/sidebar/sidebar.go (1)
  • New (110-122)
src/internal/ui/metadata/utils.go (2)
src/internal/common/string_function.go (1)
  • TruncateMiddleText (49-59)
src/internal/utils/ui_utils.go (1)
  • FooterWidth (6-8)
src/internal/ui/metadata/model.go (2)
src/internal/ui/metadata/metadata.go (1)
  • Metadata (15-20)
src/internal/ui/spf_renderers.go (1)
  • MetadataRenderer (117-121)
src/internal/model.go (3)
src/internal/ui/metadata/metadata.go (3)
  • Metadata (15-20)
  • NewMetadata (22-28)
  • GetMetadata (73-77)
src/config/icon/icon.go (2)
  • InOperation (37-37)
  • Space (10-10)
src/internal/utils/ui_utils.go (1)
  • FooterWidth (6-8)
💤 Files with no reviewable changes (4)
  • src/internal/handle_panel_up_down.go
  • src/internal/model_render.go
  • src/internal/handle_panel_up_down_test.go
  • src/internal/function.go
🧰 Additional context used
🧠 Learnings (10)
📓 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.
Learnt from: lazysegtree
PR: yorukot/superfile#0
File: :0-0
Timestamp: 2025-04-12T12:25:06.352Z
Learning: PR #770 "Sidebar code separation" is a refactoring and code reorganization effort with no new features. It involves moving code, updating import paths, renaming functions to follow PascalCase convention, and consolidating sidebar-related functionality into a dedicated package.
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/ui/sidebar/render.go:46-48
Timestamp: 2025-04-28T03:48:46.327Z
Learning: The user (lazysegtree) prefers to keep PRs focused and manageable in size, sometimes intentionally leaving TODO comments to track minor issues for later PRs rather than addressing everything at once.
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/model_render.go:254-256
Timestamp: 2025-04-28T04:27:33.074Z
Learning: When race conditions or other issues that are unrelated to the current PR's focus are identified during review, lazysegtree prefers creating separate GitHub issues to track them rather than addressing them in the current PR. This helps maintain PR focus and scope.
Learnt from: lazysegtree
PR: yorukot/superfile#906
File: src/internal/file_panel.go:11-14
Timestamp: 2025-07-12T05:32:53.131Z
Learning: lazysegtree is concerned about the efficiency impact of adding bounds checking to frequently called methods like getSelectedItem() in file panels, preferring to defer such changes to consider performance implications.
Learnt from: lazysegtree
PR: yorukot/superfile#935
File: website/src/content/docs/changelog.md:17-26
Timestamp: 2025-07-15T10:32:28.063Z
Learning: In the superfile changelog (website/src/content/docs/changelog.md), lazysegtree prefers to maintain the existing heading format with main version headings using # and sub-sections using #### (Update, Bug fix, Optimization, etc.) consistently throughout all releases, prioritizing established format consistency over strict markdown heading hierarchy compliance.
Learnt from: lazysegtree
PR: yorukot/superfile#953
File: website/public/install.ps1:25-25
Timestamp: 2025-07-21T08:49:13.041Z
Learning: In the superfile PowerShell installer (website/public/install.ps1), lazysegtree prefers that users supply correct environment variable values (like SPF_INSTALL_VERSION without leading 'v') rather than adding validation code to handle malformed input, following the principle that users should provide properly formatted values.
Learnt from: lazysegtree
PR: yorukot/superfile#953
File: website/public/install.sh:42-42
Timestamp: 2025-07-21T08:49:44.603Z
Learning: In the superfile bash installer (website/public/install.sh), lazysegtree maintains the same principle as the PowerShell installer - users should supply correct environment variable values (SPF_INSTALL_VERSION without leading 'v') rather than adding validation code to handle malformed input, following the philosophy that users should provide properly formatted values.
Learnt from: lazysegtree
PR: yorukot/superfile#775
File: src/internal/common/style_function.go:240-243
Timestamp: 2025-04-27T17:04:47.888Z
Learning: lazysegtree plans to refactor textinput.Model creation in the future to fix the code duplication issue that caused a bug where the sidebar search model was created without setting the Width property.
src/internal/wheel_function.go (3)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/consts.go:16-16
Timestamp: 2025-04-12T14:02:46.575Z
Learning: In Go packages, constants and variables should only be exported (capitalized) if they need to be accessed from outside their package. In the sidebar package, constants like sideBarInitialHeight should remain unexported as they're only used within the package.

src/internal/key_function.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/utils/file_utils.go (1)

Learnt from: lazysegtree
PR: #887
File: src/internal/handle_file_operations.go:53-53
Timestamp: 2025-06-21T15:17:49.464Z
Learning: In Go, filepath.Abs() internally calls filepath.Clean() on the result, so calling filepath.Clean() after filepath.Abs() is redundant and should be avoided.

src/internal/type.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/ui/metadata/model_test.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/default_config.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/ui/metadata/utils.go (4)

Learnt from: lazysegtree
PR: #781
File: src/internal/ui/rendering/border.go:104-114
Timestamp: 2025-04-28T04:02:28.747Z
Learning: The BorderConfig.GetBorder method in src/internal/ui/rendering/border.go already protects against negative availWidth values through the condition actualWidth >= cnt*4 which ensures that availWidth is at least 1.

Learnt from: lazysegtree
PR: #825
File: src/internal/ui/rendering/renderer_core.go:95-108
Timestamp: 2025-05-22T04:42:07.369Z
Learning: In src/internal/ui/rendering/renderer_core.go, when truncating rendered output that exceeds the maximum height, we should drop all remaining lines after reaching totalHeight without adding an ellipsis or other truncation indicator, as the goal is to have exactly totalHeight lines.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/ui/metadata/model.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

src/internal/model.go (2)

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

Learnt from: lazysegtree
PR: #770
File: src/internal/ui/sidebar/render.go:0-0
Timestamp: 2025-04-12T13:51:24.691Z
Learning: In the sidebar component of yorukot/superfile, the partial list rendering in render.go is intentional. The sidebar implements scrolling functionality where ListUp/ListDown methods in navigation.go update cursor position and renderIndex to show the appropriate portion of the directory list based on available space.

🧬 Code Graph Analysis (6)
src/internal/type.go (1)
src/internal/ui/metadata/model.go (1)
  • Model (9-19)
src/internal/ui/metadata/model_test.go (2)
src/internal/ui/metadata/metadata.go (1)
  • Metadata (15-20)
src/internal/ui/metadata/model.go (1)
  • Model (9-19)
src/internal/default_config.go (2)
src/internal/ui/metadata/model.go (1)
  • New (21-23)
src/internal/ui/sidebar/sidebar.go (1)
  • New (110-122)
src/internal/ui/metadata/utils.go (2)
src/internal/common/string_function.go (1)
  • TruncateMiddleText (49-59)
src/internal/utils/ui_utils.go (1)
  • FooterWidth (6-8)
src/internal/ui/metadata/model.go (2)
src/internal/ui/metadata/metadata.go (1)
  • Metadata (15-20)
src/internal/ui/spf_renderers.go (1)
  • MetadataRenderer (117-121)
src/internal/model.go (3)
src/internal/ui/metadata/metadata.go (3)
  • Metadata (15-20)
  • NewMetadata (22-28)
  • GetMetadata (73-77)
src/config/icon/icon.go (2)
  • InOperation (37-37)
  • Space (10-10)
src/internal/utils/ui_utils.go (1)
  • FooterWidth (6-8)
🔇 Additional comments (22)
src/internal/wheel_function.go (1)

20-20: LGTM! Method calls correctly updated for the new metadata package.

The changes properly update the method calls from listUp() and listDown() to the exported ListUp() and ListDown() methods, consistent with the refactoring that moves metadata functionality into a separate package.

Also applies to: 32-32

src/internal/key_function.go (1)

26-26: LGTM! Consistent method name updates for metadata navigation.

The changes correctly update the method calls to use the exported ListUp() and ListDown() methods from the new metadata package, maintaining consistency with the refactoring effort.

Also applies to: 39-39

src/internal/default_config.go (1)

6-6: LGTM! Proper integration of the new metadata package.

The changes correctly import the new metadata package and initialize the fileMetaData field using metadata.New(), following the same pattern as other components like the sidebar. This properly integrates the refactored metadata functionality into the default model configuration.

Also applies to: 26-26

src/internal/ui/metadata/model_test.go (1)

9-67: Good test coverage for navigation functionality.

The test effectively covers the core navigation functionality of the metadata model, including edge cases for wrapping behavior. The table-driven approach and comprehensive test scenarios provide good confidence in the ListUp/ListDown methods.

src/internal/type.go (2)

6-6: LGTM! Import addition follows established patterns.

The import for the new metadata package is correctly placed and follows the existing import organization structure.


108-109: LGTM! Model struct updates align with metadata package refactor.

The changes appropriately:

  • Replace the internal fileMetaData field with the new metadata.Model type
  • Add metadataRequestCnt for tracking metadata requests

These modifications support the separation of metadata handling into its dedicated package.

src/internal/utils/file_utils.go (1)

4-5: LGTM! Import additions support the MD5 checksum functionality.

The crypto/md5 and encoding/hex imports are appropriately added to support the new CalculateMD5Checksum function.

src/internal/ui/metadata/utils.go (3)

10-18: LGTM! Simple and efficient max key length calculation.

The function correctly iterates through metadata pairs to find the maximum key length needed for formatting alignment.


20-30: LGTM! Reasonable width calculation logic.

The function appropriately:

  • Calculates available space for values after accounting for keys and borders
  • Ensures values get at least half the panel width for readability
  • Adjusts formatting lengths accordingly

The width distribution logic makes sense for metadata display.


49-53: LGTM! Clean wrapper function for render dimension calculations.

The function appropriately combines key length calculation with width computation in a clear, reusable interface.

src/internal/ui/metadata/model.go (4)

9-23: LGTM! Well-structured Model with clear separation of concerns.

The Model struct appropriately separates:

  • Data (metadata)
  • Render state (renderIndex)
  • UI dimensions (width, height)

The New() constructor follows Go conventions by returning a zero-value struct.


54-72: LGTM! Robust navigation implementation with proper edge case handling.

The navigation methods correctly implement:

  • Cyclic navigation (wrap around at boundaries)
  • Empty metadata protection
  • Consistent behavior between up/down movement

The implementation matches the expected UI navigation patterns.


74-86: LGTM! Comprehensive blank state management.

The methods properly handle:

  • Clearing metadata with appropriate default message (SetBlank)
  • Detecting blank state by checking both data and message (IsBlank)
  • Allowing custom info messages (SetInfoMsg)

The implementation provides good flexibility for different metadata states.


88-99: LGTM! Well-structured render method with proper state handling.

The render method effectively:

  • Handles empty metadata by displaying info messages
  • Uses consistent UI rendering with ui.MetadataRenderer
  • Computes appropriate dimensions for formatting
  • Shows pagination information in the border
  • Delegates line formatting to utility functions

The implementation provides a clean separation between rendering logic and formatting utilities.

src/internal/ui/metadata/metadata.go (6)

15-36: LGTM! Clean Metadata struct design with appropriate accessors.

The struct properly encapsulates:

  • Key-value data as ordered pairs
  • Informational messages for error/status display
  • File path for reference

The constructor and accessor methods follow Go conventions and provide a clean interface.


42-71: LGTM! Well-implemented metadata sorting with clear prioritization.

The sorting logic effectively:

  • Prioritizes important metadata fields (Name, Size, Date Modified, Date Accessed)
  • Uses sort.SliceStable to maintain order stability
  • Falls back to alphabetical sorting for non-priority fields
  • Handles all comparison cases correctly

The priority-based approach ensures consistent, user-friendly metadata display ordering.


73-77: LGTM! Clean separation of metadata extraction and sorting.

The function appropriately separates concerns by delegating to getMetaDataUnsorted for extraction and then applying sorting, making the code more maintainable and testable.


79-97: LGTM! Proper symlink handling with appropriate error messages.

The function correctly:

  • Uses os.Lstat to detect symlinks without following them
  • Uses filepath.EvalSymlinks to check for broken links
  • Provides clear info messages for different symlink states
  • Handles file stat errors appropriately

The symlink detection logic is more robust than the IsSymlink utility function reviewed earlier.


98-111: LGTM! Comprehensive basic metadata extraction with good performance considerations.

The implementation effectively:

  • Extracts essential metadata (name, size, modification time, permissions)
  • Handles directory size calculation only when metadata panel is focused
  • Shows awareness of performance implications with the TODO comment

The conditional expensive operations approach balances functionality with performance, which is appropriate for a file manager UI.


113-139: LGTM! Robust extended metadata extraction with proper error handling.

The implementation handles extended metadata well:

  • Proper nil checking for exiftool to prevent crashes
  • Comprehensive error handling with logging that doesn't break execution flow
  • Respects configuration settings for optional features (metadata, MD5 checksum)
  • Continues processing despite individual extraction failures

The approach ensures the metadata panel remains functional even when some extended features fail.

src/internal/model.go (2)

292-294: LGTM! Clean addition for metadata panel sizing.

The method properly calculates and sets the metadata panel dimensions, accounting for borders with the +2 padding.


522-522: LGTM! Proper delegation to the metadata package.

The change correctly delegates rendering to the metadata model with appropriate focus state.

@lazysegtree lazysegtree force-pushed the metadata_separation branch from b6d0b7b to d562597 Compare July 23, 2025 18:00
offloaded to main model

# To-dos
- Add unit tests
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I plan to add unit tests in a new PR. This PR has grown too huge.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@coderabbitai

Create a github issue tracking adding unit tests for

  • metadata fetching
  • Functions in metadata package
  • End to end test of integration of main model with metadata package.

Focus on what should be covered and tested, not how we should do it.

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

@lazysegtree I'll create a GitHub issue to track the unit testing requirements for the metadata package functionality.


🏁 Script executed:

#!/bin/bash
# Create a GitHub issue for metadata package unit testing
gh issue create \
  --title "Add comprehensive unit tests for metadata package" \
  --body "## Background

This issue tracks the addition of comprehensive unit tests for the metadata package functionality that was separated in PR #950.

## Testing Areas to Cover

### 1. Metadata Fetching
- Test \`GetMetadata()\` function with various file types (regular files, directories, symlinks)
- Test metadata extraction with and without exiftool integration
- Test error handling for inaccessible files, broken symlinks, and permission issues
- Test metadata sorting functionality (\`sortMetadata\`)
- Verify MD5 checksum calculation for different file sizes
- Test directory size calculation (\`DirSize\`) for nested directory structures

### 2. Metadata Package Functions
- Test \`Metadata\` struct methods: \`GetPath()\`, \`GetData()\`, \`GetValue()\`
- Test \`Model\` struct functionality:
  - Navigation methods: \`ListUp()\`, \`ListDown()\` with boundary conditions
  - State management: \`SetMetadata()\`, \`SetBlank()\`, \`IsBlank()\`
  - Render index management: \`ResetRender()\`, \`ResetRenderIfInvalid()\`
  - Dimension handling: \`SetDimensions()\`
- Test utility functions in \`utils.go\`:
  - \`getMaxKeyLength()\` with various metadata sets
  - \`computeMetadataWidths()\` with different view widths
  - \`formatMetadataLines()\` with truncation scenarios
  - \`calculateMD5Checksum()\` error handling

### 3. End-to-End Integration Testing
- Test integration between main model and metadata package
- Verify metadata request tracking (\`metadataRequestCnt\`)
- Test metadata panel rendering with focus states
- Test metadata updates when file selection changes
- Verify proper cleanup and state reset scenarios
- Test window resize handling for metadata panel dimensions

## Success Criteria
- Achieve meaningful test coverage for all public functions and methods
- Include edge cases and error scenarios
- Ensure tests are deterministic and don't rely on external file system state
- Add benchmark tests for performance-critical functions like directory size calculation

## References
- PR #950: https://github.com/yorukot/superfile/pull/950
- Comment: https://github.com/yorukot/superfile/pull/950#discussion_r2226294633" \
  --assignee lazysegtree

Length of output: 2258


@lazysegtree I've successfully created GitHub issue #957 to track the comprehensive unit testing requirements for the metadata package: #957

The issue covers all three areas you requested:

  1. Metadata fetching - Testing GetMetadata() with various file types, exiftool integration, error handling, and utility functions
  2. Metadata package functions - Coverage for all struct methods, navigation, state management, and utility functions
  3. End-to-end integration testing - Testing the integration between the main model and metadata package

The issue focuses on what should be tested rather than implementation details, as you requested. It includes success criteria and references back to this PR and comment for context.

    (\   /)
   ( ._. )
  o_(")(")

✏️ Learnings added
Learnt from: lazysegtree
PR: yorukot/superfile#950
File: src/internal/ui/metadata/README.md:7-7
Timestamp: 2025-07-24T03:46:29.484Z
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.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/model_render.go:254-256
Timestamp: 2025-04-28T04:27:33.074Z
Learning: When race conditions or other issues that are unrelated to the current PR's focus are identified during review, lazysegtree prefers creating separate GitHub issues to track them rather than addressing them in the current PR. This helps maintain PR focus and scope.

Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/ui/sidebar/render.go:46-48
Timestamp: 2025-04-28T03:48:46.327Z
Learning: The user (lazysegtree) prefers to keep PRs focused and manageable in size, sometimes intentionally leaving TODO comments to track minor issues for later PRs rather than addressing everything at once.

Learnt from: lazysegtree
PR: yorukot/superfile#825
File: src/internal/model_render_test.go:15-25
Timestamp: 2025-05-22T04:53:45.663Z
Learning: In the superfile project, comments in test files documenting additional test cases with "// Additional tests" are intentional TODOs for future work and should not be flagged as missing implementations in PR reviews.

Learnt from: lazysegtree
PR: yorukot/superfile#775
File: src/internal/common/style_function.go:240-243
Timestamp: 2025-04-27T17:04:47.888Z
Learning: lazysegtree plans to refactor textinput.Model creation in the future to fix the code duplication issue that caused a bug where the sidebar search model was created without setting the Width property.

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.

Learnt from: lazysegtree
PR: yorukot/superfile#906
File: src/internal/file_panel.go:11-14
Timestamp: 2025-07-12T05:32:53.131Z
Learning: lazysegtree is concerned about the efficiency impact of adding bounds checking to frequently called methods like getSelectedItem() in file panels, preferring to defer such changes to consider performance implications.

Learnt from: lazysegtree
PR: yorukot/superfile#935
File: website/src/content/docs/changelog.md:17-26
Timestamp: 2025-07-15T10:32:28.063Z
Learning: In the superfile changelog (website/src/content/docs/changelog.md), lazysegtree prefers to maintain the existing heading format with main version headings using # and sub-sections using #### (Update, Bug fix, Optimization, etc.) consistently throughout all releases, prioritizing established format consistency over strict markdown heading hierarchy compliance.

Learnt from: lazysegtree
PR: yorukot/superfile#953
File: website/public/install.ps1:25-25
Timestamp: 2025-07-21T08:49:13.041Z
Learning: In the superfile PowerShell installer (website/public/install.ps1), lazysegtree prefers that users supply correct environment variable values (like SPF_INSTALL_VERSION without leading 'v') rather than adding validation code to handle malformed input, following the principle that users should provide properly formatted values.

Learnt from: lazysegtree
PR: yorukot/superfile#953
File: website/public/install.sh:42-42
Timestamp: 2025-07-21T08:49:44.603Z
Learning: In the superfile bash installer (website/public/install.sh), lazysegtree maintains the same principle as the PowerShell installer - users should supply correct environment variable values (SPF_INSTALL_VERSION without leading 'v') rather than adding validation code to handle malformed input, following the philosophy that users should provide properly formatted values.

Learnt from: lazysegtree
PR: yorukot/superfile#0
File: :0-0
Timestamp: 2025-04-12T12:25:06.352Z
Learning: PR #770 "Sidebar code separation" is a refactoring and code reorganization effort with no new features. It involves moving code, updating import paths, renaming functions to follow PascalCase convention, and consolidating sidebar-related functionality into a dedicated package.

@lazysegtree lazysegtree force-pushed the metadata_separation branch 3 times, most recently from ed4b8f2 to 0a773ac Compare July 24, 2025 02:50
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/internal/ui/metadata/metadata.go (1)

38-46: Fix variable shadowing in GetValue method.

The loop variable 'm' shadows the receiver variable 'm', which can be confusing and is a code smell.

Apply this diff to fix the variable shadowing:

-func (m Metadata) GetValue(key string) (string, error) {
-	for _, m := range m.data {
-		if m[0] == key {
-			return m[1], nil
+func (m Metadata) GetValue(key string) (string, error) {
+	for _, pair := range m.data {
+		if pair[0] == key {
+			return pair[1], nil
 		}
 	}
 
 	return "", fmt.Errorf("Key %s not found", key)
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 54b4a8f and ed4b8f2.

📒 Files selected for processing (8)
  • .github/workflows/superfile-build-test.yml (1 hunks)
  • src/internal/ui/metadata/const.go (1 hunks)
  • src/internal/ui/metadata/metadata.go (1 hunks)
  • src/internal/ui/metadata/metadata_test.go (1 hunks)
  • src/internal/ui/metadata/model.go (1 hunks)
  • src/internal/ui/metadata/testdata/file1.txt (1 hunks)
  • src/internal/ui/metadata/utils.go (1 hunks)
  • src/internal/utils/file_utils.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/internal/ui/metadata/testdata/file1.txt
  • .github/workflows/superfile-build-test.yml
  • src/internal/utils/file_utils.go
  • src/internal/ui/metadata/metadata_test.go
  • src/internal/ui/metadata/utils.go
  • src/internal/ui/metadata/const.go
  • src/internal/ui/metadata/model.go
🧰 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.
Learnt from: lazysegtree
PR: yorukot/superfile#0
File: :0-0
Timestamp: 2025-04-12T12:25:06.352Z
Learning: PR #770 "Sidebar code separation" is a refactoring and code reorganization effort with no new features. It involves moving code, updating import paths, renaming functions to follow PascalCase convention, and consolidating sidebar-related functionality into a dedicated package.
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/ui/sidebar/render.go:46-48
Timestamp: 2025-04-28T03:48:46.327Z
Learning: The user (lazysegtree) prefers to keep PRs focused and manageable in size, sometimes intentionally leaving TODO comments to track minor issues for later PRs rather than addressing everything at once.
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/model_render.go:254-256
Timestamp: 2025-04-28T04:27:33.074Z
Learning: When race conditions or other issues that are unrelated to the current PR's focus are identified during review, lazysegtree prefers creating separate GitHub issues to track them rather than addressing them in the current PR. This helps maintain PR focus and scope.
Learnt from: lazysegtree
PR: yorukot/superfile#906
File: src/internal/file_panel.go:11-14
Timestamp: 2025-07-12T05:32:53.131Z
Learning: lazysegtree is concerned about the efficiency impact of adding bounds checking to frequently called methods like getSelectedItem() in file panels, preferring to defer such changes to consider performance implications.
Learnt from: lazysegtree
PR: yorukot/superfile#935
File: website/src/content/docs/changelog.md:17-26
Timestamp: 2025-07-15T10:32:28.063Z
Learning: In the superfile changelog (website/src/content/docs/changelog.md), lazysegtree prefers to maintain the existing heading format with main version headings using # and sub-sections using #### (Update, Bug fix, Optimization, etc.) consistently throughout all releases, prioritizing established format consistency over strict markdown heading hierarchy compliance.
Learnt from: lazysegtree
PR: yorukot/superfile#953
File: website/public/install.ps1:25-25
Timestamp: 2025-07-21T08:49:13.041Z
Learning: In the superfile PowerShell installer (website/public/install.ps1), lazysegtree prefers that users supply correct environment variable values (like SPF_INSTALL_VERSION without leading 'v') rather than adding validation code to handle malformed input, following the principle that users should provide properly formatted values.
Learnt from: lazysegtree
PR: yorukot/superfile#953
File: website/public/install.sh:42-42
Timestamp: 2025-07-21T08:49:44.603Z
Learning: In the superfile bash installer (website/public/install.sh), lazysegtree maintains the same principle as the PowerShell installer - users should supply correct environment variable values (SPF_INSTALL_VERSION without leading 'v') rather than adding validation code to handle malformed input, following the philosophy that users should provide properly formatted values.
Learnt from: lazysegtree
PR: yorukot/superfile#775
File: src/internal/common/style_function.go:240-243
Timestamp: 2025-04-27T17:04:47.888Z
Learning: lazysegtree plans to refactor textinput.Model creation in the future to fix the code duplication issue that caused a bug where the sidebar search model was created without setting the Width property.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (6)
src/internal/ui/metadata/metadata.go (6)

1-13: LGTM! Package structure and imports are well-organized.

The package declaration and imports are appropriate for the metadata extraction functionality being implemented.


15-20: Good struct design with proper encapsulation.

The Metadata struct design is well-thought-out, using a slice of [2]string for custom ordering and providing proper encapsulation with unexported fields.


48-74: Excellent sorting implementation with clear logic.

The metadata sorting function is well-implemented with proper handling of priority fields and fallback to alphabetical sorting. The use of stable sort ensures consistent ordering.


76-80: Clean and well-designed public API.

The GetMetadata function provides a clean interface with good separation of concerns between metadata extraction and sorting.


82-143: Comprehensive metadata extraction with good error handling.

The function is well-implemented with proper error handling, symlink detection, and conditional feature support. The TODO comment on lines 109-112 shows good awareness of potential performance implications.


133-133: calculateMD5Checksum implementation verified

The calculateMD5Checksum function is defined in src/internal/ui/metadata/utils.go (lines 56–70) and correctly returns a checksum and error. No further action required.

@lazysegtree lazysegtree force-pushed the metadata_separation branch from 0a773ac to 829dc6a Compare July 24, 2025 03:06
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed4b8f2 and 829dc6a.

📒 Files selected for processing (9)
  • .github/workflows/superfile-build-test.yml (1 hunks)
  • src/internal/ui/metadata/const.go (1 hunks)
  • src/internal/ui/metadata/metadata.go (1 hunks)
  • src/internal/ui/metadata/metadata_test.go (1 hunks)
  • src/internal/ui/metadata/model.go (1 hunks)
  • src/internal/ui/metadata/testdata/file1.txt (1 hunks)
  • src/internal/ui/metadata/utils.go (1 hunks)
  • src/internal/utils/consts.go (1 hunks)
  • src/internal/utils/file_utils.go (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/internal/utils/consts.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/internal/ui/metadata/testdata/file1.txt
  • .github/workflows/superfile-build-test.yml
  • src/internal/ui/metadata/metadata_test.go
  • src/internal/utils/file_utils.go
  • src/internal/ui/metadata/utils.go
  • src/internal/ui/metadata/const.go
  • src/internal/ui/metadata/model.go
🧰 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.
Learnt from: lazysegtree
PR: yorukot/superfile#0
File: :0-0
Timestamp: 2025-04-12T12:25:06.352Z
Learning: PR #770 "Sidebar code separation" is a refactoring and code reorganization effort with no new features. It involves moving code, updating import paths, renaming functions to follow PascalCase convention, and consolidating sidebar-related functionality into a dedicated package.
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/ui/sidebar/render.go:46-48
Timestamp: 2025-04-28T03:48:46.327Z
Learning: The user (lazysegtree) prefers to keep PRs focused and manageable in size, sometimes intentionally leaving TODO comments to track minor issues for later PRs rather than addressing everything at once.
Learnt from: lazysegtree
PR: yorukot/superfile#781
File: src/internal/model_render.go:254-256
Timestamp: 2025-04-28T04:27:33.074Z
Learning: When race conditions or other issues that are unrelated to the current PR's focus are identified during review, lazysegtree prefers creating separate GitHub issues to track them rather than addressing them in the current PR. This helps maintain PR focus and scope.
Learnt from: lazysegtree
PR: yorukot/superfile#906
File: src/internal/file_panel.go:11-14
Timestamp: 2025-07-12T05:32:53.131Z
Learning: lazysegtree is concerned about the efficiency impact of adding bounds checking to frequently called methods like getSelectedItem() in file panels, preferring to defer such changes to consider performance implications.
Learnt from: lazysegtree
PR: yorukot/superfile#935
File: website/src/content/docs/changelog.md:17-26
Timestamp: 2025-07-15T10:32:28.063Z
Learning: In the superfile changelog (website/src/content/docs/changelog.md), lazysegtree prefers to maintain the existing heading format with main version headings using # and sub-sections using #### (Update, Bug fix, Optimization, etc.) consistently throughout all releases, prioritizing established format consistency over strict markdown heading hierarchy compliance.
Learnt from: lazysegtree
PR: yorukot/superfile#953
File: website/public/install.ps1:25-25
Timestamp: 2025-07-21T08:49:13.041Z
Learning: In the superfile PowerShell installer (website/public/install.ps1), lazysegtree prefers that users supply correct environment variable values (like SPF_INSTALL_VERSION without leading 'v') rather than adding validation code to handle malformed input, following the principle that users should provide properly formatted values.
Learnt from: lazysegtree
PR: yorukot/superfile#953
File: website/public/install.sh:42-42
Timestamp: 2025-07-21T08:49:44.603Z
Learning: In the superfile bash installer (website/public/install.sh), lazysegtree maintains the same principle as the PowerShell installer - users should supply correct environment variable values (SPF_INSTALL_VERSION without leading 'v') rather than adding validation code to handle malformed input, following the philosophy that users should provide properly formatted values.
Learnt from: lazysegtree
PR: yorukot/superfile#775
File: src/internal/common/style_function.go:240-243
Timestamp: 2025-04-27T17:04:47.888Z
Learning: lazysegtree plans to refactor textinput.Model creation in the future to fix the code duplication issue that caused a bug where the sidebar search model was created without setting the Width property.
🧬 Code Graph Analysis (1)
src/internal/ui/metadata/metadata.go (1)
src/internal/utils/file_utils.go (1)
  • DirSize (195-214)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build and Test (ubuntu-latest)
  • GitHub Check: Build and Test (macos-latest)
🔇 Additional comments (10)
src/internal/ui/metadata/metadata.go (10)

1-13: LGTM: Clean package structure and imports.

The package declaration and imports are well-organized and appropriate for the metadata extraction functionality. The external dependency on go-exiftool is properly imported and aligns with the metadata extraction requirements.


15-20: Well-designed struct with appropriate field visibility.

The Metadata struct design is clean with unexported fields and proper encapsulation. The use of [][2]string for data storage is well-justified by the comment on lines 48-50.


22-28: Constructor follows Go conventions.

The NewMetadata constructor properly initializes all fields and follows standard Go naming conventions.


30-36: Accessor methods are straightforward and correct.

Both GetPath() and GetData() methods provide clean access to the internal fields.


52-74: Sorting implementation is correct and well-commented.

The sorting logic properly handles priority fields and falls back to alphabetical sorting for non-priority fields. The stable sort ensures consistent ordering.


76-80: Clean separation of concerns in GetMetadata.

The function properly delegates to the unsorted version and applies sorting, maintaining good separation of concerns.


82-100: Proper error handling for file operations.

The function correctly handles file stat errors and symlink validation with appropriate error messages.


101-114: Good performance consideration with TODO comment.

The TODO comment on lines 109-112 shows awareness of potential performance issues with directory size calculation. The conditional execution only when metadataFocussed is true is a good optimization.


116-129: Robust exiftool integration with error handling.

The exiftool integration properly checks for nil pointer and handles errors from metadata extraction with appropriate logging.


131-143: MD5 checksum calculation with proper error handling.

The MD5 checksum calculation is conditionally executed based on configuration and includes proper error handling with logging.

@lazysegtree lazysegtree changed the title feat: Separate metadata panel into separate package feat: Metadata panel into separate package, UI bug fixes, Code improvements Jul 24, 2025
@lazysegtree lazysegtree added refactoring bug fixes high priority Issue/PR/Feature/bug that is considered high priority. labels Jul 24, 2025
@lazysegtree lazysegtree requested a review from yorukot July 24, 2025 03:46
@lazysegtree lazysegtree merged commit 1363c7d into main Jul 24, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug fixes high priority Issue/PR/Feature/bug that is considered high priority. refactoring
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants