1+ // Copyright 2025, Command Line Inc.
2+ // SPDX-License-Identifier: Apache-2.0
3+
4+ import { RpcApi } from "@/app/store/wshclientapi" ;
5+ import { TabRpcClient } from "@/app/store/wshrpcutil" ;
6+ import { cn , makeIconClass } from "@/util/util" ;
7+ import { memo , useState } from "react" ;
8+
9+ interface AIFeedbackButtonsProps {
10+ messageText : string ;
11+ }
12+
13+ export const AIFeedbackButtons = memo ( ( { messageText } : AIFeedbackButtonsProps ) => {
14+ const [ thumbsUpClicked , setThumbsUpClicked ] = useState ( false ) ;
15+ const [ thumbsDownClicked , setThumbsDownClicked ] = useState ( false ) ;
16+ const [ copied , setCopied ] = useState ( false ) ;
17+
18+ const handleThumbsUp = ( ) => {
19+ setThumbsUpClicked ( ! thumbsUpClicked ) ;
20+ if ( thumbsDownClicked ) {
21+ setThumbsDownClicked ( false ) ;
22+ }
23+ if ( ! thumbsUpClicked ) {
24+ RpcApi . RecordTEventCommand ( TabRpcClient , {
25+ event : "waveai:feedback" ,
26+ props : {
27+ "waveai:feedback" : "good" ,
28+ } ,
29+ } ) ;
30+ }
31+ } ;
32+
33+ const handleThumbsDown = ( ) => {
34+ setThumbsDownClicked ( ! thumbsDownClicked ) ;
35+ if ( thumbsUpClicked ) {
36+ setThumbsUpClicked ( false ) ;
37+ }
38+ if ( ! thumbsDownClicked ) {
39+ RpcApi . RecordTEventCommand ( TabRpcClient , {
40+ event : "waveai:feedback" ,
41+ props : {
42+ "waveai:feedback" : "bad" ,
43+ } ,
44+ } ) ;
45+ }
46+ } ;
47+
48+ const handleCopy = ( ) => {
49+ navigator . clipboard . writeText ( messageText ) ;
50+ setCopied ( true ) ;
51+ setTimeout ( ( ) => setCopied ( false ) , 2000 ) ;
52+ } ;
53+
54+ return (
55+ < div className = "flex items-center gap-0.5 mt-2" >
56+ < button
57+ onClick = { handleThumbsUp }
58+ className = { cn (
59+ "p-1.5 rounded cursor-pointer transition-colors" ,
60+ thumbsUpClicked
61+ ? "text-accent"
62+ : "text-secondary hover:bg-gray-700 hover:text-primary"
63+ ) }
64+ title = "Good Response"
65+ >
66+ < i className = { makeIconClass ( thumbsUpClicked ? "solid@thumbs-up" : "regular@thumbs-up" , false ) } />
67+ </ button >
68+ < button
69+ onClick = { handleThumbsDown }
70+ className = { cn (
71+ "p-1.5 rounded cursor-pointer transition-colors" ,
72+ thumbsDownClicked
73+ ? "text-accent"
74+ : "text-secondary hover:bg-gray-700 hover:text-primary"
75+ ) }
76+ title = "Bad Response"
77+ >
78+ < i className = { makeIconClass ( thumbsDownClicked ? "solid@thumbs-down" : "regular@thumbs-down" , false ) } />
79+ </ button >
80+ { messageText ?. trim ( ) && (
81+ < button
82+ onClick = { handleCopy }
83+ className = { cn (
84+ "p-1.5 rounded cursor-pointer transition-colors" ,
85+ copied
86+ ? "text-success"
87+ : "text-secondary hover:bg-gray-700 hover:text-primary"
88+ ) }
89+ title = "Copy Message"
90+ >
91+ < i className = { makeIconClass ( copied ? "solid@check" : "regular@copy" , false ) } />
92+ </ button >
93+ ) }
94+ </ div >
95+ ) ;
96+ } ) ;
97+
98+ AIFeedbackButtons . displayName = "AIFeedbackButtons" ;
0 commit comments