Skip to content

Decorations with the HTMLDecorationTemplate width value = .viewport show outside safe area in iPhone landscape #660

@sstennis1

Description

@sstennis1

Describe the bug

I've added a decoration for an image that is displayed on the left margin of the page near a saved highlight. However, when on an iPhone in landscape mode the decoration is displayed outside the safe area to the far left of the screen instead of within the safe area and near the page text (see attached screenshots). Below is the custom template logic for this decoration. This looks like a bug in the R2 handling, but I'm not certain. Please let me know if you need any further information. Thanks!

    /// The note icon needs to be positioned wherever the associated annotation text is in the reflowable content.
    /// Setting the left, right, top or bottom attributes will disrupt the correct positioning of the image.
    /// This is different than the bent corner bookmark, which is always positioned in the either top left or right corner of the page.
    static func makeAnnotationNoteTemplate(className: String) -> HTMLDecorationTemplate {
        let dimension = UIDevice.current.iPhone ? "20px" : "24px"
        let margin = UIDevice.current.iPhone ? "4px" : "4px"
        let styleSheet = """
                .\(className) {
                    z-index: 2 !important;
                    height: \(dimension) !important;
                    width: \(dimension) !important;
                    margin-left: \(margin);
                }
            """
        
        return HTMLDecorationTemplate(
            layout: .bounds,
            width: .viewport,
            element: { decoration in
                if let config = decoration.style.config as? Decoration.Style.ImageConfig {
                    let altStr = "annotation note"
                    if let imageURL = config.relativeUrl {
                        return "<div class=\"\(className)\"><img src=\"\(imageURL)\" alt=\"\(altStr)\" style=\"width:\(dimension) !important;\"/></div>"
                    }
                    else if let image64Data = config.imageBase64Data {
                        return "<div class=\"\(className)\"><img src=\"data:image/png;base64, \(image64Data)\" alt=\"\(altStr)\" style=\"width:\(dimension) !important;\"/></div>"
                    }
                    return "<div class=\"\(className)\"><img alt=\"\(altStr)\"/></div>"
                }
                else {
                    return "<div/>"
                }
            },
            stylesheet: styleSheet
        )
    }

How to reproduce?

I don't have steps for the test app, as this is supported in the app I'm working on, but the steps are essentially:

  1. Highlight some text in the epub reflowable content and save it as a highlight to display whenever viewing that page of the book.
  2. Tap on the highlight and tap on the add note icon of the context menu.
  3. Add some text for a note in the editor and save the note.
  4. See the note icon displayed in the left margin near the highlighted text.
  5. Rotate the iPhone device to landscape orientation.
  6. See the note icon displayed on the far left of the screen, perhaps obscured by the 'notch'.

Readium version

3.4.0

OS version

iOS 26.0, iOS 18.5

Testing device

iPhone 16 Pro

Environment

macOS: 15.6
platform: arm64
Xcode 26.0.1 Build version 17A400

Additional context

Image Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions