nostr-components 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2008,7 +2008,7 @@ Minimum version required to store current data is: `+o+`.
2008
2008
  max-width: 250px;
2009
2009
  white-space: pre-line;
2010
2010
  }
2011
- `)}class NostrZap extends NostrUserComponent{constructor(){super();g(this,"zapActionStatus",this.channel("zapAction"));g(this,"zapListStatus",this.channel("zapList"));g(this,"totalZapAmount",null);g(this,"cachedZapDetails",[]);g(this,"cachedAmountDialog",null);this.zapListStatus.set(NCStatus.Loading)}connectedCallback(){var t;(t=super.connectedCallback)==null||t.call(this),this.attachDelegatedListeners(),this.render()}static get observedAttributes(){return[...super.observedAttributes,"text","amount","default-amount","url"]}attributeChangedCallback(t,r,s){r!==s&&(super.attributeChangedCallback(t,r,s),this.render())}disconnectedCallback(){this.cachedAmountDialog&&typeof this.cachedAmountDialog.close=="function"&&this.cachedAmountDialog.close()}onStatusChange(t){this.render()}onUserReady(t,r){this.render(),this.updateZapCount()}validateInputs(){if(!super.validateInputs())return this.zapActionStatus.set(NCStatus.Idle),this.zapListStatus.set(NCStatus.Idle),!1;const t=this.getAttribute("text"),r=this.getAttribute("amount"),s=this.getAttribute("default-amount"),o=this.getAttribute("url"),a=this.tagName.toLowerCase();let u=null;if(t&&t.length>128)u="Max text length: 128 characters";else if(r){const c=Number(r);isNaN(c)||c<=0?u="Invalid amount":c>21e4&&(u="Amount too high (max 210,000 sats)")}else if(s){const c=Number(s);isNaN(c)||c<=0?u="Invalid default-amount":c>21e4&&(u="Default-amount too high (max 210,000 sats)")}else o&&(isValidUrl(o)||(u="Invalid URL format"));return u?(this.zapActionStatus.set(NCStatus.Error,u),this.zapListStatus.set(NCStatus.Error,u),this.userStatus.set(NCStatus.Idle),console.error(`Nostr-Components: ${a}: ${u}`),!1):!0}async handleZapClick(){if(this.userStatus.get()===NCStatus.Ready){this.zapActionStatus.set(NCStatus.Loading),this.render();try{if(!this.user){this.zapActionStatus.set(NCStatus.Error,"Could not resolve user to zap."),this.render();return}const t=this.getRelays().join(","),r=this.user.npub;this.cachedAmountDialog=await init$1({npub:r,relays:t,cachedDialogComponent:this.cachedAmountDialog,theme:this.theme==="dark"?"dark":"light",fixedAmount:(()=>{const s=this.getAttribute("amount");if(!s)return;const o=Number(s);if(isNaN(o)||o<=0||o>21e4){console.error("Nostr-Components: Zap button: Max zap amount: 210,000 sats");return}return o})(),defaultAmount:(()=>{const s=this.getAttribute("default-amount");if(!s)return 21;const o=Number(s);return isNaN(o)||o<=0||o>21e4?(console.error("Nostr-Components: Zap button: Max zap amount: 210,000 sats"),21):o})(),url:this.getAttribute("url")||void 0,anon:!1}),this.zapActionStatus.set(NCStatus.Ready)}catch(t){this.zapActionStatus.set(NCStatus.Error,(t==null?void 0:t.message)||"Unable to zap")}finally{this.render()}}}async handleHelpClick(){try{await showHelpDialog$1(this.theme==="dark"?"dark":"light")}catch(t){console.error("Error showing help dialog:",t)}}async handleZappersClick(){if(this.cachedZapDetails.length!==0)try{await openZappersDialog({zapDetails:this.cachedZapDetails,theme:this.theme==="dark"?"dark":"light"})}catch(t){console.error("Nostr-Components: Zap button: Error opening zappers dialog",t)}}attachDelegatedListeners(){this.delegateEvent("click",".nostr-zap-button",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleZapClick()}),this.delegateEvent("click",".help-icon",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleHelpClick()}),this.delegateEvent("click",".total-zap-amount",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleZappersClick()})}async updateZapCount(){if(this.user)try{this.zapListStatus.set(NCStatus.Loading),this.render(),await this.ensureNostrConnected();const t=await fetchTotalZapAmount({pubkey:this.user.pubkey,relays:this.getRelays(),url:this.getAttribute("url")||void 0});this.totalZapAmount=t.totalAmount,this.cachedZapDetails=t.zapDetails,this.zapListStatus.set(NCStatus.Ready)}catch(t){console.error("Nostr-Components: Zap button: Failed to fetch zap count",t),this.totalZapAmount=null,this.zapListStatus.set(NCStatus.Error)}finally{this.render()}}renderContent(){const t=this.userStatus.get()==NCStatus.Loading,r=this.zapListStatus.get()==NCStatus.Loading,s=this.computeOverall()===NCStatus.Error,o=this.errorMessage,a=this.getAttribute("text")||"Zap",u={isLoading:t,isAmountLoading:r,isError:s,isSuccess:!1,errorMessage:o,buttonText:a,totalZapAmount:this.totalZapAmount,hasZaps:this.cachedZapDetails.length>0};this.shadowRoot.innerHTML=`
2011
+ `)}class NostrZap extends NostrUserComponent{constructor(){super();g(this,"zapActionStatus",this.channel("zapAction"));g(this,"zapListStatus",this.channel("zapList"));g(this,"totalZapAmount",null);g(this,"cachedZapDetails",[]);g(this,"cachedAmountDialog",null)}connectedCallback(){var t;(t=super.connectedCallback)==null||t.call(this),this.zapListStatus.get()==NCStatus.Idle&&this.zapListStatus.set(NCStatus.Loading),this.attachDelegatedListeners(),this.render()}static get observedAttributes(){return[...super.observedAttributes,"text","amount","default-amount","url"]}attributeChangedCallback(t,r,s){r!==s&&(super.attributeChangedCallback(t,r,s),this.render())}disconnectedCallback(){this.cachedAmountDialog&&typeof this.cachedAmountDialog.close=="function"&&this.cachedAmountDialog.close()}onStatusChange(t){this.render()}onUserReady(t,r){this.render(),this.updateZapCount()}validateInputs(){if(!super.validateInputs())return this.zapActionStatus.set(NCStatus.Idle),this.zapListStatus.set(NCStatus.Idle),!1;const t=this.getAttribute("text"),r=this.getAttribute("amount"),s=this.getAttribute("default-amount"),o=this.getAttribute("url"),a=this.tagName.toLowerCase();let u=null;if(t&&t.length>128)u="Max text length: 128 characters";else if(r){const c=Number(r);isNaN(c)||c<=0?u="Invalid amount":c>21e4&&(u="Amount too high (max 210,000 sats)")}else if(s){const c=Number(s);isNaN(c)||c<=0?u="Invalid default-amount":c>21e4&&(u="Default-amount too high (max 210,000 sats)")}else o&&(isValidUrl(o)||(u="Invalid URL format"));return u?(this.zapActionStatus.set(NCStatus.Error,u),this.zapListStatus.set(NCStatus.Error,u),this.userStatus.set(NCStatus.Idle),console.error(`Nostr-Components: ${a}: ${u}`),!1):!0}async handleZapClick(){if(this.userStatus.get()===NCStatus.Ready){this.zapActionStatus.set(NCStatus.Loading),this.render();try{if(!this.user){this.zapActionStatus.set(NCStatus.Error,"Could not resolve user to zap."),this.render();return}const t=this.getRelays().join(","),r=this.user.npub;this.cachedAmountDialog=await init$1({npub:r,relays:t,cachedDialogComponent:this.cachedAmountDialog,theme:this.theme==="dark"?"dark":"light",fixedAmount:(()=>{const s=this.getAttribute("amount");if(!s)return;const o=Number(s);if(isNaN(o)||o<=0||o>21e4){console.error("Nostr-Components: Zap button: Max zap amount: 210,000 sats");return}return o})(),defaultAmount:(()=>{const s=this.getAttribute("default-amount");if(!s)return 21;const o=Number(s);return isNaN(o)||o<=0||o>21e4?(console.error("Nostr-Components: Zap button: Max zap amount: 210,000 sats"),21):o})(),url:this.getAttribute("url")||void 0,anon:!1}),this.zapActionStatus.set(NCStatus.Ready)}catch(t){this.zapActionStatus.set(NCStatus.Error,(t==null?void 0:t.message)||"Unable to zap")}finally{this.render()}}}async handleHelpClick(){try{await showHelpDialog$1(this.theme==="dark"?"dark":"light")}catch(t){console.error("Error showing help dialog:",t)}}async handleZappersClick(){if(this.cachedZapDetails.length!==0)try{await openZappersDialog({zapDetails:this.cachedZapDetails,theme:this.theme==="dark"?"dark":"light"})}catch(t){console.error("Nostr-Components: Zap button: Error opening zappers dialog",t)}}attachDelegatedListeners(){this.delegateEvent("click",".nostr-zap-button",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleZapClick()}),this.delegateEvent("click",".help-icon",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleHelpClick()}),this.delegateEvent("click",".total-zap-amount",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleZappersClick()})}async updateZapCount(){if(this.user)try{this.zapListStatus.set(NCStatus.Loading),this.render(),await this.ensureNostrConnected();const t=await fetchTotalZapAmount({pubkey:this.user.pubkey,relays:this.getRelays(),url:this.getAttribute("url")||void 0});this.totalZapAmount=t.totalAmount,this.cachedZapDetails=t.zapDetails,this.zapListStatus.set(NCStatus.Ready)}catch(t){console.error("Nostr-Components: Zap button: Failed to fetch zap count",t),this.totalZapAmount=null,this.zapListStatus.set(NCStatus.Error)}finally{this.render()}}renderContent(){const t=this.userStatus.get()==NCStatus.Loading,r=this.zapListStatus.get()==NCStatus.Loading,s=this.computeOverall()===NCStatus.Error,o=this.errorMessage,a=this.getAttribute("text")||"Zap",u={isLoading:t,isAmountLoading:r,isError:s,isSuccess:!1,errorMessage:o,buttonText:a,totalZapAmount:this.totalZapAmount,hasZaps:this.cachedZapDetails.length>0};this.shadowRoot.innerHTML=`
2012
2012
  ${getZapButtonStyles()}
2013
2013
  ${renderZapButton(u)}
2014
2014
  `}}customElements.define("nostr-zap",NostrZap);function escapeHtml(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}function formatTimeAgo(n){const t=Date.now()/1e3-n;return t<60?"just now":t<3600?`${Math.floor(t/60)}m ago`:t<86400?`${Math.floor(t/3600)}h ago`:t<2592e3?`${Math.floor(t/86400)}d ago`:new Date(n*1e3).toLocaleDateString()}function getUserDisplayName(n){var e,t;return(e=n.userProfile)!=null&&e.displayName?n.userProfile.displayName:(t=n.userProfile)!=null&&t.name?n.userProfile.name:`${n.pubkey.slice(0,8)}...${n.pubkey.slice(-4)}`}function getUserAvatar(n){var e,t;if((e=n.userProfile)!=null&&e.image&&n.userProfile.image.trim()!==""){let r=n.userProfile.image.trim();return console.log("Processing image URL:",r,"for user:",n.userProfile.name||n.pubkey),(r.startsWith("Qm")||r.startsWith("bafy"))&&(r=`https://ipfs.io/ipfs/${r}`,console.log("Converted IPFS to gateway URL:",r)),r.startsWith("//")&&(r="https:"+r,console.log("Added protocol to URL:",r)),console.log("Final image URL:",r),r}return console.log("No image found for user:",((t=n.userProfile)==null?void 0:t.name)||n.pubkey,"using default"),"../../assets/default_dp.png"}function renderComment(n,e=!1,t=null,r=null,s="anon",o=!1){const a=getUserDisplayName(n),u=getUserAvatar(n),c=formatTimeAgo(n.created_at),l=n.depth||0,h=6,f=t===n.id;return`
@@ -3958,7 +3958,7 @@ Minimum version required to store current data is: `+o+`.
3958
3958
  <li>Works with a browser extension like <a href="https://getalby.com" target="_blank" rel="noopener noreferrer">Alby</a> or nos2x</li>
3959
3959
  </ul>
3960
3960
  </div>
3961
- `,e.showModal()};new TextDecoder("utf-8"),new TextEncoder;function normalizeURL(n){n.indexOf("://")===-1&&(n="wss://"+n);let e=new URL(n);return e.pathname=e.pathname.replace(/\/+/g,"/"),e.pathname.endsWith("/")&&(e.pathname=e.pathname.slice(0,-1)),(e.port==="80"&&e.protocol==="ws:"||e.port==="443"&&e.protocol==="wss:")&&(e.port=""),e.searchParams.sort(),e.hash="",e.toString()}async function fetchLikesForUrl(n,e){const t=normalizeURL(n),r=new SimplePool;try{const s=await r.querySync(e,{kinds:[17],"#k":["web"],"#i":[t],limit:1e3}),o=[];let a=0,u=0;for(const l of s)o.push({authorPubkey:l.pubkey,date:new Date(l.created_at*1e3),content:l.content}),l.content==="-"?u++:a++;return o.sort((l,h)=>h.date.getTime()-l.date.getTime()),{totalCount:a-u,likeDetails:o,likedCount:a,dislikedCount:u}}catch(s){throw s instanceof Error?s:new Error(String(s))}finally{r.close(e)}}function createReactionEvent(n,e){return{kind:17,content:e,tags:[["k","web"],["i",n]],created_at:Math.floor(Date.now()/1e3)}}function createLikeEvent(n){return createReactionEvent(n,"+")}function createUnlikeEvent(n){return createReactionEvent(n,"-")}async function hasUserLiked(n,e,t){const r=new SimplePool,s=n;try{const o=await r.querySync(t,{kinds:[17],authors:[e],"#k":["web"],"#i":[s],limit:1});if(o.length===0)return!1;const a=o[0];return a.content==="+"||a.content===""}catch(o){return console.error("Nostr-Components: Like button: Error checking user like status",o),!1}finally{r.close(t)}}async function getUserPubkey(){try{if(typeof window<"u"&&window.nostr)return await window.nostr.getPublicKey()}catch(n){console.error("Nostr-Components: Like button: Error getting user pubkey",n)}return null}async function signEvent(n){try{if(typeof window<"u"&&window.nostr)return await window.nostr.signEvent(n);throw new Error("NIP-07 extension not available")}catch(e){throw console.error("Nostr-Components: Like button: Error signing event",e),e}}function isNip07Available(){return typeof window<"u"&&!!window.nostr}class NostrLike extends NostrBaseComponent{constructor(){super();g(this,"likeActionStatus",this.channel("likeAction"));g(this,"likeListStatus",this.channel("likeList"));g(this,"currentUrl","");g(this,"isLiked",!1);g(this,"likeCount",0);g(this,"cachedLikeDetails",null);g(this,"loadSeq",0);this.likeListStatus.set(NCStatus.Loading)}connectedCallback(){var t;(t=super.connectedCallback)==null||t.call(this),this.attachDelegatedListeners(),this.render()}static get observedAttributes(){return[...super.observedAttributes,"url","text"]}attributeChangedCallback(t,r,s){r!==s&&(super.attributeChangedCallback(t,r,s),(t==="url"||t==="text")&&(this.likeActionStatus.set(NCStatus.Ready),this.likeListStatus.set(NCStatus.Loading),this.isLiked=!1,this.errorMessage="",this.updateLikeCount(),this.render()))}validateInputs(){if(!super.validateInputs())return this.likeActionStatus.set(NCStatus.Idle),this.likeListStatus.set(NCStatus.Idle),!1;const t=this.getAttribute("url"),r=this.getAttribute("text"),s=this.tagName.toLowerCase();let o=null;return t&&(isValidUrl(t)||(o="Invalid URL format")),r&&r.length>32&&(o="Max text length: 32 characters"),o?(this.likeActionStatus.set(NCStatus.Error,o),this.likeListStatus.set(NCStatus.Error,o),console.error(`Nostr-Components: ${s}: ${o}`),!1):!0}onStatusChange(t){this.render()}onNostrRelaysConnected(){this.updateLikeCount(),this.render()}ensureCurrentUrl(){this.currentUrl||(this.currentUrl=normalizeURL(this.getAttribute("url")||window.location.href))}async updateLikeCount(){const t=++this.loadSeq;try{await this.ensureNostrConnected(),this.currentUrl=normalizeURL(this.getAttribute("url")||window.location.href),this.likeListStatus.set(NCStatus.Loading),this.render();const r=await fetchLikesForUrl(this.currentUrl,this.getRelays());if(t!==this.loadSeq)return;this.likeCount=r.totalCount,this.cachedLikeDetails=r,this.likeListStatus.set(NCStatus.Ready)}catch(r){console.error("[NostrLike] Failed to fetch like count:",r),this.likeListStatus.set(NCStatus.Error,"Failed to load likes")}finally{this.render()}}async handleLikeClick(){if(this.ensureCurrentUrl(),!this.currentUrl){this.likeActionStatus.set(NCStatus.Error,"Invalid URL"),this.render();return}if(this.likeActionStatus.set(NCStatus.Loading),!isNip07Available()){this.likeActionStatus.set(NCStatus.Error,"Please install a Nostr browser extension (Alby, nos2x, etc.)"),this.render();return}try{const t=await getUserPubkey();t&&(this.isLiked=await hasUserLiked(this.currentUrl,t,this.getRelays()))}catch(t){console.error("[NostrLike] Failed to check user like status:",t),this.likeActionStatus.set(NCStatus.Error,"Failed to check user like status")}finally{this.render()}if(this.isLiked){if(!window.confirm("You have already liked this. Do you want to unlike it?")){this.likeActionStatus.set(NCStatus.Ready),this.render();return}await this.handleUnlike()}else await this.handleLike()}async handleLike(){if(this.ensureCurrentUrl(),!this.currentUrl){this.likeActionStatus.set(NCStatus.Error,"Invalid URL"),this.render();return}this.likeActionStatus.set(NCStatus.Loading),this.render();try{const t=createLikeEvent(this.currentUrl),r=await signEvent(t);await new NDKEvent(this.nostrService.getNDK(),r).publish(),this.isLiked=!0,this.likeCount++,this.likeActionStatus.set(NCStatus.Ready),await this.updateLikeCount()}catch(t){console.error("[NostrLike] Failed to like:",t),this.isLiked=!1,this.likeCount--;const r=t instanceof Error?t.message:"Failed to like";this.likeActionStatus.set(NCStatus.Error,r)}finally{this.render()}}async handleUnlike(){if(this.ensureCurrentUrl(),!this.currentUrl){this.likeActionStatus.set(NCStatus.Error,"Invalid URL"),this.render();return}this.likeActionStatus.set(NCStatus.Loading),this.render();try{const t=createUnlikeEvent(this.currentUrl),r=await signEvent(t);await new NDKEvent(this.nostrService.getNDK(),r).publish(),this.isLiked=!1,this.likeCount>0&&this.likeCount--,this.likeActionStatus.set(NCStatus.Ready),await this.updateLikeCount()}catch(t){console.error("[NostrLike] Failed to unlike:",t),this.isLiked=!0,this.likeCount++;const r=t instanceof Error?t.message:"Failed to unlike";this.likeActionStatus.set(NCStatus.Error,r)}finally{this.render()}}async handleCountClick(){if(!(this.likeCount===0||!this.cachedLikeDetails))try{const{openLikersDialog:t}=await Promise.resolve().then(()=>dialogLikers);await t({likeDetails:this.cachedLikeDetails.likeDetails,theme:this.theme==="dark"?"dark":"light"})}catch(t){console.error("[NostrLike] Error opening likers dialog:",t)}}async handleHelpClick(){try{await showHelpDialog(this.theme==="dark"?"dark":"light")}catch(t){console.error("[NostrLike] Error showing help dialog:",t)}}attachDelegatedListeners(){this.delegateEvent("click",".nostr-like-button",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleLikeClick()}),this.delegateEvent("click",".like-count",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleCountClick()}),this.delegateEvent("click",".help-icon",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleHelpClick()})}renderContent(){const t=this.likeActionStatus.get()===NCStatus.Loading||this.conn.get()===NCStatus.Loading,r=this.likeListStatus.get()===NCStatus.Loading,s=this.computeOverall()===NCStatus.Error,o=this.errorMessage,a=this.getAttribute("text")||"Like",u={isLoading:t,isError:s,errorMessage:o,buttonText:a,isLiked:this.isLiked,likeCount:this.likeCount,hasLikes:this.likeCount>0,isCountLoading:r,theme:this.theme};this.shadowRoot.innerHTML=`
3961
+ `,e.showModal()};new TextDecoder("utf-8"),new TextEncoder;function normalizeURL(n){n.indexOf("://")===-1&&(n="wss://"+n);let e=new URL(n);return e.pathname=e.pathname.replace(/\/+/g,"/"),e.pathname.endsWith("/")&&(e.pathname=e.pathname.slice(0,-1)),(e.port==="80"&&e.protocol==="ws:"||e.port==="443"&&e.protocol==="wss:")&&(e.port=""),e.searchParams.sort(),e.hash="",e.toString()}async function fetchLikesForUrl(n,e){const t=normalizeURL(n),r=new SimplePool;try{const s=await r.querySync(e,{kinds:[17],"#k":["web"],"#i":[t],limit:1e3}),o=[];let a=0,u=0;for(const l of s)o.push({authorPubkey:l.pubkey,date:new Date(l.created_at*1e3),content:l.content}),l.content==="-"?u++:a++;return o.sort((l,h)=>h.date.getTime()-l.date.getTime()),{totalCount:a-u,likeDetails:o,likedCount:a,dislikedCount:u}}catch(s){throw s instanceof Error?s:new Error(String(s))}finally{r.close(e)}}function createReactionEvent(n,e){return{kind:17,content:e,tags:[["k","web"],["i",n]],created_at:Math.floor(Date.now()/1e3)}}function createLikeEvent(n){return createReactionEvent(n,"+")}function createUnlikeEvent(n){return createReactionEvent(n,"-")}async function hasUserLiked(n,e,t){const r=new SimplePool,s=n;try{const o=await r.querySync(t,{kinds:[17],authors:[e],"#k":["web"],"#i":[s],limit:1});if(o.length===0)return!1;const a=o[0];return a.content==="+"||a.content===""}catch(o){return console.error("Nostr-Components: Like button: Error checking user like status",o),!1}finally{r.close(t)}}async function getUserPubkey(){try{if(typeof window<"u"&&window.nostr)return await window.nostr.getPublicKey()}catch(n){console.error("Nostr-Components: Like button: Error getting user pubkey",n)}return null}async function signEvent(n){try{if(typeof window<"u"&&window.nostr)return await window.nostr.signEvent(n);throw new Error("NIP-07 extension not available")}catch(e){throw console.error("Nostr-Components: Like button: Error signing event",e),e}}function isNip07Available(){return typeof window<"u"&&!!window.nostr}class NostrLike extends NostrBaseComponent{constructor(){super();g(this,"likeActionStatus",this.channel("likeAction"));g(this,"likeListStatus",this.channel("likeList"));g(this,"currentUrl","");g(this,"isLiked",!1);g(this,"likeCount",0);g(this,"cachedLikeDetails",null);g(this,"loadSeq",0)}connectedCallback(){var t;(t=super.connectedCallback)==null||t.call(this),this.likeListStatus.get()===NCStatus.Idle&&this.likeListStatus.set(NCStatus.Loading),this.attachDelegatedListeners(),this.render()}static get observedAttributes(){return[...super.observedAttributes,"url","text"]}attributeChangedCallback(t,r,s){r!==s&&(super.attributeChangedCallback(t,r,s),(t==="url"||t==="text")&&(this.likeActionStatus.set(NCStatus.Ready),this.likeListStatus.set(NCStatus.Loading),this.isLiked=!1,this.errorMessage="",this.updateLikeCount(),this.render()))}validateInputs(){if(!super.validateInputs())return this.likeActionStatus.set(NCStatus.Idle),this.likeListStatus.set(NCStatus.Idle),!1;const t=this.getAttribute("url"),r=this.getAttribute("text"),s=this.tagName.toLowerCase();let o=null;return t&&(isValidUrl(t)||(o="Invalid URL format")),r&&r.length>32&&(o="Max text length: 32 characters"),o?(this.likeActionStatus.set(NCStatus.Error,o),this.likeListStatus.set(NCStatus.Error,o),console.error(`Nostr-Components: ${s}: ${o}`),!1):!0}onStatusChange(t){this.render()}onNostrRelaysConnected(){this.updateLikeCount(),this.render()}ensureCurrentUrl(){this.currentUrl||(this.currentUrl=normalizeURL(this.getAttribute("url")||window.location.href))}async updateLikeCount(){const t=++this.loadSeq;try{await this.ensureNostrConnected(),this.currentUrl=normalizeURL(this.getAttribute("url")||window.location.href),this.likeListStatus.set(NCStatus.Loading),this.render();const r=await fetchLikesForUrl(this.currentUrl,this.getRelays());if(t!==this.loadSeq)return;this.likeCount=r.totalCount,this.cachedLikeDetails=r,this.likeListStatus.set(NCStatus.Ready)}catch(r){console.error("[NostrLike] Failed to fetch like count:",r),this.likeListStatus.set(NCStatus.Error,"Failed to load likes")}finally{this.render()}}async handleLikeClick(){if(this.ensureCurrentUrl(),!this.currentUrl){this.likeActionStatus.set(NCStatus.Error,"Invalid URL"),this.render();return}if(this.likeActionStatus.set(NCStatus.Loading),!isNip07Available()){this.likeActionStatus.set(NCStatus.Error,"Please install a Nostr browser extension (Alby, nos2x, etc.)"),this.render();return}try{const t=await getUserPubkey();t&&(this.isLiked=await hasUserLiked(this.currentUrl,t,this.getRelays()))}catch(t){console.error("[NostrLike] Failed to check user like status:",t),this.likeActionStatus.set(NCStatus.Error,"Failed to check user like status")}finally{this.render()}if(this.isLiked){if(!window.confirm("You have already liked this. Do you want to unlike it?")){this.likeActionStatus.set(NCStatus.Ready),this.render();return}await this.handleUnlike()}else await this.handleLike()}async handleLike(){if(this.ensureCurrentUrl(),!this.currentUrl){this.likeActionStatus.set(NCStatus.Error,"Invalid URL"),this.render();return}this.likeActionStatus.set(NCStatus.Loading),this.render();try{const t=createLikeEvent(this.currentUrl),r=await signEvent(t);await new NDKEvent(this.nostrService.getNDK(),r).publish(),this.isLiked=!0,this.likeCount++,this.likeActionStatus.set(NCStatus.Ready),await this.updateLikeCount()}catch(t){console.error("[NostrLike] Failed to like:",t),this.isLiked=!1,this.likeCount--;const r=t instanceof Error?t.message:"Failed to like";this.likeActionStatus.set(NCStatus.Error,r)}finally{this.render()}}async handleUnlike(){if(this.ensureCurrentUrl(),!this.currentUrl){this.likeActionStatus.set(NCStatus.Error,"Invalid URL"),this.render();return}this.likeActionStatus.set(NCStatus.Loading),this.render();try{const t=createUnlikeEvent(this.currentUrl),r=await signEvent(t);await new NDKEvent(this.nostrService.getNDK(),r).publish(),this.isLiked=!1,this.likeCount>0&&this.likeCount--,this.likeActionStatus.set(NCStatus.Ready),await this.updateLikeCount()}catch(t){console.error("[NostrLike] Failed to unlike:",t),this.isLiked=!0,this.likeCount++;const r=t instanceof Error?t.message:"Failed to unlike";this.likeActionStatus.set(NCStatus.Error,r)}finally{this.render()}}async handleCountClick(){if(!(this.likeCount===0||!this.cachedLikeDetails))try{const{openLikersDialog:t}=await Promise.resolve().then(()=>dialogLikers);await t({likeDetails:this.cachedLikeDetails.likeDetails,theme:this.theme==="dark"?"dark":"light"})}catch(t){console.error("[NostrLike] Error opening likers dialog:",t)}}async handleHelpClick(){try{await showHelpDialog(this.theme==="dark"?"dark":"light")}catch(t){console.error("[NostrLike] Error showing help dialog:",t)}}attachDelegatedListeners(){this.delegateEvent("click",".nostr-like-button",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleLikeClick()}),this.delegateEvent("click",".like-count",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleCountClick()}),this.delegateEvent("click",".help-icon",t=>{var r,s;(r=t.preventDefault)==null||r.call(t),(s=t.stopPropagation)==null||s.call(t),this.handleHelpClick()})}renderContent(){const t=this.likeActionStatus.get()===NCStatus.Loading||this.conn.get()===NCStatus.Loading,r=this.likeListStatus.get()===NCStatus.Loading,s=this.computeOverall()===NCStatus.Error,o=this.errorMessage,a=this.getAttribute("text")||"Like",u={isLoading:t,isError:s,errorMessage:o,buttonText:a,isLiked:this.isLiked,likeCount:this.likeCount,hasLikes:this.likeCount>0,isCountLoading:r,theme:this.theme};this.shadowRoot.innerHTML=`
3962
3962
  ${getLikeButtonStyles()}
3963
3963
  ${renderLikeButton(u)}
3964
3964
  `}}customElements.define("nostr-like",NostrLike);function init(){typeof window<"u"&&console.log("Nostr Components initialized")}var verifiedSymbol=Symbol("verified"),isRecord=n=>n instanceof Object;function validateEvent(n){if(!isRecord(n)||typeof n.kind!="number"||typeof n.content!="string"||typeof n.created_at!="number"||typeof n.pubkey!="string"||!n.pubkey.match(/^[a-f0-9]{64}$/)||!Array.isArray(n.tags))return!1;for(let e=0;e<n.tags.length;e++){let t=n.tags[e];if(!Array.isArray(t))return!1;for(let r=0;r<t.length;r++)if(typeof t[r]=="object")return!1}return!0}new TextDecoder("utf-8");var utf8Encoder=new TextEncoder,JS=class{generateSecretKey(){return schnorr$1.utils.randomPrivateKey()}getPublicKey(n){return bytesToHex$2(schnorr$1.getPublicKey(n))}finalizeEvent(n,e){const t=n;return t.pubkey=bytesToHex$2(schnorr$1.getPublicKey(e)),t.id=getEventHash(t),t.sig=bytesToHex$2(schnorr$1.sign(getEventHash(t),e)),t[verifiedSymbol]=!0,t}verifyEvent(n){if(typeof n[verifiedSymbol]=="boolean")return n[verifiedSymbol];const e=getEventHash(n);if(e!==n.id)return n[verifiedSymbol]=!1,!1;try{const t=schnorr$1.verify(n.sig,e,n.pubkey);return n[verifiedSymbol]=t,t}catch{return n[verifiedSymbol]=!1,!1}}};function serializeEvent(n){if(!validateEvent(n))throw new Error("can't serialize event with wrong or missing properties");return JSON.stringify([0,n.pubkey,n.created_at,n.kind,n.tags,n.content])}function getEventHash(n){let e=sha256$1(utf8Encoder.encode(serializeEvent(n)));return bytesToHex$2(e)}var i=new JS,generateSecretKey=i.generateSecretKey,getPublicKey=i.getPublicKey,finalizeEvent=i.finalizeEvent;i.verifyEvent;const pure=Object.freeze(Object.defineProperty({__proto__:null,finalizeEvent,generateSecretKey,getEventHash,getPublicKey,serializeEvent,validateEvent,verifiedSymbol},Symbol.toStringTag,{value:"Module"}));function getLikersDialogStyles(n="light"){const e=n==="dark";return`