Skip to content

Commit f425e19

Browse files
committed
Big update with chat context
1 parent d4e35ef commit f425e19

File tree

13 files changed

+1139
-619
lines changed

13 files changed

+1139
-619
lines changed

src/ai_dom_editor/editor/ai_dom_content.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ class AIDOMContent {
2020
}
2121

2222
setupMessageListener() {
23+
if (window.__ctwkDOMContentListenerAdded) {
24+
return;
25+
}
26+
window.__ctwkDOMContentListenerAdded = true;
27+
2328
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
2429
if (message.action === 'collectDOMSummary') {
2530
const summary = this.collectDOMSummary();

src/ai_dom_editor/editor/ai_dom_editor.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010
<div class="ai-editor-container">
1111
<!-- Header -->
1212
<div class="ai-editor-header">
13-
<h2 class="header-title" data-i18n="aiEditorTitle">AI DOM Editor</h2>
13+
<h2 class="header-title" id="headerTitle" data-i18n="aiEditorTitle">AI DOM Editor</h2>
14+
<div class="current-script-display" id="currentScriptDisplay" style="display: none;">
15+
<i data-feather="file-text" width="16" height="16"></i>
16+
<span id="currentScriptName"></span>
17+
</div>
1418
<div class="header-actions">
1519
<button class="tool-btn" id="clearChatBtn" title="Clear conversation" data-i18n-title="aiEditorClearConversation">
1620
<i data-feather="trash-2" width="18" height="18"></i>
Lines changed: 119 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,42 @@
11
// AI DOM Editor - Main JavaScript
2-
import feather from 'feather-icons';
3-
import { ChatManager } from './helpers/chat_manager.js';
4-
import { UIManager } from './helpers/ui_manager.js';
5-
import { ApiHandler } from './helpers/api_handler.js';
6-
import { EventHandler } from './helpers/event_handler.js';
7-
import { UserscriptHandler } from './helpers/userscript_handler.js';
2+
import feather from "feather-icons";
3+
import { ChatManager } from "./helpers/chat_manager.js";
4+
import { UIManager } from "./helpers/ui_manager.js";
5+
import { ApiHandler } from "./helpers/api_handler.js";
6+
import { EventHandler } from "./helpers/event_handler.js";
7+
import { UserscriptHandler } from "./helpers/userscript_handler.js";
88

99
class AIDOMEditor {
1010
constructor() {
1111
this.selectedElement = null;
12-
12+
this.currentScript = null;
13+
1314
this.elements = {
14-
chatContainer: document.getElementById('chatContainer'),
15-
messages: document.getElementById('messages'),
16-
welcomeMessage: document.getElementById('welcomeMessage'),
17-
userInput: document.getElementById('userInput'),
18-
sendBtn: document.getElementById('sendBtn'),
19-
closeBtn: document.getElementById('closeBtn'),
20-
configBanner: document.getElementById('configBanner'),
21-
openSettingsBtn: document.getElementById('openSettingsBtn'),
22-
headerSettingsBtn: document.getElementById('headerSettingsBtn'),
23-
elementSelectorBtn: document.getElementById('elementSelectorBtn'),
24-
clearChatBtn: document.getElementById('clearChatBtn'),
25-
selectorActive: document.getElementById('selectorActive'),
26-
cancelSelector: document.getElementById('cancelSelector'),
27-
modelSelector: document.getElementById('modelSelector')
15+
chatContainer: document.getElementById("chatContainer"),
16+
messages: document.getElementById("messages"),
17+
welcomeMessage: document.getElementById("welcomeMessage"),
18+
userInput: document.getElementById("userInput"),
19+
sendBtn: document.getElementById("sendBtn"),
20+
closeBtn: document.getElementById("closeBtn"),
21+
configBanner: document.getElementById("configBanner"),
22+
openSettingsBtn: document.getElementById("openSettingsBtn"),
23+
headerSettingsBtn: document.getElementById("headerSettingsBtn"),
24+
elementSelectorBtn: document.getElementById("elementSelectorBtn"),
25+
clearChatBtn: document.getElementById("clearChatBtn"),
26+
selectorActive: document.getElementById("selectorActive"),
27+
cancelSelector: document.getElementById("cancelSelector"),
28+
modelSelector: document.getElementById("modelSelector"),
29+
headerTitle: document.getElementById("headerTitle"),
30+
currentScriptDisplay: document.getElementById("currentScriptDisplay"),
31+
currentScriptName: document.getElementById("currentScriptName"),
2832
};
29-
33+
3034
this.chatManager = new ChatManager(this);
3135
this.uiManager = new UIManager(this);
3236
this.apiHandler = new ApiHandler(this);
3337
this.eventHandler = new EventHandler(this);
3438
this.userscriptHandler = new UserscriptHandler(this);
35-
39+
3640
this.init();
3741
}
3842

@@ -41,38 +45,119 @@ class AIDOMEditor {
4145
await this.initializeAI();
4246
}
4347

48+
setCurrentScript(scriptName) {
49+
if (scriptName) {
50+
this.currentScript = { name: scriptName };
51+
this.elements.currentScriptName.textContent = scriptName;
52+
this.elements.currentScriptDisplay.style.display = "flex";
53+
this.elements.headerTitle.style.display = "none";
54+
} else {
55+
this.currentScript = null;
56+
this.elements.currentScriptDisplay.style.display = "none";
57+
this.elements.headerTitle.style.display = "block";
58+
}
59+
feather.replace();
60+
61+
// Persist current script to storage
62+
this.saveCurrentScriptState();
63+
64+
// Dispatch event to notify UI components of script change
65+
document.dispatchEvent(
66+
new CustomEvent("currentScriptChanged", {
67+
detail: { currentScript: this.currentScript },
68+
})
69+
);
70+
}
71+
72+
async saveCurrentScriptState() {
73+
try {
74+
const [tab] = await chrome.tabs.query({
75+
active: true,
76+
currentWindow: true,
77+
});
78+
if (!tab || !tab.url) return;
79+
80+
const url = new URL(tab.url);
81+
const siteUrl = `${url.protocol}//${url.hostname}`;
82+
const storageKey = `aiCurrentScript_${siteUrl}`;
83+
84+
if (this.currentScript) {
85+
await chrome.storage.local.set({
86+
[storageKey]: this.currentScript.name,
87+
});
88+
} else {
89+
await chrome.storage.local.remove(storageKey);
90+
}
91+
} catch (error) {
92+
console.error("Error saving current script state:", error);
93+
}
94+
}
95+
96+
async restoreCurrentScriptState() {
97+
try {
98+
const [tab] = await chrome.tabs.query({
99+
active: true,
100+
currentWindow: true,
101+
});
102+
if (!tab || !tab.url) return;
103+
104+
const url = new URL(tab.url);
105+
const siteUrl = `${url.protocol}//${url.hostname}`;
106+
const storageKey = `aiCurrentScript_${siteUrl}`;
107+
108+
const { [storageKey]: scriptName } = await chrome.storage.local.get(
109+
storageKey
110+
);
111+
if (scriptName) {
112+
// Verify the script actually exists before restoring
113+
const { scripts = [] } = await chrome.storage.local.get("scripts");
114+
const scriptExists = scripts.some((s) => s.name === scriptName);
115+
116+
if (scriptExists) {
117+
this.setCurrentScript(scriptName);
118+
} else {
119+
// Script doesn't exist anymore, clear the stored state
120+
await chrome.storage.local.remove(storageKey);
121+
}
122+
}
123+
} catch (error) {
124+
console.error("Error restoring current script state:", error);
125+
}
126+
}
127+
44128
async getUserLanguage() {
45129
try {
46-
const { settings = {} } = await chrome.storage.local.get('settings');
47-
const userLanguage = settings.language || 'auto';
48-
49-
if (userLanguage === 'auto') {
50-
return chrome.i18n.getUILanguage().split('-')[0];
130+
const { settings = {} } = await chrome.storage.local.get("settings");
131+
const userLanguage = settings.language || "auto";
132+
133+
if (userLanguage === "auto") {
134+
return chrome.i18n.getUILanguage().split("-")[0];
51135
}
52-
136+
53137
return userLanguage;
54138
} catch (error) {
55-
console.error('Error getting language:', error);
56-
return 'en';
139+
console.error("Error getting language:", error);
140+
return "en";
57141
}
58142
}
59143

60144
async initializeAI() {
61145
try {
62146
const lang = await this.getUserLanguage();
63-
document.documentElement.setAttribute('lang', lang);
147+
document.documentElement.setAttribute("lang", lang);
64148
} catch (error) {
65-
console.error('Error setting language:', error);
149+
console.error("Error setting language:", error);
66150
}
67151
await this.apiHandler.loadAPIConfig();
68152
await this.apiHandler.loadAvailableModels();
69153
await this.chatManager.loadChatHistory();
154+
await this.restoreCurrentScriptState();
70155
this.eventHandler.setupEventListeners();
71156
this.eventHandler.setupMessageListener();
72157
feather.replace();
73158
}
74159
}
75160

76-
document.addEventListener('DOMContentLoaded', () => {
161+
document.addEventListener("DOMContentLoaded", () => {
77162
new AIDOMEditor();
78163
});

src/ai_dom_editor/editor/helpers/chat_manager.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
// src/ai_dom_editor/editor/helpers/chat_manager.js
2-
31
import feather from 'feather-icons';
42

53
export class ChatManager {
64
constructor(editor) {
75
this.editor = editor;
86
this.messages = [];
97
this.currentSiteUrl = '';
10-
this.scriptId = null; // Add scriptId property
8+
this.scriptId = null;
119
}
1210

1311
setScriptId(scriptId) {
@@ -29,6 +27,8 @@ export class ChatManager {
2927
const storageKey = `aiChatHistory_${this.scriptId}`;
3028
const { [storageKey]: history } = await chrome.storage.local.get(storageKey);
3129

30+
this.editor.elements.messages.innerHTML = '';
31+
3232
if (history && history.messages && history.messages.length > 0) {
3333
this.messages = history.messages;
3434
this.editor.uiManager.hideWelcomeMessage();
@@ -40,6 +40,9 @@ export class ChatManager {
4040

4141
feather.replace();
4242
this.editor.uiManager.scrollToBottom();
43+
} else {
44+
this.messages = [];
45+
this.editor.uiManager.showWelcomeMessage();
4346
}
4447
} catch (error) {
4548
console.error('Error loading chat history:', error);

src/ai_dom_editor/editor/helpers/event_handler.js

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// src/ai_dom_editor/editor/helpers/event_handler.js
1+
import ScriptAnalyzer from '../../../utils/scriptAnalyzer.js';
22

33
export class EventHandler {
44
constructor(editor) {
@@ -119,20 +119,38 @@ export class EventHandler {
119119

120120
try {
121121
let previousCode = this.editor.chatManager.getPreviousCode();
122-
const scriptNameMatch = message.match(/@(\S+)/);
123-
if (scriptNameMatch) {
124-
const scriptName = scriptNameMatch[1];
125-
try {
126-
previousCode = await this.editor.userscriptHandler.getScriptContent(scriptName);
127-
this.editor.chatManager.setScriptId(scriptName);
128-
} catch (error) {
129-
this.editor.chatManager.addMessage('assistant', `Error: ${error.message}`);
130-
this.editor.chatManager.removeMessage(loadingId);
131-
return;
122+
let userMessage = message;
123+
124+
if (message.includes('@')) {
125+
const allScripts = await this.editor.userscriptHandler.getAllScripts();
126+
const atIndex = message.lastIndexOf('@');
127+
const textAfterAt = message.substring(atIndex + 1);
128+
let matchedScript = null;
129+
130+
for (const scriptName of allScripts) {
131+
if (textAfterAt.startsWith(scriptName)) {
132+
if (!matchedScript || scriptName.length > matchedScript.length) {
133+
matchedScript = scriptName;
134+
}
135+
}
136+
}
137+
138+
if (matchedScript) {
139+
try {
140+
const fullCode = await this.editor.userscriptHandler.getScriptContent(matchedScript);
141+
previousCode = ScriptAnalyzer.extractCodeFromIIFE(fullCode);
142+
this.editor.setCurrentScript(matchedScript);
143+
const promptWithoutScriptRef = message.substring(0, atIndex) + textAfterAt.substring(matchedScript.length);
144+
userMessage = promptWithoutScriptRef.trim();
145+
} catch (error) {
146+
this.editor.chatManager.addMessage('assistant', `Error: ${error.message}`);
147+
this.editor.chatManager.removeMessage(loadingId);
148+
return;
149+
}
132150
}
133151
}
134152

135-
const aiResponse = await this.editor.apiHandler.callAIAPI(message, domSummary, previousCode);
153+
const aiResponse = await this.editor.apiHandler.callAIAPI(userMessage, domSummary, previousCode);
136154
this.editor.chatManager.removeMessage(loadingId);
137155
this.handleAIResponse(aiResponse);
138156
} catch (error) {

0 commit comments

Comments
 (0)