Skip to content

feat(Editor): add return value on file upload callback#534

Merged
ArgoZhang merged 2 commits intomasterfrom
feat-editor
Aug 18, 2025
Merged

feat(Editor): add return value on file upload callback#534
ArgoZhang merged 2 commits intomasterfrom
feat-editor

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented Aug 18, 2025

Link issues

fixes #533

Summary By Copilot

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Allow the file upload callback to return a custom URL and use it for inserting uploaded images into the editor

New Features:

  • Support returning a URL string from the OnFileUpload callback
  • Pass the returned URL to the editor and use it as the image source

Bug Fixes:

Enhancements:

  • Update createImage helper to accept an optional URL parameter

@bb-auto bb-auto Bot added the enhancement New feature or request label Aug 18, 2025
@bb-auto bb-auto Bot added this to the v9.2.0 milestone Aug 18, 2025
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Aug 18, 2025

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

This PR enhances the editor’s file upload flow by allowing the OnFileUpload callback to return a URL, which is then used for the inserted image instead of a temporary blob. It updates both the JS initialization logic to await and apply the returned URL, and the C# interop signature to propagate the string result.

Sequence diagram for updated file upload and image insertion flow

sequenceDiagram
    participant JS as Editor.razor.js
    participant CSharp as Editor.razor.cs
    participant Callback as OnFileUpload
    actor User
    User->>JS: Selects file(s) to upload
    JS->>CSharp: ImageUpload(name, type, size, stream)
    CSharp->>Callback: OnFileUpload(file)
    Callback-->>CSharp: Returns image URL
    CSharp-->>JS: Returns image URL
    JS->>JS: createImage(file, url)
    JS->>JS: Insert image node with URL into editor
Loading

Class diagram for updated Editor file upload callback

classDiagram
    class Editor {
        +Func<EditorUploadFile, Task<string>>? OnFileUpload
        +Task<string> ImageUpload(string name, string contentType, long size, IJSStreamReference stream)
    }
    class EditorUploadFile {
        +string Name
        +string ContentType
        +long Size
        +Stream Data
    }
    Editor --> EditorUploadFile: uses
    Editor : OnFileUpload returns Task<string> (URL)
    Editor : ImageUpload returns string (URL)
Loading

Flow diagram for new image insertion using returned URL

flowchart TD
    A[User selects file] --> B[JS receives file]
    B --> C[JS calls C# ImageUpload]
    C --> D[C# calls OnFileUpload]
    D --> E[OnFileUpload returns URL]
    E --> F[JS creates image with URL]
    F --> G[Image inserted into editor]
Loading

File-Level Changes

Change Details Files
Handle returned URL in JavaScript upload flow
  • Await upload callback to get URL before inserting image
  • Pass returned URL into createImage and insertNode
  • Adjust createImage to use URL or fallback to objectURL
src/components/BootstrapBlazor.SummerNote/Components/Editor/Editor.razor.js
Update C# upload callback to return string
  • Change OnFileUpload parameter from Task to Task
  • Capture and return the string result from OnFileUpload
  • Default to empty string when callback returns null
src/components/BootstrapBlazor.SummerNote/Components/Editor/Editor.razor.cs

Assessment against linked issues

Issue Objective Addressed Explanation
#533 Add a return value to the file upload callback in the Editor component.

Possibly linked issues


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

@ArgoZhang ArgoZhang merged commit e14cf45 into master Aug 18, 2025
1 check passed
@ArgoZhang ArgoZhang deleted the feat-editor branch August 18, 2025 06:36
Copy link
Copy Markdown

@sourcery-ai sourcery-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.

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `src/components/BootstrapBlazor.SummerNote/Components/Editor/Editor.razor.js:222` </location>
<code_context>
 }

-const createImage = file => {
+const createImage = (file, url) => {
     const element = document.createElement('img');
-    element.src = URL.createObjectURL(file);
+    element.src = url || URL.createObjectURL(file);
     return element;
 }
</code_context>

<issue_to_address>
The fallback to URL.createObjectURL may leak object URLs if not revoked.

Add logic to revoke the object URL after the image loads to prevent memory leaks when using the fallback.
</issue_to_address>

### Comment 2
<location> `src/components/BootstrapBlazor.SummerNote/Components/Editor/Editor.razor.cs:282` </location>
<code_context>
-            await OnFileUpload(file);
+            ret = await OnFileUpload(file);
         }
+        return ret ?? "";
     }

</code_context>

<issue_to_address>
Returning an empty string may mask upload failures.

Consider returning null or a distinct error value instead, so client-side code can reliably detect upload failures and handle them appropriately.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
    public async Task<string> ImageUpload(string name, string contentType, long size, IJSStreamReference stream)
    {
        string? ret = null;
        await using var data = await stream.OpenReadStreamAsync(size);
        var file = new EditorUploadFile(name, contentType, size, data);
        if (OnFileUpload != null)
        {
            ret = await OnFileUpload(file);
        }
        return ret ?? "";
    }
=======
    public async Task<string?> ImageUpload(string name, string contentType, long size, IJSStreamReference stream)
    {
        string? ret = null;
        await using var data = await stream.OpenReadStreamAsync(size);
        var file = new EditorUploadFile(name, contentType, size, data);
        if (OnFileUpload != null)
        {
            ret = await OnFileUpload(file);
        }
        return ret;
    }
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +222 to +224
const createImage = (file, url) => {
const element = document.createElement('img');
element.src = URL.createObjectURL(file);
element.src = url || URL.createObjectURL(file);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): The fallback to URL.createObjectURL may leak object URLs if not revoked.

Add logic to revoke the object URL after the image loads to prevent memory leaks when using the fallback.

Comment on lines +273 to 283
public async Task<string> ImageUpload(string name, string contentType, long size, IJSStreamReference stream)
{
var data = await stream.OpenReadStreamAsync(size);
string? ret = null;
await using var data = await stream.OpenReadStreamAsync(size);
var file = new EditorUploadFile(name, contentType, size, data);
if (OnFileUpload != null)
{
await OnFileUpload(file);
ret = await OnFileUpload(file);
}
return ret ?? "";
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): Returning an empty string may mask upload failures.

Consider returning null or a distinct error value instead, so client-side code can reliably detect upload failures and handle them appropriately.

Suggested change
public async Task<string> ImageUpload(string name, string contentType, long size, IJSStreamReference stream)
{
var data = await stream.OpenReadStreamAsync(size);
string? ret = null;
await using var data = await stream.OpenReadStreamAsync(size);
var file = new EditorUploadFile(name, contentType, size, data);
if (OnFileUpload != null)
{
await OnFileUpload(file);
ret = await OnFileUpload(file);
}
return ret ?? "";
}
public async Task<string?> ImageUpload(string name, string contentType, long size, IJSStreamReference stream)
{
string? ret = null;
await using var data = await stream.OpenReadStreamAsync(size);
var file = new EditorUploadFile(name, contentType, size, data);
if (OnFileUpload != null)
{
ret = await OnFileUpload(file);
}
return ret;
}

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.

feat(Editor): add return value on file upload callback

1 participant