@@ -5,6 +5,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
55 if ( message . type === "ENABLE_PICKER" ) {
66 if ( ! isPickerEnabled ) enablePicker ( ) ;
77 }
8+ return true ;
89} ) ;
910
1011function enablePicker ( ) {
@@ -37,157 +38,160 @@ function onMouseOut(e) {
3738async function onClick ( e ) {
3839 e . preventDefault ( ) ;
3940 e . stopPropagation ( ) ;
40-
4141 const clickedElement = e . target ;
42- const selectedCode = clickedElement . textContent ;
42+ const selectedCode = clickedElement . textContent . trim ( ) ;
43+ if ( ! selectedCode ) {
44+ disablePicker ( ) ;
45+ return ;
46+ }
4347 const cacheKey = `translation_${ hashCode ( selectedCode ) } ` ;
4448 const originalWidth = clickedElement . getBoundingClientRect ( ) . width ;
4549 disablePicker ( ) ;
46-
4750 const { targetLanguage } = await chrome . storage . sync . get ( 'targetLanguage' ) ;
4851 const lang = targetLanguage || 'Java' ;
49-
5052 const cachedData = await getFromCache ( cacheKey ) ;
5153 if ( cachedData && cachedData [ lang ] ) {
5254 injectOrUpdateTranslations ( cachedData , clickedElement , originalWidth ) ;
5355 return ;
5456 }
55-
5657 const loadingDiv = document . createElement ( 'div' ) ;
5758 loadingDiv . className = 'translator-loading' ;
5859 loadingDiv . textContent = `Translating to ${ lang } ...` ;
60+ loadingDiv . style . width = `${ originalWidth } px` ;
5961 clickedElement . parentNode . insertBefore ( loadingDiv , clickedElement . nextSibling ) ;
60-
6162 chrome . runtime . sendMessage ( { type : "TRANSLATE_CODE" , code : selectedCode } , async ( response ) => {
6263 loadingDiv . remove ( ) ;
63-
64+ if ( chrome . runtime . lastError ) {
65+ console . error ( 'CodeTranslateAI: Message port closed unexpectedly.' , chrome . runtime . lastError . message ) ;
66+ alert ( 'Error: Could not connect to the translation service.' ) ;
67+ return ;
68+ }
6469 if ( response . error ) {
6570 alert ( `Error: ${ response . error } ` ) ;
6671 } else if ( response . translation ) {
6772 const cleanedTranslation = response . translation . replace ( / ` ` ` [ a - z ] * \n / g, '' ) . replace ( / ` ` ` / g, '' ) . trim ( ) ;
68-
6973 const newData = cachedData || { } ;
7074 newData [ lang ] = cleanedTranslation ;
7175 await saveToCache ( cacheKey , newData , 10 ) ;
72-
7376 injectOrUpdateTranslations ( newData , clickedElement , originalWidth ) ;
7477 }
7578 } ) ;
7679}
7780
7881function injectOrUpdateTranslations ( translations , originalElement , width ) {
7982 const componentStyles = `
80- .tab-nav {
81- display: flex;
82- border-bottom: 1px solid #ccc;
83- background-color: #f0f0f0;
84- }
85- .tab-link {
86- padding: 10px 15px;
87- cursor: pointer;
88- border: none;
89- background-color: transparent;
90- font-size: 1em;
91- font-weight: 500;
92- color: #333;
93- border-bottom: 3px solid transparent;
83+ .tab-nav {
84+ display: flex;
85+ border-bottom: 1px solid #ccc;
86+ background-color: #f0f0f0;
9487 }
95- .tab-link:hover {
96- background-color: #e5e5e5;
88+ .tab-link {
89+ padding: 10px 15px;
90+ cursor: pointer;
91+ border: none;
92+ background-color: transparent;
93+ font-size: 1em;
94+ /* --- FIX 1: Make inactive tabs more visible --- */
95+ font-weight: 500;
96+ color: #555;
97+ border-bottom: 3px solid transparent;
9798 }
98- .tab-link.active {
99- color: #007bff;
100- border-bottom: 3px solid #007bff;
99+ .tab-link:hover {
100+ background-color: #e5e5e5;
101101 }
102- .tab-content-area {
103- background-color: #fff;
102+ .tab-link.active {
103+ color: #007bff;
104+ font-weight: 600; /* Make active tab slightly bolder */
105+ border-bottom: 3px solid #007bff;
104106 }
105- .tab-content {
106- display: none;
107+ .tab-content {
108+ display: none;
107109 }
108- .tab-content.active {
109- display: block;
110+ .tab-content.active {
111+ display: block;
110112 }
111- pre {
112- margin: 0;
113- padding: 16px;
114- white-space: pre-wrap;
115- word-wrap: break-word;
116- background-color: #f6f8fa;
117- border-top: 1px solid #ddd;
118- margin-bottom: 10px;
113+ pre {
114+ margin: 0;
115+ white-space: pre-wrap;
116+ word-wrap: break-word;
119117 }
120- code {
121- font-family: monospace;
122- font-size: 14px;
123- color: #24292e;
124- line-height: 1;
118+ code {
119+ font-family: monospace;
120+ /* --- FIX 2: Made the code font size smaller --- */
121+ font-size: 0.8em;
125122 }
126123 ` ;
127124
125+ // The rest of the function remains exactly the same...
128126 let container = originalElement . nextElementSibling ;
129127 if ( ! container || container . id !== 'my-code-translator-container' ) {
130128 container = document . createElement ( 'div' ) ;
131129 container . id = 'my-code-translator-container' ;
132-
133130 const shadowRoot = container . attachShadow ( { mode : 'open' } ) ;
134131
132+ const prismTheme = document . createElement ( 'link' ) ;
133+ prismTheme . rel = 'stylesheet' ;
134+ prismTheme . href = chrome . runtime . getURL ( 'packages/prism.css' ) ;
135+ shadowRoot . appendChild ( prismTheme ) ;
136+
135137 const styleElement = document . createElement ( 'style' ) ;
136138 styleElement . textContent = componentStyles ;
137139 shadowRoot . appendChild ( styleElement ) ;
138140
139141 const uiWrapper = document . createElement ( 'div' ) ;
142+ uiWrapper . className = 'ui-wrapper' ;
140143 shadowRoot . appendChild ( uiWrapper ) ;
141144
142145 originalElement . parentNode . insertBefore ( container , originalElement . nextSibling ) ;
143146 }
144147
145148 container . style . width = `${ width } px` ;
146149 container . style . boxSizing = 'border-box' ;
147-
148150 const shadowRoot = container . shadowRoot ;
149- const uiWrapper = shadowRoot . querySelector ( 'div ' ) ;
151+ const uiWrapper = shadowRoot . querySelector ( '.ui-wrapper ' ) ;
150152 uiWrapper . innerHTML = '' ;
151-
152153 const tabNav = document . createElement ( 'div' ) ;
153154 tabNav . className = 'tab-nav' ;
154-
155155 const contentArea = document . createElement ( 'div' ) ;
156156 contentArea . className = 'tab-content-area' ;
157-
158157 uiWrapper . appendChild ( tabNav ) ;
159158 uiWrapper . appendChild ( contentArea ) ;
160-
161- Object . keys ( translations ) . forEach ( ( lang , index ) => {
162- const tabButton = document . createElement ( 'button' ) ;
163- tabButton . className = 'tab-link' ;
164- tabButton . textContent = lang ;
165-
159+ Object . keys ( translations ) . forEach ( lang => {
166160 const contentPanel = document . createElement ( 'div' ) ;
167161 contentPanel . className = 'tab-content' ;
168-
162+ contentPanel . dataset . lang = lang ;
163+ const langClass = `language-${ lang . toLowerCase ( ) } ` ;
169164 const pre = document . createElement ( 'pre' ) ;
165+ pre . className = langClass ;
170166 const code = document . createElement ( 'code' ) ;
167+ code . className = langClass ;
171168 code . textContent = translations [ lang ] ;
172169 pre . appendChild ( code ) ;
173170 contentPanel . appendChild ( pre ) ;
174-
175- tabNav . appendChild ( tabButton ) ;
176171 contentArea . appendChild ( contentPanel ) ;
177-
178- if ( index === 0 ) {
179- tabButton . classList . add ( 'active' ) ;
180- contentPanel . classList . add ( 'active' ) ;
181- }
182-
172+ } ) ;
173+ Object . keys ( translations ) . forEach ( ( lang , index ) => {
174+ const tabButton = document . createElement ( 'button' ) ;
175+ tabButton . className = 'tab-link' ;
176+ tabButton . textContent = lang ;
183177 tabButton . addEventListener ( 'click' , ( ) => {
184178 shadowRoot . querySelectorAll ( '.tab-link' ) . forEach ( btn => btn . classList . remove ( 'active' ) ) ;
185179 shadowRoot . querySelectorAll ( '.tab-content' ) . forEach ( panel => panel . classList . remove ( 'active' ) ) ;
186-
187180 tabButton . classList . add ( 'active' ) ;
188- contentPanel . classList . add ( 'active' ) ;
181+ shadowRoot . querySelector ( `.tab-content[data-lang=" ${ lang } "]` ) . classList . add ( 'active' ) ;
189182 } ) ;
183+ tabNav . appendChild ( tabButton ) ;
184+ if ( index === 0 ) {
185+ tabButton . click ( ) ;
186+ }
190187 } ) ;
188+ try {
189+ if ( window . Prism ) {
190+ contentArea . querySelectorAll ( `pre[class*="language-"]` ) . forEach ( element => window . Prism . highlightElement ( element ) ) ;
191+ }
192+ } catch ( e ) {
193+ console . error ( 'CodeTranslateAI: Error highlighting syntax.' , e ) ;
194+ }
191195}
192196
193197function hashCode ( str ) {
@@ -202,25 +206,16 @@ function hashCode(str) {
202206
203207async function saveToCache ( key , data , daysToExpire ) {
204208 const expirationMs = daysToExpire * 24 * 60 * 60 * 1000 ;
205- const cacheItem = {
206- data : data ,
207- expiresAt : Date . now ( ) + expirationMs ,
208- } ;
209+ const cacheItem = { data : data , expiresAt : Date . now ( ) + expirationMs } ;
209210 await chrome . storage . local . set ( { [ key ] : cacheItem } ) ;
210211}
211212
212213async function getFromCache ( key ) {
213214 const result = await chrome . storage . local . get ( key ) ;
214215 const cacheItem = result [ key ] ;
215-
216- if ( ! cacheItem ) {
217- return null ;
218- }
219-
220- if ( Date . now ( ) > cacheItem . expiresAt ) {
221- await chrome . storage . local . remove ( key ) ;
216+ if ( ! cacheItem || Date . now ( ) > cacheItem . expiresAt ) {
217+ if ( cacheItem ) await chrome . storage . local . remove ( key ) ;
222218 return null ;
223219 }
224-
225220 return cacheItem . data ;
226221}
0 commit comments