5 Commits

Author SHA1 Message Date
9285f8e583 Update web/superball.html 2025-11-18 04:11:37 +00:00
c5ec067a79 Update web/superball.html 2025-11-18 03:54:22 +00:00
387f5d4725 Update web/superball.html 2025-11-18 02:37:28 +00:00
c4d73026b5 CSS 2025-11-16 04:38:00 +00:00
516c4f2f80 Adds reply and profile creation along with post functionality
This commit introduces new features to enhance user interaction and profile management:

- Adds the ability to create replies for comments
- Enables profile creation for users
- Supports post creation for sharing updates and content
2025-11-16 04:36:10 +00:00
2 changed files with 223 additions and 16 deletions

View File

@@ -216,11 +216,11 @@ label {
@keyframes pulse {
0%,
100% {
opacity: 1;
opacity: 1;
}
50% {
opacity: 0.5;
opacity: 0.5;
}
}
@@ -737,4 +737,55 @@ small {
.floating-tab:hover {
transform: scale(1.05);
}
/* .input-group {
margin: 20px;
} */
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
textarea {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
.tabs {
display: flex;
margin: 20px 20px 0;
border-bottom: 1px solid #ccc;
}
.tab {
padding: 10px 20px;
cursor: pointer;
background-color: #f1f1f1;
border: 1px solid #ccc;
border-bottom: none;
margin-right: 5px;
border-radius: 4px 4px 0 0;
}
.tab.active {
background-color: #fff;
border-bottom: 1px solid #fff;
}
.tab-content {
display: none;
padding: 20px;
border: 1px solid #ccc;
border-radius: 4px;
}
.tab-content.active {
display: block;
}

View File

@@ -29,8 +29,44 @@
<div class="section">
<h2>Final Event (What gets posted at the end)</h2>
<div class="input-group">
<label for="final-content">Message Content:</label>
<textarea id="final-content" rows="3" placeholder="Enter your message content..."></textarea>
<div class="tabs">
<div class="tab active" data-tab="tab1">Post</div>
<div class="tab" data-tab="tab2">Reply</div>
<div class="tab" data-tab="tab3">Create Profile</div>
</div>
<div class="tab-content active" id="tab1">
<h3>Post</h3>
<label for="final-content">Message Content:</label>
<textarea id="final-content" rows="3" placeholder="Enter your message content..."></textarea>
</div>
<div class="tab-content" id="tab2">
<h3>Reply</h3>
<label for="nevent">Nevent:</label>
<textarea id="nevent" placeholder="Enter the nevent for the note..."></textarea>
<label for="reply-content">Message Content:</label>
<textarea id="reply-content" rows="3" placeholder="Enter your message content..."></textarea>
</div>
<div class="tab-content" id="tab3">
<h3>Create Profile</h3>
<label for="name">Name:</label>
<textarea id="name" placeholder="Enter your name..."></textarea>
<label for="about">About:</label>
<textarea id="about" rows="2" placeholder="A short bio..."></textarea>
<label for="profile-pic">Profile Picture:</label>
<textarea id="profile-pic" placeholder="URL of your profile pic..."></textarea>
<label for="display-name">Display Name:</label>
<textarea id="display-name" placeholder="Enter your display name..."></textarea>
<label for="website">Website:</label>
<textarea id="website" placeholder="Web URL..."></textarea>
<label for="banner">Banner:</label>
<textarea id="banner" placeholder="Enter your bannerm a (~1024x768) wide picture url..."></textarea>
<label for="nip05">NIP05:</label>
<textarea id="nip05" placeholder="Enter your nip05 in the format username@domain.com..."></textarea>
<label for="lud16">Lightning Address:</label>
<textarea id="lud16" placeholder="Enter your lightning address..."></textarea>
</div>
</div>
<button onclick="createFinalEvent()">Create Event That Will Be Published Publicly</button>
@@ -79,6 +115,26 @@
<!-- <script src="./nostr-lite.js"></script> -->
<script>
document.addEventListener('DOMContentLoaded', function() {
const tabs = document.querySelectorAll('.tab');
const tabContents = document.querySelectorAll('.tab-content');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
// Remove active class from all tabs and contents
tabs.forEach(t => t.classList.remove('active'));
tabContents.forEach(c => c.classList.remove('active'));
// Add active class to clicked tab
tab.classList.add('active');
// Show corresponding content
const tabId = tab.getAttribute('data-tab');
document.getElementById(tabId).classList.add('active');
});
});
});
// Global variables
let nlLite = null;
let userPubkey = null;
@@ -232,7 +288,11 @@
} else {
console.log('INFO', 'No relay list found, using defaults');
userRelays = [
{ url: 'wss://relay.laantungir.net', type: 'both' }
{ url: 'wss://relay.laantungir.net', type: 'both' },
{ url: 'wss://relay.primal.net', type: 'both' },
{ url: 'wss://nos.lol', type: 'both' },
{ url: 'wss://relay.damus.io', type: 'both' },
{ url: 'wss://offchain.pub', type: 'both' }
];
return userRelays;
}
@@ -712,22 +772,118 @@
// Create final event (kind 1)
async function createFinalEvent() {
const content = document.getElementById('final-content').value.trim();
// Get the active tab
const activeTab = document.querySelector('.tab.active').getAttribute('data-tab');
// Get content based on active tab
let content = '';
let nevent = '';
let neventData;
let name = '';
let about = '';
let profilePic = '';
let displayName = '';
let website = '';
let banner = '';
let nip05 = '';
let lud16 = '';
switch(activeTab) {
case 'tab1': // Post
content = document.getElementById('final-content').value.trim();
break;
case 'tab2': // Reply
content = document.getElementById('reply-content').value.trim();
nevent = document.getElementById('nevent').value.trim();
break;
case 'tab3': // Create Profile
name = document.getElementById('name').value.trim();
about = document.getElementById('about').value.trim();
profilePic = document.getElementById('profile-pic').value.trim();
displayName = document.getElementById('display-name').value.trim();
website = document.getElementById('website').value.trim();
banner = document.getElementById('banner').value.trim();
nip05 = document.getElementById('nip05').value.trim();
lud16 = document.getElementById('lud16').value.trim();
break;
}
if (!content) {
alert('Please enter message content');
return;
// Validate content based on tab
if (activeTab === 'tab1') {
if (!content) {
alert('Please enter message content');
return;
}
} else if (activeTab === 'tab2') {
if (!content) {
alert('Please enter message content');
return;
}
if (!nevent.startsWith('nevent')) {
alert('Please enter a valid nevent');
return;
}
try {
neventData = window.NostrTools.nip19.decode(nevent).data;
} catch (error) {
alert('Error decoding nevent string', error.message);
return;
}
} else if (activeTab === 'tab3') {
if (!name) {
alert('Please enter your name');
return;
}
}
try {
// Create the final event (kind 1) - pure message, no relay info
const eventTemplate = {
kind: 1,
content: content,
tags: [],
created_at: Math.floor(Date.now() / 1000)
};
let eventTemplate = {};
switch(activeTab) {
case 'tab1': // Post
eventTemplate = {
kind: 1,
content: content,
tags: [],
created_at: Math.floor(Date.now() / 1000)
};
break;
case 'tab2': // Reply
eventTemplate = {
kind: 1,
content: content,
tags: [['e', neventData.id, neventData.relays[0], 'root'], ['p', neventData.author]],
created_at: Math.floor(Date.now() / 1000)
};
neventData.relays.slice(1).forEach(relay => {
eventTemplate.tags.push(['r', relay]);
});
break;
case 'tab3': // Create Profile
eventTemplate = {
kind: 0,
content: JSON.stringify({
name: name,
about: about,
picture: profilePic,
display_name: displayName,
website: website,
banner: banner,
nip05: nip05,
lud16: lud16
}),
tags: [],
created_at: Math.floor(Date.now() / 1000)
};
break;
}
// Your existing event publishing logic here
console.log('Event to publish:', eventTemplate);
// ... rest of your publishing code
// Sign the event using window.nostr (NIP-07)
finalEvent = await window.nostr.signEvent(eventTemplate);