@@ -58,6 +58,27 @@ import { animate } from "motion"
5858import { useLocation } from "@solidjs/router"
5959import { attached , inline , kind } from "./message-file"
6060
61+ async function writeClipboard ( text : string ) : Promise < boolean > {
62+ const body = typeof document === "undefined" ? undefined : document . body
63+ if ( body ) {
64+ const textarea = document . createElement ( "textarea" )
65+ textarea . value = text
66+ textarea . setAttribute ( "readonly" , "" )
67+ textarea . style . position = "fixed"
68+ textarea . style . opacity = "0"
69+ textarea . style . pointerEvents = "none"
70+ body . appendChild ( textarea )
71+ textarea . select ( )
72+ const copied = document . execCommand ( "copy" )
73+ body . removeChild ( textarea )
74+ if ( copied ) return true
75+ }
76+
77+ const clipboard = typeof navigator === "undefined" ? undefined : navigator . clipboard
78+ if ( ! clipboard ?. writeText ) return false
79+ return clipboard . writeText ( text ) . then ( ( ) => true , ( ) => false )
80+ }
81+
6182function ShellSubmessage ( props : { text : string ; animate ?: boolean } ) {
6283 let widthRef : HTMLSpanElement | undefined
6384 let valueRef : HTMLSpanElement | undefined
@@ -1064,9 +1085,10 @@ export function UserMessageDisplay(props: { message: UserMessage; parts: PartTyp
10641085 const handleCopy = async ( ) => {
10651086 const content = text ( )
10661087 if ( ! content ) return
1067- await navigator . clipboard . writeText ( content )
1068- setState ( "copied" , true )
1069- setTimeout ( ( ) => setState ( "copied" , false ) , 2000 )
1088+ if ( await writeClipboard ( content ) ) {
1089+ setState ( "copied" , true )
1090+ setTimeout ( ( ) => setState ( "copied" , false ) , 2000 )
1091+ }
10701092 }
10711093
10721094 const revert = ( ) => {
@@ -1490,9 +1512,10 @@ PART_MAPPING["text"] = function TextPartDisplay(props) {
14901512 const handleCopy = async ( ) => {
14911513 const content = text ( )
14921514 if ( ! content ) return
1493- await navigator . clipboard . writeText ( content )
1494- setCopied ( true )
1495- setTimeout ( ( ) => setCopied ( false ) , 2000 )
1515+ if ( await writeClipboard ( content ) ) {
1516+ setCopied ( true )
1517+ setTimeout ( ( ) => setCopied ( false ) , 2000 )
1518+ }
14961519 }
14971520
14981521 return (
@@ -1834,9 +1857,10 @@ ToolRegistry.register({
18341857 const handleCopy = async ( ) => {
18351858 const content = text ( )
18361859 if ( ! content ) return
1837- await navigator . clipboard . writeText ( content )
1838- setCopied ( true )
1839- setTimeout ( ( ) => setCopied ( false ) , 2000 )
1860+ if ( await writeClipboard ( content ) ) {
1861+ setCopied ( true )
1862+ setTimeout ( ( ) => setCopied ( false ) , 2000 )
1863+ }
18401864 }
18411865
18421866 return (
0 commit comments