Skip to content

Commit aa3eaef

Browse files
Evin JohnEvin John
authored andcommitted
update v3.5
1 parent 3e68ad4 commit aa3eaef

File tree

6 files changed

+770
-170
lines changed

6 files changed

+770
-170
lines changed

chrome-extension/README-TRIAGE-AI.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,23 @@ Based on comprehensive analysis, the system routes prompts to:
153153
- Reasoning: keyword: edit, keyword: photo, pattern: image editing, has shared images
154154
**Output:** "Using the provided image, please add a vibrant sunset background to the scene. Ensure the change integrates seamlessly with the original lighting and composition, creating a warm, golden atmosphere that complements the existing elements while maintaining the original style and perspective."
155155

156+
### Platform-Specific Examples
157+
158+
#### ChatGPT (DALL-E)
159+
**Input:** "create a logo for my startup"
160+
**Platform:** ChatGPT
161+
**Output:** "Professional startup logo design, minimalist style, modern typography, clean geometric shapes, high quality, detailed, no text, no watermark"
162+
163+
#### Gemini/AI Studio
164+
**Input:** "create a logo for my startup"
165+
**Platform:** Gemini
166+
**Output:** "Create a modern, minimalist logo for a startup company with clean typography and geometric design elements. The design should be professional and memorable, with a contemporary color scheme suitable for digital and print applications, featuring sharp focus on brand identity and scalability."
167+
168+
#### DALL-E Example
169+
**Input:** "anime character with blue hair"
170+
**Platform:** ChatGPT (DALL-E)
171+
**Output:** "Anime character with blue hair and green eyes, kawaii style, soft lighting, centered composition, detailed character design, high quality, no text, no watermark"
172+
156173
### AI Prompting Example
157174
**Input:** "write code for fibonacci"
158175
**Analysis:**
@@ -285,6 +302,19 @@ The system now includes sophisticated image generation capabilities:
285302
- Handles image editing scenarios appropriately
286303
- Preserves references to user's photos and images
287304

305+
**Platform-Specific Optimization:**
306+
- **ChatGPT**: Uses DALL-E prompting techniques
307+
- Natural, descriptive language (not technical parameters)
308+
- Quality boosters: "high quality", "detailed", "professional"
309+
- Negative prompts: "no text", "no watermark"
310+
- Artistic style references and lighting descriptions
311+
- Photography terminology and composition details
312+
- **Gemini/AI Studio**: Uses official Gemini image generation templates
313+
- Photorealistic scenes with camera specifications
314+
- Stylized illustrations and stickers
315+
- Product mockups and commercial photography
316+
- Sequential art and comic panels
317+
288318
## Future Enhancements
289319

290320
Potential improvements include:

chrome-extension/ai-studio-sparkle.js

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,85 @@
9696
sparklePath.removeAttribute("filter");
9797
});
9898

99+
// Add hover popup functionality
100+
let hoverTimeout;
101+
let popup = null;
102+
103+
console.log('Threadly: Adding hover events to sparkle element');
104+
console.log('Threadly: SVG element:', svg);
105+
console.log('Threadly: SVG position:', svg.getBoundingClientRect());
106+
107+
svg.addEventListener('mouseenter', () => {
108+
console.log('Threadly: Mouse entered sparkle - HOVER EVENT TRIGGERED!');
109+
hoverTimeout = setTimeout(() => {
110+
console.log('Threadly: Creating popup after hover delay');
111+
112+
// Create a simple test popup first
113+
const testPopup = document.createElement('div');
114+
testPopup.style.position = 'absolute';
115+
testPopup.style.top = '-50px';
116+
testPopup.style.left = '50%';
117+
testPopup.style.transform = 'translateX(-50%)';
118+
testPopup.style.background = 'red';
119+
testPopup.style.color = 'white';
120+
testPopup.style.padding = '10px';
121+
testPopup.style.borderRadius = '5px';
122+
testPopup.style.zIndex = '99999';
123+
testPopup.textContent = 'TEST POPUP';
124+
svg.style.position = 'relative';
125+
svg.appendChild(testPopup);
126+
console.log('Threadly: Test popup created and appended');
127+
console.log('Threadly: SVG children count:', svg.children.length);
128+
129+
// Then try the real popup
130+
popup = createModeSelectionPopup(svg);
131+
if (popup) {
132+
console.log('Threadly: Popup created successfully');
133+
} else {
134+
console.log('Threadly: Popup creation failed');
135+
}
136+
}, 300); // Show popup after 300ms hover
137+
});
138+
139+
svg.addEventListener('mouseleave', () => {
140+
console.log('Threadly: Mouse left sparkle');
141+
clearTimeout(hoverTimeout);
142+
143+
// Remove test popup
144+
const testPopup = svg.querySelector('div[style*="background: red"]');
145+
if (testPopup) {
146+
testPopup.remove();
147+
console.log('Threadly: Test popup removed');
148+
}
149+
150+
if (popup) {
151+
console.log('Threadly: Removing popup');
152+
popup.remove();
153+
popup = null;
154+
}
155+
});
156+
99157
// Add click handler (exact same as Claude)
100158
svg.addEventListener('click', (event) => {
101159
event.preventDefault();
102160
event.stopPropagation();
103161
console.log('Threadly: Sparkle clicked!');
162+
163+
// Test: Manually trigger hover event for debugging
164+
console.log('Threadly: Manually triggering hover test');
165+
const testEvent = new MouseEvent('mouseenter', {
166+
bubbles: true,
167+
cancelable: true,
168+
view: window
169+
});
170+
svg.dispatchEvent(testEvent);
171+
172+
// If popup is visible, remove it and proceed with autonomous mode
173+
if (popup) {
174+
popup.remove();
175+
popup = null;
176+
}
177+
104178
handleSparkleClick();
105179
});
106180

@@ -111,6 +185,159 @@
111185
return svg;
112186
}
113187

188+
// Create mode selection popup
189+
function createModeSelectionPopup(sparkleElement) {
190+
console.log('Threadly: Creating mode selection popup');
191+
console.log('Threadly: Sparkle element:', sparkleElement);
192+
193+
try {
194+
// Remove existing popup if any
195+
const existingPopup = document.querySelector('.threadly-mode-popup');
196+
if (existingPopup) {
197+
console.log('Threadly: Removing existing popup');
198+
existingPopup.remove();
199+
}
200+
201+
// Create popup container
202+
console.log('Threadly: Creating popup div element');
203+
const popup = document.createElement('div');
204+
popup.className = 'threadly-mode-popup';
205+
console.log('Threadly: Setting popup innerHTML');
206+
popup.innerHTML = `
207+
<div class="threadly-mode-option correction" data-mode="correction">
208+
<span class="mode-icon">✏️</span>
209+
<span class="mode-text">CORRECT</span>
210+
</div>
211+
<div class="threadly-mode-option image" data-mode="image">
212+
<span class="mode-icon">🎨</span>
213+
<span class="mode-text">IMAGE</span>
214+
</div>
215+
<div class="threadly-mode-option refine" data-mode="refine">
216+
<span class="mode-icon">✨</span>
217+
<span class="mode-text">REFINE</span>
218+
</div>
219+
`;
220+
221+
// Position popup relative to sparkle element
222+
console.log('Threadly: Setting sparkle element position');
223+
sparkleElement.style.position = 'relative';
224+
console.log('Threadly: Appending popup to sparkle element');
225+
sparkleElement.appendChild(popup);
226+
console.log('Threadly: Popup appended to sparkle element');
227+
console.log('Threadly: Popup element:', popup);
228+
console.log('Threadly: Sparkle element position:', sparkleElement.getBoundingClientRect());
229+
230+
// Show popup with animation
231+
setTimeout(() => {
232+
console.log('Threadly: Adding show class to popup');
233+
popup.classList.add('show');
234+
console.log('Threadly: Popup classes:', popup.className);
235+
console.log('Threadly: Popup position:', popup.getBoundingClientRect());
236+
}, 10);
237+
238+
// Add click handlers for each option
239+
popup.addEventListener('click', (e) => {
240+
const mode = e.target.closest('.threadly-mode-option')?.dataset.mode;
241+
if (mode) {
242+
handleModeSelection(mode, sparkleElement);
243+
popup.remove();
244+
}
245+
});
246+
247+
// Hide popup when clicking outside
248+
const hidePopup = (e) => {
249+
if (!popup.contains(e.target) && !sparkleElement.contains(e.target)) {
250+
popup.remove();
251+
document.removeEventListener('click', hidePopup);
252+
}
253+
};
254+
255+
setTimeout(() => {
256+
document.addEventListener('click', hidePopup);
257+
}, 100);
258+
259+
return popup;
260+
} catch (error) {
261+
console.error('Threadly: Error creating popup:', error);
262+
return null;
263+
}
264+
}
265+
266+
// Handle mode selection
267+
async function handleModeSelection(mode, sparkleElement) {
268+
console.log('Threadly: Mode selected:', mode);
269+
270+
// Get current input text
271+
const textArea = document.querySelector('textarea, [contenteditable="true"]');
272+
if (!textArea) {
273+
console.log('Threadly: No text area found');
274+
return;
275+
}
276+
277+
const currentText = textArea.value || textArea.textContent || textArea.innerText;
278+
if (!currentText || currentText.trim() === '') {
279+
console.log('Threadly: No text to process');
280+
return;
281+
}
282+
283+
// Visual feedback
284+
startClickAnimationSequence(sparkleElement);
285+
286+
try {
287+
if (window.PromptRefiner) {
288+
const promptRefiner = new window.PromptRefiner();
289+
await promptRefiner.initialize();
290+
291+
let refinedPrompt;
292+
const platform = detectCurrentPlatform();
293+
294+
switch (mode) {
295+
case 'correction':
296+
refinedPrompt = await promptRefiner.performGrammarCorrection(currentText);
297+
break;
298+
case 'image':
299+
refinedPrompt = await promptRefiner.refineImageGenerationPrompt(currentText, platform);
300+
break;
301+
case 'refine':
302+
refinedPrompt = await promptRefiner.refinePrompt(currentText, platform);
303+
break;
304+
}
305+
306+
// Replace text in the input
307+
if (refinedPrompt) {
308+
if (textArea.tagName === 'TEXTAREA') {
309+
textArea.value = refinedPrompt;
310+
} else {
311+
textArea.textContent = refinedPrompt;
312+
}
313+
314+
// Trigger input event to notify the platform
315+
textArea.dispatchEvent(new Event('input', { bubbles: true }));
316+
textArea.dispatchEvent(new Event('change', { bubbles: true }));
317+
}
318+
}
319+
} catch (error) {
320+
console.error('Threadly: Error processing prompt:', error);
321+
}
322+
}
323+
324+
// Detect current platform
325+
function detectCurrentPlatform() {
326+
const url = window.location.href;
327+
if (url.includes('chat.openai.com') || url.includes('chatgpt.com')) {
328+
return 'chatgpt';
329+
} else if (url.includes('claude.ai')) {
330+
return 'claude';
331+
} else if (url.includes('aistudio.google.com')) {
332+
return 'ai-studio';
333+
} else if (url.includes('gemini.google.com')) {
334+
return 'gemini';
335+
} else if (url.includes('perplexity.ai')) {
336+
return 'perplexity';
337+
}
338+
return 'chatgpt'; // default fallback
339+
}
340+
114341
// Handle sparkle click functionality with prompt refine feature (exact copy from Claude)
115342
async function handleSparkleClick() {
116343
console.log('Threadly: Sparkle clicked - prompt refine activated!');
@@ -427,7 +654,9 @@
427654
console.log('Threadly: Upload button parent:', uploadButton.parentElement);
428655

429656
// Create the sparkle icon
657+
console.log('Threadly: Creating sparkle icon');
430658
const sparkleIcon = createSparkleIcon();
659+
console.log('Threadly: Sparkle icon created:', sparkleIcon);
431660

432661
// Style the sparkle icon
433662
sparkleIcon.style.display = 'inline-block';
@@ -436,6 +665,7 @@
436665
sparkleIcon.style.top = '0';
437666
sparkleIcon.style.marginLeft = '0px';
438667
sparkleIcon.style.marginRight = '8px';
668+
console.log('Threadly: Sparkle icon styled');
439669

440670
// Find the main text bar container using multiple selectors for different page states
441671
let textBarContainer = document.querySelector("body > app-root > ms-app > div > div > div.layout-wrapper.ng-tns-c895710572-0 > div > span > ms-prompt-switcher > ms-chunk-editor > section > footer > ms-prompt-input-wrapper > div > div > div");
@@ -503,11 +733,14 @@
503733
try {
504734
textBarContainer.insertBefore(sparkleWrapper, uploadButtonWrapper);
505735
console.log('Threadly: SUCCESS - Sparkle wrapper inserted before upload button wrapper');
736+
console.log('Threadly: Sparkle icon in DOM:', document.querySelector('[data-threadly-sparkle="true"]'));
737+
console.log('Threadly: Sparkle icon position:', sparkleIcon.getBoundingClientRect());
506738
} catch (error) {
507739
console.error('Threadly: Insert sparkle wrapper failed:', error);
508740
// Fallback: append to text bar container
509741
textBarContainer.appendChild(sparkleWrapper);
510742
console.log('Threadly: FALLBACK - Sparkle wrapper appended to text bar container');
743+
console.log('Threadly: Sparkle icon in DOM:', document.querySelector('[data-threadly-sparkle="true"]'));
511744
}
512745
} else {
513746
// Try to find the parent container of the upload button and insert before it

0 commit comments

Comments
 (0)