@@ -102,10 +102,10 @@ protected function _renderContent() {
102102 $ gemini_key = get_option ( 'visualizer_gemini_api_key ' , '' );
103103 $ claude_key = get_option ( 'visualizer_claude_api_key ' , '' );
104104
105- // Check if keys exist ( for placeholder text)
106- $ has_openai_key = ! empty ( $ openai_key );
107- $ has_gemini_key = ! empty ( $ gemini_key );
108- $ has_claude_key = ! empty ( $ claude_key );
105+ // Mask the keys for display
106+ $ openai_key_display = $ this -> _maskAPIKey ( $ openai_key );
107+ $ gemini_key_display = $ this -> _maskAPIKey ( $ gemini_key );
108+ $ claude_key_display = $ this -> _maskAPIKey ( $ claude_key );
109109
110110 echo '<form method="post" action=""> ' ;
111111 wp_nonce_field ( 'visualizer_ai_settings ' , 'visualizer_ai_settings_nonce ' );
@@ -116,11 +116,8 @@ protected function _renderContent() {
116116 echo '<tr> ' ;
117117 echo '<th scope="row"><label for="visualizer_openai_api_key"> ' . esc_html__ ( 'OpenAI API Key (ChatGPT) ' , 'visualizer ' ) . '</label></th> ' ;
118118 echo '<td> ' ;
119- echo '<input type="password" id="visualizer_openai_api_key" name="visualizer_openai_api_key" value="" class="regular-text" placeholder=" ' . ( $ has_openai_key ? esc_attr__ ( 'API key is set (enter new key to replace) ' , 'visualizer ' ) : esc_attr__ ( 'Enter API key ' , 'visualizer ' ) ) . '" autocomplete="off" /> ' ;
120- if ( $ has_openai_key ) {
121- echo '<input type="hidden" name="visualizer_openai_api_key_exists" value="1" /> ' ;
122- echo '<p class="description" style="color: #46b450; font-weight: 500;"><span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span> ' . esc_html__ ( 'API key is configured ' , 'visualizer ' ) . '</p> ' ;
123- }
119+ echo '<input type="text" id="visualizer_openai_api_key" name="visualizer_openai_api_key" value=" ' . esc_attr ( $ openai_key_display ) . '" class="regular-text" placeholder=" ' . esc_attr__ ( 'Enter API key ' , 'visualizer ' ) . '" autocomplete="off" readonly /> ' ;
120+ echo '<button type="button" class="button visualizer-change-key" data-target="visualizer_openai_api_key" style="margin-left: 5px;"> ' . esc_html__ ( 'Change Key ' , 'visualizer ' ) . '</button> ' ;
124121 echo '<p class="description"> ' . esc_html__ ( 'Enter your OpenAI API key to enable ChatGPT integration. ' , 'visualizer ' ) . ' <a href="https://platform.openai.com/api-keys" target="_blank"> ' . esc_html__ ( 'Get API Key ' , 'visualizer ' ) . '</a></p> ' ;
125122 echo '</td> ' ;
126123 echo '</tr> ' ;
@@ -129,11 +126,8 @@ protected function _renderContent() {
129126 echo '<tr> ' ;
130127 echo '<th scope="row"><label for="visualizer_gemini_api_key"> ' . esc_html__ ( 'Google Gemini API Key ' , 'visualizer ' ) . '</label></th> ' ;
131128 echo '<td> ' ;
132- echo '<input type="password" id="visualizer_gemini_api_key" name="visualizer_gemini_api_key" value="" class="regular-text" placeholder=" ' . ( $ has_gemini_key ? esc_attr__ ( 'API key is set (enter new key to replace) ' , 'visualizer ' ) : esc_attr__ ( 'Enter API key ' , 'visualizer ' ) ) . '" autocomplete="off" /> ' ;
133- if ( $ has_gemini_key ) {
134- echo '<input type="hidden" name="visualizer_gemini_api_key_exists" value="1" /> ' ;
135- echo '<p class="description" style="color: #46b450; font-weight: 500;"><span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span> ' . esc_html__ ( 'API key is configured ' , 'visualizer ' ) . '</p> ' ;
136- }
129+ echo '<input type="text" id="visualizer_gemini_api_key" name="visualizer_gemini_api_key" value=" ' . esc_attr ( $ gemini_key_display ) . '" class="regular-text" placeholder=" ' . esc_attr__ ( 'Enter API key ' , 'visualizer ' ) . '" autocomplete="off" readonly /> ' ;
130+ echo '<button type="button" class="button visualizer-change-key" data-target="visualizer_gemini_api_key" style="margin-left: 5px;"> ' . esc_html__ ( 'Change Key ' , 'visualizer ' ) . '</button> ' ;
137131 echo '<p class="description"> ' . esc_html__ ( 'Enter your Google Gemini API key. ' , 'visualizer ' ) . ' <a href="https://makersuite.google.com/app/apikey" target="_blank"> ' . esc_html__ ( 'Get API Key ' , 'visualizer ' ) . '</a></p> ' ;
138132 echo '</td> ' ;
139133 echo '</tr> ' ;
@@ -142,11 +136,8 @@ protected function _renderContent() {
142136 echo '<tr> ' ;
143137 echo '<th scope="row"><label for="visualizer_claude_api_key"> ' . esc_html__ ( 'Anthropic Claude API Key ' , 'visualizer ' ) . '</label></th> ' ;
144138 echo '<td> ' ;
145- echo '<input type="password" id="visualizer_claude_api_key" name="visualizer_claude_api_key" value="" class="regular-text" placeholder=" ' . ( $ has_claude_key ? esc_attr__ ( 'API key is set (enter new key to replace) ' , 'visualizer ' ) : esc_attr__ ( 'Enter API key ' , 'visualizer ' ) ) . '" autocomplete="off" /> ' ;
146- if ( $ has_claude_key ) {
147- echo '<input type="hidden" name="visualizer_claude_api_key_exists" value="1" /> ' ;
148- echo '<p class="description" style="color: #46b450; font-weight: 500;"><span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span> ' . esc_html__ ( 'API key is configured ' , 'visualizer ' ) . '</p> ' ;
149- }
139+ echo '<input type="text" id="visualizer_claude_api_key" name="visualizer_claude_api_key" value=" ' . esc_attr ( $ claude_key_display ) . '" class="regular-text" placeholder=" ' . esc_attr__ ( 'Enter API key ' , 'visualizer ' ) . '" autocomplete="off" readonly /> ' ;
140+ echo '<button type="button" class="button visualizer-change-key" data-target="visualizer_claude_api_key" style="margin-left: 5px;"> ' . esc_html__ ( 'Change Key ' , 'visualizer ' ) . '</button> ' ;
150141 echo '<p class="description"> ' . esc_html__ ( 'Enter your Anthropic Claude API key. ' , 'visualizer ' ) . ' <a href="https://console.anthropic.com/account/keys" target="_blank"> ' . esc_html__ ( 'Get API Key ' , 'visualizer ' ) . '</a></p> ' ;
151142 echo '</td> ' ;
152143 echo '</tr> ' ;
@@ -159,6 +150,45 @@ protected function _renderContent() {
159150
160151 echo '</form> ' ;
161152
153+ // Add JavaScript to handle Change Key button
154+ ?>
155+ <script type="text/javascript">
156+ jQuery(document).ready(function($) {
157+ $('.visualizer-change-key').on('click', function() {
158+ var $button = $(this);
159+ var targetId = $button.attr('data-target');
160+ var $input = $('#' + targetId);
161+
162+ // Make field editable and clear it
163+ $input.prop('readonly', false).val('').focus();
164+
165+ // Change button text
166+ $button.text('<?php echo esc_js ( __ ( 'Cancel ' , 'visualizer ' ) ); ?> ');
167+ $button.removeClass('visualizer-change-key').addClass('visualizer-cancel-change');
168+ });
169+
170+ $(document).on('click', '.visualizer-cancel-change', function() {
171+ var $button = $(this);
172+ var targetId = $button.attr('data-target');
173+ var $input = $('#' + targetId);
174+ var originalValue = $input.attr('data-original');
175+
176+ // Restore readonly and original masked value
177+ $input.prop('readonly', true).val(originalValue || '');
178+
179+ // Change button text back
180+ $button.text('<?php echo esc_js ( __ ( 'Change Key ' , 'visualizer ' ) ); ?> ');
181+ $button.removeClass('visualizer-cancel-change').addClass('visualizer-change-key');
182+ });
183+
184+ // Store original masked values
185+ $('input[type="text"][id^="visualizer_"]').each(function() {
186+ $(this).attr('data-original', $(this).val());
187+ });
188+ });
189+ </script>
190+ <?php
191+
162192 echo '</div> ' ; // End opacity wrapper
163193
164194 if ( $ is_locked ) {
@@ -177,19 +207,33 @@ protected function _renderContent() {
177207 * @return void
178208 */
179209 private function _saveSettings () {
180- // Only update OpenAI key if a new value is provided
210+ // Get current keys
211+ $ current_openai = get_option ( 'visualizer_openai_api_key ' , '' );
212+ $ current_gemini = get_option ( 'visualizer_gemini_api_key ' , '' );
213+ $ current_claude = get_option ( 'visualizer_claude_api_key ' , '' );
214+
215+ // Only update OpenAI key if a new value is provided and it's not the masked version
181216 if ( isset ( $ _POST ['visualizer_openai_api_key ' ] ) && ! empty ( $ _POST ['visualizer_openai_api_key ' ] ) ) {
182- update_option ( 'visualizer_openai_api_key ' , sanitize_text_field ( $ _POST ['visualizer_openai_api_key ' ] ) );
217+ $ new_key = sanitize_text_field ( $ _POST ['visualizer_openai_api_key ' ] );
218+ if ( $ new_key !== $ this ->_maskAPIKey ( $ current_openai ) ) {
219+ update_option ( 'visualizer_openai_api_key ' , $ new_key );
220+ }
183221 }
184222
185- // Only update Gemini key if a new value is provided
223+ // Only update Gemini key if a new value is provided and it's not the masked version
186224 if ( isset ( $ _POST ['visualizer_gemini_api_key ' ] ) && ! empty ( $ _POST ['visualizer_gemini_api_key ' ] ) ) {
187- update_option ( 'visualizer_gemini_api_key ' , sanitize_text_field ( $ _POST ['visualizer_gemini_api_key ' ] ) );
225+ $ new_key = sanitize_text_field ( $ _POST ['visualizer_gemini_api_key ' ] );
226+ if ( $ new_key !== $ this ->_maskAPIKey ( $ current_gemini ) ) {
227+ update_option ( 'visualizer_gemini_api_key ' , $ new_key );
228+ }
188229 }
189230
190- // Only update Claude key if a new value is provided
231+ // Only update Claude key if a new value is provided and it's not the masked version
191232 if ( isset ( $ _POST ['visualizer_claude_api_key ' ] ) && ! empty ( $ _POST ['visualizer_claude_api_key ' ] ) ) {
192- update_option ( 'visualizer_claude_api_key ' , sanitize_text_field ( $ _POST ['visualizer_claude_api_key ' ] ) );
233+ $ new_key = sanitize_text_field ( $ _POST ['visualizer_claude_api_key ' ] );
234+ if ( $ new_key !== $ this ->_maskAPIKey ( $ current_claude ) ) {
235+ update_option ( 'visualizer_claude_api_key ' , $ new_key );
236+ }
193237 }
194238 }
195239
0 commit comments