Skip to content

Commit cac9ac1

Browse files
committed
refactor: move ai from remote functions to its respective file
1 parent e3d0989 commit cac9ac1

File tree

3 files changed

+251
-277
lines changed

3 files changed

+251
-277
lines changed

src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

Lines changed: 1 addition & 277 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ function RemoteFunctions(config = {}) {
4949
let _nodeInfoBox;
5050
let _nodeMoreOptionsBox;
5151
let _moreOptionsDropdown;
52-
let _aiPromptBox;
5352
let _hotCorner;
5453
let _setup = false;
5554
let _hoverLockTimer = null;
@@ -294,18 +293,6 @@ function RemoteFunctions(config = {}) {
294293
return element.offsetTop + (element.offsetParent ? getDocumentOffsetTop(element.offsetParent) : 0);
295294
}
296295

297-
/**
298-
* This function gets called when the AI button is clicked
299-
* it shows a AI prompt box to the user
300-
* @param {Event} event
301-
* @param {DOMElement} element - the HTML DOM element that was clicked
302-
*/
303-
function _handleAIOptionClick(event, element) {
304-
// make sure there is no existing AI prompt box, and no other box as well
305-
dismissAllUIBoxes();
306-
_aiPromptBox = new AIPromptBox(element); // create a new one
307-
}
308-
309296
/**
310297
* This function will get triggered when from the multiple advance DOM buttons, one is clicked
311298
* this function just checks which exact button was clicked and call the required function
@@ -316,9 +303,7 @@ function RemoteFunctions(config = {}) {
316303
function handleOptionClick(e, action, element) {
317304
if (action === "edit-text") {
318305
startEditing(element);
319-
} else if (action === "ai") {
320-
_handleAIOptionClick(e, element);
321-
} else if(LivePreviewView.getNodeMoreOptionsHandler(action)) {
306+
}else if(LivePreviewView.getNodeMoreOptionsHandler(action)) {
322307
const handler = LivePreviewView.getNodeMoreOptionsHandler(action);
323308
return handler && handler.handleClick && handler.handleClick(e, element);
324309
}
@@ -684,12 +669,6 @@ function RemoteFunctions(config = {}) {
684669

685670
let content = `<div class="node-options">`;
686671

687-
// @abose @devansh
688-
// hiding it for now as AI is not yet ready
689-
// content += `<span data-action="ai" title="${strings.ai}">
690-
// ${ICONS.ai}
691-
// </span>`;
692-
693672
// Only include edit text option if element supports it
694673
if (showEditTextOption) {
695674
content += `<span data-action="edit-text" class="lp-opt-edit-text" title="${strings.editText}">
@@ -1097,210 +1076,6 @@ function RemoteFunctions(config = {}) {
10971076
}
10981077
};
10991078

1100-
// AI prompt box, it is displayed when user clicks on the AI button in the more options box
1101-
function AIPromptBox(element) {
1102-
this.element = element;
1103-
this.selectedModel = 'fast';
1104-
this.remove = this.remove.bind(this);
1105-
this.create();
1106-
}
1107-
1108-
AIPromptBox.prototype = {
1109-
_getBoxPosition: function(boxWidth, boxHeight) {
1110-
const elemBounds = this.element.getBoundingClientRect();
1111-
const offset = LivePreviewView.screenOffset(this.element);
1112-
1113-
let topPos = offset.top - boxHeight - 6; // 6 for just some little space to breathe
1114-
let leftPos = offset.left + elemBounds.width - boxWidth;
1115-
1116-
// Check if the box would go off the top of the viewport
1117-
if (elemBounds.top - boxHeight < 6) {
1118-
topPos = offset.top + elemBounds.height + 6;
1119-
}
1120-
1121-
// Check if the box would go off the left of the viewport
1122-
if (leftPos < 0) {
1123-
leftPos = offset.left;
1124-
}
1125-
1126-
return {topPos: topPos, leftPos: leftPos};
1127-
},
1128-
1129-
_style: function() {
1130-
this.body = window.document.createElement("div");
1131-
this.body.setAttribute(GLOBALS.PHCODE_INTERNAL_ATTR, "true");
1132-
// using shadow dom so that user styles doesn't override it
1133-
const shadow = this.body.attachShadow({ mode: "open" });
1134-
1135-
// Calculate responsive dimensions based on viewport width
1136-
const viewportWidth = window.innerWidth;
1137-
let boxWidth, boxHeight;
1138-
1139-
if (viewportWidth >= 400) {
1140-
boxWidth = Math.min(310, viewportWidth * 0.85);
1141-
boxHeight = 60;
1142-
} else if (viewportWidth >= 350) {
1143-
boxWidth = Math.min(275, viewportWidth * 0.85);
1144-
boxHeight = 70;
1145-
} else if (viewportWidth >= 300) {
1146-
boxWidth = Math.min(230, viewportWidth * 0.85);
1147-
boxHeight = 80;
1148-
} else if (viewportWidth >= 250) {
1149-
boxWidth = Math.min(180, viewportWidth * 0.85);
1150-
boxHeight = 100;
1151-
} else if (viewportWidth >= 200) {
1152-
boxWidth = Math.min(130, viewportWidth * 0.85);
1153-
boxHeight = 120;
1154-
} else {
1155-
boxWidth = Math.min(100, viewportWidth * 0.85);
1156-
boxHeight = 140;
1157-
}
1158-
1159-
const content = `
1160-
<div class="phoenix-ai-prompt-box">
1161-
<div class="phoenix-ai-prompt-input-container">
1162-
<textarea
1163-
class="phoenix-ai-prompt-textarea"
1164-
placeholder="${strings.aiPromptPlaceholder}"
1165-
></textarea>
1166-
</div>
1167-
<div class="phoenix-ai-bottom-controls">
1168-
<select class="phoenix-ai-model-select">
1169-
<option value="fast">Fast AI</option>
1170-
<option value="moderate">Moderate AI</option>
1171-
<option value="slow">Slow AI</option>
1172-
</select>
1173-
<button class="phoenix-ai-prompt-send-button" disabled>
1174-
${icons.paperPlane}
1175-
</button>
1176-
</div>
1177-
</div>
1178-
`;
1179-
1180-
shadow.innerHTML = `
1181-
<style>
1182-
${cssStyles.aiPromptBox}
1183-
:host {
1184-
--ai-box-width: ${boxWidth}px;
1185-
--ai-box-height: ${boxHeight}px;
1186-
}
1187-
</style>
1188-
${content}
1189-
`;
1190-
this._shadow = shadow;
1191-
},
1192-
1193-
create: function() {
1194-
this._style();
1195-
window.document.body.appendChild(this.body);
1196-
1197-
// Get the actual rendered dimensions of the box and position it
1198-
const boxElement = this._shadow.querySelector('.phoenix-ai-prompt-box');
1199-
if (boxElement) {
1200-
const boxRect = boxElement.getBoundingClientRect();
1201-
const pos = this._getBoxPosition(boxRect.width, boxRect.height);
1202-
1203-
boxElement.style.left = pos.leftPos + 'px';
1204-
boxElement.style.top = pos.topPos + 'px';
1205-
}
1206-
1207-
// Focus on the textarea
1208-
const textarea = this._shadow.querySelector('.phoenix-ai-prompt-textarea');
1209-
if (textarea) { // small timer to make sure that the text area element is fetched
1210-
setTimeout(() => textarea.focus(), 50);
1211-
}
1212-
1213-
this._attachEventHandlers();
1214-
1215-
// Prevent clicks inside the AI box from bubbling up and closing it
1216-
this.body.addEventListener('click', (event) => {
1217-
event.stopPropagation();
1218-
});
1219-
},
1220-
1221-
_attachEventHandlers: function() {
1222-
const textarea = this._shadow.querySelector('.phoenix-ai-prompt-textarea');
1223-
const sendButton = this._shadow.querySelector('.phoenix-ai-prompt-send-button');
1224-
const modelSelect = this._shadow.querySelector('.phoenix-ai-model-select');
1225-
1226-
// Handle textarea input to enable/disable send button
1227-
if (textarea && sendButton) {
1228-
textarea.addEventListener('input', (event) => {
1229-
const hasText = event.target.value.trim().length > 0;
1230-
sendButton.disabled = !hasText;
1231-
});
1232-
1233-
// enter key
1234-
textarea.addEventListener('keydown', (event) => {
1235-
if (event.key === 'Enter' && !event.shiftKey) {
1236-
event.preventDefault();
1237-
if (textarea.value.trim()) {
1238-
this._handleSend(event, textarea.value.trim());
1239-
}
1240-
} else if (event.key === 'Escape') {
1241-
event.preventDefault();
1242-
this.remove();
1243-
}
1244-
});
1245-
}
1246-
1247-
// send button click
1248-
if (sendButton) {
1249-
sendButton.addEventListener('click', (event) => {
1250-
event.preventDefault();
1251-
event.stopPropagation();
1252-
if (textarea && textarea.value.trim()) {
1253-
this._handleSend(event, textarea.value.trim());
1254-
}
1255-
});
1256-
}
1257-
1258-
// model selection change
1259-
if (modelSelect) {
1260-
modelSelect.addEventListener('change', (event) => {
1261-
this.selectedModel = event.target.value;
1262-
});
1263-
}
1264-
},
1265-
1266-
_handleSend: function(event, prompt) {
1267-
const element = this.element;
1268-
if(!LivePreviewView.isElementEditable(element)) {
1269-
return;
1270-
}
1271-
const tagId = element.getAttribute(GLOBALS.DATA_BRACKETS_ID_ATTR);
1272-
1273-
window._Brackets_MessageBroker.send({
1274-
livePreviewEditEnabled: true,
1275-
event: event,
1276-
element: element,
1277-
prompt: prompt,
1278-
tagId: Number(tagId),
1279-
selectedModel: this.selectedModel,
1280-
AISend: true
1281-
});
1282-
this.remove();
1283-
},
1284-
1285-
remove: function() {
1286-
if (this._handleKeydown) {
1287-
document.removeEventListener('keydown', this._handleKeydown);
1288-
this._handleKeydown = null;
1289-
}
1290-
1291-
if (this._handleResize) {
1292-
window.removeEventListener('resize', this._handleResize);
1293-
this._handleResize = null;
1294-
}
1295-
1296-
if (this.body && this.body.parentNode && this.body.parentNode === window.document.body) {
1297-
window.document.body.removeChild(this.body);
1298-
this.body = null;
1299-
_aiPromptBox = null;
1300-
}
1301-
}
1302-
};
1303-
13041079
/**
13051080
* hot corner class,
13061081
* to switch to preview mode and back
@@ -1793,7 +1568,6 @@ function RemoteFunctions(config = {}) {
17931568
function selectElement(element) {
17941569
dismissNodeMoreOptionsBox();
17951570
dismissMoreOptionsDropdown();
1796-
dismissAIPromptBox();
17971571
dismissNodeInfoBox();
17981572
dismissToastMessage();
17991573
cleanupPreviousElementState();
@@ -2068,12 +1842,6 @@ function RemoteFunctions(config = {}) {
20681842
_nodeInfoBox.remove();
20691843
_nodeInfoBox = new NodeInfoBox(element);
20701844
}
2071-
2072-
if (_aiPromptBox) {
2073-
const element = _aiPromptBox.element;
2074-
_aiPromptBox.remove();
2075-
_aiPromptBox = new AIPromptBox(element);
2076-
}
20771845
}
20781846

20791847
// redraw active highlights
@@ -2158,49 +1926,16 @@ function RemoteFunctions(config = {}) {
21581926
}
21591927
}
21601928

2161-
// this function is responsible to reposition the AI box
2162-
// so we need to reposition it when for ex: a fixed positioned element is selected in the live preview
2163-
// now when live preview is scrolled the element remains at a fixed position but the AI box will drift away
2164-
// so we reposition it when its a fixed element
2165-
function _repositionAIBox() {
2166-
if (!_aiPromptBox || !_aiPromptBox.element || !_aiPromptBox._shadow) { return; }
2167-
2168-
const aiBox = _aiPromptBox._shadow.querySelector('.phoenix-ai-prompt-box');
2169-
if (!aiBox) { return; }
2170-
2171-
const aiBoxBounds = aiBox.getBoundingClientRect();
2172-
const elementBounds = _aiPromptBox.element.getBoundingClientRect();
2173-
2174-
// this is to store the prev value, so that we can compare it the second time
2175-
if(!_aiPromptBox._possDifference) {
2176-
_aiPromptBox._possDifference = aiBoxBounds.top - elementBounds.top;
2177-
} else {
2178-
const calcNewDifference = aiBoxBounds.top - elementBounds.top;
2179-
const prevDifference = _aiPromptBox._possDifference;
2180-
2181-
// 4 is just for pixelated differences
2182-
if (Math.abs(calcNewDifference - prevDifference) > 4) {
2183-
const boxPositions = _aiPromptBox._getBoxPosition(aiBoxBounds.width, aiBoxBounds.height);
2184-
2185-
aiBox.style.left = boxPositions.leftPos + 'px';
2186-
aiBox.style.top = boxPositions.topPos + 'px';
2187-
_aiPromptBox._possDifference = calcNewDifference;
2188-
}
2189-
}
2190-
}
2191-
21921929
function _scrollHandler(e) {
21931930
// Document scrolls can be updated immediately. Any other scrolls
21941931
// need to be updated on a timer to ensure the layout is correct.
21951932
if (e.target === window.document) {
21961933
_dismissBoxesForFixedElements();
2197-
_repositionAIBox(); // and reposition the AI box
21981934
} else {
21991935
if (_localHighlight) {
22001936
window.setTimeout(redrawHighlights, 0);
22011937
}
22021938
_dismissBoxesForFixedElements();
2203-
_repositionAIBox();
22041939
}
22051940
}
22061941

@@ -2574,23 +2309,12 @@ function RemoteFunctions(config = {}) {
25742309
}
25752310
}
25762311

2577-
/**
2578-
* Helper function to dismiss AIPromptBox if it exists
2579-
*/
2580-
function dismissAIPromptBox() {
2581-
if (_aiPromptBox) {
2582-
_aiPromptBox.remove();
2583-
_aiPromptBox = null;
2584-
}
2585-
}
2586-
25872312
/**
25882313
* Helper function to dismiss all UI boxes at once
25892314
*/
25902315
function dismissAllUIBoxes() {
25912316
dismissNodeMoreOptionsBox();
25922317
dismissMoreOptionsDropdown();
2593-
dismissAIPromptBox();
25942318
dismissNodeInfoBox();
25952319
dismissToastMessage();
25962320
getAllNodeMoreOptionsHandlers().forEach(handler => (handler.dismiss && handler.dismiss()));

0 commit comments

Comments
 (0)