mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2025-09-08 23:18:43 +00:00
updated directory structure to fix root Service Worker issues and performance improvements
This commit is contained in:
557
components/iframe_forms/iframe-application-form.html
Normal file
557
components/iframe_forms/iframe-application-form.html
Normal file
@@ -0,0 +1,557 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>bitvid Whitelist Application 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;
|
||||
}
|
||||
|
||||
/* 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, 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;
|
||||
}
|
||||
|
||||
/* Style for checkboxes – display inline with a label */
|
||||
.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>
|
||||
bitvid is currently in early access. If you would like to request
|
||||
access, please fill out this application. Applications will be
|
||||
reviewed manually, and approvals will be based on alignment with
|
||||
bitvid’s community values.
|
||||
</p>
|
||||
<form id="wl-form">
|
||||
<!-- 1. Applicant Information -->
|
||||
<h2>1. Applicant Information</h2>
|
||||
<label for="applicantNpub">Nostr Public Key (npub):</label>
|
||||
<input
|
||||
type="text"
|
||||
id="applicantNpub"
|
||||
placeholder="Enter your npub"
|
||||
required
|
||||
/>
|
||||
|
||||
<label for="contactMethod"
|
||||
>Preferred Contact Method (if applicable):</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
id="contactMethod"
|
||||
placeholder="Nostr DM, email, or other"
|
||||
/>
|
||||
|
||||
<label for="username">Username or Alias (if applicable):</label>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
placeholder="Enter your preferred name"
|
||||
/>
|
||||
|
||||
<!-- 2. Content Intent -->
|
||||
<h2>2. Content Intent</h2>
|
||||
<p>
|
||||
What type of content do you plan to upload? (Check all that apply)
|
||||
</p>
|
||||
<div class="checkbox-group">
|
||||
<label
|
||||
><input type="checkbox" name="contentType" value="Educational" />
|
||||
Educational</label
|
||||
>
|
||||
<label
|
||||
><input
|
||||
type="checkbox"
|
||||
name="contentType"
|
||||
value="Entertainment"
|
||||
/>
|
||||
Entertainment</label
|
||||
>
|
||||
<label
|
||||
><input
|
||||
type="checkbox"
|
||||
name="contentType"
|
||||
value="News & Journalism"
|
||||
/>
|
||||
News & Journalism</label
|
||||
>
|
||||
<label
|
||||
><input
|
||||
type="checkbox"
|
||||
name="contentType"
|
||||
value="Creative Works"
|
||||
/>
|
||||
Creative Works</label
|
||||
>
|
||||
<label
|
||||
><input
|
||||
type="checkbox"
|
||||
name="contentType"
|
||||
value="Discussions & Opinions"
|
||||
/>
|
||||
Discussions & Opinions</label
|
||||
>
|
||||
<label
|
||||
><input type="checkbox" name="contentType" value="Other" />
|
||||
Other</label
|
||||
>
|
||||
</div>
|
||||
<label for="otherContent">Other (please specify):</label>
|
||||
<input
|
||||
type="text"
|
||||
id="otherContent"
|
||||
placeholder="Describe if Other was selected"
|
||||
/>
|
||||
|
||||
<label for="whyJoin">Why do you want to join bitvid?</label>
|
||||
<textarea
|
||||
id="whyJoin"
|
||||
rows="3"
|
||||
placeholder="Explain your motivation"
|
||||
></textarea>
|
||||
|
||||
<label for="priorExperience"
|
||||
>Have you created content on other platforms before?</label
|
||||
>
|
||||
<select id="priorExperience">
|
||||
<option value="">Select an option</option>
|
||||
<option value="Yes">Yes</option>
|
||||
<option value="No">No</option>
|
||||
</select>
|
||||
|
||||
<label for="experienceLinks"
|
||||
>If yes, provide links or references to your previous work:</label
|
||||
>
|
||||
<textarea
|
||||
id="experienceLinks"
|
||||
rows="2"
|
||||
placeholder="Paste links or describe your work"
|
||||
></textarea>
|
||||
|
||||
<!-- 3. Community Engagement -->
|
||||
<h2>3. Community Engagement</h2>
|
||||
<label for="familiarGuidelines"
|
||||
>Are you familiar with bitvid’s Community Guidelines?</label
|
||||
>
|
||||
<select id="familiarGuidelines">
|
||||
<option value="">Select an option</option>
|
||||
<option value="Yes">Yes</option>
|
||||
<option value="No">No</option>
|
||||
</select>
|
||||
|
||||
<label for="agreeGuidelines"
|
||||
>Do you agree to follow the guidelines and respect decentralized
|
||||
moderation?</label
|
||||
>
|
||||
<select id="agreeGuidelines">
|
||||
<option value="">Select an option</option>
|
||||
<option value="Yes">Yes</option>
|
||||
<option value="No">No</option>
|
||||
</select>
|
||||
|
||||
<label for="communityContribution"
|
||||
>How do you plan to contribute positively to the bitvid
|
||||
community?</label
|
||||
>
|
||||
<textarea
|
||||
id="communityContribution"
|
||||
rows="3"
|
||||
placeholder="Explain your approach"
|
||||
></textarea>
|
||||
|
||||
<!-- 4. Additional Information -->
|
||||
<h2>4. Additional Information</h2>
|
||||
<label for="specialSkills"
|
||||
>Do you have any special skills or interests that could help improve
|
||||
bitvid?</label
|
||||
>
|
||||
<textarea
|
||||
id="specialSkills"
|
||||
rows="3"
|
||||
placeholder="e.g., software development, moderation, design, advocacy"
|
||||
></textarea>
|
||||
|
||||
<label for="testFeatures"
|
||||
>Would you be interested in helping test new features?</label
|
||||
>
|
||||
<select id="testFeatures">
|
||||
<option value="">Select an option</option>
|
||||
<option value="Yes">Yes</option>
|
||||
<option value="No">No</option>
|
||||
</select>
|
||||
|
||||
<!-- 5. Declaration -->
|
||||
<h2>5. Declaration</h2>
|
||||
<p>
|
||||
By submitting this application, you confirm that:
|
||||
<br />- The information provided is accurate. <br />- You understand
|
||||
that approval is based on community alignment and available
|
||||
capacity. <br />- You acknowledge that whitelist status may be
|
||||
revoked if guidelines are violated.
|
||||
</p>
|
||||
<label for="signature">Signature (Digital or Written):</label>
|
||||
<input type="text" id="signature" placeholder="Your signature" />
|
||||
|
||||
<label for="declarationDate">Date:</label>
|
||||
<input type="date" id="declarationDate" />
|
||||
|
||||
<button type="submit">Submit Application</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) here.
|
||||
const recipientNpub =
|
||||
"npub13yarr7j6vjqjjkahd63dmr27curypehx45ucue286ac7sft27y0srnpmpe";
|
||||
const RELAYS = [
|
||||
"wss://relay.snort.social",
|
||||
"wss://relay.damus.io",
|
||||
"wss://relay.primal.net",
|
||||
];
|
||||
const pool = new SimplePool();
|
||||
|
||||
document
|
||||
.getElementById("wl-form")
|
||||
.addEventListener("submit", async (ev) => {
|
||||
ev.preventDefault();
|
||||
clear();
|
||||
try {
|
||||
// Retrieve applicant-provided input.
|
||||
const applicantNpub = document
|
||||
.getElementById("applicantNpub")
|
||||
.value.trim();
|
||||
const contactMethod = document
|
||||
.getElementById("contactMethod")
|
||||
.value.trim();
|
||||
const username = document.getElementById("username").value.trim();
|
||||
|
||||
// Section 2: Content Intent
|
||||
// Get all checked content types
|
||||
const contentTypeNodes = document.querySelectorAll(
|
||||
'input[name="contentType"]:checked'
|
||||
);
|
||||
let contentTypes = [];
|
||||
contentTypeNodes.forEach((node) => {
|
||||
contentTypes.push(node.value);
|
||||
});
|
||||
const otherContent = document
|
||||
.getElementById("otherContent")
|
||||
.value.trim();
|
||||
const whyJoin = document.getElementById("whyJoin").value.trim();
|
||||
const priorExperience = document
|
||||
.getElementById("priorExperience")
|
||||
.value.trim();
|
||||
const experienceLinks = document
|
||||
.getElementById("experienceLinks")
|
||||
.value.trim();
|
||||
|
||||
// Section 3: Community Engagement
|
||||
const familiarGuidelines = document
|
||||
.getElementById("familiarGuidelines")
|
||||
.value.trim();
|
||||
const agreeGuidelines = document
|
||||
.getElementById("agreeGuidelines")
|
||||
.value.trim();
|
||||
const communityContribution = document
|
||||
.getElementById("communityContribution")
|
||||
.value.trim();
|
||||
|
||||
// Section 4: Additional Information
|
||||
const specialSkills = document
|
||||
.getElementById("specialSkills")
|
||||
.value.trim();
|
||||
const testFeatures = document
|
||||
.getElementById("testFeatures")
|
||||
.value.trim();
|
||||
|
||||
// Section 5: Declaration
|
||||
const signature = document
|
||||
.getElementById("signature")
|
||||
.value.trim();
|
||||
const declarationDate = document
|
||||
.getElementById("declarationDate")
|
||||
.value.trim();
|
||||
|
||||
// Construct the whitelist application content.
|
||||
const applicationContent = `
|
||||
# **bitvid Whitelist Application Form**
|
||||
|
||||
**1. Applicant Information**
|
||||
- **Nostr Public Key (npub):** ${applicantNpub}
|
||||
- **Preferred Contact Method:** ${contactMethod || "N/A"}
|
||||
- **Username or Alias:** ${username || "N/A"}
|
||||
|
||||
**2. Content Intent**
|
||||
- **Planned Content Types:** ${contentTypes.join(", ") || "N/A"}
|
||||
- **Other (if applicable):** ${otherContent || "N/A"}
|
||||
- **Why do you want to join bitvid?**
|
||||
${whyJoin || "N/A"}
|
||||
- **Have you created content on other platforms before?** ${
|
||||
priorExperience || "N/A"
|
||||
}
|
||||
- **Links or references to your previous work:**
|
||||
${experienceLinks || "N/A"}
|
||||
|
||||
**3. Community Engagement**
|
||||
- **Familiar with bitvid’s Community Guidelines?** ${
|
||||
familiarGuidelines || "N/A"
|
||||
}
|
||||
- **Agree to follow guidelines and respect moderation?** ${
|
||||
agreeGuidelines || "N/A"
|
||||
}
|
||||
- **How do you plan to contribute to the community?**
|
||||
${communityContribution || "N/A"}
|
||||
|
||||
**4. Additional Information**
|
||||
- **Special skills or interests:**
|
||||
${specialSkills || "N/A"}
|
||||
- **Interested in testing new features?** ${testFeatures || "N/A"}
|
||||
|
||||
**5. Declaration**
|
||||
By submitting this application, you confirm that:
|
||||
- The information provided is accurate.
|
||||
- You understand that approval is based on community alignment and available capacity.
|
||||
- You acknowledge that whitelist status may be revoked if guidelines are violated.
|
||||
|
||||
**Signature (Digital or Written):** ${signature || "N/A"}
|
||||
**Date:** ${declarationDate || "N/A"}
|
||||
|
||||
---
|
||||
|
||||
**Processing Time:** Applications will be reviewed within **7-14 days**. If approved, you will receive a confirmation via your provided contact method. If additional information is needed, we will reach out.
|
||||
|
||||
For further questions, contact us through bitvid’s Nostr support channels.
|
||||
`.trim();
|
||||
|
||||
log(
|
||||
"[DEBUG] Constructed application content:\n" +
|
||||
applicationContent
|
||||
);
|
||||
|
||||
// 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 application content.
|
||||
log("Encrypting application content (nip04)...");
|
||||
const ciphertext = await nip04.encrypt(
|
||||
ephemeralPriv,
|
||||
targetPubHex,
|
||||
applicationContent
|
||||
);
|
||||
log("[DEBUG] Ciphertext: " + ciphertext);
|
||||
log("Encryption done.");
|
||||
|
||||
// Build the Nostr 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 (computing the id and signature).
|
||||
const event = finalizeEvent(eventTemplate, ephemeralPriv);
|
||||
log("[DEBUG] Final event: " + JSON.stringify(event));
|
||||
|
||||
// Publish the event to all relays.
|
||||
log("Publishing the application to relays...");
|
||||
await Promise.any(pool.publish(RELAYS, event));
|
||||
log("At least one relay accepted the event.", "success");
|
||||
|
||||
// For each relay, subscribe to verify the event appears.
|
||||
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 application 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 application was found in storage, a moderator will review your application within 7-14 days."
|
||||
);
|
||||
} catch (err) {
|
||||
log("Error: " + err.message, "error");
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user