Skip to content

Add ImageEnlarger feature with modal viewer#924

Open
PythonSmall-Q wants to merge 16 commits intodevfrom
feat/resize-picture
Open

Add ImageEnlarger feature with modal viewer#924
PythonSmall-Q wants to merge 16 commits intodevfrom
feat/resize-picture

Conversation

@PythonSmall-Q
Copy link
Member

@PythonSmall-Q PythonSmall-Q commented Mar 7, 2026

This pull request adds a new optional "Image Enlargement" feature to the user script, allowing users to click on images to view them in an interactive modal with zoom, reset, and save options. The feature is integrated as a toggleable utility and includes both UI and keyboard controls for improved user experience.

New Feature: Image Enlargement

  • Added a new utility entry for "ImageEnlarger" in the available features list, making the image enlargement functionality toggleable in the script settings.
  • Implemented the image enlargement functionality:
    • Injects custom CSS for preview and modal styling.
    • Adds a modal that displays clicked images with zoom in/out, reset, and save buttons.
    • Supports keyboard shortcuts for zoom and closing the modal.
    • Automatically applies to all existing and dynamically added images, except for avatars.
    • Handles potential errors gracefully, with debug alerts if enabled.

Summary by Sourcery

Add an optional image enlargement utility that provides a modal viewer with zoom and save controls for images across the site.

New Features:

  • Introduce a toggleable "ImageEnlarger" utility in the feature list to enable or disable image enlargement in script settings.
  • Provide a full-screen modal image viewer with zoom in/out, reset, and image download controls, including keyboard shortcuts and click-to-close behavior.
  • Automatically enhance non-avatar images on the page and newly added images with clickable enlargement previews while handling errors via the existing debug mechanism.

Introduce an ImageEnlarger utility: add a toggle option to the feature list and implement a modal image viewer with CSS, toolbar (zoom in/out, reset, save), keyboard shortcuts, and click-to-open behavior. Images are annotated with a preview class and the feature ignores gravatar/cravatar sources; it applies to existing and dynamically added images via a MutationObserver. Errors are logged and surface a DebugMode alert when enabled.
Copilot AI review requested due to automatic review settings March 7, 2026 01:08
@hendragon-bot hendragon-bot bot added the user-script This issue or pull request is related to the main user script label Mar 7, 2026
@PythonSmall-Q PythonSmall-Q requested a review from boomzero March 7, 2026 01:09
@sourcery-ai
Copy link

sourcery-ai bot commented Mar 7, 2026

Reviewer's Guide

Implements a new toggleable ImageEnlarger utility that injects modal-viewer CSS/DOM, wires zoom/reset/save controls and keyboard shortcuts, and automatically decorates non-avatar images (including dynamically added ones) with click-to-enlarge behavior, with errors funneled through existing debug handling.

Sequence diagram for ImageEnlarger click-to-enlarge and controls

sequenceDiagram
    actor User
    participant ImageElement
    participant ImageEnlargerUtility
    participant ImageModal
    participant KeyboardHandler

    User->>ImageElement: click
    ImageElement->>ImageEnlargerUtility: click event handler
    ImageEnlargerUtility->>ImageModal: OpenImageModal(imgSrc)
    ImageModal-->>ImageModal: CurrentZoom = 1
    ImageModal-->>ImageModal: UpdateImageSize()
    ImageModal-->>User: modal displayed with image

    User->>ImageModal: click ZoomInBtn
    ImageModal->>ImageModal: CurrentZoom = min(CurrentZoom + ZoomStep, MaxZoom)
    ImageModal-->>ImageModal: UpdateImageSize()

    User->>ImageModal: click ZoomOutBtn
    ImageModal->>ImageModal: CurrentZoom = max(CurrentZoom - ZoomStep, MinZoom)
    ImageModal-->>ImageModal: UpdateImageSize()

    User->>ImageModal: click ResetZoomBtn
    ImageModal->>ImageModal: CurrentZoom = 1
    ImageModal-->>ImageModal: UpdateImageSize()

    User->>KeyboardHandler: press + or - or Escape
    KeyboardHandler->>ImageModal: handle keydown when modal is show
    alt + key
        KeyboardHandler->>ImageModal: trigger ZoomInBtn.click
    else - key
        KeyboardHandler->>ImageModal: trigger ZoomOutBtn.click
    else Escape key
        KeyboardHandler->>ImageModal: CloseImageModal()
        ImageModal-->>User: modal hidden
    end

    User->>ImageModal: click SaveBtn
    ImageModal->>ImageEnlargerUtility: create temporary anchor with ModalImage.src
    ImageEnlargerUtility-->>User: browser download dialog
Loading

Flow diagram for ImageEnlarger initialization and image handling

flowchart TD
    A[Check UtilityEnabled ImageEnlarger] -->|enabled| B[Inject CSS styles for previews and modal]
    A -->|not enabled| Z[Do nothing]

    B --> C[Create modal container ImageModal]
    C --> D[Add CloseButton to ImageModal]
    D --> E[Create ModalContent with ModalImage]
    E --> F[Create Toolbar with ZoomInBtn ZoomOutBtn ResetZoomBtn SaveBtn]
    F --> G[Append ImageModal to document body]

    G --> H[Initialize zoom state CurrentZoom ZoomStep MinZoom MaxZoom]
    H --> I[Register event handlers]

    I --> I1[CloseButton click -> CloseImageModal]
    I --> I2[ImageModal click on background -> CloseImageModal]
    I --> I3[ZoomInBtn click -> increase CurrentZoom and UpdateImageSize]
    I --> I4[ZoomOutBtn click -> decrease CurrentZoom and UpdateImageSize]
    I --> I5[ResetZoomBtn click -> reset CurrentZoom and UpdateImageSize]
    I --> I6[SaveBtn click -> create download link from ModalImage.src]
    I --> I7[document keydown when modal show -> handle Escape plus minus]

    I --> J[ApplyEnlargerToImages on existing images]
    J --> J1[Select all img elements]
    J1 --> J2{Is candidate image?}
    J2 -->|yes| J3[Add class xmoj-image-preview and click handler to open modal]
    J2 -->|no| J4[Skip image]

    J --> K[Create MutationObserver]
    K --> L[Observer.observe document body childList subtree]
    L --> M[On mutations -> ApplyEnlargerToImages again]

    subgraph ErrorHandling
        N[try block around ImageEnlarger setup]
        N -->|throws| O[catch e]
        O --> P[console.error e]
        P --> Q{UtilityEnabled DebugMode?}
        Q -->|yes| R[SmartAlert with error details]
        Q -->|no| S[End]
    end
Loading

File-Level Changes

Change Details Files
Added ImageEnlarger as a configurable utility option in the feature list so the enlargement behavior can be toggled via script settings.
  • Extended the utilities configuration array with a new entry for the ImageEnlarger feature.
  • Positioned the new utility alongside existing popup and debug options to keep feature ordering consistent.
XMOJ.user.js
Implemented the ImageEnlarger modal viewer with styling, controls, keyboard shortcuts, and automatic binding to page images.
  • Injected a <style> block defining preview hover styling, modal layout, toolbar, and close button appearance for the image viewer.
  • Programmatically created and appended the modal DOM structure, including image container, toolbar buttons (zoom in/out, reset, save), and close control.
  • Maintained zoom state with bounds and applied scaling via CSS transforms, updating in response to button interactions and keyboard shortcuts (+, -).
  • Handled modal open/close behavior via click handlers (image click, close button, backdrop click) and Escape key handling.
  • Implemented a save action that constructs a temporary download link for the currently displayed image source.
  • Introduced ApplyEnlargerToImages to attach click-to-enlarge behavior to all qualifying tags while skipping avatar-like sources (gravatar/cravatar) and the modal image itself.
  • Set up a MutationObserver on document.body so newly added images are also processed by ApplyEnlargerToImages.
  • Wrapped the entire feature in a UtilityEnabled("ImageEnlarger") guard and a try/catch that logs errors and surfaces them through SmartAlert when DebugMode is active.
XMOJ.user.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

This comment was marked as outdated.

sourcery-ai[bot]

This comment was marked as outdated.

cubic-dev-ai[bot]

This comment was marked as outdated.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="XMOJ.user.js">

<violation number="1" location="XMOJ.user.js:5811">
P2: The modal image is not actually excluded from enhancement because the parent-class check targets the wrong element.</violation>

<violation number="2" location="XMOJ.user.js:5819">
P2: Image clicks don’t prevent default link navigation, so linked images can navigate away instead of staying in the modal viewer.</violation>

<violation number="3" location="XMOJ.user.js:5827">
P2: The mutation observer triggers a full-image rescan on every DOM mutation, which can cause unnecessary performance overhead.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@PythonSmall-Q
Copy link
Member Author

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link
Contributor

Copilot AI commented Mar 7, 2026

@PythonSmall-Q I've opened a new pull request, #925, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 6 commits March 7, 2026 01:22
…rc, and MutationObserver performance

Co-authored-by: PythonSmall-Q <106425289+PythonSmall-Q@users.noreply.github.com>
Co-authored-by: PythonSmall-Q <106425289+PythonSmall-Q@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Shan Wenxiao <seanoj_noreply@yeah.net>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Shan Wenxiao <seanoj_noreply@yeah.net>
Fix ImageEnlarger: accessibility, modal re-entry, responsive images, MutationObserver perf
Copy link
Member

@boomzero boomzero left a comment

Choose a reason for hiding this comment

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

Last time someone tried to modify every , we ran into some issue with CORS or something, so it's worth checking if every page works

@boomzero
Copy link
Member

boomzero commented Mar 7, 2026

你测试一下短消息内嵌图片

@PythonSmall-Q
Copy link
Member Author

你测试一下短消息内嵌图片

都测试过了,没有问题

@PythonSmall-Q
Copy link
Member Author

@copilot 放大图片后需要可以让用户左右滑动,同时下载图片应该直接调出下载而不是redir到地址

Copy link
Contributor

Copilot AI commented Mar 8, 2026

@PythonSmall-Q I've opened a new pull request, #926, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 4 commits March 8, 2026 14:27
Co-authored-by: PythonSmall-Q <106425289+PythonSmall-Q@users.noreply.github.com>
Co-authored-by: PythonSmall-Q <106425289+PythonSmall-Q@users.noreply.github.com>
Co-authored-by: PythonSmall-Q <106425289+PythonSmall-Q@users.noreply.github.com>
Fix image viewer: broken pan, missing wheel zoom, download navigates instead of saving
@pull-request-size pull-request-size bot added size/XL and removed size/L labels Mar 8, 2026
Copy link
Member

@boomzero boomzero left a comment

Choose a reason for hiding this comment

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

If so, lgtm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL user-script This issue or pull request is related to the main user script

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants