blob: b21686bf53e770f3e0ef9e2e314d7dacc34ceb74 [file] [log] [blame]
Philip Zeyliger33d282f2025-05-03 04:01:54 +00001import { css, html, LitElement } from "lit";
2import { customElement, property, state } from "lit/decorators.js";
3import { ToolCall } from "../types";
4
Philip Zeyliger80b488d2025-05-10 18:21:54 -07005@customElement("sketch-tool-card-take-screenshot")
6export class SketchToolCardTakeScreenshot extends LitElement {
Philip Zeyliger33d282f2025-05-03 04:01:54 +00007 @property()
8 toolCall: ToolCall;
9
10 @property()
11 open: boolean;
12
13 @state()
14 imageLoaded: boolean = false;
15
16 @state()
17 loadError: boolean = false;
18
19 static styles = css`
20 .summary-text {
21 font-style: italic;
22 padding: 0.5em;
23 }
24
25 .screenshot-container {
26 margin: 10px 0;
27 display: flex;
28 flex-direction: column;
29 align-items: center;
30 }
31
32 .screenshot {
33 max-width: 100%;
34 max-height: 500px;
35 border-radius: 4px;
36 box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
37 border: 1px solid #ddd;
38 }
39
40 .loading-indicator {
41 margin: 20px;
42 color: #666;
43 font-style: italic;
44 }
45
46 .error-message {
47 color: #d32f2f;
48 font-style: italic;
49 margin: 10px 0;
50 }
51
52 .screenshot-info {
53 margin-top: 8px;
54 font-size: 12px;
55 color: #666;
56 }
57
58 .selector-info {
59 padding: 4px 8px;
60 background-color: #f5f5f5;
61 border-radius: 4px;
62 font-family: monospace;
63 margin: 5px 0;
64 display: inline-block;
65 }
66 `;
67
68 constructor() {
69 super();
70 }
71
72 connectedCallback() {
73 super.connectedCallback();
74 }
75
76 disconnectedCallback() {
77 super.disconnectedCallback();
78 }
79
80 render() {
81 // Parse the input to get selector
82 let selector = "";
83 try {
84 if (this.toolCall?.input) {
85 const input = JSON.parse(this.toolCall.input);
86 selector = input.selector || "(full page)";
87 }
88 } catch (e) {
89 console.error("Error parsing screenshot input:", e);
90 }
91
Philip Zeyliger542bda32025-06-11 18:31:03 -070092 // Extract the screenshot ID from the result text
Philip Zeyliger33d282f2025-05-03 04:01:54 +000093 let screenshotId = "";
94 let hasResult = false;
95 if (this.toolCall?.result_message?.tool_result) {
Philip Zeyliger542bda32025-06-11 18:31:03 -070096 // The tool result is now a text like "Screenshot taken (saved as /tmp/sketch-screenshots/{id}.png)"
97 // Extract the ID from this text
98 const resultText = this.toolCall.result_message.tool_result;
99 const pathMatch = resultText.match(
100 /\/tmp\/sketch-screenshots\/(.*?)\.png/,
101 );
102 if (pathMatch) {
103 screenshotId = pathMatch[1];
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000104 hasResult = true;
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000105 }
106 }
107
108 // Construct the URL for the screenshot (using relative URL without leading slash)
109 const screenshotUrl = screenshotId ? `screenshot/${screenshotId}` : "";
110
111 return html`
112 <sketch-tool-card .open=${this.open} .toolCall=${this.toolCall}>
113 <span slot="summary" class="summary-text">
114 Screenshot of ${selector}
115 </span>
116 <div slot="input" class="selector-info">
Autoformatter4962f152025-05-06 17:24:20 +0000117 ${selector !== "(full page)"
118 ? `Taking screenshot of element: ${selector}`
119 : `Taking full page screenshot`}
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000120 </div>
121 <div slot="result">
122 ${hasResult
123 ? html`
124 <div class="screenshot-container">
125 ${!this.imageLoaded && !this.loadError
Autoformatter4962f152025-05-06 17:24:20 +0000126 ? html`<div class="loading-indicator">
127 Loading screenshot...
128 </div>`
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000129 : ""}
130 ${this.loadError
Autoformatter4962f152025-05-06 17:24:20 +0000131 ? html`<div class="error-message">
132 Failed to load screenshot
133 </div>`
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000134 : html`
135 <img
136 class="screenshot"
137 src="${screenshotUrl}"
138 @load=${() => (this.imageLoaded = true)}
139 @error=${() => (this.loadError = true)}
140 ?hidden=${!this.imageLoaded}
141 />
142 ${this.imageLoaded
Autoformatter4962f152025-05-06 17:24:20 +0000143 ? html`<div class="screenshot-info">
Philip Zeyliger542bda32025-06-11 18:31:03 -0700144 Screenshot saved and displayed
Autoformatter4962f152025-05-06 17:24:20 +0000145 </div>`
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000146 : ""}
147 `}
148 </div>
149 `
150 : ""}
151 </div>
152 </sketch-tool-card>
153 `;
154 }
155}
156
157declare global {
158 interface HTMLElementTagNameMap {
Philip Zeyliger80b488d2025-05-10 18:21:54 -0700159 "sketch-tool-card-take-screenshot": SketchToolCardTakeScreenshot;
Philip Zeyliger33d282f2025-05-03 04:01:54 +0000160 }
161}