Hello Joaquim! First of all, I don’t want you to misinterpret this email, please. You know how much I value you as a friend and consider you one of the greatest assets of this community. So, I ask you to take everything I’m about to write with all the affection in the world, which is how I’ve written it.
As I mentioned before, I’m not the one to judge whether something should or shouldn’t be done with AI. If you’d like, and if people are willing to dive in, we could open a parallel philosophical debate about it (I’m serious, even if it’s off-topic, I think, like with other important things in life, we should engage more in debate and discuss constructively—something our society needs more than bread to eat).
The reason for this email is that I’ve reviewed what you sent (I always make an effort to value all contributions, rest assured I’ll never undervalue anything).
The reason I commented in the previous email is that I didn’t want you to spend time cleaning up code that isn’t right, and I’ll try to explain why. I hope this email can serve as a mini-guide or at least help us approach these things correctly from the start, so you can keep improving the collection manager, already on the right track, whether you use ChatGPT or do it yourself.
I won’t get into whether to use AI tools or not. You could have used them, and the code could have been acceptable for a PR. As I’ve said, I’m not going to be the judge there because, as I’ve often pointed out, I’m not the owner of the project. However, I am the person most involved with the code and making significant internal changes, so I feel responsible for trying to steer these efforts so they truly add value and don’t detract in the short term. The great danger here is that it’s “easy” to create things that seem to work but are like putting a stick in the spokes of a bike wheel.
As everything is picking up great momentum, I want everyone who gets excited about contributing to do so on the right path, so we don’t fall back into patching temporary solutions that end up staying forever or creating incomprehensible things that are hard to follow or have a steep learning curve.
What you sent, functionally, does what it’s supposed to, but internally it doesn’t respect how Icestudio works. Basically, it’s a “brute force” solution, a patch (and, as I said, I won’t get into whether it’s better or worse programmed).
Icestudio, though it may not seem like it, is more complex than it appears, and one of the things that’s taking me a lot of time is restructuring the entire core without starting from scratch. Little by little, I’ve been reorganizing the internals (and there’s still more to do), all while ensuring Icestudio keeps working and even improves with each change. This internal structure isn’t just about moving code around; thousands of new lines have been written to create an internal integration protocol and a dedicated working API.
ChatGPT clearly didn’t understand anything and built a solution as it would for a simple webpage script. I’ll try to explain how it should have been done (and in fact, I’m sending it resolved with a video so you can see it in action). At the end of the email, i'm putting a link to download the relevant "well made code" (for some reason gmail don't permit me attach to the email).
One of the tasks I’m prioritizing is documenting Icestudio’s internal plugin system, as it’s the natural way for the system to grow. Everything is plugins, and they communicate with each other through a system of messages and events, after the next wip i'll have two focus, the "collection store" and documentation to motivate others to contribute.
The collection manager isn’t an independent element; it relies on other Icestudio plugins and services to get its data. Therefore, we must see the entire system’s operation as a whole—not out of whim, but because if it’s not done right, functionalities that depend on everything following a standard could break.
What do I mean by “nothing breaks”? For example, the collection tree relies on another component that maintains a database of blocks scanned from the hard drive and keeps a virtual tree of it (to know if a node is open or closed, if a block is in use, etc.). Other plugins could interfere with this at some point (e.g., imagine you or someone else creates a component that, when you open a folder, shows the block icons at the bottom so you can easily drag them… I just thought of this on the spot, it might not make sense, but the idea I want to convey is that there’s a communication and interaction protocol between the different pieces. If we break this organized structure, things might stop working, or in the future, someone who expects things to work a certain way might crash or struggle to debug, thinking it’s their bug when the issue is that a specific service was altered in a non-standard way).
There’s another danger in this regard: ChatGPT, for example, has added a ton of try-catch blocks (a pattern I want to eliminate as much as possible because a poorly managed try-catch is like having an illness you don’t want to acknowledge).
Since ChatGPT naturally didn’t understand how the system works as a whole, it’s also not clear to me that it properly maintained the event flow of the communication bus between plugins (I haven’t analyzed every line, but I got the sense it didn’t maintain the correct flow).
In a complex system, this is very delicate. It’s one thing to use these systems for a specific functionality and another to use them, as in this case, in “vibe coding” mode, like “take all this and give me this other functionality…”
So, to make this constructive, as I mentioned earlier, I’ve developed the same functionality, and I’ll try to explain the proper steps. I’m attaching the folders to replace. I haven’t done the PR because that’s your job, Joaquim ;) In fact, as I mention later, I’d love for you to keep developing it if you’re up for it (you have my full support and help in the process).
Before the explanation, I’d insist that whenever you want to tackle an improvement, we discuss it on GitHub, like we did with what I proposed to @lmcapacho. I think it’s been a super constructive experience, and my idea is to keep doing that. I haven’t opened more issues because no one else has raised their hand, but if someone wants to work on something, just say so, and we’ll start opening tasks. There’s zero pressure—Luis Miguel is moving at his own pace, he’s taken on that task and will take as long as he needs. If it becomes urgent at some point, we’ll lend a hand, or if he gets tired and doesn’t want to finish it alone, he just has to say so. I think good vibes have always prevailed, and the idea is to keep it that way.
For example, the ideal would be to open a task like the one for the code blocks we’re discussing because the collection manager has many possible improvements. If you’re excited about it, phew, that’d be awesome, and I’m willing to help and guide you until we gain traction—count on me without hesitation.
I propose, Joaquim, that if you’re motivated by this module, which is also super useful, we dive in. Open a proposal for discussion on GitHub, we’ll work on it together, and you can get started. For example, I was going to suggest that, based on my code, you get motivated to make the search show open folders. That’d be a good point to solidify your knowledge, see how to manage the tree… The search could be optimized better; I did it your way, parsing the DOM, but in the right place and propagating events correctly. However, it might be more efficient to use the database directly and render the corresponding tree (this would need to be measured; I’m not sure it’s a clear improvement, but it’d be interesting to evaluate). And there are tons of other things on my list.
Whether you use ChatGPT or not to carry out these tasks, everyone should go with what feels most comfortable. I emphasize this because I don’t want the email’s purpose to be misunderstood—I’m not criticizing you for using ChatGPT, but rather that the code isn’t implemented correctly.
Let’s get to the right solution.
First, you need to understand the plugin system minimally. There are different types of plugins:
* System plugins, which have no interface and are processes. Soon, the API will be a plugin, and other components will be able to “request,” for example, synthesizing a specific block or saving a bitstream, etc.
* Independent window plugins, like the serial terminal. A new window opens, and the plugin “lives” in its own universe, though it has a way to request things (in the next WIP, the board manager will be this type and will use Icestudio services to get boards, save them, etc.).
* Embedded window plugins, like the collection manager, which coexist within Icestudio’s graphical window. This is complex because the plugin can have its own interface, colors, etc., and must not interfere with Icestudio.
Let’s focus on the embedded plugin, which is what concerns us. Since the system is designed so anyone can create a plugin, there’s a tricky point: the plugin shouldn’t break Icestudio. And since it’s web technology, playing with CSS, etc., it’s super easy for external code to break Icestudio.
For this, in embedded windows like the collection manager, we use an artifact called shadow DOM (you can look it up if you want). If you open Icestudio’s inspector on the collection manager, you’ll see this:

This indicates that the entire HTML node is inside a shadow DOM, which is essentially an independent element with its own CSS events, etc. (this is the basis of web components used by frameworks like React, Vue, etc.).
Because of this, the plugin has two base CSS files: host.css and style.css. The styles that affect the plugin itself go in style.css, and if we need to add CSS that, for some reason.
The styles that will affect the plugin itself will go in style.css, and if we want to add any CSS that, for some reason, needs to be inherited by Icestudio, it will be added to host.css (the host is the node that will embed our shadow DOM). In general, host.css will always remain empty.
Then, in the case of the Collection Manager, you have the folders related to the stylesheets for the light and dark themes.
So, in general, for example, in this case, for the search input, I’ve added the only two styles I needed to style.css.
Now, the code—let’s see how this should have been integrated correctly.
All plugins have an HTML file with the plugin’s base content (it can be modified later, but so to speak, this is what will be loaded initially into the shadow DOM).
In this case, just like ChatGPT did, the search bar is added:
https://fontawesome.com/search?o=r&s=solidWe only have the free, open-source ones included, but there are plenty (magnifying glasses and anything else you might need). Why is this? To ensure everything done in Icestudio has a consistent aesthetic. In the new version, I’m restructuring icons and a ton of other things that right now are a bit of a mess, each from a different source.
I mention this because, in ChatGPT’s version, an icon was included directly as an SVG source. Icestudio is already quite overloaded, and although it may seem trivial, an SVG consists of several nodes and is something that’s hard to maintain in the future (color changes, aesthetic consistency with other icons, etc.).
As I said, my version doesn’t have an icon, but it could be one of the changes Joaquim makes. Instead of real-time, you could switch to a click-based search with a magnifying glass. I think this is what I mentioned we should discuss, as it’s an important component.
With this, the search bar would already appear in our Collection Manager. Now let’s give it functionality.
This case is ideal because, by doing it right, we not only add a search feature to the Collection Manager but also, in one fell swoop, any other components that might need a search function in a tree would get it automatically. Let me explain.
The correct way to proceed would have been to first create an event handler for the input in the Collection Manager. To do this, you’d add a block similar to what’s done for handling click events on the tree:
As I mentioned, Icestudio has an internal API, and I hope it keeps growing so we can create plugins very quickly. To achieve this, I’m encapsulating functionalities as they arise (I have a huge list for the API, but they’re for the future, and since they haven’t been needed yet, I haven’t invested time in them—I implement what I need as I go). Among these functionalities, Icestudio’s API manages mouse and keyboard events. The idea is that plugins, whenever possible, don’t need to touch the DOM or manipulate jQuery directly—all that kind of stuff will be handled by Icestudio’s API.
In this case, you specify the ID of the element to capture, pass the shadow DOM node (since it belongs to the plugin, and otherwise Icestudio wouldn’t be able to access it), and then provide the function that will handle the events in the plugin (Icestudio captures the events, manages them, etc., and calls the relevant user functions).

This makes it easier in the future for multiple plugins to associate with event captures on similar elements, allowing them to perform different actions independently without knowing about each other or risking blocking one another.
The management function inside the Collection Manager is super simple:

Why is it so simple? Because the collection tree has its own component within Icestudio. It’s a component for creating nested trees. In this case, it’s used to display collections, but the tree could be used for anything else. Once again, the idea is to create components that can be reused in plugins easily.
For example, in the new version I’m about to release, we’ll have a board manager to edit, create, etc., boards directly from Icestudio. It uses this same component. All the work of displaying the tree, etc= etc., doesn’t need to be redone—you just load the component and link specific user functions to certain events (clicks on leaf elements, folder clicks, etc.).
The components are located in  resources/libs/Icestudio
There, little by little, all the core parts of Icestudio will be modularized. For this specific case, since we didn’t have the input event handled, I had to implement it. Now the good thing is that for any future component or plugin, we already have the input event captured (and this will keep happening with whatever we need—checkboxes, etc.). We capture input instead of, say, keyup, because input allows capturing the “paste” event.
So, just this once, we had to touch the file GUI/WaffleGUI.js inside that folder, specifically the activateEventsFromId function.
As I mentioned, for this type of input, we won’t need to touch it again, and as I said, if we keep advancing with plugins, developing new ones will become much more agile.
And as you can see in the Collection Manager’s user function, within our function, we call a function from the CollectionsTree component called filter.
We also had to implement this function, which is similar to the one ChatGPT implemented for filtering but located in the GUI/WaffleUITree.js component.
I implemented two functions: the main one, filter, which receives the text to search for, and another one you can see in the image that sets the visibility state of the containing folders.
