Files
saphid--frame-control/site/public/js/feedback.js
T

94 lines
3.6 KiB
JavaScript

// The feedback form: posts to /api/feedback (site/functions/api/feedback.js), which opens a GitHub issue.
const form = document.getElementById("feedback");
const errorBox = document.getElementById("error");
const send = document.getElementById("send");
const started = performance.now();
const HINTS = {
bug: "What you tried, what happened, and what you expected.",
idea: "What you'd like, and what it would help you do.",
question: "What you'd like to know.",
other: "Anything you'd like to tell us.",
};
// Prefill the computer field; people rarely know the exact wording otherwise.
(function guessOs() {
const ua = navigator.userAgent;
const guess = /Windows/.test(ua) ? "Windows" : /Macintosh/.test(ua) ? "macOS" : /iPhone|iPad/.test(ua) ? "iOS"
: /Android/.test(ua) ? "" : /Linux/.test(ua) ? "Linux" : "";
if (guess) form.elements.os.value = guess;
})();
form.addEventListener("change", (e) => {
if (e.target.name === "kind") document.getElementById("message-hint").textContent = HINTS[e.target.value];
});
// A prefilled GitHub issue form (.github/ISSUE_TEMPLATE), for when this form can't reach GitHub itself.
function githubUrl(data) {
const params = data.kind === "idea"
? new URLSearchParams({ template: "idea.yml", title: data.title, what: data.message })
: new URLSearchParams({ template: "bug.yml", title: data.title, description: data.message,
version: data.version, os: [data.os, data.steamos && `SteamOS ${data.steamos}`].filter(Boolean).join(", ") });
return `https://github.com/saphid/frame-control/issues/new?${params}`;
}
function showError(message, data) {
errorBox.textContent = message + " ";
if (data) {
const a = document.createElement("a");
a.href = githubUrl(data);
a.target = "_blank";
a.rel = "noopener";
a.textContent = "Open it on GitHub instead";
errorBox.append(a);
}
errorBox.hidden = false;
errorBox.scrollIntoView({ behavior: "smooth", block: "center" });
}
form.addEventListener("submit", async (e) => {
e.preventDefault();
errorBox.hidden = true;
const data = Object.fromEntries(new FormData(form));
if (data.title.trim().length < 5) {
form.elements.title.focus();
return showError("Give it a short title (at least 5 characters).");
}
if (data.message.trim().length < 10) {
form.elements.message.focus();
return showError("Tell us a little more in Details.");
}
send.disabled = true;
send.textContent = "Sending…";
try {
// The server treats anything sent sooner as a script (site/lib/feedback.js MIN_FILL_MS).
const wait = 3100 - (performance.now() - started);
if (wait > 0) await new Promise((resolve) => setTimeout(resolve, wait));
const res = await fetch("/api/feedback", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ ...data, elapsed: Math.round(performance.now() - started) }),
});
const reply = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(reply.error || "Something went wrong sending that.");
form.hidden = true;
document.getElementById("done").hidden = false;
if (reply.url) {
const link = document.getElementById("issue-link");
link.href = reply.url;
link.hidden = false;
document.getElementById("done-text").textContent = `Your feedback is now issue #${reply.number} on GitHub.`
+ (data.github ? " You'll be notified when someone replies." : " Bookmark it to follow along.");
}
window.scrollTo({ top: 0, behavior: "smooth" });
} catch (err) {
showError(err.message || "Couldn't reach the server.", data);
} finally {
send.disabled = false;
send.textContent = "Send feedback";
}
});