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 Request/Bugfix] Stream Data to/from Quill #65

Open
JaronrH opened this issue Oct 11, 2023 · 1 comment
Open

[Feature Request/Bugfix] Stream Data to/from Quill #65

JaronrH opened this issue Oct 11, 2023 · 1 comment
Labels
Feature Request New feature or request Triage Issue needs to be triaged

Comments

@JaronrH
Copy link

JaronrH commented Oct 11, 2023

I ran into an issue where SignalR fails to send/receive data if the payload is over roughly 32kb. So, if you're trying to use something like LoadContent() or GetContent() with a lot of data, the SignalR connection will be dropped due to an error. I found the solution is to chunk the data using DotNetStreamReference and IJSStreamReference on the .NET side and an ArrayBuffer on the JS side.

For Example... .NET:

    internal static async ValueTask<string> GetContentAsync(
        IJSRuntime jsRuntime,
        ElementReference quillElement)
    {
        var dataReference = await jsRuntime.InvokeAsync<IJSStreamReference>("QuillFunctions.getQuillContent", quillElement);
        await using var dataReferenceStream = await dataReference.OpenReadStreamAsync(maxAllowedSize: 10_000_000);
        var reader = new StreamReader(dataReferenceStream, Encoding.Unicode);
        return await reader.ReadToEndAsync();
    }

    internal static async ValueTask<bool> LoadQuillContentAsync(
        IJSRuntime jsRuntime,
        ElementReference quillElement,
        string content)
    {
        var byteArray = Encoding.Unicode.GetBytes(content);
        var stream = new MemoryStream(byteArray);
        using var streamRef = new DotNetStreamReference(stream: stream, leaveOpen: false);
            return await jsRuntime.InvokeAsync<bool>("QuillFunctions.loadQuillContent", quillElement, streamRef);
    }

JS:

       getQuillContent: async function (quillElement) {
            return str2ab(JSON.stringify(quillElement.__quill.getContents()));
        },
        loadQuillContent: async function (quillElement, quillContentStream) {
            const data = await quillContentStream.arrayBuffer();
            const quillContent = ab2str(data);
            content = JSON.parse(quillContent);
            return quillElement.__quill.setContents(content, 'api') != null;
        },

(Note the return was changed from returning the delta to a boolean -- returning the delta would need to be chunked or the same error would happen again!)

With JS Helper Functions:

    function ab2str(buf) {
        return String.fromCharCode.apply(null, new Uint16Array(buf));
    }

    function str2ab(str) {
        var buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
        var bufView = new Uint16Array(buf);
        for (var i = 0, strLen = str.length; i < strLen; i++) {
            bufView[i] = str.charCodeAt(i);
        }
        return buf;
    }
@JaronrH JaronrH added Feature Request New feature or request Triage Issue needs to be triaged labels Oct 11, 2023
@ADefWebserver
Copy link
Collaborator

I will consider looking at a PR if anyone wants to submit one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request New feature or request Triage Issue needs to be triaged
Projects
None yet
Development

No branches or pull requests

2 participants