mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2025-09-08 06:58:43 +00:00
updated forms
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
<!-- componentsbug-fix-form.html
|
||||
<!-- components/bug-fix-form.html
|
||||
// https://bitvid.network?modal=bug => open bugFixModal
|
||||
//
|
||||
// Admin: npub13yarr7j6vjqjjkahd63dmr27curypehx45ucue286ac7sft27y0srnpmpe
|
||||
// Form:
|
||||
// Responces:
|
||||
// Responses:
|
||||
-->
|
||||
<div
|
||||
id="bugFixModal"
|
||||
@@ -26,11 +25,13 @@
|
||||
<div
|
||||
class="modal-content bg-gray-900 w-full max-w-[90%] lg:max-w-6xl my-0 rounded-lg overflow-hidden relative"
|
||||
>
|
||||
<!-- Header bar (sticky) with exit button -->
|
||||
<!-- Header bar (sticky) with updated title styling -->
|
||||
<div
|
||||
class="sticky top-0 bg-gradient-to-b from-black/80 to-transparent p-4 flex items-center justify-between"
|
||||
class="sticky top-0 bg-gradient-to-b from-black/80 to-transparent p-4 flex items-center justify-between border-b border-gray-700"
|
||||
>
|
||||
<h2 class="text-2xl font-bold text-white mb-0">Bug Fix Form</h2>
|
||||
<h2 class="text-3xl font-extrabold text-white tracking-wide pb-2">
|
||||
Bug Fix Form
|
||||
</h2>
|
||||
<button
|
||||
id="closeBugFixModal"
|
||||
class="flex items-center justify-center w-10 h-10 rounded-full bg-black/50 hover:bg-black/70 transition-all duration-200 backdrop-blur focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-black focus:ring-blue-500"
|
||||
@@ -55,7 +56,7 @@
|
||||
<div class="p-6">
|
||||
<div class="w-full" style="height: 80vh">
|
||||
<iframe
|
||||
src=""
|
||||
src="https://beta.bitvid.network/components/iframe_forms/iframe-bug-fix-form.html"
|
||||
class="w-full h-full"
|
||||
frameborder="0"
|
||||
style="border: none; box-shadow: 0 0 2px rgba(0, 0, 0, 0.2)"
|
||||
|
@@ -22,11 +22,13 @@
|
||||
<div
|
||||
class="modal-content bg-gray-900 w-full max-w-[90%] lg:max-w-6xl my-0 rounded-lg overflow-hidden relative"
|
||||
>
|
||||
<!-- Header bar (sticky) with exit button -->
|
||||
<!-- Header bar (sticky) with updated title styling -->
|
||||
<div
|
||||
class="sticky top-0 bg-gradient-to-b from-black/80 to-transparent p-4 flex items-center justify-between"
|
||||
class="sticky top-0 bg-gradient-to-b from-black/80 to-transparent p-4 flex items-center justify-between border-b border-gray-700"
|
||||
>
|
||||
<h2 class="text-2xl font-bold text-white mb-0">Feature Request Form</h2>
|
||||
<h2 class="text-3xl font-extrabold text-white tracking-wide pb-2">
|
||||
Feature Request Form
|
||||
</h2>
|
||||
<button
|
||||
id="closeFeatureRequestModal"
|
||||
class="flex items-center justify-center w-10 h-10 rounded-full bg-black/50 hover:bg-black/70 transition-all duration-200 backdrop-blur focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-black focus:ring-blue-500"
|
||||
@@ -51,7 +53,7 @@
|
||||
<div class="p-6">
|
||||
<div class="w-full" style="height: 80vh">
|
||||
<iframe
|
||||
src="https://formstr.app/#/f/naddr1qvzqqqr4mqpzqkc2xxfvy4y2lfc46kp9v0zxj3tffhdn67wper4f3cdcntevf5zxqy08wumn8ghj7un9d3shjtnwdaehgu3wwa5hyetydejhgtn2wqhsqxmzd968v6tytarx2ct5w4ex2h6jv4ch2etnw305vmmjd5qxscwv?hideTitleImage=true"
|
||||
src="https://beta.bitvid.network/components/iframe_forms/iframe-request-form.html"
|
||||
class="w-full h-full"
|
||||
frameborder="0"
|
||||
style="border: none; box-shadow: 0 0 2px rgba(0, 0, 0, 0.2)"
|
||||
|
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Admin: npub13yarr7j6vjqjjkahd63dmr27curypehx45ucue286ac7sft27y0srnpmpe
|
||||
// Form:
|
||||
// Responces:
|
||||
// Responses:
|
||||
-->
|
||||
<div
|
||||
id="generalFeedbackModal"
|
||||
@@ -26,11 +26,11 @@
|
||||
<div
|
||||
class="modal-content bg-gray-900 w-full max-w-[90%] lg:max-w-6xl my-0 rounded-lg overflow-hidden relative"
|
||||
>
|
||||
<!-- Header bar (sticky) with exit button -->
|
||||
<!-- Header bar (sticky) with updated title styling -->
|
||||
<div
|
||||
class="sticky top-0 bg-gradient-to-b from-black/80 to-transparent p-4 flex items-center justify-between"
|
||||
class="sticky top-0 bg-gradient-to-b from-black/80 to-transparent p-4 flex items-center justify-between border-b border-gray-700"
|
||||
>
|
||||
<h2 class="text-2xl font-bold text-white mb-0">
|
||||
<h2 class="text-3xl font-extrabold text-white tracking-wide pb-2">
|
||||
General Feedback Form
|
||||
</h2>
|
||||
<button
|
||||
@@ -57,7 +57,7 @@
|
||||
<div class="p-6">
|
||||
<div class="w-full" style="height: 80vh">
|
||||
<iframe
|
||||
src=""
|
||||
src="https://beta.bitvid.network/components/iframe_forms/iframe-feedback-form.html"
|
||||
class="w-full h-full"
|
||||
frameborder="0"
|
||||
style="border: none; box-shadow: 0 0 2px rgba(0, 0, 0, 0.2)"
|
||||
|
399
src/components/iframe_forms/iframe-bug-fix-form.html
Normal file
399
src/components/iframe_forms/iframe-bug-fix-form.html
Normal file
@@ -0,0 +1,399 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>bitvid Bug Report Form</title>
|
||||
<!-- Link to your main stylesheet -->
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<style>
|
||||
/* Override for form page to match modal field styling */
|
||||
|
||||
/* Remove width constraints from body so our container can be full width */
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
/* Override the .container to use the full available width */
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Card-like container for the form, similar to modal-content */
|
||||
.form-container {
|
||||
background-color: #111827; /* Tailwind's bg-gray-900 */
|
||||
padding: 1.5rem;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Labels in a light gray */
|
||||
label {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
font-weight: bold;
|
||||
color: #E5E7EB; /* Tailwind's text-gray-200 */
|
||||
}
|
||||
|
||||
/* Input, textarea, and select mimic modal field styles */
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
width: 100%;
|
||||
margin-bottom: 0.75em;
|
||||
background-color: #1F2937; /* Tailwind's bg-gray-800 */
|
||||
color: #F3F4F6; /* Tailwind's text-gray-100 */
|
||||
border: 1px solid #374151; /* Tailwind's border-gray-700 */
|
||||
padding: 0.5em;
|
||||
border-radius: 0.375rem; /* rounded-md */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input:focus,
|
||||
textarea:focus,
|
||||
select:focus {
|
||||
border-color: #3B82F6; /* blue-500 */
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 1px #3B82F6;
|
||||
}
|
||||
|
||||
/* Checkbox group styling */
|
||||
.checkbox-group label {
|
||||
display: inline-block;
|
||||
margin-right: 1rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Button styled similarly to modal publish button */
|
||||
button {
|
||||
padding: 0.5em 1em;
|
||||
background: #3B82F6; /* blue-500 */
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 0.375rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Status log area */
|
||||
#status {
|
||||
margin-top: 1em;
|
||||
padding: 0.5em;
|
||||
background: #111827;
|
||||
white-space: pre-wrap;
|
||||
min-height: 80px;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
.status-line {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
.error {
|
||||
color: #F87171; /* a red tint */
|
||||
}
|
||||
.success {
|
||||
color: #3B82F6; /* blue-500 */
|
||||
}
|
||||
.warn {
|
||||
color: #FACC15; /* a yellow tone */
|
||||
}
|
||||
|
||||
/* Custom Scrollbar styling for WebKit browsers */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #3B82F6;
|
||||
border-radius: 4px;
|
||||
}
|
||||
/* Custom Scrollbar styling for Firefox */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #3B82F6 transparent;
|
||||
}
|
||||
</style>
|
||||
<!-- Load nostr‑tools v2.10.4 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/nostr-tools@2.10.4/lib/nostr.bundle.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="form-container">
|
||||
<p>
|
||||
If you have encountered a bug or technical issue on bitvid, please fill out this form to help us diagnose and resolve the problem. Providing detailed information will assist us in troubleshooting more efficiently.
|
||||
</p>
|
||||
<form id="bug-form">
|
||||
<!-- Section 1: User Information -->
|
||||
<h2>1. User Information</h2>
|
||||
<label for="userNpub">Nostr Public Key (npub) (optional):</label>
|
||||
<input type="text" id="userNpub" placeholder="Enter your npub (optional)" />
|
||||
<p>Are you a (check all that apply):</p>
|
||||
<div class="checkbox-group">
|
||||
<label><input type="checkbox" name="userRole" value="Viewer" /> Viewer</label>
|
||||
<label><input type="checkbox" name="userRole" value="Content Creator" /> Content Creator</label>
|
||||
<label><input type="checkbox" name="userRole" value="Developer/Contributor" /> Developer / Contributor</label>
|
||||
</div>
|
||||
|
||||
<!-- Section 2: Bug Details -->
|
||||
<h2>2. Bug Details</h2>
|
||||
<label for="issueDescription">Describe the issue:</label>
|
||||
<textarea id="issueDescription" rows="3" placeholder="Provide a clear and concise description of the problem"></textarea>
|
||||
<label for="stepsToReproduce">Steps to reproduce the bug:</label>
|
||||
<textarea id="stepsToReproduce" rows="3" placeholder="List the actions taken before encountering the issue"></textarea>
|
||||
<label for="expectedBehavior">Expected behavior:</label>
|
||||
<textarea id="expectedBehavior" rows="2" placeholder="What should have happened instead?"></textarea>
|
||||
<label for="actualBehavior">Actual behavior:</label>
|
||||
<textarea id="actualBehavior" rows="2" placeholder="What actually happened?"></textarea>
|
||||
|
||||
<!-- Section 3: Device & Environment -->
|
||||
<h2>3. Device & Environment</h2>
|
||||
<p>What device were you using? (check all that apply):</p>
|
||||
<div class="checkbox-group">
|
||||
<label><input type="checkbox" name="deviceUsed" value="Desktop" /> Desktop</label>
|
||||
<label><input type="checkbox" name="deviceUsed" value="Mobile" /> Mobile</label>
|
||||
<label><input type="checkbox" name="deviceUsed" value="Tablet" /> Tablet</label>
|
||||
</div>
|
||||
<label for="operatingSystem">Operating System:</label>
|
||||
<input type="text" id="operatingSystem" placeholder="e.g., Windows, macOS, Linux, iOS, Android" />
|
||||
<label for="browserInfo">Browser (if applicable):</label>
|
||||
<input type="text" id="browserInfo" placeholder="e.g., Chrome, Firefox, Safari" />
|
||||
<label for="usingVPN">Are you using a VPN or privacy-focused browser settings?</label>
|
||||
<select id="usingVPN">
|
||||
<option value="">Select an option</option>
|
||||
<option value="Yes">Yes</option>
|
||||
<option value="No">No</option>
|
||||
</select>
|
||||
|
||||
<!-- Section 4: Screenshots or Logs -->
|
||||
<h2>4. Screenshots or Logs (If Available)</h2>
|
||||
<label for="screenshotInfo">Can you provide a screenshot or screen recording?</label>
|
||||
<textarea id="screenshotInfo" rows="2" placeholder="Attach if possible (e.g., URL to screenshot)"></textarea>
|
||||
<label for="errorMessages">Did the issue generate any error messages?</label>
|
||||
<textarea id="errorMessages" rows="2" placeholder="Include the exact error messages, if any"></textarea>
|
||||
<label for="consoleLogs">Any relevant console logs?</label>
|
||||
<textarea id="consoleLogs" rows="2" placeholder="Paste any browser console logs if available"></textarea>
|
||||
|
||||
<!-- Section 5: Additional Information -->
|
||||
<h2>5. Additional Information</h2>
|
||||
<label for="bugFrequency">How frequently does this bug occur?</label>
|
||||
<select id="bugFrequency">
|
||||
<option value="">Select an option</option>
|
||||
<option value="Every time">Every time</option>
|
||||
<option value="Occasionally">Occasionally</option>
|
||||
<option value="Rarely">Rarely</option>
|
||||
</select>
|
||||
<label for="impactCore">Does this bug impact core functionality (e.g., video playback, uploads, etc.)?</label>
|
||||
<select id="impactCore">
|
||||
<option value="">Select an option</option>
|
||||
<option value="Yes">Yes</option>
|
||||
<option value="No">No</option>
|
||||
</select>
|
||||
<label for="additionalNotes">Any additional notes or suggestions?</label>
|
||||
<textarea id="additionalNotes" rows="3" placeholder="Describe any other relevant details"></textarea>
|
||||
|
||||
<button type="submit">Submit Bug Report</button>
|
||||
</form>
|
||||
<div id="status"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Logging functions for both on-page and console output.
|
||||
function log(msg, type = "info") {
|
||||
const div = document.createElement("div");
|
||||
div.classList.add("status-line");
|
||||
if (type === "error") div.classList.add("error");
|
||||
if (type === "success") div.classList.add("success");
|
||||
if (type === "warn") div.classList.add("warn");
|
||||
div.textContent = msg;
|
||||
document.getElementById("status").appendChild(div);
|
||||
console.log(`[${type.toUpperCase()}] ${msg}`);
|
||||
}
|
||||
function clear() {
|
||||
document.getElementById("status").innerHTML = "";
|
||||
}
|
||||
if (!window.NostrTools) {
|
||||
log("NostrTools not loaded. Check console or ad-blockers.", "error");
|
||||
return;
|
||||
}
|
||||
const {
|
||||
generateSecretKey,
|
||||
getPublicKey,
|
||||
finalizeEvent,
|
||||
nip04,
|
||||
nip19,
|
||||
SimplePool,
|
||||
Relay
|
||||
} = window.NostrTools;
|
||||
|
||||
// Set the recipient's NPUB (your personal NPUB)
|
||||
const recipientNpub = "npub13yarr7j6vjqjjkahd63dmr27curypehx45ucue286ac7sft27y0srnpmpe";
|
||||
const RELAYS = [
|
||||
"wss://relay.snort.social",
|
||||
"wss://relay.damus.io",
|
||||
"wss://relay.primal.net"
|
||||
];
|
||||
const pool = new SimplePool();
|
||||
|
||||
document.getElementById("bug-form").addEventListener("submit", async (ev) => {
|
||||
ev.preventDefault();
|
||||
clear();
|
||||
try {
|
||||
// Section 1: User Information
|
||||
const userNpub = document.getElementById("userNpub").value.trim();
|
||||
const roleNodes = document.querySelectorAll('input[name="userRole"]:checked');
|
||||
let userRoles = [];
|
||||
roleNodes.forEach(node => {
|
||||
userRoles.push(node.value);
|
||||
});
|
||||
|
||||
// Section 2: Bug Details
|
||||
const issueDescription = document.getElementById("issueDescription").value.trim();
|
||||
const stepsToReproduce = document.getElementById("stepsToReproduce").value.trim();
|
||||
const expectedBehavior = document.getElementById("expectedBehavior").value.trim();
|
||||
const actualBehavior = document.getElementById("actualBehavior").value.trim();
|
||||
|
||||
// Section 3: Device & Environment
|
||||
const deviceNodes = document.querySelectorAll('input[name="deviceUsed"]:checked');
|
||||
let devicesUsed = [];
|
||||
deviceNodes.forEach(node => {
|
||||
devicesUsed.push(node.value);
|
||||
});
|
||||
const operatingSystem = document.getElementById("operatingSystem").value.trim();
|
||||
const browserInfo = document.getElementById("browserInfo").value.trim();
|
||||
const usingVPN = document.getElementById("usingVPN").value.trim();
|
||||
|
||||
// Section 4: Screenshots or Logs
|
||||
const screenshotInfo = document.getElementById("screenshotInfo").value.trim();
|
||||
const errorMessages = document.getElementById("errorMessages").value.trim();
|
||||
const consoleLogs = document.getElementById("consoleLogs").value.trim();
|
||||
|
||||
// Section 5: Additional Information
|
||||
const bugFrequency = document.getElementById("bugFrequency").value.trim();
|
||||
const impactCore = document.getElementById("impactCore").value.trim();
|
||||
const additionalNotes = document.getElementById("additionalNotes").value.trim();
|
||||
|
||||
// Construct the bug report content as Markdown.
|
||||
const bugReportContent = `
|
||||
# **bitvid Bug Report Form**
|
||||
|
||||
If you have encountered a bug or technical issue on bitvid, please fill out this form to help us diagnose and resolve the problem. Providing detailed information will assist us in troubleshooting more efficiently.
|
||||
|
||||
## **1. User Information**
|
||||
- **Nostr Public Key (npub) (optional):** ${userNpub || "N/A"}
|
||||
- **Roles:** ${userRoles.length > 0 ? userRoles.join(", ") : "N/A"}
|
||||
|
||||
## **2. Bug Details**
|
||||
- **Describe the issue:**
|
||||
${issueDescription || "N/A"}
|
||||
- **Steps to reproduce the bug:**
|
||||
${stepsToReproduce || "N/A"}
|
||||
- **Expected behavior:**
|
||||
${expectedBehavior || "N/A"}
|
||||
- **Actual behavior:**
|
||||
${actualBehavior || "N/A"}
|
||||
|
||||
## **3. Device & Environment**
|
||||
- **Devices used:** ${devicesUsed.length > 0 ? devicesUsed.join(", ") : "N/A"}
|
||||
- **Operating System:** ${operatingSystem || "N/A"}
|
||||
- **Browser:** ${browserInfo || "N/A"}
|
||||
- **Using VPN/Privacy Settings:** ${usingVPN || "N/A"}
|
||||
|
||||
## **4. Screenshots or Logs**
|
||||
- **Screenshot/Recording:** ${screenshotInfo || "N/A"}
|
||||
- **Error Messages:** ${errorMessages || "N/A"}
|
||||
- **Console Logs:** ${consoleLogs || "N/A"}
|
||||
|
||||
## **5. Additional Information**
|
||||
- **Bug Frequency:** ${bugFrequency || "N/A"}
|
||||
- **Impact on Core Functionality:** ${impactCore || "N/A"}
|
||||
- **Additional Notes:** ${additionalNotes || "N/A"}
|
||||
|
||||
---
|
||||
|
||||
**Processing & Resolution:**
|
||||
Our team reviews bug reports regularly. While we aim to fix critical issues as soon as possible, some bugs may take longer to resolve. We appreciate your patience and help in improving bitvid!
|
||||
|
||||
For urgent issues, contact us through bitvid’s Nostr support channels.
|
||||
`.trim();
|
||||
|
||||
log("[DEBUG] Constructed bug report content:\n" + bugReportContent);
|
||||
|
||||
// Decode the recipient NPUB to get the public key.
|
||||
log("Decoding recipient npub...");
|
||||
const decoded = nip19.decode(recipientNpub);
|
||||
log("[DEBUG] Decoded npub: " + JSON.stringify(decoded));
|
||||
if (decoded.type !== "npub") {
|
||||
throw new Error("Decoded type is not npub.");
|
||||
}
|
||||
const targetPubHex = decoded.data;
|
||||
log("Recipient pubkey: " + targetPubHex.slice(0, 16) + "...");
|
||||
|
||||
// Generate an ephemeral key pair.
|
||||
log("Generating ephemeral key...");
|
||||
const ephemeralPriv = generateSecretKey();
|
||||
const ephemeralPubHex = getPublicKey(ephemeralPriv);
|
||||
log("Ephemeral pubkey: " + ephemeralPubHex.slice(0, 16) + "...");
|
||||
|
||||
// Encrypt the bug report content.
|
||||
log("Encrypting bug report content (nip04)...");
|
||||
const ciphertext = await nip04.encrypt(ephemeralPriv, targetPubHex, bugReportContent);
|
||||
log("[DEBUG] Ciphertext: " + ciphertext);
|
||||
log("Encryption done.");
|
||||
|
||||
// Build the event template.
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const eventTemplate = {
|
||||
kind: 4,
|
||||
created_at: now,
|
||||
tags: [["p", targetPubHex]],
|
||||
content: ciphertext,
|
||||
};
|
||||
log("[DEBUG] Event template before finalizing: " + JSON.stringify(eventTemplate));
|
||||
|
||||
// Finalize the event.
|
||||
const event = finalizeEvent(eventTemplate, ephemeralPriv);
|
||||
log("[DEBUG] Final event: " + JSON.stringify(event));
|
||||
|
||||
// Publish the event to all relays.
|
||||
log("Publishing the bug report to relays...");
|
||||
await Promise.any(pool.publish(RELAYS, event));
|
||||
log("At least one relay accepted the event.", "success");
|
||||
|
||||
// Subscribe to each relay.
|
||||
for (const url of RELAYS) {
|
||||
log("Connecting to " + url + " for subscription...");
|
||||
const relay = await Relay.connect(url);
|
||||
relay.subscribe([{ authors: [ephemeralPubHex], kinds: [4] }], {
|
||||
onEvent(foundEvent) {
|
||||
if (foundEvent.id === event.id) {
|
||||
log("[" + url + "] => Found our bug report in storage! ID: " + foundEvent.id.slice(0, 8) + "...", "success");
|
||||
}
|
||||
},
|
||||
onEose() {
|
||||
relay.close();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
log("Done. If the logs show that at least one relay accepted the event and the bug report was found in storage, our team will review your report within 7-14 days.");
|
||||
} catch (err) {
|
||||
log("Error: " + err.message, "error");
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
345
src/components/iframe_forms/iframe-feedback-form.html
Normal file
345
src/components/iframe_forms/iframe-feedback-form.html
Normal file
@@ -0,0 +1,345 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>bitvid General Feedback Form</title>
|
||||
<!-- Link to your main stylesheet -->
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<style>
|
||||
/* Override for form page to match modal field styling */
|
||||
|
||||
/* Remove width constraints from body so our container can be full width */
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
/* Override the .container to use the full available width */
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Card-like container for the form */
|
||||
.form-container {
|
||||
background-color: #111827; /* Tailwind's bg-gray-900 */
|
||||
padding: 1.5rem;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Labels in a light gray */
|
||||
label {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
font-weight: bold;
|
||||
color: #E5E7EB; /* Tailwind's text-gray-200 */
|
||||
}
|
||||
|
||||
/* Input, textarea, and select styling */
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
width: 100%;
|
||||
margin-bottom: 0.75em;
|
||||
background-color: #1F2937; /* Tailwind's bg-gray-800 */
|
||||
color: #F3F4F6; /* Tailwind's text-gray-100 */
|
||||
border: 1px solid #374151; /* Tailwind's border-gray-700 */
|
||||
padding: 0.5em;
|
||||
border-radius: 0.375rem; /* rounded-md */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input:focus,
|
||||
textarea:focus,
|
||||
select:focus {
|
||||
border-color: #3B82F6; /* blue-500 */
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 1px #3B82F6;
|
||||
}
|
||||
|
||||
/* Checkbox group styling */
|
||||
.checkbox-group label {
|
||||
display: inline-block;
|
||||
margin-right: 1rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Radio group styling (for experience rating) */
|
||||
.radio-group label {
|
||||
display: inline-block;
|
||||
margin-right: 1rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Button styling */
|
||||
button {
|
||||
padding: 0.5em 1em;
|
||||
background: #3B82F6; /* blue-500 */
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 0.375rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Status log area */
|
||||
#status {
|
||||
margin-top: 1em;
|
||||
padding: 0.5em;
|
||||
background: #111827;
|
||||
white-space: pre-wrap;
|
||||
min-height: 80px;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
.status-line {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
.error {
|
||||
color: #F87171;
|
||||
}
|
||||
.success {
|
||||
color: #3B82F6;
|
||||
}
|
||||
.warn {
|
||||
color: #FACC15;
|
||||
}
|
||||
|
||||
/* Custom Scrollbar styling for WebKit browsers */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #3B82F6;
|
||||
border-radius: 4px;
|
||||
}
|
||||
/* Custom Scrollbar styling for Firefox */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #3B82F6 transparent;
|
||||
}
|
||||
</style>
|
||||
<!-- Load nostr‑tools v2.10.4 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/nostr-tools@2.10.4/lib/nostr.bundle.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="form-container">
|
||||
<p>
|
||||
Your feedback helps us improve bitvid! Whether it’s a suggestion, a concern, or general thoughts on the platform, we’d love to hear from you.
|
||||
</p>
|
||||
<form id="feedback-form">
|
||||
<!-- Section 1: User Information -->
|
||||
<h2>1. User Information</h2>
|
||||
<label for="userNpub">Nostr Public Key (npub) (optional):</label>
|
||||
<input type="text" id="userNpub" placeholder="Enter your npub (optional)" />
|
||||
<p>Are you a (check all that apply):</p>
|
||||
<div class="checkbox-group">
|
||||
<label><input type="checkbox" name="userRole" value="Viewer" /> Viewer</label>
|
||||
<label><input type="checkbox" name="userRole" value="Content Creator" /> Content Creator</label>
|
||||
<label><input type="checkbox" name="userRole" value="Developer/Contributor" /> Developer / Contributor</label>
|
||||
</div>
|
||||
|
||||
<!-- Section 2: General Feedback -->
|
||||
<h2>2. General Feedback</h2>
|
||||
<label>How would you rate your experience on bitvid so far?</label>
|
||||
<div class="radio-group">
|
||||
<label><input type="radio" name="experienceRating" value="Excellent" /> Excellent</label>
|
||||
<label><input type="radio" name="experienceRating" value="Good" /> Good</label>
|
||||
<label><input type="radio" name="experienceRating" value="Average" /> Average</label>
|
||||
<label><input type="radio" name="experienceRating" value="Needs Improvement" /> Needs Improvement</label>
|
||||
</div>
|
||||
<label for="likeMost">What do you like most about bitvid?</label>
|
||||
<textarea id="likeMost" rows="3" placeholder="Describe the features, usability, or content you enjoy"></textarea>
|
||||
<label for="improvements">What would you like to see improved?</label>
|
||||
<textarea id="improvements" rows="3" placeholder="Provide specific areas for improvement"></textarea>
|
||||
<label for="confusingFeatures">Are there any features or tools you find confusing or difficult to use?</label>
|
||||
<textarea id="confusingFeatures" rows="3" placeholder="Explain any challenges you’ve encountered"></textarea>
|
||||
|
||||
<!-- Section 3: Additional Comments -->
|
||||
<h2>3. Additional Comments</h2>
|
||||
<label for="otherSuggestions">Do you have any other suggestions or thoughts about bitvid?</label>
|
||||
<textarea id="otherSuggestions" rows="3" placeholder="Share any other feedback"></textarea>
|
||||
<label for="followUp">Would you like to be contacted for follow-up discussions?</label>
|
||||
<select id="followUp">
|
||||
<option value="">Select an option</option>
|
||||
<option value="Yes">Yes</option>
|
||||
<option value="No">No</option>
|
||||
</select>
|
||||
<label for="preferredContact">Preferred contact method (if applicable):</label>
|
||||
<input type="text" id="preferredContact" placeholder="Nostr DM, email, or other" />
|
||||
|
||||
<button type="submit">Submit General Feedback</button>
|
||||
</form>
|
||||
<div id="status"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Logging function for on-page and console output.
|
||||
function log(msg, type = "info") {
|
||||
const div = document.createElement("div");
|
||||
div.classList.add("status-line");
|
||||
if (type === "error") div.classList.add("error");
|
||||
if (type === "success") div.classList.add("success");
|
||||
if (type === "warn") div.classList.add("warn");
|
||||
div.textContent = msg;
|
||||
document.getElementById("status").appendChild(div);
|
||||
console.log(`[${type.toUpperCase()}] ${msg}`);
|
||||
}
|
||||
function clear() {
|
||||
document.getElementById("status").innerHTML = "";
|
||||
}
|
||||
if (!window.NostrTools) {
|
||||
log("NostrTools not loaded. Check console or ad-blockers.", "error");
|
||||
return;
|
||||
}
|
||||
const { generateSecretKey, getPublicKey, finalizeEvent, nip04, nip19, SimplePool, Relay } = window.NostrTools;
|
||||
|
||||
// Set the recipient's NPUB (your personal NPUB)
|
||||
const recipientNpub = "npub13yarr7j6vjqjjkahd63dmr27curypehx45ucue286ac7sft27y0srnpmpe";
|
||||
const RELAYS = [
|
||||
"wss://relay.snort.social",
|
||||
"wss://relay.damus.io",
|
||||
"wss://relay.primal.net"
|
||||
];
|
||||
const pool = new SimplePool();
|
||||
|
||||
document.getElementById("feedback-form").addEventListener("submit", async (ev) => {
|
||||
ev.preventDefault();
|
||||
clear();
|
||||
|
||||
try {
|
||||
// Section 1: User Information
|
||||
const userNpub = document.getElementById("userNpub").value.trim();
|
||||
const roleNodes = document.querySelectorAll('input[name="userRole"]:checked');
|
||||
let userRoles = [];
|
||||
roleNodes.forEach(node => {
|
||||
userRoles.push(node.value);
|
||||
});
|
||||
|
||||
// Section 2: General Feedback
|
||||
const experienceRadio = document.querySelector('input[name="experienceRating"]:checked');
|
||||
const experienceRating = experienceRadio ? experienceRadio.value : "N/A";
|
||||
const likeMost = document.getElementById("likeMost").value.trim();
|
||||
const improvements = document.getElementById("improvements").value.trim();
|
||||
const confusingFeatures = document.getElementById("confusingFeatures").value.trim();
|
||||
|
||||
// Section 3: Additional Comments
|
||||
const otherSuggestions = document.getElementById("otherSuggestions").value.trim();
|
||||
const followUp = document.getElementById("followUp").value.trim();
|
||||
const preferredContact = document.getElementById("preferredContact").value.trim();
|
||||
|
||||
// Construct the Markdown feedback content
|
||||
const feedbackContent = `
|
||||
# **bitvid General Feedback Form**
|
||||
|
||||
Your feedback helps us improve bitvid! Whether it’s a suggestion, a concern, or general thoughts on the platform, we’d love to hear from you.
|
||||
|
||||
## **1. User Information**
|
||||
- **Nostr Public Key (npub) (optional):** ${userNpub || "N/A"}
|
||||
- **Are you a (check all that apply):** ${userRoles.length > 0 ? userRoles.join(", ") : "N/A"}
|
||||
|
||||
## **2. General Feedback**
|
||||
- **How would you rate your experience on bitvid so far?** ${experienceRating}
|
||||
- **What do you like most about bitvid?**
|
||||
${likeMost || "N/A"}
|
||||
- **What would you like to see improved?**
|
||||
${improvements || "N/A"}
|
||||
- **Are there any features or tools you find confusing or difficult to use?**
|
||||
${confusingFeatures || "N/A"}
|
||||
|
||||
## **3. Additional Comments**
|
||||
- **Do you have any other suggestions or thoughts about bitvid?**
|
||||
${otherSuggestions || "N/A"}
|
||||
- **Would you like to be contacted for follow-up discussions?** ${followUp || "N/A"}
|
||||
- **Preferred contact method (if applicable):** ${preferredContact || "N/A"}
|
||||
|
||||
---
|
||||
### **Processing & Consideration**
|
||||
We review all feedback regularly to improve bitvid. While not all suggestions may be implemented, we greatly appreciate your input and strive to enhance the platform based on community insights.
|
||||
|
||||
For additional discussions, reach out via bitvid’s Nostr support channels.
|
||||
`.trim();
|
||||
|
||||
log("[DEBUG] Constructed feedback content:\n" + feedbackContent);
|
||||
|
||||
// Decode the recipient NPUB to get the public key.
|
||||
log("Decoding recipient npub...");
|
||||
const decoded = nip19.decode(recipientNpub);
|
||||
log("[DEBUG] Decoded npub: " + JSON.stringify(decoded));
|
||||
if (decoded.type !== "npub") {
|
||||
throw new Error("Decoded type is not npub.");
|
||||
}
|
||||
const targetPubHex = decoded.data;
|
||||
log("Recipient pubkey: " + targetPubHex.slice(0, 16) + "...");
|
||||
|
||||
// Generate an ephemeral key pair.
|
||||
log("Generating ephemeral key...");
|
||||
const ephemeralPriv = generateSecretKey();
|
||||
const ephemeralPubHex = getPublicKey(ephemeralPriv);
|
||||
log("Ephemeral pubkey: " + ephemeralPubHex.slice(0, 16) + "...");
|
||||
|
||||
// Encrypt the feedback content.
|
||||
log("Encrypting feedback content (nip04)...");
|
||||
const ciphertext = await nip04.encrypt(ephemeralPriv, targetPubHex, feedbackContent);
|
||||
log("[DEBUG] Ciphertext: " + ciphertext);
|
||||
log("Encryption done.");
|
||||
|
||||
// Build the event template.
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const eventTemplate = {
|
||||
kind: 4,
|
||||
created_at: now,
|
||||
tags: [["p", targetPubHex]],
|
||||
content: ciphertext,
|
||||
};
|
||||
log("[DEBUG] Event template before finalizing: " + JSON.stringify(eventTemplate));
|
||||
|
||||
// Finalize the event.
|
||||
const event = finalizeEvent(eventTemplate, ephemeralPriv);
|
||||
log("[DEBUG] Final event: " + JSON.stringify(event));
|
||||
|
||||
// Publish the event to all relays.
|
||||
log("Publishing the feedback to relays...");
|
||||
await Promise.any(pool.publish(RELAYS, event));
|
||||
log("At least one relay accepted the event.", "success");
|
||||
|
||||
// Subscribe to each relay to verify storage.
|
||||
for (const url of RELAYS) {
|
||||
log("Connecting to " + url + " for subscription...");
|
||||
const relay = await Relay.connect(url);
|
||||
relay.subscribe([{ authors: [ephemeralPubHex], kinds: [4] }], {
|
||||
onEvent(foundEvent) {
|
||||
if (foundEvent.id === event.id) {
|
||||
log("[" + url + "] => Found our feedback in storage! ID: " + foundEvent.id.slice(0, 8) + "...", "success");
|
||||
}
|
||||
},
|
||||
onEose() {
|
||||
relay.close();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
log("Done. If the logs show that at least one relay accepted the event and the feedback was stored, it will be reviewed accordingly.");
|
||||
} catch (err) {
|
||||
log("Error: " + err.message, "error");
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
357
src/components/iframe_forms/iframe-request-form.html
Normal file
357
src/components/iframe_forms/iframe-request-form.html
Normal file
@@ -0,0 +1,357 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>bitvid Feature Request Form</title>
|
||||
<!-- Link to your main stylesheet -->
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<style>
|
||||
/* Override for form page to match modal field styling */
|
||||
|
||||
/* Remove width constraints from body so our container can be full width */
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
/* Full-width container */
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Card-like container for the form */
|
||||
.form-container {
|
||||
background-color: #111827;
|
||||
padding: 1.5rem;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Labels */
|
||||
label {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
font-weight: bold;
|
||||
color: #E5E7EB;
|
||||
}
|
||||
|
||||
/* Input, textarea, and select styling */
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
width: 100%;
|
||||
margin-bottom: 0.75em;
|
||||
background-color: #1F2937;
|
||||
color: #F3F4F6;
|
||||
border: 1px solid #374151;
|
||||
padding: 0.5em;
|
||||
border-radius: 0.375rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input:focus,
|
||||
textarea:focus,
|
||||
select:focus {
|
||||
border-color: #3B82F6;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 1px #3B82F6;
|
||||
}
|
||||
|
||||
/* Checkbox group styling */
|
||||
.checkbox-group label {
|
||||
display: inline-block;
|
||||
margin-right: 1rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Button styling */
|
||||
button {
|
||||
padding: 0.5em 1em;
|
||||
background: #3B82F6;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 0.375rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Status log area */
|
||||
#status {
|
||||
margin-top: 1em;
|
||||
padding: 0.5em;
|
||||
background: #111827;
|
||||
white-space: pre-wrap;
|
||||
min-height: 80px;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
.status-line {
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
.error {
|
||||
color: #F87171;
|
||||
}
|
||||
.success {
|
||||
color: #3B82F6;
|
||||
}
|
||||
.warn {
|
||||
color: #FACC15;
|
||||
}
|
||||
|
||||
/* Custom Scrollbar styling */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: #3B82F6;
|
||||
border-radius: 4px;
|
||||
}
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #3B82F6 transparent;
|
||||
}
|
||||
</style>
|
||||
<!-- Load nostr‑tools v2.10.4 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/nostr-tools@2.10.4/lib/nostr.bundle.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="form-container">
|
||||
<p>
|
||||
Have an idea for improving bitvid? We’d love to hear it! Please use this form to request new features or enhancements. Your feedback helps shape the future of bitvid.
|
||||
</p>
|
||||
<form id="feature-form">
|
||||
<!-- Section 1: User Information -->
|
||||
<h2>1. User Information</h2>
|
||||
<label for="userNpub">Nostr Public Key (npub) (optional):</label>
|
||||
<input type="text" id="userNpub" placeholder="Enter your npub (optional)" />
|
||||
<p>Are you a (check all that apply):</p>
|
||||
<div class="checkbox-group">
|
||||
<label><input type="checkbox" name="userRole" value="Viewer" /> Viewer</label>
|
||||
<label><input type="checkbox" name="userRole" value="Content Creator" /> Content Creator</label>
|
||||
<label><input type="checkbox" name="userRole" value="Developer/Contributor" /> Developer / Contributor</label>
|
||||
</div>
|
||||
|
||||
<!-- Section 2: Feature Request Details -->
|
||||
<h2>2. Feature Request Details</h2>
|
||||
<label for="featureName">Feature Name:</label>
|
||||
<input type="text" id="featureName" placeholder="Short, descriptive title" required />
|
||||
<label for="featureDescription">Describe the feature:</label>
|
||||
<textarea id="featureDescription" rows="3" placeholder="Explain in detail what the feature does and how it works"></textarea>
|
||||
<label for="featureImportance">Why is this feature important?</label>
|
||||
<textarea id="featureImportance" rows="2" placeholder="Describe how this will improve the platform and benefit users"></textarea>
|
||||
<label for="beneficiary">Who would benefit from this feature?</label>
|
||||
<input type="text" id="beneficiary" placeholder="e.g., Content Creators, Viewers, Both" />
|
||||
|
||||
<!-- Section 3: Additional Information -->
|
||||
<h2>3. Additional Information</h2>
|
||||
<label for="existingPlatforms">Are there existing platforms that have this feature?</label>
|
||||
<textarea id="existingPlatforms" rows="2" placeholder="Provide examples if applicable"></textarea>
|
||||
<label for="mockups">Do you have any mockups or examples?</label>
|
||||
<textarea id="mockups" rows="2" placeholder="Links, screenshots, or diagrams"></textarea>
|
||||
<label for="willingToTest">Would you be willing to help test this feature if implemented?</label>
|
||||
<select id="willingToTest">
|
||||
<option value="">Select an option</option>
|
||||
<option value="Yes">Yes</option>
|
||||
<option value="No">No</option>
|
||||
</select>
|
||||
|
||||
<!-- Section 4: Priority & Impact -->
|
||||
<h2>4. Priority & Impact</h2>
|
||||
<p>How urgent is this feature?</p>
|
||||
<div class="checkbox-group">
|
||||
<label><input type="checkbox" name="featurePriority" value="High" /> High (Essential for platform success)</label>
|
||||
<label><input type="checkbox" name="featurePriority" value="Medium" /> Medium (Would improve experience significantly)</label>
|
||||
<label><input type="checkbox" name="featurePriority" value="Low" /> Low (Nice to have, but not urgent)</label>
|
||||
</div>
|
||||
<label for="techChallenges">Does this feature require technical expertise to implement?</label>
|
||||
<textarea id="techChallenges" rows="2" placeholder="Describe any dependencies or challenges"></textarea>
|
||||
|
||||
<button type="submit">Submit Feature Request</button>
|
||||
</form>
|
||||
<div id="status"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Logging function
|
||||
function log(msg, type = "info") {
|
||||
const div = document.createElement("div");
|
||||
div.classList.add("status-line");
|
||||
if (type === "error") div.classList.add("error");
|
||||
if (type === "success") div.classList.add("success");
|
||||
if (type === "warn") div.classList.add("warn");
|
||||
div.textContent = msg;
|
||||
document.getElementById("status").appendChild(div);
|
||||
console.log(`[${type.toUpperCase()}] ${msg}`);
|
||||
}
|
||||
function clear() {
|
||||
document.getElementById("status").innerHTML = "";
|
||||
}
|
||||
if (!window.NostrTools) {
|
||||
log("NostrTools not loaded. Check console or ad-blockers.", "error");
|
||||
return;
|
||||
}
|
||||
const { generateSecretKey, getPublicKey, finalizeEvent, nip04, nip19, SimplePool, Relay } = window.NostrTools;
|
||||
|
||||
// Set the recipient's NPUB (your personal NPUB)
|
||||
const recipientNpub = "npub13yarr7j6vjqjjkahd63dmr27curypehx45ucue286ac7sft27y0srnpmpe";
|
||||
const RELAYS = [
|
||||
"wss://relay.snort.social",
|
||||
"wss://relay.damus.io",
|
||||
"wss://relay.primal.net"
|
||||
];
|
||||
const pool = new SimplePool();
|
||||
|
||||
document.getElementById("feature-form").addEventListener("submit", async (ev) => {
|
||||
ev.preventDefault();
|
||||
clear();
|
||||
try {
|
||||
// Section 1: User Information
|
||||
const userNpub = document.getElementById("userNpub").value.trim();
|
||||
const roleNodes = document.querySelectorAll('input[name="userRole"]:checked');
|
||||
let userRoles = [];
|
||||
roleNodes.forEach(node => {
|
||||
userRoles.push(node.value);
|
||||
});
|
||||
|
||||
// Section 2: Feature Request Details
|
||||
const featureName = document.getElementById("featureName").value.trim();
|
||||
const featureDescription = document.getElementById("featureDescription").value.trim();
|
||||
const featureImportance = document.getElementById("featureImportance").value.trim();
|
||||
const beneficiary = document.getElementById("beneficiary").value.trim();
|
||||
|
||||
// Section 3: Additional Information
|
||||
const existingPlatforms = document.getElementById("existingPlatforms").value.trim();
|
||||
const mockups = document.getElementById("mockups").value.trim();
|
||||
const willingToTest = document.getElementById("willingToTest").value.trim();
|
||||
|
||||
// Section 4: Priority & Impact
|
||||
const priorityNodes = document.querySelectorAll('input[name="featurePriority"]:checked');
|
||||
let featurePriorities = [];
|
||||
priorityNodes.forEach(node => {
|
||||
featurePriorities.push(node.value);
|
||||
});
|
||||
const techChallenges = document.getElementById("techChallenges").value.trim();
|
||||
|
||||
// Construct Markdown feature request
|
||||
const featureRequestContent = `
|
||||
# **bitvid Feature Request Form**
|
||||
|
||||
Have an idea for improving bitvid? We’d love to hear it! Please use this form to request new features or enhancements. Your feedback helps shape the future of bitvid.
|
||||
|
||||
## **1. User Information**
|
||||
- **Nostr Public Key (npub) (optional):** ${userNpub || "N/A"}
|
||||
- **Roles:** ${userRoles.length > 0 ? userRoles.join(", ") : "N/A"}
|
||||
|
||||
## **2. Feature Request Details**
|
||||
- **Feature Name:** ${featureName || "N/A"}
|
||||
- **Describe the feature:**
|
||||
${featureDescription || "N/A"}
|
||||
- **Why is this feature important?**
|
||||
${featureImportance || "N/A"}
|
||||
- **Who would benefit from this feature?**
|
||||
${beneficiary || "N/A"}
|
||||
|
||||
## **3. Additional Information**
|
||||
- **Are there existing platforms that have this feature?**
|
||||
${existingPlatforms || "N/A"}
|
||||
- **Do you have any mockups or examples?**
|
||||
${mockups || "N/A"}
|
||||
- **Would you be willing to help test this feature if implemented?** ${willingToTest || "N/A"}
|
||||
|
||||
## **4. Priority & Impact**
|
||||
- **How urgent is this feature?**
|
||||
${featurePriorities.length > 0 ? featurePriorities.join(", ") : "N/A"}
|
||||
- **Does this feature require technical expertise to implement?**
|
||||
${techChallenges || "N/A"}
|
||||
|
||||
---
|
||||
|
||||
### **Processing & Consideration**
|
||||
All feature requests are reviewed, but not all may be implemented. We prioritize based on user demand, feasibility, and impact on bitvid. Thank you for helping us improve!
|
||||
|
||||
For further discussions, reach out through bitvid’s Nostr support channels.
|
||||
`.trim();
|
||||
|
||||
log("[DEBUG] Constructed feature request content:\n" + featureRequestContent);
|
||||
|
||||
// Decode the recipient NPUB
|
||||
log("Decoding recipient npub...");
|
||||
const decoded = nip19.decode(recipientNpub);
|
||||
log("[DEBUG] Decoded npub: " + JSON.stringify(decoded));
|
||||
if (decoded.type !== "npub") {
|
||||
throw new Error("Decoded type is not npub.");
|
||||
}
|
||||
const targetPubHex = decoded.data;
|
||||
log("Recipient pubkey: " + targetPubHex.slice(0, 16) + "...");
|
||||
|
||||
// Generate an ephemeral key pair
|
||||
log("Generating ephemeral key...");
|
||||
const ephemeralPriv = generateSecretKey();
|
||||
const ephemeralPubHex = getPublicKey(ephemeralPriv);
|
||||
log("Ephemeral pubkey: " + ephemeralPubHex.slice(0, 16) + "...");
|
||||
|
||||
// Encrypt the feature request content
|
||||
log("Encrypting feature request content (nip04)...");
|
||||
const ciphertext = await nip04.encrypt(ephemeralPriv, targetPubHex, featureRequestContent);
|
||||
log("[DEBUG] Ciphertext: " + ciphertext);
|
||||
log("Encryption done.");
|
||||
|
||||
// Build the event template
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const eventTemplate = {
|
||||
kind: 4,
|
||||
created_at: now,
|
||||
tags: [["p", targetPubHex]],
|
||||
content: ciphertext,
|
||||
};
|
||||
log("[DEBUG] Event template before finalizing: " + JSON.stringify(eventTemplate));
|
||||
|
||||
// Finalize the event
|
||||
const event = finalizeEvent(eventTemplate, ephemeralPriv);
|
||||
log("[DEBUG] Final event: " + JSON.stringify(event));
|
||||
|
||||
// Publish to relays
|
||||
log("Publishing the feature request to relays...");
|
||||
await Promise.any(pool.publish(RELAYS, event));
|
||||
log("At least one relay accepted the event.", "success");
|
||||
|
||||
// Subscribe to verify event storage
|
||||
for (const url of RELAYS) {
|
||||
log("Connecting to " + url + " for subscription...");
|
||||
const relay = await Relay.connect(url);
|
||||
relay.subscribe([{ authors: [ephemeralPubHex], kinds: [4] }], {
|
||||
onEvent(foundEvent) {
|
||||
if (foundEvent.id === event.id) {
|
||||
log("[" + url + "] => Found our feature request in storage! ID: " + foundEvent.id.slice(0, 8) + "...", "success");
|
||||
}
|
||||
},
|
||||
onEose() {
|
||||
relay.close();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
log("Done. If the logs show that at least one relay accepted the event and the feature request was stored, it will be reviewed accordingly.");
|
||||
} catch (err) {
|
||||
log("Error: " + err.message, "error");
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user