Files
bitvid/components/iframe_forms/iframe-request-form.html

472 lines
15 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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="../../css/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 nostrtools 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? Wed 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 &amp; 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? Wed 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 bitvids 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>