Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion frontend/crash-recorded-standalone.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,13 @@ <h2>What you can do</h2>
</div>

<details>
<summary>View Stack Trace</summary>
<summary>
View Stack Trace
<button class="copy-trace-btn" onclick="event.stopPropagation();var t=document.querySelector('.stacktrace').textContent;navigator.clipboard.writeText(t).then(function(){this.querySelector('span').textContent='Copied!';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2e3)}.bind(this))" title="Copy stack trace">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add error handling for clipboard API failure.

The navigator.clipboard.writeText() call has no .catch() handler. If clipboard access is denied (e.g., in non-secure contexts or when permissions are blocked), the promise rejects silently and the "Copied!" feedback never appears, leaving users confused.

🛡️ Proposed fix with error handling
-          <button class="copy-trace-btn" onclick="event.stopPropagation();var t=document.querySelector('.stacktrace').textContent;navigator.clipboard.writeText(t).then(function(){this.querySelector('span').textContent='Copied!';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2e3)}.bind(this))" title="Copy stack trace">
+          <button class="copy-trace-btn" onclick="event.stopPropagation();var t=document.querySelector('.stacktrace').textContent;navigator.clipboard.writeText(t).then(function(){this.querySelector('span').textContent='Copied!';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2000)}.bind(this)).catch(function(){this.querySelector('span').textContent='Failed';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2000)}.bind(this))" title="Copy stack trace">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button class="copy-trace-btn" onclick="event.stopPropagation();var t=document.querySelector('.stacktrace').textContent;navigator.clipboard.writeText(t).then(function(){this.querySelector('span').textContent='Copied!';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2e3)}.bind(this))" title="Copy stack trace">
<button class="copy-trace-btn" onclick="event.stopPropagation();var t=document.querySelector('.stacktrace').textContent;navigator.clipboard.writeText(t).then(function(){this.querySelector('span').textContent='Copied!';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2000)}.bind(this)).catch(function(){this.querySelector('span').textContent='Failed';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2000)}.bind(this))" title="Copy stack trace">
🤖 Prompt for AI Agents
In `@frontend/crash-recorded-standalone.html` at line 54, The inline onclick
handler for the copy button uses navigator.clipboard.writeText(...) without a
.catch, so failures are silent; update the handler attached to elements with
class "copy-trace-btn" (the current inline onclick) to add a .catch handler on
the promise returned by navigator.clipboard.writeText that logs the error
(console.error) and provides UI feedback (e.g., change the button's inner span
text to "Copy failed" or similar, then revert after a timeout), and ensure the
success .then still sets "Copied!" and reverts after 2s; keep using
event.stopPropagation() and the existing element lookup
(document.querySelector('.stacktrace')) but handle rejection paths explicitly.

<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="14" height="14"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
<span>Copy</span>
</button>
</summary>
<div class="stacktrace">%STACKTRACE%</div>
</details>

Expand Down
21 changes: 21 additions & 0 deletions frontend/crash-recorded.css
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,27 @@ summary:hover {
font-size: 0.9375rem;
}
}
.copy-trace-btn {
margin-left: auto;
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
background: #262626;
border: 1px solid #383838;
border-radius: 4px;
color: #a3a3a3;
cursor: pointer;
transition: color 0.15s, background 0.15s;
}
.copy-trace-btn:hover {
background: #333;
color: #f472b6;
}
.copy-trace-btn svg {
flex-shrink: 0;
}
Comment on lines +233 to +253
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Add empty lines before CSS rules for consistency.

Stylelint flags missing empty lines before .copy-trace-btn, .copy-trace-btn:hover, and .copy-trace-btn svg rules. Adding empty lines improves readability and matches the formatting pattern used elsewhere in this file.

🧹 Proposed formatting fix
 .hidden {
   display: none;
 }
+
 .copy-trace-btn {
   margin-left: auto;
   display: inline-flex;
   align-items: center;
   gap: 0.35rem;
   padding: 0.25rem 0.5rem;
   font-size: 0.75rem;
   background: `#262626`;
   border: 1px solid `#383838`;
   border-radius: 4px;
   color: `#a3a3a3`;
   cursor: pointer;
   transition: color 0.15s, background 0.15s;
 }
+
 .copy-trace-btn:hover {
   background: `#333`;
   color: `#f472b6`;
 }
+
 .copy-trace-btn svg {
   flex-shrink: 0;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.copy-trace-btn {
margin-left: auto;
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
background: #262626;
border: 1px solid #383838;
border-radius: 4px;
color: #a3a3a3;
cursor: pointer;
transition: color 0.15s, background 0.15s;
}
.copy-trace-btn:hover {
background: #333;
color: #f472b6;
}
.copy-trace-btn svg {
flex-shrink: 0;
}
.hidden {
display: none;
}
.copy-trace-btn {
margin-left: auto;
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
background: `#262626`;
border: 1px solid `#383838`;
border-radius: 4px;
color: `#a3a3a3`;
cursor: pointer;
transition: color 0.15s, background 0.15s;
}
.copy-trace-btn:hover {
background: `#333`;
color: `#f472b6`;
}
.copy-trace-btn svg {
flex-shrink: 0;
}
🧰 Tools
🪛 Stylelint (17.2.0)

[error] 233-246: Expected empty line before rule (rule-empty-line-before)

(rule-empty-line-before)


[error] 247-250: Expected empty line before rule (rule-empty-line-before)

(rule-empty-line-before)


[error] 251-253: Expected empty line before rule (rule-empty-line-before)

(rule-empty-line-before)

🤖 Prompt for AI Agents
In `@frontend/crash-recorded.css` around lines 233 - 253, The CSS blocks for the
selectors .copy-trace-btn, .copy-trace-btn:hover, and .copy-trace-btn svg are
missing a blank line before each rule; update the formatting so there is an
empty line preceding each of these selectors to match the file's established
spacing and satisfy Stylelint (i.e., insert a single blank line immediately
above the .copy-trace-btn rule, above .copy-trace-btn:hover, and above
.copy-trace-btn svg).

.hidden {
display: none;
}
8 changes: 7 additions & 1 deletion frontend/crash-recorded.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@ <h2>Help us fix it</h2>
</div>

<details>
<summary>View Stack Trace</summary>
<summary>
View Stack Trace
<button class="copy-trace-btn" onclick="event.stopPropagation();var t=document.querySelector('.stacktrace').textContent;navigator.clipboard.writeText(t).then(function(){this.querySelector('span').textContent='Copied!';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2e3)}.bind(this))" title="Copy stack trace">
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add error handling for clipboard API failure.

Same issue as the standalone version—no .catch() handler for navigator.clipboard.writeText(). If clipboard access fails, users get no feedback.

🛡️ Proposed fix with error handling
-          <button class="copy-trace-btn" onclick="event.stopPropagation();var t=document.querySelector('.stacktrace').textContent;navigator.clipboard.writeText(t).then(function(){this.querySelector('span').textContent='Copied!';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2e3)}.bind(this))" title="Copy stack trace">
+          <button class="copy-trace-btn" onclick="event.stopPropagation();var t=document.querySelector('.stacktrace').textContent;navigator.clipboard.writeText(t).then(function(){this.querySelector('span').textContent='Copied!';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2000)}.bind(this)).catch(function(){this.querySelector('span').textContent='Failed';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2000)}.bind(this))" title="Copy stack trace">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button class="copy-trace-btn" onclick="event.stopPropagation();var t=document.querySelector('.stacktrace').textContent;navigator.clipboard.writeText(t).then(function(){this.querySelector('span').textContent='Copied!';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2e3)}.bind(this))" title="Copy stack trace">
<button class="copy-trace-btn" onclick="event.stopPropagation();var t=document.querySelector('.stacktrace').textContent;navigator.clipboard.writeText(t).then(function(){this.querySelector('span').textContent='Copied!';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2000)}.bind(this)).catch(function(){this.querySelector('span').textContent='Failed';var b=this;setTimeout(function(){b.querySelector('span').textContent='Copy'},2000)}.bind(this))" title="Copy stack trace">
🤖 Prompt for AI Agents
In `@frontend/crash-recorded.html` at line 63, The inline onclick handler on the
button (class "copy-trace-btn") calls navigator.clipboard.writeText(...) but
lacks error handling; update the handler for navigator.clipboard.writeText (or
the function it calls) to add a .catch() (or try/catch if converted to async) so
clipboard errors are handled and user feedback is given (e.g., change the
button's inner span text to "Failed" or show an error tooltip) and optionally
log the error to console; ensure you reference the same DOM access used now
(document.querySelector('.stacktrace').textContent and
this.querySelector('span')) so success still sets "Copied!" and failure sets a
clear failure state.

<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="14" height="14"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
<span>Copy</span>
</button>
</summary>
<div class="stacktrace">%STACKTRACE%</div>
</details>

Expand Down
24 changes: 22 additions & 2 deletions frontend/frontend.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Parse, RemapAPIResponse } from "../lib/parser";
import { os_names } from "../lib/format";
import { os_names, addrsToPlainText } from "../lib/format";

import { parse } from "../lib/parser";
import { parseCacheKey, debounce, escapeHTML as eschtml } from "../lib/util";
Expand Down Expand Up @@ -191,11 +191,31 @@ const screens: Record<UIState, () => void> = {
out.innerHTML = /* html */ `
<div class='card'>
${cardHead()}
<table><tbody>${list}</tbody></table>
<div class='table-wrapper'>
<table><tbody>${list}</tbody></table>
<button class='copy-btn' title='Copy stack trace'>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
<span>Copy</span>
</button>
</div>
${cardFooter()}
<div class='spacing'>${issue}</div>
</div>
`;

const copyBtn = out.querySelector(".copy-btn") as HTMLButtonElement;
if (copyBtn) {
copyBtn.addEventListener("click", () => {
const lines = addrsToPlainText(fetched!.commit.oid, fetched!.addresses);
const text = `${parsed!.message}\n\n${lines.join("\n")}`;
navigator.clipboard.writeText(text).then(() => {
copyBtn.querySelector("span")!.textContent = "Copied!";
setTimeout(() => {
copyBtn.querySelector("span")!.textContent = "Copy";
}, 2000);
});
Comment on lines +211 to +216
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add error handling for clipboard API failure.

The navigator.clipboard.writeText() call lacks a .catch() handler. Unlike the HTML templates, TypeScript makes it easy to handle this properly.

🛡️ Proposed fix with error handling
         navigator.clipboard.writeText(text).then(() => {
           copyBtn.querySelector("span")!.textContent = "Copied!";
           setTimeout(() => {
             copyBtn.querySelector("span")!.textContent = "Copy";
           }, 2000);
+        }).catch(() => {
+          copyBtn.querySelector("span")!.textContent = "Failed";
+          setTimeout(() => {
+            copyBtn.querySelector("span")!.textContent = "Copy";
+          }, 2000);
         });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
navigator.clipboard.writeText(text).then(() => {
copyBtn.querySelector("span")!.textContent = "Copied!";
setTimeout(() => {
copyBtn.querySelector("span")!.textContent = "Copy";
}, 2000);
});
navigator.clipboard.writeText(text).then(() => {
copyBtn.querySelector("span")!.textContent = "Copied!";
setTimeout(() => {
copyBtn.querySelector("span")!.textContent = "Copy";
}, 2000);
}).catch(() => {
copyBtn.querySelector("span")!.textContent = "Failed";
setTimeout(() => {
copyBtn.querySelector("span")!.textContent = "Copy";
}, 2000);
});
🤖 Prompt for AI Agents
In `@frontend/frontend.ts` around lines 211 - 216, The clipboard write call using
navigator.clipboard.writeText(text) in the click handler should handle failures;
add a .catch(err => { ... }) after the .then to handle rejection, e.g. set
copyBtn.querySelector("span")!.textContent to an error/fallback message (or
revert to "Copy"), and log the error (console.error or a logger) so failures are
visible; ensure you still restore the button text in a timeout on both success
and failure paths and reference navigator.clipboard.writeText, copyBtn, and the
span querySelector in your changes.

});
}
},

// When fetch fails, fallback to this screen.
Expand Down
34 changes: 34 additions & 0 deletions frontend/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,40 @@ button:hover,
}
}

.table-wrapper {
position: relative;
}

.copy-btn {
position: absolute;
top: 0;
right: 0;
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.3rem 0.6rem;
font-size: 0.8rem;
background-color: var(--fn-bg);
border: 1px solid var(--fn-border);
border-radius: 6px;
color: var(--fg);
cursor: pointer;
opacity: 0.7;
transition: opacity 0.15s;
}

.copy-btn:hover {
opacity: 1;
background-color: var(--pink);
border-color: rgb(247, 97, 174);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Use modern color-function notation.

Stylelint flags rgb(247, 97, 174) as using legacy syntax. Modern CSS uses space-separated values without commas.

🧹 Proposed fix
 .copy-btn:hover {
   opacity: 1;
   background-color: var(--pink);
-  border-color: rgb(247, 97, 174);
+  border-color: rgb(247 97 174);
   color: black;
 }
🧰 Tools
🪛 Stylelint (17.2.0)

[error] 314-314: Expected modern color-function notation (color-function-notation)

(color-function-notation)

🤖 Prompt for AI Agents
In `@frontend/style.css` at line 314, Replace the legacy comma-separated rgb()
value used on the border-color declaration with the modern space-separated
color-function syntax; locate the border-color: rgb(247, 97, 174) statement and
change it to use rgb(247 97 174) (no commas) so it satisfies Stylelint's modern
color-function rule.

color: black;
}

.copy-btn svg {
width: 14px;
height: 14px;
}

@media (max-width: 480px) {
.card {
margin-left: -1em;
Expand Down