@@ -333,12 +333,51 @@ const loadApiKeys = async () => {
333333 }
334334};
335335
336+ const tryExecCommandCopy = (text ) => {
337+ let textArea = null ;
338+ try {
339+ if (typeof document === ' undefined' ) return false ;
340+ textArea = document .createElement (' textarea' );
341+ textArea .value = text;
342+ textArea .setAttribute (' readonly' , ' ' );
343+ textArea .style .position = ' fixed' ;
344+ textArea .style .opacity = ' 0' ;
345+ textArea .style .pointerEvents = ' none' ;
346+ textArea .style .left = ' -9999px' ;
347+ document .body .appendChild (textArea);
348+ textArea .focus ();
349+ textArea .select ();
350+ textArea .setSelectionRange (0 , text .length );
351+ return document .execCommand (' copy' );
352+ } catch (_) {
353+ return false ;
354+ } finally {
355+ try {
356+ textArea? .remove ? .();
357+ } catch (_) {
358+ // ignore cleanup errors
359+ }
360+ }
361+ };
362+
363+ const copyTextToClipboard = async (text ) => {
364+ if (! text) return false ;
365+ if (tryExecCommandCopy (text)) return true ;
366+ if (typeof navigator === ' undefined' || ! navigator .clipboard ? .writeText ) return false ;
367+ try {
368+ await navigator .clipboard .writeText (text);
369+ return true ;
370+ } catch (_) {
371+ return false ;
372+ }
373+ };
374+
336375const copyCreatedApiKey = async () => {
337376 if (! createdApiKeyPlaintext .value ) return ;
338- try {
339- await navigator . clipboard . writeText ( createdApiKeyPlaintext . value );
377+ const ok = await copyTextToClipboard ( createdApiKeyPlaintext . value );
378+ if (ok) {
340379 showToast (tm (' apiKey.messages.copySuccess' ), ' success' );
341- } catch (_) {
380+ } else {
342381 showToast (tm (' apiKey.messages.copyFailed' ), ' error' );
343382 }
344383};
0 commit comments