bric3 / excalidraw-jetbrains-plugin

Create or edit Excalidraw files within Jetbrains IDEs (IntelliJ, CLion, Webstorm, Goland, ...)
https://plugins.jetbrains.com/plugin/17096-excalidraw-integration/
MIT License
77 stars 12 forks source link

Handle embedded images added to a drawing #199

Open bric3 opened 9 months ago

bric3 commented 9 months ago
  1. Copy image to excalidraw
  2. Close drawing
  3. Re-open

The drawing have the placeholder for the image, but the image was not saved.

[!INFO] The issue is the lack of APIs to load binary files in the excalidraw js library (see #200).

ixqbar commented 6 months ago

+1

bric3 commented 5 months ago

Feel free to contribute to speed things up.

lionelhorn commented 2 months ago

@bric3

I tried to have a look at the issue. My approch was to get the initialData and only then render the

 <Excalidraw />

component. Doing it like that, it seems there is no need to use the api to updateScene or anything.

https://github.com/user-attachments/assets/23740b27-0df5-4f8d-b8c3-01c5ac44af41

lionelhorn commented 2 months ago

Changed too much stuff in my fork to be able to do a small PR. But I linked my version above. I would be glad to help to get this issue fixed. Let me know.

bric3 commented 2 months ago

@lionelhorn, I'm going on holiday soon. So I don't know when I will be able to have good look at your work.

Also as you may have guessed, I'm far from a web-developer. I have a very shallow understanding of React itself, even Typescript. So when I see the proposition is to use Vite or tailwind, whose I know nothing but the name, I'm lost. I'm not against those two, but still I need to digest that. So maybe you could also help me by detailing the thought process why it's needed, etc. So I can have a better understanding of the stakes and the overall change. Does an iframe is necessary ? By the way I like how you split the files, it feels much better and cleaner that way.

By the way thank you very much for helping me fixing this.

lionelhorn commented 2 months ago

@bric3 Many of the deps I used are not necessary but are what I'm familiar to and I used them to get something running quickly.

My first issue (that may come from my lack of knowledge of the jetbrains plugin dev lifecycle & gradle) was that, in development mode, I needed to close the sandbox ide window and rerun the "run plugin" task just to see changes in the html and js assets. Which lead to a poor DX.

That's why I added vite. For its HMR capabilities in dev. When I made a change to the html UI, the iframe just updated with the new code.

Tailwind is not necessary at all. Juste added it to style a little overlay debug div to display inner state on page (separate from the native jetbrains UI)

Mobx is used for state management replacing react useState. Again not necessary. Just what was easier for me to get something cleaner code wise than passing the setters of useState to the bridge.

Iframe probably not necessary either. Just let me reuse the gradle task and assets bundling from your existing excalidraw-assets gradle build as I'm not familiar enough with it to modify it.

lionelhorn commented 2 months ago

I tried to do a simpler rewrite by not introducing any additinal deps (no vite, no tailwind, no mobx). The only thing I didn't manage to do was a clean api with only react state management (useState)

As there is a need for the Excalidraw component to re-render based on viewMode, theme, etc..

bric3 commented 2 months ago

I needed to close the sandbox ide window and rerun the "run plugin" task just to see changes in the html and js assets. Which lead to a poor DX.

Yeah, I haven't quite got around that yet. It probably needs custom development mode that looks for a different source location.

I just googled HMR, is it Hot Module Replacement ?

I tried to do a simpler rewrite by not introducing any additinal deps (no vite, no tailwind, no mobx). The only thing I didn't manage to do was a clean api with only react state management (useState)

Yeah that feels like a smaller step.

I'll think of how to hot reload things. Are you using directly yarn or other nodejs based executable to build instead of gradle tasks ?

lionelhorn commented 2 months ago

I just googled HMR, is it Hot Module Replacement ?

Yes

I'll think of how to hot reload things. Are you using directly yarn or other nodejs based executable to build instead of gradle tasks ?

When I use vite for a frontend app like here. I just use the build tooling included in vite started via vite build

bric3 commented 2 months ago

@lionelhorn I have merged some work related to IntelliJ Plugin building (necessary when targeting 2024.2). I will try to find some time to improve the hot reload of the web-app without restarting the runned IJ.

bric3 commented 2 months ago

@lionelhorn I pushed a preliminary support for loading the web-app from a different path. At this time when the sandboxed ID is run (Run Excalidraw Plugin), or via ./gradlew :plugin:runIde it teels the plugin to load files from

excalidraw-assets
├── build
│   ├── assets
│   ├── react-build <2>
│   └── ...
└── ...

Where the assets directory contains Excalidraw JS and fonts and react-build is where the app build is located.

In order to generate those directories you can use ./gradlew :excalidraw-assets:assembleFrontend (which can be run from IntelliJ, Gradle toolwindow then select the right task in excalidraw-assets). To use the new web-app, just close the current editor in the sandbox and re-open one, it will load the updates files. At this time this kinda tied to Gradle, I may improve the situation as I learn more.

More details in this commit : 2018b71fb53f66fdb030d1438882b7449ffacc59

lionelhorn commented 2 months ago

Thanks @bric3 for the update. I'll have a look at the commit.

bric3 commented 1 month ago

@lionelhorn FYI I'm looking at your changes and try to integrate them on the latest commit on master.

image

See #200

lionelhorn commented 1 month ago

@bric3 Good news! Were you able to get it working on your end?

bric3 commented 1 month ago

Yes :)

bric3 commented 1 month ago

I'd like to test a bit more before merging your work.

Also, @lionelhorn maybe you could re-review the change, if you feel something is incorrect or could be improved on this code. I get the most of this change but I may have not captured everything and as such left some bug when porting your great changes.

I'm really happy over how the code is now broken down to smaller pieces.

bric3 commented 1 month ago

There's still a few issues, I'm not sure how to address this at this time.

2024-09-02 09:40:31,435 [   9829]   WARN - #c.i.s.ComponentManagerImpl - com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable initializer requests com.intellij.util.LocaleSensitiveApplicationCacheService instance
2024-09-02 09:40:33,574 [  11968]   WARN - #com.github.bric3.excalidraw.editor.ExcalidrawWebViewController - repro.excalidraw: runJS: controller is disposed: saveAsCoroutines
2024-09-02 09:40:33,574 [  11968]   WARN - #com.github.bric3.excalidraw.editor.ExcalidrawWebViewController - repro.excalidraw: runJS: controller is disposed: saveAsCoroutines
2024-09-02 09:40:33,906 [  12300] SEVERE - #com.github.bric3.excalidraw.editor.ExcalidrawWebViewController - hello.excalidraw: [LOGSEVERITY_ERROR][https://excalidraw-jetbrains-plugin/static/js/main.0e5247f0.js:43]:
Uncaught TypeError: window.cefQuery is not a function
java.lang.Throwable: hello.excalidraw: [LOGSEVERITY_ERROR][https://excalidraw-jetbrains-plugin/static/js/main.0e5247f0.js:43]:
Uncaught TypeError: window.cefQuery is not a function
    at com.intellij.openapi.diagnostic.Logger.error(Logger.java:376)
    at com.github.bric3.excalidraw.editor.ExcalidrawWebViewController$initJcefPanel$5.onConsoleMessage(ExcalidrawWebViewController.kt:219)
    at com.intellij.ui.jcef.JBCefClient$3.lambda$onConsoleMessage$4(JBCefClient.java:301)
    at com.intellij.ui.jcef.JBCefClient$HandlerSupport.lambda$handle$0(JBCefClient.java:733)
    at java.base/java.lang.Iterable.forEach(Iterable.java:75)
    at java.base/java.util.Collections$SynchronizedCollection.forEach(Collections.java:2131)
    at com.intellij.ui.jcef.JBCefClient$HandlerSupport.handle(JBCefClient.java:733)
    at com.intellij.ui.jcef.JBCefClient$HandlerSupport.handleBoolean(JBCefClient.java:738)
    at com.intellij.ui.jcef.JBCefClient$3.onConsoleMessage(JBCefClient.java:300)
    at jcef/org.cef.CefClient.onConsoleMessage(CefClient.java:354)
...
2024-09-02 09:41:09,502 [  47896] SEVERE - #c.i.u.SlowOperations - Slow operations are prohibited on EDT. See SlowOperations.assertSlowOperationsAreAllowed javadoc.
java.lang.Throwable: Slow operations are prohibited on EDT. See SlowOperations.assertSlowOperationsAreAllowed javadoc.
    at com.intellij.openapi.diagnostic.Logger.error(Logger.java:376)
    at com.intellij.util.SlowOperations.assertSlowOperationsAreAllowed(SlowOperations.java:101)
    at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexDataImpl.ensureIsUpToDate(WorkspaceFileIndexDataImpl.kt:130)
    at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexDataImpl.getFileInfo(WorkspaceFileIndexDataImpl.kt:75)
    at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexImpl.getFileInfo(WorkspaceFileIndexImpl.kt:247)
    at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexImpl.findFileSet(WorkspaceFileIndexImpl.kt:203)
    at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexImpl.isInContent(WorkspaceFileIndexImpl.kt:69)
    at com.intellij.openapi.roots.impl.ProjectFileIndexImpl.isInContent(ProjectFileIndexImpl.java:206)
    at com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider.isProjectFile(NonProjectFileWritingAccessProvider.java:136)
    at com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider.isWriteAccessAllowed(NonProjectFileWritingAccessProvider.java:122)
    at com.github.bric3.excalidraw.editor.ExcalidrawEditorProvider$createEditorAsync$1.build(ExcalidrawEditorProvider.kt:20)
...
2024-09-02 09:42:07,651 [ 106045] SEVERE - #com.github.bric3.excalidraw.editor.ExcalidrawWebViewController - with-embedded-pic-2024-01-09-1133.excalidraw.svg: [LOGSEVERITY_ERROR][https://excalidraw-jetbrains-plugin/static/js/main.0e5247f0.js:43]:
Uncaught (in promise) Error: Excalidraw api not defined.
java.lang.Throwable: with-embedded-pic-2024-01-09-1133.excalidraw.svg: [LOGSEVERITY_ERROR][https://excalidraw-jetbrains-plugin/static/js/main.0e5247f0.js:43]:
Uncaught (in promise) Error: Excalidraw api not defined.
    at com.intellij.openapi.diagnostic.Logger.error(Logger.java:376)
    at com.github.bric3.excalidraw.editor.ExcalidrawWebViewController$initJcefPanel$5.onConsoleMessage(ExcalidrawWebViewController.kt:219)
...