Skip to content

Commit 36f5b47

Browse files
committed
rewrote the entire attachment system (+ live sync code chunk + whole project attachment)
1 parent 9989495 commit 36f5b47

3 files changed

Lines changed: 207 additions & 56 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
export default class Attachment {
2+
static _blockly = null;
3+
4+
constructor() {
5+
this._attachment = null;
6+
this._attachmentIds = [];
7+
this._name = null;
8+
this._blockIdMap = new Map(); // For faster lookups
9+
}
10+
11+
static set blockly(blockly) {
12+
if (typeof blockly !== "object" || blockly === null) {
13+
throw new Error("blockly must be a valid object");
14+
}
15+
Attachment._blockly = blockly;
16+
}
17+
18+
attachment(attachment, spriteName = "Sprite1") {
19+
if (Attachment._blockly === null) {
20+
throw new Error("blockly instance is not set. Please set it using Attachment.blockly");
21+
}
22+
if (!attachment || attachment.nodeType !== Node.ELEMENT_NODE) {
23+
throw new Error("Invalid attachment. It must be an XML document element.");
24+
}
25+
26+
this._attachment = attachment;
27+
const blocks = attachment.getElementsByTagName("block");
28+
29+
const blockIds = [];
30+
if(attachment.getAttribute("id")) {
31+
blockIds.push(attachment.getAttribute("id"));
32+
}
33+
for (let block of blocks) {
34+
const id = block.getAttribute("id");
35+
if (id) {
36+
blockIds.push(id);
37+
}
38+
}
39+
if (blockIds.length === 0) {
40+
throw new Error("No blocks found in the attachment.");
41+
}
42+
this._attachmentIds = blockIds;
43+
this._name = `${spriteName} - Code Chunk (${blockIds.length} Blocks)`;
44+
}
45+
46+
get spriteName() {
47+
if (!this._name) {
48+
throw new Error("Attachment is not set. Use the attachment() method first.");
49+
}
50+
return this._name;
51+
}
52+
53+
_buildBlockIdMap(workspace) {
54+
this._blockIdMap.clear();
55+
const blocks = workspace.getElementsByTagName("block");
56+
for (let block of blocks) {
57+
const id = block.getAttribute("id");
58+
if (id) {
59+
this._blockIdMap.set(id, block);
60+
}
61+
}
62+
}
63+
64+
GetAttachment(currentWorkspace) {
65+
if (this._attachmentIds.length === 0) {
66+
throw new Error("Attachment is not set. Use the attachment() method first.");
67+
}
68+
if (!currentWorkspace || currentWorkspace.nodeType !== Node.ELEMENT_NODE) {
69+
throw new Error("Invalid workspace. It must be an XML document element.");
70+
}
71+
72+
this._buildBlockIdMap(currentWorkspace);
73+
74+
// Check head block first
75+
const headBlock = this._blockIdMap.get(this._attachmentIds[0]);
76+
if (headBlock) {
77+
//console.log(`DUBUG: Found head block with ID: ${this._attachmentIds[0]}`);
78+
return headBlock;
79+
}
80+
81+
//console.log("DUBUG: Attachment head block not found in the current workspace.");
82+
// Search other blocks if head block is missing
83+
for (const id of this._attachmentIds) {
84+
const block = this._blockIdMap.get(id);
85+
if (block) {
86+
//console.log(`DUBUG: Found block with ID: ${id}`);
87+
let parent = block;
88+
while (parent.parentNode && parent.parentNode.nodeName.toLowerCase() != "xml"){
89+
parent = parent.parentNode;
90+
}
91+
//console.log(`DUBUG: Found parent block`, parent);
92+
return parent;
93+
}
94+
}
95+
96+
console.warn("Attachment not found in the current workspace.");
97+
return null;
98+
}
99+
}

‎src/addons/addons/ai-integration/helpers.js‎

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,6 @@ export default class helpers {
5555

5656
return result;
5757
}
58-
static removeAttachmentListener() {
59-
document.getElementById('removeAttachement').addEventListener('click', () => {
60-
document.getElementById('attachedFile').remove();
61-
document.AI_INTEGRATION.currentInputHasAttachment = false;
62-
document.AI_INTEGRATION.attachmentDetails.attachmentText = "";
63-
document.AI_INTEGRATION.attachmentDetails.attachmentBlocks = "";
64-
});
65-
}
6658
static updateAIModels(geminiKey, openrouterKey) {
6759
if (document.getElementById('AI_Selector_select') == null) return;
6860
for (var i of document.AI_INTEGRATION.AIModels) {
@@ -98,14 +90,17 @@ export default class helpers {
9890
return fetchPromise
9991
.finally(() => clearTimeout(timeoutId));
10092
}
93+
static disableCodeChunkAttachment() {
94+
document.getElementById('Context_Selector_select').value = '0';
95+
document.getElementById('Context_Selector_select').style.width = "26px";
96+
document.getElementById('Context_Selector_select').children[0].disabled = true;
97+
document.getElementById('Context_Selector_select').children.innerText = "Code Chunk";
98+
}
10199
static messageErrorOccured(messageContents) {
102100
document.AI_INTEGRATION.chatHistory.push({ "role": "user", "message": messageContents });
103101
//document.AI_INTEGRATION.chatHistory.push({ "role": "assistant", "message": "Error reading response" }); //not sure if the AI needs to know that it failed
104102

105-
//clean up attachments
106-
document.AI_INTEGRATION.currentInputHasAttachment = false;
107-
if(document.getElementById('attachedFile') != null) document.getElementById('attachedFile').remove();
108-
103+
helpers.disableCodeChunkAttachment();
109104

110105
document.AI_INTEGRATION.AI_currently_blabbering = false;
111106
if (document.getElementById('currentlyBlabberingOnThis') != null) {
@@ -137,7 +132,7 @@ export default class helpers {
137132
),
138133
]);
139134
}
140-
static async returnEntireProjectAsXML(addon) {
135+
static returnEntireProjectAsXML(addon) {
141136
//create new XML document
142137
const xmlDoc = document.implementation.createDocument("", "", null);
143138

@@ -148,14 +143,16 @@ export default class helpers {
148143
for (var x of addon.tab.redux.state.scratchGui.vm.runtime.targets) {
149144
// Create a child element with text content
150145
const childElement = xmlDoc.createElement("sprite");
146+
//add sprite name as attribute
147+
childElement.setAttribute("name", x.getName());
151148
childElement.innerHTML = x.blocks.toXML();
152149
rootElement.appendChild(childElement);
153150
}
154151
// Serialize XML to string
155152
const serializer = new XMLSerializer();
156153
const xmlString = serializer.serializeToString(xmlDoc);
157154

158-
console.log(xmlString);
155+
return xmlString;
159156
}
160157
static APIKeyRequiredModal() {
161158
const div = document.createElement('div');

0 commit comments

Comments
 (0)