Skip to content
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

Feature/relative splitview images #300

Merged
merged 7 commits into from
Feb 11, 2025

Conversation

damongolding
Copy link
Owner

@damongolding damongolding commented Feb 11, 2025

Summary by CodeRabbit

  • New Features

    • Expanded display configurations introducing new layout options such as landscape, portrait, split-view, and split-view landscape.
    • Enhanced image presentation with improved metadata assignment and asset categorisation across various content sources.
  • Refactor

    • Streamlined image processing pipeline for more robust and context-aware visual renderings.
    • Organised request processing to support flexible image handling and improved performance.
    • Updated CSS for improved alignment and presentation of metadata in the user interface.
    • Introduced new structures and methods to enhance clarity and modularity in request handling and image processing.
    • Improved the handling of asset properties and metadata for better integration with kiosk functionalities.

@damongolding damongolding added the enhancement New feature or request label Feb 11, 2025
Copy link
Contributor

coderabbitai bot commented Feb 11, 2025

Walkthrough

This pull request introduces several enhancements, including new data structures and helper functions to support kiosk-related image processing. New fields for asset metadata (Bucket and BucketID) are added across multiple modules, along with a new options struct to refine image view handling. Additionally, a method to reset bucket arrays in configuration is implemented, and new layout constants are added. The modifications also refactor how image requests are processed via improved helper functions, while documentation comments are updated for clarity.

Changes

File(s) Change Summary
internal/common/common.go - Added new import for the kiosk package.
- Introduced ViewImageDataOptions struct with fields: RelativeAssetWanted, RelativeAssetBucket, RelativeAssetBucketID, and ImageOrientation.
- Updated comment for the User field in ViewImageData.
internal/config/config.go - Added a new method ResetBuckets to clear Person, Album, and Date slices.
- Modified ConfigWithOverrides to call ResetBuckets.
internal/immich/immich*.go - Across multiple files (e.g. immich.go, immich_album.go, immich_date.go, immich_favourites.go, immich_memories.go, immich_person.go, immich_random.go):
- Added Bucket and BucketID fields to asset structures.
- Updated asset assignment logic to set these fields using appropriate kiosk.Source constants.
internal/kiosk/kiosk.go - Added four new layout constants: LayoutLandscape, LayoutPortrait, LayoutSplitview, and LayoutSplitviewLandscape.
internal/routes/routes.go & .../routes_asset_helpers.go - Added a new type requestMetadata containing requestID, deviceID, and urlString.
- Refactored processViewImageData: now accepts a ViewImageDataOptions parameter.
- Introduced additional helper methods: setupRequestConfig, setupImmichAsset, determineAllowedAssetTypes, handleRelativeAssetConfig, handleFaceProcessing, and convertImages.
- Renamed ProcessViewImageData to ProcessViewImageDataWithOptions.
internal/templates/partials/metadata.templ - Added a new import for the kiosk package.
- Updated the AssetMetadata function to include a layout condition for kiosk.LayoutSplitviewLandscape.
frontend/public/assets/css/kiosk.css - Updated class selector from .asset--metadata--is-first .asset--metadata--icon to .right-align-icons .asset--metadata--icon.
frontend/src/css/image.css - Updated class selector from .asset--metadata--is-first .asset--metadata--icon to .right-align-icons .asset--metadata--icon and modified alignment properties for .asset--metadata under .frame--layout-splitview:nth-child(1).

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant RequestHandler
    participant ConfigHelper
    participant AssetCreator
    participant ProcessingHelpers

    Client->>RequestHandler: ProcessViewImageDataWithOptions(requestConfig, context, isPrefetch, options)
    RequestHandler->>ConfigHelper: setupRequestConfig(config)
    RequestHandler->>AssetCreator: setupImmichAsset(config, orientation)
    RequestHandler->>ProcessingHelpers: determineAllowedAssetTypes(config, isPrefetch)
    RequestHandler->>ProcessingHelpers: handleRelativeAssetConfig(config, options)
    RequestHandler->>ProcessingHelpers: handleFaceProcessing(image, asset, config, metadata)
    RequestHandler->>ProcessingHelpers: convertImages(image, assetType, config, metadata, isPrefetch)
    AssetCreator-->>RequestHandler: Asset populated (with Bucket/BucketID)
    RequestHandler-->>Client: Return ViewImageData
Loading

Possibly related PRs

  • Added webhooks #187: The changes in the main PR, specifically the introduction of the ViewImageDataOptions struct in internal/common/common.go, are related to the modifications in the retrieved PR that involve updates to the Config struct in config/config.go, as both involve enhancements to configuration management and data structures relevant to the kiosk functionality.
  • display album/person name #233: The changes in the main PR, which introduce a new struct ViewImageDataOptions and fields related to kiosk operations, are related to the retrieved PR as both involve modifications to the internal/config/config.go and internal/immich/immich.go files, specifically with the integration of the kiosk package and the addition of fields that enhance the handling of assets in the context of kiosks.
  • feature: support multiple users with multiple api keys #231: The changes in the main PR, specifically the addition of the User field to the ViewImageData struct in internal/common/common.go, are directly related to the modifications in the retrieved PR, which also introduces a User field in the same struct, enhancing user-specific configurations.

Poem

Hop-hop, I’m the coding bunny,
Carrots and code, oh so sunny!
Added options, fields so true,
Kiosk magic in all we do.
Bugs hop away, leaving flair anew!
🥕💻 Happy coding from my burrow to you!

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 golangci-lint (1.62.2)

level=warning msg="[runner] Can't run linter goanalysis_metalinter: buildir: failed to load package : could not load export data: no export data for "github.com/damongolding/immich-kiosk/internal/templates/components/image""
level=error msg="Running error: can't run linter goanalysis_metalinter\nbuildir: failed to load package : could not load export data: no export data for "github.com/damongolding/immich-kiosk/internal/templates/components/image""

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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.

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

🧹 Nitpick comments (7)
internal/routes/routes_asset_helpers.go (5)

379-383: Propagate errors or log them for more context.
Currently, the code returns an error directly to the caller. Adding a debug log before returning may ease diagnostics.

+ log.Debug(metadata.requestID, "processAsset error:", err)
return nil, err

396-400: Exception handling for conversion.
The approach to constructing two variants (normal and blurred) is sound, though consider logging or handling if either conversion fails.


410-419: Random user selection may cause unpredictability.
If random selection is undesired in certain scenarios, consider offering a deterministic ordering or explicit user pick to avoid confusion for kiosk operators.


474-488: Dual conversion approach for normal and blurred image.
This design is well-thought-out, enhancing code clarity. As an optional improvement, handle potential errors separately to log more specific failure cases.


639-645: Repeated second image logic.
This block largely duplicates the approach from the portrait splitview. Extracting common functionality into a helper function could improve maintainability.

- for i := ...
-   if ...
-     break
+ fetchSecondSplitViewAsset(&viewData, ...)
internal/immich/immich_favourites.go (1)

208-209: Consider using a distinct source category for favourites.

The current implementation sets Bucket to kiosk.SourceAlbums, but favourites might be better represented as a distinct source category since they can span across multiple albums. Consider introducing a dedicated source category like kiosk.SourceFavourites to better reflect the nature of favourite images.

internal/immich/immich.go (1)

180-181: LGTM! Consider adding field documentation.

The new fields are correctly added with appropriate JSON tags. Consider adding documentation comments to explain their purpose and expected values.

+// Bucket represents the source category of the asset (e.g., albums, date ranges)
 Bucket      kiosk.Source     `json:"-"`
+// BucketID uniquely identifies the specific source within the bucket category
 BucketID    string           `json:"-"`
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 30d7d3a and f675bca.

📒 Files selected for processing (13)
  • internal/common/common.go (3 hunks)
  • internal/config/config.go (1 hunks)
  • internal/immich/immich.go (2 hunks)
  • internal/immich/immich_album.go (1 hunks)
  • internal/immich/immich_date.go (1 hunks)
  • internal/immich/immich_favourites.go (1 hunks)
  • internal/immich/immich_memories.go (1 hunks)
  • internal/immich/immich_person.go (1 hunks)
  • internal/immich/immich_random.go (1 hunks)
  • internal/kiosk/kiosk.go (1 hunks)
  • internal/routes/routes.go (1 hunks)
  • internal/routes/routes_asset_helpers.go (6 hunks)
  • internal/templates/partials/metadata.templ (2 hunks)
🔇 Additional comments (24)
internal/routes/routes_asset_helpers.go (14)

348-361: Well-structured documentation and function signature.
This docstring clearly outlines the purpose and usage of the function. It improves maintainability by clarifying each parameter and return value.


362-365: Validate fallback for empty headers.
Consider verifying scenarios where deviceID or requestID might be absent or blank, ensuring the rest of the flow handles missing metadata gracefully.


369-377: Collation of initial setup is neat.
By grouping request configuration, asset setup, and allowed asset types in one place, the code remains readable and maintainable. Keep an eye on concurrency if future changes rely on shared state.


385-387: Face processing logic is straightforward.
The code is neatly separated into a helper function, adhering to single-responsibility principles.


388-394: Robust image optimisation.
Processing remains optional and is neatly toggled by a config flag, keeping performance overhead in check.


421-429: Orientation-based asset setup.
Clear separation of orientation logic from asset creation is a positive approach, aiding future expansions or different orientation rules.


431-439: Conditional asset type determination.
The logic is straightforward, toggling video inclusion only when both the feature flag and isPrefetch conditions are met. This helps keep prefetch overhead manageable.


441-457: Relative asset config is properly isolated.
Resetting buckets before appending the specific type ensures a clean slate, preventing unexpected overlap with previous choices.


459-472: Efficient face check.
Calling CheckForFaces only when necessary avoids redundant requests. Including a user-configurable approach ensures custom control over processing cost.


492-493: Convenient wrapper function.
Providing a default invocation of processViewImageData without orientation constraints is a good pattern for simpler usage.


495-497: Extended functionality with options.
The ProcessViewImageDataWithOptions method neatly encapsulates the newly introduced parameters, ensuring backwards compatibility.


575-582: Conditional orientation assignment.
Defining options for landscape or portrait explicitly aligns with the kiosk layout while preserving flexibility. Ensure that any future layouts receive a similar block.


599-609: Second image retrieval in splitview.
This incremental approach to fetch a second portrait-oriented image is sound. Consider randomised fallback if the second image picks the same asset.


619-635: Landscape splitview logic.
Mirroring the portrait splitview approach ensures consistent behaviour. The code is nicely self-documenting.

internal/kiosk/kiosk.go (1)

17-20: New layout constants are neatly introduced.
These provide more flexible options for kiosk modes without impacting existing logic. Consider grouping or naming them in a manner that highlights their usage scope (e.g., “LayoutMode”).

internal/routes/routes.go (1)

41-47: requestMetadata struct solidifies request context.
This newly added structure is a good practice, bundling key request data consistently and facilitating future expansions (e.g., adding more context fields).

internal/immich/immich_random.go (1)

128-130: LGTM! Source tracking enhancement.

The addition of asset.Bucket = kiosk.SourceRandom before the asset assignment properly tracks the source of randomly selected images.

internal/common/common.go (2)

103-103: LGTM! Improved documentation.

The added comment clarifies the purpose of the User field.


116-121: LGTM! Well-structured options type.

The new ViewImageDataOptions struct is well-designed with clear field names and appropriate types for handling relative asset relationships.

internal/immich/immich_memories.go (1)

159-162: LGTM! Enhanced memory asset metadata.

The changes properly set the source bucket and memory title before assigning the asset, maintaining clear asset origin tracking.

internal/immich/immich_person.go (1)

168-170: LGTM! Comprehensive person asset metadata.

The changes properly set both the source bucket and person ID, providing complete context for person-related assets.

internal/immich/immich_date.go (1)

139-140: LGTM! Appropriate source categorisation for date range assets.

The implementation correctly categorises date range assets with a distinct source and uses the date range as the bucket identifier.

internal/immich/immich_album.go (1)

272-273: LGTM! Appropriate source categorisation for album assets.

The implementation correctly categorises album assets with the appropriate source and uses the album ID as the bucket identifier.

internal/config/config.go (1)

433-441: LGTM! Well-documented and properly implemented.

The ResetBuckets method effectively centralises the logic for clearing asset bucket fields, making the code more maintainable and reducing the likelihood of inconsistencies. The documentation clearly explains the purpose and importance of resetting these fields.

internal/templates/partials/metadata.templ Outdated Show resolved Hide resolved
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

🧹 Nitpick comments (3)
internal/routes/routes_asset_helpers.go (3)

412-419: Add defensive check for empty user list.

The function should handle the case where config.User is nil to prevent potential panics.

Apply this diff to add the defensive check:

 func setupRequestConfig(config *config.Config) {
-    if len(config.User) > 0 {
+    if config.User != nil && len(config.User) > 0 {
         randomIndex := rand.IntN(len(config.User))
         config.SelectedUser = config.User[randomIndex]
     } else {
         config.SelectedUser = ""
     }
 }

578-578: Fix typo in constant name.

The constant name has a typo: "Attepmts" should be "Attempts".

Apply this diff to fix the typo:

-const maxImageRetrievalAttepmts = 3
+const maxImageRetrievalAttempts = 3

580-592: Consider adding exponential backoff to retry logic.

The retry logic could benefit from exponential backoff to handle temporary failures more gracefully.

Apply this diff to add exponential backoff:

-    for i := 0; i < maxImageRetrievalAttempts; i++ {
+    for i := 0; i < maxImageRetrievalAttempts; i++ {
+        if i > 0 {
+            time.Sleep(time.Duration(1<<uint(i-1)) * time.Second)
+        }
         viewDataSplitViewSecond, err := ProcessViewImageDataWithOptions(requestConfig, c, isPrefetch, options)
         if err != nil {
             return err
         }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bebddaf and cb7650b.

📒 Files selected for processing (1)
  • internal/routes/routes_asset_helpers.go (5 hunks)
🔇 Additional comments (1)
internal/routes/routes_asset_helpers.go (1)

348-361: LGTM! Well-documented function signature change.

The updated function signature with ViewImageDataOptions parameter improves flexibility and maintainability. The documentation is clear and comprehensive.

internal/routes/routes_asset_helpers.go Show resolved Hide resolved
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)
internal/immich/immich_helpers.go (1)

33-34: Fix typo in documentation comment.

The word "impliment" should be "implement".

-// withImmichApiCache Decorator to impliment cache for the immichApiCall func
+// withImmichApiCache Decorator to implement cache for the immichApiCall func
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between cb7650b and ec37b14.

📒 Files selected for processing (9)
  • internal/immich/immich_album.go (3 hunks)
  • internal/immich/immich_date.go (2 hunks)
  • internal/immich/immich_faces.go (1 hunks)
  • internal/immich/immich_favourites.go (3 hunks)
  • internal/immich/immich_helpers.go (2 hunks)
  • internal/immich/immich_memories.go (2 hunks)
  • internal/immich/immich_person.go (3 hunks)
  • internal/immich/immich_random.go (2 hunks)
  • taskfile.yml (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • taskfile.yml
🚧 Files skipped from review as they are similar to previous changes (6)
  • internal/immich/immich_date.go
  • internal/immich/immich_album.go
  • internal/immich/immich_person.go
  • internal/immich/immich_random.go
  • internal/immich/immich_favourites.go
  • internal/immich/immich_memories.go
🔇 Additional comments (2)
internal/immich/immich_faces.go (1)

80-80: LGTM! The function name change improves clarity.

The renaming from immichApiCallDecorator to withImmichApiCache better reflects the function's purpose of managing API call caching.

internal/immich/immich_helpers.go (1)

274-274: LGTM! The function call is consistently updated.

The change to use withImmichApiCache aligns with the function renaming.

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

♻️ Duplicate comments (1)
internal/routes/routes_asset_helpers.go (1)

462-472: ⚠️ Potential issue

Add error handling for face detection.

The CheckForFaces call should include error handling to prevent potential failures from being silently ignored.

Apply this diff to add error handling:

 func handleFaceProcessing(img image.Image, asset *immich.ImmichAsset, config config.Config, metadata requestMetadata) image.Image {
     if strings.EqualFold(config.ImageEffect, "smart-zoom") && len(asset.People)+len(asset.UnassignedFaces) == 0 {
-        asset.CheckForFaces(metadata.requestID, metadata.deviceID)
+        if err := asset.CheckForFaces(metadata.requestID, metadata.deviceID); err != nil {
+            log.Error("Failed to check for faces", "error", err)
+        }
     }

     if ShouldDrawFacesOnImages() {
         log.Debug("Drawing faces")
         return DrawFaceOnImage(img, asset)
     }
     return img
 }
🧹 Nitpick comments (1)
internal/routes/routes_asset_helpers.go (1)

578-592: Enhance error handling in fetchSecondSplitViewAsset.

The function should return a more descriptive error after maximum attempts, and the magic number should be documented.

Apply this diff to improve the implementation:

 const maxImageRetrievalAttempts = 3
+// maxImageRetrievalAttempts defines the maximum number of attempts to find a unique
+// second image for split view layouts before giving up to prevent infinite loops.

 for i := 0; i < maxImageRetrievalAttempts; i++ {
     viewDataSplitViewSecond, err := ProcessViewImageDataWithOptions(requestConfig, c, isPrefetch, options)
     if err != nil {
         return err
     }

     if viewDataSplitView.ImmichAsset.ID != viewDataSplitViewSecond.ImmichAsset.ID {
         viewData.Assets = append(viewData.Assets, viewDataSplitViewSecond)
         return nil
     }
 }
-return nil
+return fmt.Errorf("failed to find unique second image after %d attempts", maxImageRetrievalAttempts)
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ec37b14 and 4f66df0.

📒 Files selected for processing (2)
  • internal/immich/immich_helpers.go (2 hunks)
  • internal/routes/routes_asset_helpers.go (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/immich/immich_helpers.go
🔇 Additional comments (1)
internal/routes/routes_asset_helpers.go (1)

361-408: Excellent refactoring of processViewImageData!

The function has been well-structured with clear separation of concerns, making it more maintainable and easier to test.

internal/routes/routes_asset_helpers.go Show resolved Hide resolved
@damongolding damongolding merged commit f85a94f into task/release Feb 11, 2025
3 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Feb 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant