This commit is contained in:
Your Name
2025-09-09 09:32:09 -04:00
commit 37fb89c0a9
135 changed files with 36437 additions and 0 deletions

View File

@@ -0,0 +1,121 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Minimal Nostr Login Test (Remote)</title>
</head>
<body>
<div id="user-info" style="display: none;">
<div id="user-name"></div>
<img id="user-picture" style="display: none;">
</div>
<script>
// Load nostr-login script with configuration from your website
const script = document.createElement('script');
script.src = 'https://laantungir.net/nostr-login/unpkg.js';
// Configure with Laan theme and Welcome Login start screen
script.setAttribute('data-theme', 'laan');
script.setAttribute('data-start-screen', 'welcome-login');
script.setAttribute('data-methods', 'connect,extension,local,readOnly');
script.setAttribute('data-no-banner', 'false');
document.head.appendChild(script);
// Wait for script to load, then set up event listeners
script.onload = () => {
setupEventListeners();
};
function setupEventListeners() {
// Listen for authentication events
document.addEventListener('nlAuth', (e) => {
const { type, pubkey, name } = e.detail;
if (type === 'login' || type === 'signup') {
console.log('User logged in:', e.detail);
showUserInfo();
// Check for profile updates periodically
startProfilePolling();
} else if (type === 'logout') {
console.log('User logged out');
hideUserInfo();
stopProfilePolling();
}
});
}
let profileInterval;
function startProfilePolling() {
// Check immediately
updateUserProfile();
// Then check every 2 seconds for profile updates
profileInterval = setInterval(updateUserProfile, 2000);
// Stop checking after 15 seconds (profile should be loaded by then)
setTimeout(stopProfilePolling, 15000);
}
function stopProfilePolling() {
if (profileInterval) {
clearInterval(profileInterval);
profileInterval = null;
}
}
function updateUserProfile() {
try {
// Try to get user info from localStorage (current user)
const userInfo = JSON.parse(localStorage.getItem('__nostrlogin_nip46') || 'null');
if (userInfo) {
updateUserDisplay(userInfo);
}
} catch (error) {
// Silently handle errors to avoid interference
}
}
function showUserInfo() {
const userInfoDiv = document.getElementById('user-info');
userInfoDiv.style.display = 'block';
updateUserProfile();
}
function updateUserDisplay(userInfo) {
const userNameDiv = document.getElementById('user-name');
const userPicture = document.getElementById('user-picture');
// Display name with proper fallback hierarchy
const displayName = userInfo.name ||
(userInfo.nip05 && userInfo.nip05.split('@')[0]) ||
(userInfo.pubkey && userInfo.pubkey.substring(0, 16) + '...') ||
'Unknown';
userNameDiv.textContent = displayName;
// Update profile picture if available
if (userInfo.picture) {
userPicture.src = userInfo.picture;
userPicture.style.display = 'block';
userPicture.style.width = '200px';
// userPicture.style.height = '200px';
}
}
function hideUserInfo() {
const userInfoDiv = document.getElementById('user-info');
const userNameDiv = document.getElementById('user-name');
const userPicture = document.getElementById('user-picture');
userInfoDiv.style.display = 'none';
userNameDiv.textContent = '';
userPicture.src = '';
userPicture.style.display = 'none';
}
</script>
</body>
</html>

121
examples/minimal-test.html Normal file
View File

@@ -0,0 +1,121 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Minimal Nostr Login Test</title>
</head>
<body>
<div id="user-info" style="display: none;">
<div id="user-name"></div>
<img id="user-picture" style="display: none;">
</div>
<script>
// Load nostr-login script with configuration
const script = document.createElement('script');
script.src = '../packages/auth/dist/unpkg.js';
// Configure with Laan theme and Welcome Login start screen
script.setAttribute('data-theme', 'laan');
script.setAttribute('data-start-screen', 'welcome-login');
script.setAttribute('data-methods', 'connect,extension,local,readOnly');
script.setAttribute('data-no-banner', 'false');
document.head.appendChild(script);
// Wait for script to load, then set up event listeners
script.onload = () => {
setupEventListeners();
};
function setupEventListeners() {
// Listen for authentication events
document.addEventListener('nlAuth', (e) => {
const { type, pubkey, name } = e.detail;
if (type === 'login' || type === 'signup') {
console.log('User logged in:', e.detail);
showUserInfo();
// Check for profile updates periodically
startProfilePolling();
} else if (type === 'logout') {
console.log('User logged out');
hideUserInfo();
stopProfilePolling();
}
});
}
let profileInterval;
function startProfilePolling() {
// Check immediately
updateUserProfile();
// Then check every 2 seconds for profile updates
profileInterval = setInterval(updateUserProfile, 2000);
// Stop checking after 15 seconds (profile should be loaded by then)
setTimeout(stopProfilePolling, 15000);
}
function stopProfilePolling() {
if (profileInterval) {
clearInterval(profileInterval);
profileInterval = null;
}
}
function updateUserProfile() {
try {
// Try to get user info from localStorage (current user)
const userInfo = JSON.parse(localStorage.getItem('__nostrlogin_nip46') || 'null');
if (userInfo) {
updateUserDisplay(userInfo);
}
} catch (error) {
// Silently handle errors to avoid interference
}
}
function showUserInfo() {
const userInfoDiv = document.getElementById('user-info');
userInfoDiv.style.display = 'block';
updateUserProfile();
}
function updateUserDisplay(userInfo) {
const userNameDiv = document.getElementById('user-name');
const userPicture = document.getElementById('user-picture');
// Display name with proper fallback hierarchy
const displayName = userInfo.name ||
(userInfo.nip05 && userInfo.nip05.split('@')[0]) ||
(userInfo.pubkey && userInfo.pubkey.substring(0, 16) + '...') ||
'Unknown';
userNameDiv.textContent = displayName;
// Update profile picture if available
if (userInfo.picture) {
userPicture.src = userInfo.picture;
userPicture.style.display = 'block';
userPicture.style.width = '200px';
// userPicture.style.height = '200px';
}
}
function hideUserInfo() {
const userInfoDiv = document.getElementById('user-info');
const userNameDiv = document.getElementById('user-name');
const userPicture = document.getElementById('user-picture');
userInfoDiv.style.display = 'none';
userNameDiv.textContent = '';
userPicture.src = '';
userPicture.style.display = 'none';
}
</script>
</body>
</html>

838
examples/rtl-test.html Normal file
View File

@@ -0,0 +1,838 @@
<!doctype html>
<html lang="" class="has-dark-text" dir="rtl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>من الجميل في نوستر هي قدرة…</title>
<link
rel="stylesheet"
href="https://blossom.npubpro.com/9d9f5663fcc8ec87f256d3959fcd763ae234774d7cfcaf85a5ad10e3adea63e3.css"
/>
<style>
:root {
--background-color: #ffffff;
}
</style>
<script>
/* The script for calculating the color contrast was taken from
https://gomakethings.com/dynamically-changing-the-text-color-based-on-background-color-contrast-with-vanilla-js/ */
var accentColor = getComputedStyle(
document.documentElement,
).getPropertyValue('--background-color')
accentColor = accentColor.trim().slice(1)
var r = parseInt(accentColor.substr(0, 2), 16)
var g = parseInt(accentColor.substr(2, 2), 16)
var b = parseInt(accentColor.substr(4, 2), 16)
var yiq = (r * 299 + g * 587 + b * 114) / 1000
var textColor = yiq >= 128 ? 'dark' : 'light'
document.documentElement.className = `has-${textColor}-text`
</script>
<meta property="og:title" content="من الجميل في نوستر هي قدرة…" />
<meta name="twitter:title" content="من الجميل في نوستر هي قدرة…" />
<meta
name="description"
content="من الجميل في نوستر هي قدرة التطبيقات على التخاطر.
إذا بتفضلوا استخدام مساحة مثل الDiscord، ضيفوا صفحتنا على flotilla.social للتواصل بصيغة التشات.
اضغط إضافة مساحة Add Space،
ثم الدخول على مساحة Join a space،
وضيفوا ريلاي relay.nostrarabia.com
نراكم. 🫡
#nostrarabia…"
/>
<meta
property="og:description"
content="من الجميل في نوستر هي قدرة التطبيقات على التخاطر.
إذا بتفضلوا استخدام مساحة مثل الDiscord، ضيفوا صفحتنا على flotilla.social للتواصل بصيغة التشات.
اضغط إضافة مساحة Add Space،
ثم الدخول على مساحة Join a space،
وضيفوا ريلاي relay.nostrarabia.com
نراكم. 🫡
#nostrarabia…"
/>
<meta
name="twitter:description"
content="من الجميل في نوستر هي قدرة التطبيقات على التخاطر.
إذا بتفضلوا استخدام مساحة مثل الDiscord، ضيفوا صفحتنا على flotilla.social للتواصل بصيغة التشات.
اضغط إضافة مساحة Add Space،
ثم الدخول على مساحة Join a space،
وضيفوا ريلاي relay.nostrarabia.com
نراكم. 🫡
#nostrarabia…"
/>
<meta
property="og:image"
content="https://image.nostr.build/4afea744d3f72f4f7af1f7d632a8594159ef65f49b48cb00890c3904c57e1822.jpg"
/>
<meta
name="twitter:image"
content="https://image.nostr.build/4afea744d3f72f4f7af1f7d632a8594159ef65f49b48cb00890c3904c57e1822.jpg"
/>
<meta name="twitter:image:alt" content="من الجميل في نوستر هي قدرة…" />
<link
rel="canonical"
href="https://nostrarabia.npub.pro/post/note1dplcmt2885l9tsy6c4xenm3w7hrg92af42sz76p0ypd7ft0muvpqg80sqn/"
/>
<link
rel="og:url"
href="https://nostrarabia.npub.pro/post/note1dplcmt2885l9tsy6c4xenm3w7hrg92af42sz76p0ypd7ft0muvpqg80sqn/"
/>
<meta property="og:site_name" content="نوستر" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@nostrprotocol" />
<meta property="og:type" content="website" />
<!--
***********************
Powered by npub.pro
***********************
-->
<meta
name="nostr:site"
content="naddr1qqxkummnw3shywnzxg6kyv34qythwumn8ghj7un9d3shjtnwwp6kyurjduhxxmmdqgsgzt8ltta9m8pmgzptstrsxew06tf8nsn64yfrzwu0e07kt3q2a6crqsqqqaesldfhew"
/>
<meta name="author" content="نوستر بالعربي" />
<meta
name="nostr:author"
content="npub1syk07kh6tkwrksyzhqk8qdjul5kj08p842gjxyacljlavhzq4m4slmdu3p"
/>
<meta
name="nostr:id"
content="note1dplcmt2885l9tsy6c4xenm3w7hrg92af42sz76p0ypd7ft0muvpqg80sqn"
/>
<meta
name="nostr:event_id"
content="note1dplcmt2885l9tsy6c4xenm3w7hrg92af42sz76p0ypd7ft0muvpqg80sqn"
/>
<link
rel="manifest"
href="https://nostrarabia.npub.pro/manifest.webmanifest"
/>
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"
></script>
<link
rel="preload"
as="style"
href="https://cdn.jsdelivr.net/npm/venobox@2.1.8/dist/venobox.min.css"
/>
<link
rel="icon"
href="https://image.nostr.build/4afea744d3f72f4f7af1f7d632a8594159ef65f49b48cb00890c3904c57e1822.jpg"
type="image/jpeg"
/>
<link
rel="apple-touch-icon"
href="https://image.nostr.build/4afea744d3f72f4f7af1f7d632a8594159ef65f49b48cb00890c3904c57e1822.jpg"
/>
<meta name="theme-color" content="#ffffff" />
<script>
document.documentElement.setAttribute('dir', 'rtl')
</script>
<style>
.np-oembed-video-link {
display: inline-block;
position: relative;
}
.np-oembed-video-link img {
max-width: 100%;
}
.np-oembed-video-link:after {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 96px;
height: 96px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAACXBIWXMAAAsTAAALEwEAmpwYAAAJeUlEQVR4nO1daYwUVRD+9oBlV9kFJESjixxq8GAl3lEU1EXiwQ+RQwUPvIi3xgMVD7wxCgYTDwQFlxANakw0Jho1iqJoBEQMIuqqYHA9dleRBXZhZExpTeyU1T09M/1ed8/0l7xkd2be1a/7Vb2qr6qBBAkSJEiQoHjRA8AwABMA3AFgMYDlANYAaAbQDqCLSzt/Rt99xL+9g+sO47YS5IhKAIcDmAbgLQDbAaQDKjsBrAAwE0AjgKpkdXSU8wVqArAlwAXIVqiv5wCczGMoefTnu/VHi4uQdik0hgeBf8ZUctgfwDMAdvi8WM0AXgXwMIBLAZwA4BAAAwH0BtCNS2/+jL4bwb+lOq9xG376Ilk0H8B+KAEMAvA8gFSWi7IRwAIA5wHYJ8D+qa3zASz08VSmWCmgBS460N17LYAOjwuwmWUIyZIyS+Mi5WEOgFaPcW0DMKOYFIBTAHztMeG1fNdWhzjGah7DWo9xruebJdbqK91Zf7lMcDVfhApEB2UAxgD4xGXMu/iJ6o6YYYDHpDYBmIjo4xweqzYHOpjui5jgVAC/uxzKZgPoifigFsCjPHY5H7IKjEbEcb6LKksy5DDEF4cD+EaZF811MiKKa1zkxcsAeiH+6MkquyZXbkLEcJ/LFnU5ig9Xumxh9yIiuEoZXCeAsShejAGwVZn3DWEPbJKyTZFAH47ix9EAflO2rwvD1KZ2KJpHA0oHDTxnKeita19kEW1TTAyl8GRoT4o0CbXzWcyaXeojxRB3JkoXZyiC/hNbJ/rZijArRm0qCOWGTP9GMYoFl7PTF0x3GiO8qAh58kYaAZmfvxIdfsPmhQT/HR7XK1YKI6b7O5WDX5DmkNMAfAngAwBnIb44UnHA3WbC07dNdEKyJChUKAbJd5m6E0fMEXPZGrTWJW04mwK22vZ1MXOnADwNoB/ihToALWIui4Jq/ADlEQzan+G2IGkufwC4MWaOoUnKFj84iIafFQ2vMuDz3iPLgqQdSsR4xAcrxfjpaS/4RC7NIyaMhn1EH9sVjc5Z3mKqT9QxXqEY1RfS4EzR4FpDDL/eiumhG4DrFFuRcwt4gre7qIKu1Tox7gcKaUxyl8gjaAK9RD+/O77ryxfejcvVzgtHCxhFXCjGuyHfm3qUwpuqgTmtJC2EuMQQAK97bGNfR1S+VPN8nGM9KZ+GmkQj82AOtcriu6ExC3/qbQBDES0sEGOk/3NCd4WFTnxaU+gp+vrTx/huUu68TNnBhzNSFqKAk5QbLqct9niFa2uS3rm76G+Lz3r9WJV0I+O1sg+cSHtholzheB2XSwMzRGU6i5jEbqK/jhzrHwjgDY9tjFTo0xEupAi4PZfKS0VlYqGbRI1i+8mXfNCc5fxyMMLBFDGWd3LRCjpF5SBDAtz6TDsKGTLzBcUR3uoRiUWHs1khcMX6K4dfXzGPw0RFuuNMo4cy2EKxF2+1bvLlVwBTLZO9vxdj8EUImSgqUeSSaVSJPjsDbJt8Nu97bGPrmEFjA/IcNS4fR5RxvzCrsWmxrQQNki/feSzMa0FZY3PgI0z3U2mxqHQJzKObco4wJaum8TnH6/xClgMTmCr6I80rKz4UlSh40jQqFcOhSezNDiNJ2MiUnwFcbMCQeqLoh9zVWfGFqGRDTawQfaZgB0cAWOaxja0K2ELRINr/3E+lH0QlG5FC5aLPv2APZWyU/CGLfCFeQaEYKNolmZYVMiKVvHk2LkraUWgrsQ2yFtyjkDmcqvjYgD2jRNbOii5RyZYfOy1KWOjP5D9tUcimZ129D2tBdol+bcWqawfjpR5nFusLEsaWBeVEXQ67IM/kkx6eyZ+Y6W59ywpDqIe5IJUALlOCb+TZpDYsoR6G2gvlzqyw0OdIVj29rMMHha32LgvhYAiFbtTNYF8DFKa6s6xnrjGicDAMw3Ria0Gq2XTiZprvMJxoJi/TSRjGRRva3RjF/O0899DF2RMRNC6GYX6H4hSrCqhdog+96bE9UQ7GYxFh8/uhITiooJyQqwNQMR/3UGNbmMRm87wjn9Chfr138m4tiI/qE1tFn/mS8kg7u0KJEs6ULt6GbUd+7auYYnzvAu9ZopAGvSAjfKixYZEcLsqX5EC4q1CmXR7oEH2SsS8X/0aTh38jCmEMi/IR6BkMF5V/tLDX/in69BOhVc03j5Z3JM1t3hyBQJ9yNr04x5aTItFduUCmD4ibRX/Z9vhxHj6MXZwgmZgnUcDJhVJJwRNyNkK5bKOwIEOysBRX5krTtICFYoyUszhnNFoMR4BCnK5TgnrmuOSqSrOV+tqIJdUEXzO525ANLdIBO1DConvz5xWcusMtt+4OZiKaYopEJmAHnAvdRkgblNC1PkwwWO2xPb3BW1icQtruL6TBesXGZCrLQptCLEh7qLFkm4o6JohxdwbBk54vGv3MkArc5rEAmbKVrbFxeDFLmRIW/VQQDQ9WBOnZCB6tHgtBauySmL1K4jwxh1SQb1yQPpKfDNiCfo2ANTYo1DH7MWffRy6+YGmNpYzPQWKFaP8Xdo7F8c03j4m5dJh4uqeLTnZyxucg3ZstfB6ZHePky0cpJv9bTHRUpSTnCjqBWVkEAjQLQS8lpO5Lk7a0RsWiSsI2wb94SVFG6Mk3ikcUwUuhx6WOa5Tr8pCNjiuVGJJUkacWz4YxytHgY5v5V+qVc8M2TjhQajhG8cdYTaScAaXTTlKN4382uC5O3BPaa4G0ZPzHl3Ay/gvCHtiVijDrjHmqVz8yQwvsuR4RwT3K4HZy+u1i1KZSynzvRsRwtUvWhFcczqY4o9YlsiqSrzzKYLLLS8G+5YhXxNgc0qzMiwT4uYg4Rrv4NlKGg/JNoI4NhdoW1RqmNpUPbXK5izm9hZMMhxVD6Adl7M+Q2akz5UNL9Fqrr15dE8FXr5azBvVpllevRjUDqm+SmFdS5HXMzKgJcYw1nGBMEhKk1da4odD267vdIpcyppclfIdWWHoaiDI71yMZjdOPXzSv73ZiAJOO3chuaYeLuImfnP4By7YpPAbJtdXOUU0x8+MXRJyYp1CM0i7le44+msUhzCM5onUQ87e6c+nDnzXwb6Zyndc9wtk0VXZuQLlNYod6Jo5t9Hmx0gbLBh6L6fySsUA5JxteqJCuTZbNnJdxZEzJFFZQweSJaRzxtD3ABdjJ7JaZ7I4OO24klqhimTCemS+LOLnBajZntPG+38V/N/N3y1goT+dYkoZi1ZQSJEiQIEECwt/UKk4KqlBwIwAAAABJRU5ErkJggg==');
background-size: cover;
content: '';
}
</style>
<style>
:root {
--ghost-accent-color: #139ad4;
}
</style>
<link rel="stylesheet" href="https://cdn.npubpro.com/maptalks.css" />
<link
rel="alternate"
type="application/rss+xml"
title="نوستر"
href="https://nostrarabia.npub.pro/rss/"
/>
<link
rel="stylesheet"
type="text/css"
href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300..800&amp;display=swap"
/>
<link
rel="stylesheet"
type="text/css"
href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@300..800&amp;display=swap"
/>
<link
rel="preload"
as="script"
href="https://blossom.npubpro.com/64f7c3c5de348a7d1a5c7d1519abfa33fec8c5442c583fda441d25cd7b5990cf.js"
/>
<link
rel="preload"
as="style"
href="https://blossom.npubpro.com/8c397e35e20c7e4c6e163f0d17511294a2fba1c1a13823b91e2c220c3c38e83b.css"
/>
<link
rel="preload"
as="style"
href="https://blossom.npubpro.com/9d9f5663fcc8ec87f256d3959fcd763ae234774d7cfcaf85a5ad10e3adea63e3.css"
/>
<link
rel="preload"
as="script"
href="https://blossom.npubpro.com/b8292724b60caed6133f097c3f0427163e93e87724da84861192e1322d4146f5.js"
/>
<link
rel="preload"
as="script"
href="https://blossom.npubpro.com/b866f2b384af7668032c0c2fd523717520537bf812de9870cf1a960b11087333.js"
/>
<link
rel="preload"
as="style"
href="https://blossom.npubpro.com/eb267981d379bed63595b7ebd1dd6cb775c912a6f9b0f16c2faee5050afbf381.css"
/>
</head>
<body
class="post-template tag-nostrarabia is-head-left-logo has-parallax-feed is-dropdown-loaded"
style="overflow: initial"
>
<div class="gh-site">
<header id="gh-head" class="gh-head gh-outer">
<div class="gh-head-inner gh-inner">
<div class="gh-head-brand">
<div class="gh-head-brand-wrapper">
<a
class="gh-head-logo"
href="https://nostrarabia.npub.pro"
>
<img
src="https://image.nostr.build/4afea744d3f72f4f7af1f7d632a8594159ef65f49b48cb00890c3904c57e1822.jpg"
alt="نوستر"
/>
</a>
</div>
<button
class="gh-search gh-icon-btn"
aria-label="Search this site"
data-ghost-search=""
>
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17.5 17.5L12.5 12.5L17.5 17.5ZM14.1667 8.33333C14.1667 9.09938 14.0158 9.85792 13.7226 10.5657C13.4295 11.2734 12.9998 11.9164 12.4581 12.4581C11.9164 12.9998 11.2734 13.4295 10.5657 13.7226C9.85792 14.0158 9.09938 14.1667 8.33333 14.1667C7.56729 14.1667 6.80875 14.0158 6.10101 13.7226C5.39328 13.4295 4.75022 12.9998 4.20854 12.4581C3.66687 11.9164 3.23719 11.2734 2.94404 10.5657C2.65088 9.85792 2.5 9.09938 2.5 8.33333C2.5 6.78624 3.11458 5.30251 4.20854 4.20854C5.30251 3.11458 6.78624 2.5 8.33333 2.5C9.88043 2.5 11.3642 3.11458 12.4581 4.20854C13.5521 5.30251 14.1667 6.78624 14.1667 8.33333Z"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
></path>
</svg>
</button>
<button class="gh-burger"></button>
</div>
<nav class="gh-head-menu">
<ul class="nav">
<li class="nav-alreysyh">
<a href="https://nostrarabia.npub.pro/"
>الرئيسية</a
>
</li>
<li class="nav-nwstr-arby">
<a
href="https://nostrarabia.npub.pro/tag/nostrarabia/"
>نوستر عربي</a
>
</li>
<li class="nav-talm-albytkwyn">
<a
href="https://nostrarabia.npub.pro/tag/learnbitcoin/"
>تعلّم البيتكوين</a
>
</li>
<li class="nav-talm-alaqtsad-alnmsawy">
<a
href="https://nostrarabia.npub.pro/tag/Learnaustrianeconomics/"
>تعلّم الاقتصاد النمساوي</a
>
</li>
<li class="nav-alaadhaa">
<a
href="https://nostrarabia.npub.pro/tag/community/"
>الأعضاء</a
>
</li>
<li class="nav-akhbar">
<a href="https://nostrarabia.npub.pro/tag/news/"
>أخبار</a
>
</li>
<button
class="nav-more-toggle gh-icon-btn"
aria-label="More"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 32 32"
fill="currentColor"
>
<path
d="M21.333 16c0-1.473 1.194-2.667 2.667-2.667v0c1.473 0 2.667 1.194 2.667 2.667v0c0 1.473-1.194 2.667-2.667 2.667v0c-1.473 0-2.667-1.194-2.667-2.667v0zM13.333 16c0-1.473 1.194-2.667 2.667-2.667v0c1.473 0 2.667 1.194 2.667 2.667v0c0 1.473-1.194 2.667-2.667 2.667v0c-1.473 0-2.667-1.194-2.667-2.667v0zM5.333 16c0-1.473 1.194-2.667 2.667-2.667v0c1.473 0 2.667 1.194 2.667 2.667v0c0 1.473-1.194 2.667-2.667 2.667v0c-1.473 0-2.667-1.194-2.667-2.667v0z"
></path>
</svg>
<div class="gh-dropdown">
<li class="nav-mymz">
<a
href="https://nostrarabia.npub.pro/tag/memes/"
>ميمز</a
>
</li>
<li class="nav-adwat">
<a
href="https://nostrarabia.npub.pro/tag/tools/"
>أدوات</a
>
</li>
<li class="nav-idamna">
<a
href="https://nostrarabia.npub.pro/tag/supportus/"
>إدعمنا</a
>
</li>
</div>
</button>
</ul>
</nav>
<div class="gh-head-actions">
<button
class="gh-search gh-icon-btn"
aria-label="Search this site"
data-ghost-search=""
>
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17.5 17.5L12.5 12.5L17.5 17.5ZM14.1667 8.33333C14.1667 9.09938 14.0158 9.85792 13.7226 10.5657C13.4295 11.2734 12.9998 11.9164 12.4581 12.4581C11.9164 12.9998 11.2734 13.4295 10.5657 13.7226C9.85792 14.0158 9.09938 14.1667 8.33333 14.1667C7.56729 14.1667 6.80875 14.0158 6.10101 13.7226C5.39328 13.4295 4.75022 12.9998 4.20854 12.4581C3.66687 11.9164 3.23719 11.2734 2.94404 10.5657C2.65088 9.85792 2.5 9.09938 2.5 8.33333C2.5 6.78624 3.11458 5.30251 4.20854 4.20854C5.30251 3.11458 6.78624 2.5 8.33333 2.5C9.88043 2.5 11.3642 3.11458 12.4581 4.20854C13.5521 5.30251 14.1667 6.78624 14.1667 8.33333Z"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
></path>
</svg>
</button>
</div>
</div>
</header>
<main class="gh-main gh-outer">
<div class="gh-inner">
<article class="gh-article post tag-nostrarabia no-image">
<section class="gh-content gh-canvas">
<np-content
event="note1dplcmt2885l9tsy6c4xenm3w7hrg92af42sz76p0ypd7ft0muvpqg80sqn"
><p>
من الجميل في نوستر هي قدرة التطبيقات على
التخاطر.<br /><br />إذا بتفضلوا استخدام
مساحة مثل الDiscord، ضيفوا صفحتنا على
flotilla.social للتواصل بصيغة التشات.
<br /><br />اضغط إضافة مساحة Add Space،<br />ثم
الدخول على مساحة Join a space،<br />وضيفوا
ريلاي relay.nostrarabia.com<br /><br />نراكم.
🫡<br /><br /><a href="/tag/nostrarabia/"
>#nostrarabia</a
>
</p>
</np-content>
<style>
np-map {
margin: 0.5rem 0;
}
np-content p {
margin-bottom: 2rem;
}
np-content h1 {
margin-top: 4rem;
margin-bottom: 2rem;
}
np-content h2 {
margin-top: 4rem;
margin-bottom: 2rem;
}
np-content h3 {
margin-top: 4rem;
margin-bottom: 2rem;
}
np-content h4 {
margin-top: 4rem;
margin-bottom: 2rem;
}
np-content h5 {
margin-top: 4rem;
margin-bottom: 2rem;
}
np-content h6 {
margin-top: 4rem;
margin-bottom: 2rem;
}
</style>
<np-content-cta
data-cta-list="zap,like,share"
data-cta-main="zap"
data-button-color="#139ad4"
data-text-button-color="#fff"
data-event-addr="note1dplcmt2885l9tsy6c4xenm3w7hrg92af42sz76p0ypd7ft0muvpqg80sqn"
data-event-id="note1dplcmt2885l9tsy6c4xenm3w7hrg92af42sz76p0ypd7ft0muvpqg80sqn"
data-author-npub="npub1syk07kh6tkwrksyzhqk8qdjul5kj08p842gjxyacljlavhzq4m4slmdu3p"
id="np-content-cta"
></np-content-cta>
<div
style="display: none"
id="zap-button"
data-anon=""
data-npub="npub1syk07kh6tkwrksyzhqk8qdjul5kj08p842gjxyacljlavhzq4m4slmdu3p"
data-note-id="note1dplcmt2885l9tsy6c4xenm3w7hrg92af42sz76p0ypd7ft0muvpqg80sqn"
data-relays="wss://purplepag.es/,wss://user.kindpag.es/,wss://relay.nos.social/,wss://relay.primal.net/,wss://relay.damus.io/,wss://relay.nostrarabia.com/"
data-button-color="#139ad4"
data-amount=""
></div>
<np-content-comments
data-id="note1dplcmt2885l9tsy6c4xenm3w7hrg92af42sz76p0ypd7ft0muvpqg80sqn"
data-relays="wss://purplepag.es/,wss://user.kindpag.es/,wss://relay.nos.social/,wss://relay.primal.net/,wss://relay.damus.io/,wss://relay.nostrarabia.com/"
data-client="nostrarabia.npub.pro"
></np-content-comments
><np-content-dm
data-peer-npub="npub1syk07kh6tkwrksyzhqk8qdjul5kj08p842gjxyacljlavhzq4m4slmdu3p"
data-relays="wss://purplepag.es/,wss://user.kindpag.es/,wss://relay.nos.social/,wss://relay.primal.net/,wss://relay.damus.io/,wss://relay.nostrarabia.com/"
></np-content-dm>
<header class="gh-article-header">
<h1 class="gh-article-title">
من الجميل في نوستر هي قدرة…
</h1>
</header>
<aside class="gh-article-meta">
<div class="gh-article-meta-inner">
<figure class="gh-author-image">
<img
src="https://mir-s3-cdn-cf.behance.net/projects/404/01ffa529646977.55fca90cee60d.jpg"
alt="نوستر بالعربي"
/>
</figure>
<div class="gh-article-meta-wrapper">
<h4 class="gh-author-name">
<a
href="/author/npub1syk07kh6tkwrksyzhqk8qdjul5kj08p842gjxyacljlavhzq4m4slmdu3p/"
>نوستر بالعربي</a
>
</h4>
<time
class="gh-article-date"
datetime="2024-12-01"
>Dec 01, 2024</time
>
</div>
<!-- <a
class="gh-article-tag"
href="/tag/nostrarabia/"
style="--tag-color:"
>nostrarabia</a
> -->
</div>
</aside>
</section>
<footer class="gh-article-footer gh-canvas">
<nav class="gh-navigation">
<div class="gh-navigation-previous">
<a
class="gh-navigation-link"
href="/post/1733010811046/"
>← Previous</a
>
</div>
<div class="gh-navigation-middle"></div>
<div class="gh-navigation-next">
<a
class="gh-navigation-link"
href="/post/1733278250434/"
>Next →</a
>
</div>
</nav>
</footer>
</article>
</div>
</main>
<footer class="gh-foot gh-outer">
<div class="gh-foot-inner gh-inner">
<nav class="gh-foot-menu"></nav>
<div class="gh-copyright">
نوستر © 2024. Powered by
<a
href="https://npub.pro/"
target="_blank"
rel="noopener"
>Npub.pro</a
>. Theme by
<a
href="https://ghost.org/"
target="_blank"
rel="noopener"
>Ghost</a
>
</div>
</div>
</footer>
</div>
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<div class="pswp__bg"></div>
<div class="pswp__scroll-wrap">
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<div class="pswp__counter"></div>
<button
class="pswp__button pswp__button--close"
title="Close (Esc)"
></button>
<button
class="pswp__button pswp__button--share"
title="Share"
></button>
<button
class="pswp__button pswp__button--fs"
title="Toggle fullscreen"
></button>
<button
class="pswp__button pswp__button--zoom"
title="Zoom in/out"
></button>
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div
class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"
>
<div class="pswp__share-tooltip"></div>
</div>
<button
class="pswp__button pswp__button--arrow--left"
title="Previous (arrow left)"
></button>
<button
class="pswp__button pswp__button--arrow--right"
title="Next (arrow right)"
></button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
<script src="https://blossom.npubpro.com/64f7c3c5de348a7d1a5c7d1519abfa33fec8c5442c583fda441d25cd7b5990cf.js"></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/venobox@2.1.8/dist/venobox.min.css"
type="text/css"
media="screen"
/>
<script>
;(() => {
const script = document.createElement('script')
script.async = true
script.type = 'text/javascript'
script.src =
'https://cdn.jsdelivr.net/npm/venobox@2.1.8/dist/venobox.min.js'
script.onload = () => {
new VenoBox({
selector: '.vbx-media',
spinColor: '#139ad4',
overlayColor: '#139ad4',
})
}
document.body.appendChild(script)
})()
</script>
<script
async=""
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/venobox@2.1.8/dist/venobox.min.js"
></script>
<script
type="text/javascript"
async=""
src="https://cdn.npubpro.com/zapthreads.iife.0.6.0.js"
></script>
<script
type="text/javascript"
async=""
src="https://cdn.npubpro.com/nostr-site-zapthreads.1.0.2.js"
></script>
<script
type="text/javascript"
async=""
src="https://cdn.npubpro.com/content-cta.iife.1.0.22.js"
></script>
<script
async=""
src="../packages/auth/dist/unpkg.js"
data-perms="sign_event:1,sign_event:7,sign_event:3,sign_event:9734,sign_event:10003,sign_event:9802,nip04_encrypt,nip04_decrypt"
data-start-screen="local-signup"
data-signup-relays="wss://relay.primal.net/,wss://relay.damus.io/,wss://relay.nostrarabia.com/"
></script>
<script>
;(async () => {
if (!window.nostrSite)
await new Promise((ok) =>
document.addEventListener('npLoad', ok),
)
const ep = window.nostrSite.plugins.register('nostr-login')
document.addEventListener('nlAuth', async (e) => {
console.log('nlAuth', e)
ep.dispatch('auth', {
type: e.detail.type,
pubkey: e.detail.pubkey,
})
if (
e.detail.type === 'login' ||
e.detail.type === 'signup'
) {
window.__nlAuthed = true
} else {
window.__nlAuthed = false
}
const npub = window.nostrSite.nostrTools.nip19.npubEncode(
await window.nostr.getPublicKey(),
)
const zapButton = document.querySelector('#zap-button')
if (zapButton) {
if (window.__nlAuthed)
zapButton.setAttribute('data-anon', '')
else zapButton.setAttribute('data-anon', 'true')
}
})
})()
</script>
<script src="https://cdn.npubpro.com/nostr-zap.0.22.2.js"></script>
<div></div>
<np-content-cta-selection></np-content-cta-selection>
<script>
;(async () => {
if (!window.nostrSite)
await new Promise((ok) =>
document.addEventListener('npLoad', ok),
)
const ep = window.nostrSite.plugins.register('nostr-zap')
console.log('nostr-zap ep', ep)
ep.subscribe('action-zap', (amount) => {
const button = document.querySelector('#zap-button')
button.setAttribute('data-amount', amount || '')
button.dispatchEvent(new Event('click'))
})
document.addEventListener('nostr-zap-published', (e) => {
console.log('nostr-zap on zap published', e)
ep.dispatch('event-published', e.detail)
})
})()
</script>
<script
async=""
src="https://unpkg.com/nostr-site-search@1.0.12/dist/index.js"
></script>
<script>
document.addEventListener('np-search-goto', (e) => {
console.log('np-search-goto', e)
window.location.href = e.detail
})
</script>
<script
async=""
src="https://cdn.npubpro.com/embeds.iife.1.0.4.js"
></script>
<script
type="text/javascript"
src="https://cdn.npubpro.com/maptalks.min.js"
></script>
<script>
const container = document.querySelector('np-map')
console.log('map', container)
if (container) {
const coords = container
.getAttribute('coords')
.split(',')
.map((c) => Number(c))
console.log('coords', coords)
const div = document.createElement('div')
div.style.width = '100%'
div.style.height = '300px'
container.append(div)
const map = new maptalks.Map(div, {
center: coords,
zoom: 15,
zoomControl: true, // add zoom control
scaleControl: true, // add scale control
baseLayer: new maptalks.TileLayer('base', {
// urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
urlTemplate:
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: ['a', 'b', 'c'], // "d"
attribution:
'&copy; <a href="http://osm.org">OpenStreetMap</a>',
}),
})
const point = new maptalks.Marker(coords, {
visible: true,
editable: false,
cursor: 'pointer',
draggable: false,
// symbol : {
// 'textFaceName' : 'sans-serif',
// 'textName' : 'MapTalks',
// 'textFill' : '#34495e',
// 'textHorizontalAlignment' : 'right',
// 'textSize' : 40
// }
})
point.on('click touchend', (e) => console.log(e))
new maptalks.VectorLayer('vector', point).addTo(map)
}
</script>
<script
type="text/javascript"
src="https://cdn.npubpro.com/index.js"
onload="window.nostrSite.startTab();"
></script>
<style>
#pwa-toast {
visibility: hidden;
position: fixed;
right: 0;
bottom: 0;
margin: 16px;
padding: 12px;
border: 1px solid #8885;
border-radius: 4px;
z-index: 1;
text-align: left;
box-shadow: 3px 4px 5px 0 #8885;
display: grid;
background-color: #fff;
}
#pwa-toast .message {
margin-bottom: 8px;
}
#pwa-toast .buttons {
display: flex;
}
#pwa-toast button {
border: 1px solid #8885;
outline: none;
margin-right: 5px;
border-radius: 2px;
padding: 3px 10px;
}
#pwa-toast.show {
visibility: visible;
}
button#pwa-refresh {
display: none;
}
#pwa-toast.show.refresh button#pwa-refresh {
display: block;
}
</style>
<iframe
width="0"
height="0"
border="0"
id="__nostr-login-worker-iframe-3-use-nsec-app"
style="display: none"
src="https://3.use.nsec.app/iframe"
></iframe
><deepl-input-controller></deepl-input-controller>
</body>
</html>

343
examples/test_options.html Normal file
View File

@@ -0,0 +1,343 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nostr Login Interactive Test</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.container { max-width: 800px; margin: 0 auto; }
.controls { background: #f5f5f5; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
.control-group { margin-bottom: 15px; }
.control-group label { display: inline-block; width: 150px; font-weight: bold; }
.control-group input, .control-group select { margin-left: 10px; padding: 5px; }
.checkbox-group { display: flex; gap: 10px; flex-wrap: wrap; }
.checkbox-group label { width: auto; margin-right: 15px; }
.current-config { background: #e8f4fd; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
.login-area { background: #fff; border: 2px solid #ddd; padding: 20px; border-radius: 8px; }
button { padding: 10px 15px; margin: 5px; cursor: pointer; }
.apply-btn { background: #007cba; color: white; border: none; border-radius: 5px; }
.reset-btn { background: #999; color: white; border: none; border-radius: 5px; }
.note { background: #fff3cd; padding: 10px; border-radius: 5px; margin-top: 10px; font-size: 14px; }
</style>
</head>
<body>
<div class="container">
<h1>Nostr Login Interactive Test</h1>
<!-- Controls Section -->
<div class="controls">
<h3>Configuration Options</h3>
<div class="control-group">
<label>Theme:</label>
<select id="themeSelect">
<option value="default">Default</option>
<option value="ocean">Ocean</option>
<option value="lemonade">Lemonade</option>
<option value="purple">Purple</option>
<option value="laan">Laan</option>
</select>
</div>
<div class="control-group">
<label>Dark Mode:</label>
<input type="checkbox" id="darkModeCheck">
</div>
<div class="control-group">
<label>Start Screen:</label>
<select id="startScreenSelect">
<option value="">Default</option>
<option value="welcome">Welcome</option>
<option value="welcome-login">Welcome Login</option>
<option value="welcome-signup">Welcome Signup</option>
<option value="signup">Signup</option>
<option value="local-signup">Local Signup</option>
<option value="login">Login</option>
<option value="connect">Connect</option>
<option value="login-bunker-url">Login Bunker URL</option>
<option value="login-read-only">Login Read Only</option>
<option value="switch-account">Switch Account</option>
</select>
</div>
<div class="control-group">
<label>Auth Methods:</label>
<div class="checkbox-group">
<label><input type="checkbox" value="connect" checked> Connect (NIP-46)</label>
<label><input type="checkbox" value="extension" checked> Extension</label>
<label><input type="checkbox" value="readOnly" checked> Read Only</label>
<label><input type="checkbox" value="local" checked> Local</label>
</div>
</div>
<div class="control-group">
<label>No Banner:</label>
<input type="checkbox" id="noBannerCheck">
</div>
<div class="control-group">
<label>Bunkers:</label>
<input type="text" id="bunkersInput" placeholder="e.g., nsec.app,highlighter.com" style="width: 300px;">
</div>
<div class="control-group">
<label>Permissions:</label>
<input type="text" id="permsInput" placeholder="e.g., sign_event:1,nip04_encrypt" style="width: 300px;">
</div>
<div class="control-group">
<label>Title:</label>
<input type="text" id="titleInput" placeholder="Custom welcome title" style="width: 300px;">
</div>
<div class="control-group">
<label>Description:</label>
<input type="text" id="descriptionInput" placeholder="Custom welcome description" style="width: 300px;">
</div>
<button class="apply-btn" onclick="applyConfig()">Apply Configuration</button>
<button class="reset-btn" onclick="resetConfig()">Reset to Defaults</button>
<div class="note">
<strong>Note:</strong> Configuration changes will be applied by reloading the page with new settings.
</div>
</div>
<!-- Current Configuration Display -->
<div class="current-config">
<h4>Current Configuration:</h4>
<pre id="configDisplay"></pre>
</div>
<!-- Login/User Section -->
<div class="login-area">
<!-- Login Section -->
<div id="loginSection">
<h3>Test Login</h3>
<button id="loginBtn">Login with Nostr</button>
<button onclick="launchSpecificScreen()">Launch with Start Screen</button>
</div>
<!-- User Info Section (hidden initially) -->
<div id="userSection" style="display: none;">
<h3>Welcome!</h3>
<p><strong>Your Public Key (hex):</strong></p>
<div id="pubkeyHex" style="word-break: break-all; background: #f0f0f0; padding: 10px; border-radius: 4px;"></div>
<br>
<button id="logoutBtn">Logout</button>
</div>
</div>
</div>
<!-- Dynamic script loading with configuration -->
<script>
let currentConfig = {};
let scriptLoaded = false;
// Load nostr-login with current configuration
function loadNostrLogin() {
if (scriptLoaded) return;
const script = document.createElement('script');
script.src = '../packages/auth/dist/unpkg.js';
// Apply configuration as data attributes
const config = getStoredConfig();
if (config.theme) script.setAttribute('data-theme', config.theme);
if (config.darkMode !== undefined) script.setAttribute('data-dark-mode', config.darkMode);
if (config.startScreen) script.setAttribute('data-start-screen', config.startScreen);
if (config.noBanner !== undefined) script.setAttribute('data-no-banner', config.noBanner);
if (config.bunkers) script.setAttribute('data-bunkers', config.bunkers);
if (config.perms) script.setAttribute('data-perms', config.perms);
if (config.title) script.setAttribute('data-title', config.title);
if (config.description) script.setAttribute('data-description', config.description);
if (config.methods && config.methods.length > 0) {
script.setAttribute('data-methods', config.methods.join(','));
}
document.head.appendChild(script);
scriptLoaded = true;
// Wait for script to load, then set up event listeners
script.onload = () => {
setupEventListeners();
};
}
// Get stored configuration from localStorage
function getStoredConfig() {
try {
return JSON.parse(localStorage.getItem('nostrLoginConfig') || '{}');
} catch {
return {};
}
}
// Store configuration in localStorage
function storeConfig(config) {
localStorage.setItem('nostrLoginConfig', JSON.stringify(config));
}
// Listen for nostr-login auth events
function setupEventListeners() {
document.addEventListener('nlAuth', async (e) => {
console.log('nlAuth event:', e.detail);
if (e.detail.type === 'login' || e.detail.type === 'signup') {
await showUserInfo();
} else if (e.detail.type === 'logout') {
showLoginSection();
}
});
}
// Get and display user info
async function showUserInfo() {
try {
const pubkey = await window.nostr.getPublicKey();
console.log('Got pubkey:', pubkey);
// Display pubkey
document.getElementById('pubkeyHex').textContent = pubkey;
// Hide login section, show user section
document.getElementById('loginSection').style.display = 'none';
document.getElementById('userSection').style.display = 'block';
} catch (error) {
console.error('Failed to get pubkey:', error);
}
}
// Show login section
function showLoginSection() {
document.getElementById('loginSection').style.display = 'block';
document.getElementById('userSection').style.display = 'none';
document.getElementById('pubkeyHex').textContent = '';
}
// Apply configuration
function applyConfig() {
// Collect all settings
const config = {
theme: document.getElementById('themeSelect').value,
darkMode: document.getElementById('darkModeCheck').checked,
startScreen: document.getElementById('startScreenSelect').value,
noBanner: document.getElementById('noBannerCheck').checked,
bunkers: document.getElementById('bunkersInput').value,
perms: document.getElementById('permsInput').value,
title: document.getElementById('titleInput').value,
description: document.getElementById('descriptionInput').value,
methods: Array.from(document.querySelectorAll('input[type="checkbox"][value]'))
.filter(cb => cb.checked)
.map(cb => cb.value)
};
// Remove empty values
Object.keys(config).forEach(key => {
if (config[key] === '' || (Array.isArray(config[key]) && config[key].length === 0)) {
delete config[key];
}
});
currentConfig = config;
storeConfig(config);
updateConfigDisplay();
console.log('Applied config:', config);
// Reload page to apply new configuration
window.location.reload();
}
// Reset configuration
function resetConfig() {
document.getElementById('themeSelect').value = 'default';
document.getElementById('darkModeCheck').checked = false;
document.getElementById('startScreenSelect').value = '';
document.getElementById('noBannerCheck').checked = false;
document.getElementById('bunkersInput').value = '';
document.getElementById('permsInput').value = '';
document.getElementById('titleInput').value = '';
document.getElementById('descriptionInput').value = '';
// Reset auth methods to all checked
document.querySelectorAll('input[type="checkbox"][value]').forEach(cb => cb.checked = true);
currentConfig = {};
localStorage.removeItem('nostrLoginConfig');
updateConfigDisplay();
}
// Update config display
function updateConfigDisplay() {
document.getElementById('configDisplay').textContent = JSON.stringify(currentConfig, null, 2);
}
// Launch with specific screen
function launchSpecificScreen() {
const startScreen = document.getElementById('startScreenSelect').value || 'welcome';
document.dispatchEvent(new CustomEvent('nlLaunch', { detail: startScreen }));
}
// Load configuration from storage and update UI
function loadConfigIntoUI() {
const config = getStoredConfig();
currentConfig = config;
// Set default to laan theme for testing
if (config.theme) document.getElementById('themeSelect').value = config.theme;
else document.getElementById('themeSelect').value = 'laan';
if (config.darkMode !== undefined) document.getElementById('darkModeCheck').checked = config.darkMode;
if (config.startScreen) document.getElementById('startScreenSelect').value = config.startScreen;
if (config.noBanner !== undefined) document.getElementById('noBannerCheck').checked = config.noBanner;
if (config.bunkers) document.getElementById('bunkersInput').value = config.bunkers;
if (config.perms) document.getElementById('permsInput').value = config.perms;
if (config.title) document.getElementById('titleInput').value = config.title;
if (config.description) document.getElementById('descriptionInput').value = config.description;
// Load auth methods
document.querySelectorAll('input[type="checkbox"][value]').forEach(cb => {
cb.checked = !config.methods || config.methods.includes(cb.value);
});
updateConfigDisplay();
}
// Handle login button click
document.addEventListener('DOMContentLoaded', () => {
// Load configuration into UI
loadConfigIntoUI();
// Load nostr-login with current config
loadNostrLogin();
document.getElementById('loginBtn').addEventListener('click', () => {
// Trigger nostr-login modal
document.dispatchEvent(new CustomEvent('nlLaunch', { detail: 'welcome' }));
});
// Handle logout button click
document.getElementById('logoutBtn').addEventListener('click', () => {
// Trigger logout
document.dispatchEvent(new Event('nlLogout'));
});
// Update config display when inputs change
document.querySelectorAll('input, select').forEach(input => {
input.addEventListener('change', () => {
// Auto-apply dark mode for immediate feedback
if (input.id === 'darkModeCheck') {
document.dispatchEvent(new CustomEvent('nlDarkMode', { detail: input.checked }));
}
});
});
});
</script>
</body>
</html>

135
examples/usage.html Normal file
View File

@@ -0,0 +1,135 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Input and Output Fields</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.container {
max-width: 400px;
margin: auto;
}
input, button, textarea {
width: 100%;
padding: 10px;
margin: 10px 0;
box-sizing: border-box;
}
.button-container {
display: flex;
flex-wrap: wrap;
gap: 10px; /* Adds space between the buttons */
}
.button-container button {
flex: 1 1 calc(50% - 10px); /* Makes each button take up half the width minus the gap */
box-sizing: border-box;
}
</style>
<script src='https://www.unpkg.com/nostr-login@latest/dist/unpkg.js'></script>
</head>
<body>
<div class="container">
<h1>Try Nostr-Login</h1>
<textarea id="inputField" rows="4" placeholder="Paste your json formatted event here"></textarea>
<label>Output:</label>
<textarea id="outputField" rows="4" placeholder="Output will be shown here" readonly></textarea>
<button onclick="fillExampleData()">Fill with example event</button>
<button onclick="SignEventFn()">Sign Event</button>
<div class="button-container">
<button onclick="cryptWithNIP04('encrypt')">Encrypt with NIP-04</button>
<button onclick="cryptWithNIP04('decrypt')">Decrypt with NIP-04</button>
<button onclick="cryptWithNIP44('encrypt')">Encrypt with NIP-44</button>
<button onclick="cryptWithNIP44('decrypt')">Decrypt with NIP-44</button>
</div>
<button onclick="switchOutputInput()">Switch Output Input</button>
</div>
<form id="testpw" action="/usage.html" method="POST">
<input type="text" name="name" value="npub">
<input type="password" name="password" value="a;h123UIFBEKSDBF,SA">
<button type="submit">Submit</button>
</form>
<script>
const form = document.querySelector("#testpw");
form.onsubmit = (e) => {
e.preventDefault();
}
</script>
<script>
// Example Nostr event as json string
var ExampleData = `{ "content": "hello world", "created_at": 1731313613, "id": "", "kind": 1, "pubkey": "568ad8bf00ed530eb44614e4b363271f36f6b645700630470c51f98e7e58fbf0", "tags": [] }`
// Function to get public key
async function getPublicKey() {
return await window.nostr.getPublicKey();
}
// Function to encrypt with NIP-04
async function cryptWithNIP04(encryptType) {
try {
var publicKey = await getPublicKey();
var data = document.getElementById('inputField').value;
var result;
if (encryptType === "encrypt") {
result = await window.nostr.nip04.encrypt(publicKey, data);
} else if (encryptType === "decrypt") {
result = await window.nostr.nip04.decrypt(publicKey, data);
}
document.getElementById('outputField').value = result;
} catch (error) {
console.error("Error in cryptWithNIP04:", error);
}
}
// Function to encrypt with NIP-44
async function cryptWithNIP44(encryptType) {
try {
var publicKey = await getPublicKey();
var data = document.getElementById('inputField').value;
var result;
if (encryptType === "encrypt") {
result = await window.nostr.nip44.encrypt(publicKey, data);
} else if (encryptType === "decrypt") {
result = await window.nostr.nip44.decrypt(publicKey, data);
}
document.getElementById('outputField').value = result;
} catch (error) {
console.error("Error in cryptWithNIP44:", error);
}
}
// Sign nostr event
async function SignEventFn() {
try {
var input = document.getElementById('inputField').value;
// Convert the text from input to json object
var json_data = JSON.parse(input);
// Sign the event object using the plugin signEvent method
var signedEvent = await window.nostr.signEvent(json_data);
document.getElementById('outputField').value = JSON.stringify(signedEvent, null, 2);
} catch (error) {
console.error("Error in SignEventFn:", error);
}
}
// Fill example data for easy testing
function fillExampleData() {
document.getElementById('outputField').value = '';
document.getElementById('inputField').value = ExampleData;
}
// Switch input and output fields
function switchOutputInput() {
var tempOutput = document.getElementById('outputField').value;
document.getElementById('inputField').value = tempOutput;
document.getElementById('outputField').value = '';
}
</script>
</body>
</html>