nostr-components 0.2.0
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.
- package/LICENSE +21 -0
- package/README.md +334 -0
- package/dist/assets/base-styles-CBypR3FR.js +145 -0
- package/dist/assets/base-styles-CBypR3FR.js.map +1 -0
- package/dist/assets/copy-delegation-C4uvRTVM.js +15 -0
- package/dist/assets/copy-delegation-C4uvRTVM.js.map +1 -0
- package/dist/assets/dialog-component-Dqg0QU9I.js +66 -0
- package/dist/assets/dialog-component-Dqg0QU9I.js.map +1 -0
- package/dist/assets/dialog-likers-BzTesCZa.js +238 -0
- package/dist/assets/dialog-likers-BzTesCZa.js.map +1 -0
- package/dist/assets/icons-Dr_d9MII.js +105 -0
- package/dist/assets/icons-Dr_d9MII.js.map +1 -0
- package/dist/assets/nip05-utils-BNBHUmkr.js +2 -0
- package/dist/assets/nip05-utils-BNBHUmkr.js.map +1 -0
- package/dist/assets/nostr-service-pr_crY62.js +78 -0
- package/dist/assets/nostr-service-pr_crY62.js.map +1 -0
- package/dist/assets/nostr-user-component-Q7GeeFyu.js +2 -0
- package/dist/assets/nostr-user-component-Q7GeeFyu.js.map +1 -0
- package/dist/assets/preload-helper-D7HrI6pR.js +2 -0
- package/dist/assets/preload-helper-D7HrI6pR.js.map +1 -0
- package/dist/assets/pure-jrVhRVpB.js +2 -0
- package/dist/assets/pure-jrVhRVpB.js.map +1 -0
- package/dist/assets/theme-C1r1Zw8r.js +2 -0
- package/dist/assets/theme-C1r1Zw8r.js.map +1 -0
- package/dist/assets/user-resolver-C-E6KdwY.js +2 -0
- package/dist/assets/user-resolver-C-E6KdwY.js.map +1 -0
- package/dist/assets/utils--bxLbhGF.js +2 -0
- package/dist/assets/utils--bxLbhGF.js.map +1 -0
- package/dist/assets/zap-utils-B1sz0Abx.js +2 -0
- package/dist/assets/zap-utils-B1sz0Abx.js.map +1 -0
- package/dist/components/nostr-comment.es.js +924 -0
- package/dist/components/nostr-comment.es.js.map +1 -0
- package/dist/components/nostr-dm.es.js +217 -0
- package/dist/components/nostr-dm.es.js.map +1 -0
- package/dist/components/nostr-follow-button.es.js +103 -0
- package/dist/components/nostr-follow-button.es.js.map +1 -0
- package/dist/components/nostr-like.es.js +296 -0
- package/dist/components/nostr-like.es.js.map +1 -0
- package/dist/components/nostr-live-chat.es.js +523 -0
- package/dist/components/nostr-live-chat.es.js.map +1 -0
- package/dist/components/nostr-post.es.js +441 -0
- package/dist/components/nostr-post.es.js.map +1 -0
- package/dist/components/nostr-profile-badge.es.js +100 -0
- package/dist/components/nostr-profile-badge.es.js.map +1 -0
- package/dist/components/nostr-profile.es.js +287 -0
- package/dist/components/nostr-profile.es.js.map +1 -0
- package/dist/components/nostr-zap.es.js +694 -0
- package/dist/components/nostr-zap.es.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/nostr-comment.d.ts +4 -0
- package/dist/nostr-components.es.js +2 -0
- package/dist/nostr-components.es.js.map +1 -0
- package/dist/nostr-components.umd.js +4200 -0
- package/dist/nostr-components.umd.js.map +1 -0
- package/dist/nostr-dm.d.ts +4 -0
- package/dist/nostr-follow-button.d.ts +4 -0
- package/dist/nostr-like.d.ts +4 -0
- package/dist/nostr-live-chat.d.ts +4 -0
- package/dist/nostr-post.d.ts +4 -0
- package/dist/nostr-profile-badge.d.ts +4 -0
- package/dist/nostr-profile.d.ts +4 -0
- package/dist/nostr-zap.d.ts +4 -0
- package/dist/src/base/base-component/nostr-base-component.d.ts +116 -0
- package/dist/src/base/copy-delegation.d.ts +5 -0
- package/dist/src/base/dialog-component/dialog-component.d.ts +67 -0
- package/dist/src/base/dialog-component/style.d.ts +5 -0
- package/dist/src/base/event-component/nostr-event-component.d.ts +53 -0
- package/dist/src/base/render-options.d.ts +5 -0
- package/dist/src/base/resolvers/event-resolver.d.ts +20 -0
- package/dist/src/base/resolvers/user-resolver.d.ts +19 -0
- package/dist/src/base/text-row/render-name.d.ts +7 -0
- package/dist/src/base/text-row/render-nip05.d.ts +1 -0
- package/dist/src/base/text-row/render-npub.d.ts +1 -0
- package/dist/src/base/text-row/render-text-row.d.ts +9 -0
- package/dist/src/base/user-component/nostr-user-component.d.ts +43 -0
- package/dist/src/common/base-styles.d.ts +44 -0
- package/dist/src/common/constants.d.ts +4 -0
- package/dist/src/common/date-utils.d.ts +9 -0
- package/dist/src/common/icons.d.ts +7 -0
- package/dist/src/common/nip05-utils.d.ts +13 -0
- package/dist/src/common/nostr-service.d.ts +40 -0
- package/dist/src/common/theme.d.ts +4 -0
- package/dist/src/common/types.d.ts +1 -0
- package/dist/src/common/utils.d.ts +34 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/nostr-comment/nostr-comment.d.ts +60 -0
- package/dist/src/nostr-comment/render.d.ts +15 -0
- package/dist/src/nostr-comment/utils.d.ts +81 -0
- package/dist/src/nostr-dm/nostr-dm.d.ts +34 -0
- package/dist/src/nostr-dm/render.d.ts +15 -0
- package/dist/src/nostr-follow-button/nostr-follow-button.d.ts +24 -0
- package/dist/src/nostr-follow-button/render.d.ts +11 -0
- package/dist/src/nostr-follow-button/style.d.ts +1 -0
- package/dist/src/nostr-like/dialog-help-style.d.ts +1 -0
- package/dist/src/nostr-like/dialog-help.d.ts +2 -0
- package/dist/src/nostr-like/dialog-likers-style.d.ts +1 -0
- package/dist/src/nostr-like/dialog-likers.d.ts +24 -0
- package/dist/src/nostr-like/like-utils.d.ts +52 -0
- package/dist/src/nostr-like/nostr-like.d.ts +49 -0
- package/dist/src/nostr-like/render.d.ts +10 -0
- package/dist/src/nostr-like/style.d.ts +1 -0
- package/dist/src/nostr-live-chat/nostr-live-chat.d.ts +65 -0
- package/dist/src/nostr-live-chat/render.d.ts +31 -0
- package/dist/src/nostr-post/nostr-post.d.ts +25 -0
- package/dist/src/nostr-post/parse-text.d.ts +8 -0
- package/dist/src/nostr-post/render-content.d.ts +5 -0
- package/dist/src/nostr-post/render.d.ts +19 -0
- package/dist/src/nostr-post/style.d.ts +1 -0
- package/dist/src/nostr-profile/nostr-profile.d.ts +24 -0
- package/dist/src/nostr-profile/render-stats.d.ts +1 -0
- package/dist/src/nostr-profile/render.d.ts +22 -0
- package/dist/src/nostr-profile/style.d.ts +1 -0
- package/dist/src/nostr-profile-badge/nostr-profile-badge.d.ts +34 -0
- package/dist/src/nostr-profile-badge/render.d.ts +11 -0
- package/dist/src/nostr-profile-badge/style.d.ts +1 -0
- package/dist/src/nostr-zap/dialog-help-style.d.ts +5 -0
- package/dist/src/nostr-zap/dialog-help.d.ts +2 -0
- package/dist/src/nostr-zap/dialog-zap-style.d.ts +6 -0
- package/dist/src/nostr-zap/dialog-zap.d.ts +31 -0
- package/dist/src/nostr-zap/dialog-zappers-style.d.ts +1 -0
- package/dist/src/nostr-zap/dialog-zappers.d.ts +25 -0
- package/dist/src/nostr-zap/nostr-zap.d.ts +45 -0
- package/dist/src/nostr-zap/render.d.ts +9 -0
- package/dist/src/nostr-zap/style.d.ts +1 -0
- package/dist/src/nostr-zap/zap-utils.d.ts +53 -0
- package/dist/themes/dark.css +10 -0
- package/dist/themes/light.css +10 -0
- package/dist/themes.css +52 -0
- package/dist/vite.config.d.ts +2 -0
- package/dist/vite.config.esm.d.ts +2 -0
- package/dist/vite.config.umd.d.ts +2 -0
- package/package.json +95 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
var P=Object.defineProperty;var H=(h,f,t)=>f in h?P(h,f,{enumerable:!0,configurable:!0,writable:!0,value:t}):h[f]=t;var a=(h,f,t)=>H(h,typeof f!="symbol"?f+"":f,t);import{_ as L}from"../assets/preload-helper-D7HrI6pR.js";import{N as A,D,c as v,d as $,e as M,g as S}from"../assets/nostr-service-pr_crY62.js";import{g as R,a as C}from"../assets/theme-C1r1Zw8r.js";import{r as U}from"../assets/nip05-utils-BNBHUmkr.js";import"../assets/icons-Dr_d9MII.js";function K(h){try{return new Date(h*1e3).toLocaleString()}catch{return""}}function _(h){try{const f=Date.now(),t=h*1e3,r=f-t,e=Math.floor(r/1e3);if(e<60)return"just now";if(e<3600){const s=Math.floor(e/60);return`${s} ${s===1?"min":"mins"} ago`}if(e<86400){const s=Math.floor(e/3600);return`${s} ${s===1?"hour":"hours"} ago`}if(e<2592e3){const s=Math.floor(e/86400);return`${s} ${s===1?"day":"days"} ago`}if(e<31536e3){const s=Math.floor(e/2592e3);return`${s} ${s===1?"month":"months"} ago`}const o=Math.floor(e/31536e3);return`${o} ${o===1?"year":"years"} ago`}catch{return""}}function I(h){return h==="me"||h==="them"?h:"them"}function y(h){return h==null?"":String(h).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function O({theme:h,recipientNpub:f,recipientName:t,recipientPicture:r,message:e,messages:o,isLoading:s,isFinding:l,isError:p,errorMessage:i,currentUserName:d,currentUserPicture:b,showWelcome:k,welcomeText:u,startChatText:n,maxMessageLength:g}){const m=typeof g=="number"?g:1e3,N=(e||"").length,E=Math.max(0,m-N),T=E<=10?"nostr-chat-char-counter warn":"nostr-chat-char-counter";return`
|
|
2
|
+
<div class="nostr-chat-container ${p?"nostr-chat-error":""}">
|
|
3
|
+
<div class="nostr-chat-header">
|
|
4
|
+
<div class="nostr-chat-header-left">
|
|
5
|
+
${f&&t?`
|
|
6
|
+
<div class="nostr-chat-recipient">
|
|
7
|
+
<div class="nostr-chat-recipient-info">
|
|
8
|
+
<img
|
|
9
|
+
src="${y(r)||""}"
|
|
10
|
+
alt="${y(t)||""}"
|
|
11
|
+
class="nostr-chat-recipient-avatar"
|
|
12
|
+
onerror="this.onerror=null; this.src='https://via.placeholder.com/40';"
|
|
13
|
+
>
|
|
14
|
+
<span class="nostr-chat-recipient-name">${y(t)||y(f)}</span>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
`:`
|
|
18
|
+
<div class="nostr-chat-recipient-placeholder">
|
|
19
|
+
${R(24,24)}
|
|
20
|
+
<span>Nostr Live Chat</span>
|
|
21
|
+
</div>
|
|
22
|
+
`}
|
|
23
|
+
</div>
|
|
24
|
+
<div class="nostr-chat-header-right">
|
|
25
|
+
${d?`
|
|
26
|
+
<div class="nostr-chat-self">
|
|
27
|
+
<img
|
|
28
|
+
src="${y(b)||""}"
|
|
29
|
+
alt="${y(d)||"You"}"
|
|
30
|
+
class="nostr-chat-self-avatar"
|
|
31
|
+
onerror="this.onerror=null; this.src='https://via.placeholder.com/32';"
|
|
32
|
+
>
|
|
33
|
+
<span class="nostr-chat-self-name">${y(d)}</span>
|
|
34
|
+
</div>
|
|
35
|
+
`:""}
|
|
36
|
+
<button class="nostr-chat-close-btn" title="Minimize">×</button>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<div class="nostr-chat-content">
|
|
41
|
+
${f?k?`
|
|
42
|
+
<div class="nostr-chat-welcome">
|
|
43
|
+
<div class="nostr-chat-welcome-text">${y(u)||"Welcome!"}</div>
|
|
44
|
+
<button class="nostr-chat-start-btn">${y(n)||"Start chat"}</button>
|
|
45
|
+
</div>
|
|
46
|
+
`:`
|
|
47
|
+
<div class="nostr-chat-history">
|
|
48
|
+
${o.map(w=>`
|
|
49
|
+
<div class="nostr-chat-message-row nostr-chat-message-${I(w.sender)} ${w.sender==="me"&&w.status==="sending"?"sending":""} ${w.sender==="me"&&w.status==="failed"?"failed":""}">
|
|
50
|
+
<div class="nostr-chat-message-bubble">${y(w.text)}</div>
|
|
51
|
+
<div class="nostr-chat-message-meta">
|
|
52
|
+
<span class="nostr-chat-message-timestamp" title="${y(K(w.timestamp))}">${y(_(w.timestamp))}</span>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
`).join("")}
|
|
56
|
+
</div>
|
|
57
|
+
<div class="nostr-chat-actions">
|
|
58
|
+
<textarea
|
|
59
|
+
class="nostr-chat-textarea"
|
|
60
|
+
placeholder="Type your message..."
|
|
61
|
+
maxlength="${m}"
|
|
62
|
+
>${y(e)}</textarea>
|
|
63
|
+
<div class="${T}" aria-live="polite">${E} chars left</div>
|
|
64
|
+
<button class="nostr-chat-send-btn" ${s?"disabled":""}>
|
|
65
|
+
${s?C():"Send"}
|
|
66
|
+
</button>
|
|
67
|
+
</div>
|
|
68
|
+
`:`
|
|
69
|
+
<div class="nostr-chat-npub-input-container">
|
|
70
|
+
<input type="text" class="nostr-chat-npub-input" placeholder="Enter recipient's npub/nip05 address..." />
|
|
71
|
+
<button class="nostr-chat-find-btn" ${l?"disabled":""}>
|
|
72
|
+
${l?`${C()} <span>Finding...</span>`:"<span>Find</span>"}
|
|
73
|
+
</button>
|
|
74
|
+
</div>
|
|
75
|
+
`}
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
${p?`<small class="nostr-chat-error-message">${y(i)}</small>`:""}
|
|
79
|
+
</div>
|
|
80
|
+
`}function z(h){return`
|
|
81
|
+
<style>
|
|
82
|
+
:host {
|
|
83
|
+
--nstrc-chat-background-dark: #222222;
|
|
84
|
+
--nstrc-chat-background-light: #FFFFFF;
|
|
85
|
+
--nstrc-chat-text-color-dark: #FFFFFF;
|
|
86
|
+
--nstrc-chat-text-color-light: #000000;
|
|
87
|
+
--nstrc-chat-border-dark: 1px solid #444444;
|
|
88
|
+
--nstrc-chat-border-light: 1px solid #DDDDDD;
|
|
89
|
+
--nstrc-chat-input-background-dark: #333333;
|
|
90
|
+
--nstrc-chat-input-background-light: #F9F9F9;
|
|
91
|
+
--nstrc-chat-my-message-background-dark: #5A3E85;
|
|
92
|
+
--nstrc-chat-my-message-background-light: #E6DDF4;
|
|
93
|
+
/* Unified accent variables with light/dark variants */
|
|
94
|
+
--nstrc-chat-accent-color-dark: #5A3E85;
|
|
95
|
+
--nstrc-chat-accent-color-light: #7E4FD2;
|
|
96
|
+
--nstrc-chat-accent-text-color-dark: #FFFFFF;
|
|
97
|
+
--nstrc-chat-accent-text-color-light: #FFFFFF;
|
|
98
|
+
--nstrc-chat-their-message-background-dark: #3A3A3A;
|
|
99
|
+
--nstrc-chat-their-message-background-light: #F0F0F0;
|
|
100
|
+
--nstrc-chat-button-background-dark: #5A3E85;
|
|
101
|
+
--nstrc-chat-button-background-light: #7E4FD2;
|
|
102
|
+
--nstrc-chat-button-text-dark: #FFFFFF;
|
|
103
|
+
--nstrc-chat-button-text-light: #FFFFFF;
|
|
104
|
+
--nstrc-chat-error-color: #FF4D4F;
|
|
105
|
+
--nstrc-chat-border-radius: 12px;
|
|
106
|
+
|
|
107
|
+
--nstrc-chat-background: var(--nstrc-chat-background-${h});
|
|
108
|
+
--nstrc-chat-text-color: var(--nstrc-chat-text-color-${h});
|
|
109
|
+
--nstrc-chat-border: var(--nstrc-chat-border-${h});
|
|
110
|
+
--nstrc-chat-input-background: var(--nstrc-chat-input-background-${h});
|
|
111
|
+
--nstrc-chat-my-message-background: var(--nstrc-chat-my-message-background-${h});
|
|
112
|
+
--nstrc-chat-their-message-background: var(--nstrc-chat-their-message-background-${h});
|
|
113
|
+
--nstrc-chat-button-background: var(--nstrc-chat-button-background-${h});
|
|
114
|
+
--nstrc-chat-button-text: var(--nstrc-chat-button-text-${h});
|
|
115
|
+
--nstrc-chat-accent-color: var(--nstrc-chat-accent-color-${h});
|
|
116
|
+
--nstrc-chat-accent-text-color: var(--nstrc-chat-accent-text-color-${h});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* Floating modes shrink the host so it doesn't affect page layout */
|
|
120
|
+
:host([display-type="fab"]),
|
|
121
|
+
:host([display-type="bottom-bar"]),
|
|
122
|
+
:host([display-type="full"]) {
|
|
123
|
+
width: 0;
|
|
124
|
+
height: 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* Floating panel wrapper */
|
|
128
|
+
.nostr-chat-float-panel {
|
|
129
|
+
position: fixed;
|
|
130
|
+
bottom: 20px;
|
|
131
|
+
right: 20px;
|
|
132
|
+
z-index: 2147483000;
|
|
133
|
+
box-shadow: 0 8px 24px rgba(0,0,0,0.18);
|
|
134
|
+
border-radius: var(--nstrc-chat-border-radius);
|
|
135
|
+
display: none;
|
|
136
|
+
}
|
|
137
|
+
.nostr-chat-float-panel.open { display: block; }
|
|
138
|
+
|
|
139
|
+
/* Close (minimize) button for floating panel */
|
|
140
|
+
.nostr-chat-close-btn {
|
|
141
|
+
width: 32px;
|
|
142
|
+
height: 32px;
|
|
143
|
+
border-radius: 50%;
|
|
144
|
+
display: flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
justify-content: center;
|
|
147
|
+
font-weight: 700;
|
|
148
|
+
font-size: 16px;
|
|
149
|
+
cursor: pointer;
|
|
150
|
+
background: rgba(0,0,0,0.1);
|
|
151
|
+
color: var(--nstrc-chat-text-color);
|
|
152
|
+
border: none;
|
|
153
|
+
transition: background-color 0.2s ease;
|
|
154
|
+
}
|
|
155
|
+
.nostr-chat-close-btn:hover {
|
|
156
|
+
background: rgba(0,0,0,0.2);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* Hide close button in embed mode */
|
|
160
|
+
:host([display-type="embed"]) .nostr-chat-close-btn {
|
|
161
|
+
display: none;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* Launcher: FAB */
|
|
165
|
+
.nostr-chat-launcher.fab {
|
|
166
|
+
position: fixed;
|
|
167
|
+
bottom: 20px;
|
|
168
|
+
right: 20px;
|
|
169
|
+
z-index: 2147483000;
|
|
170
|
+
display: flex;
|
|
171
|
+
align-items: center;
|
|
172
|
+
gap: 10px;
|
|
173
|
+
font-family: Inter, sans-serif;
|
|
174
|
+
}
|
|
175
|
+
.nostr-chat-launcher .bubble {
|
|
176
|
+
background: var(--nstrc-chat-background);
|
|
177
|
+
color: var(--nstrc-chat-text-color);
|
|
178
|
+
border: var(--nstrc-chat-border);
|
|
179
|
+
border-radius: 14px;
|
|
180
|
+
padding: 10px 12px;
|
|
181
|
+
box-shadow: 0 6px 20px rgba(0,0,0,0.12);
|
|
182
|
+
}
|
|
183
|
+
.nostr-chat-launcher .bubble .title { font-weight: 700; font-size: 14px; }
|
|
184
|
+
.nostr-chat-launcher .bubble .subtitle { font-size: 12px; opacity: 0.8; }
|
|
185
|
+
.nostr-chat-launcher .fab-btn {
|
|
186
|
+
width: 64px;
|
|
187
|
+
height: 64px;
|
|
188
|
+
border-radius: 50%;
|
|
189
|
+
background: var(--nstrc-chat-accent-color);
|
|
190
|
+
color: var(--nstrc-chat-accent-text-color);
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: center;
|
|
193
|
+
justify-content: center;
|
|
194
|
+
border: none;
|
|
195
|
+
cursor: pointer;
|
|
196
|
+
box-shadow: 0 6px 20px rgba(0,0,0,0.18);
|
|
197
|
+
font-size: 24px; /* Larger emoji/icon */
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* Launcher: Bottom bar */
|
|
201
|
+
.nostr-chat-launcher.bottom-bar {
|
|
202
|
+
position: fixed;
|
|
203
|
+
left: 50%;
|
|
204
|
+
transform: translateX(-50%);
|
|
205
|
+
bottom: 20px;
|
|
206
|
+
z-index: 2147483000;
|
|
207
|
+
}
|
|
208
|
+
.nostr-chat-launcher .bar-btn {
|
|
209
|
+
padding: 12px 20px;
|
|
210
|
+
border-radius: 999px;
|
|
211
|
+
background: var(--nstrc-chat-accent-color);
|
|
212
|
+
color: var(--nstrc-chat-accent-text-color);
|
|
213
|
+
border: none;
|
|
214
|
+
cursor: pointer;
|
|
215
|
+
font-weight: 700;
|
|
216
|
+
box-shadow: 0 6px 20px rgba(0,0,0,0.18);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.nostr-chat-container {
|
|
220
|
+
display: flex;
|
|
221
|
+
flex-direction: column;
|
|
222
|
+
font-family: Inter, sans-serif;
|
|
223
|
+
width: 100%;
|
|
224
|
+
height: 100%;
|
|
225
|
+
max-width: 400px;
|
|
226
|
+
max-height: 600px;
|
|
227
|
+
box-sizing: border-box;
|
|
228
|
+
border-radius: var(--nstrc-chat-border-radius);
|
|
229
|
+
border: var(--nstrc-chat-border);
|
|
230
|
+
background-color: var(--nstrc-chat-background);
|
|
231
|
+
color: var(--nstrc-chat-text-color);
|
|
232
|
+
overflow: hidden;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.nostr-chat-header {
|
|
236
|
+
padding: 12px 16px;
|
|
237
|
+
border-bottom: var(--nstrc-chat-border);
|
|
238
|
+
display: flex;
|
|
239
|
+
align-items: center;
|
|
240
|
+
justify-content: space-between;
|
|
241
|
+
flex-shrink: 0;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.nostr-chat-header-right {
|
|
245
|
+
display: flex;
|
|
246
|
+
align-items: center;
|
|
247
|
+
gap: 12px;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.nostr-chat-recipient, .nostr-chat-recipient-placeholder {
|
|
251
|
+
display: flex;
|
|
252
|
+
align-items: center; /* Ensures vertical centering */
|
|
253
|
+
gap: 12px;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.nostr-chat-recipient-avatar {
|
|
257
|
+
width: 36px;
|
|
258
|
+
height: 36px;
|
|
259
|
+
border-radius: 50%;
|
|
260
|
+
object-fit: cover;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.nostr-chat-recipient-info {
|
|
264
|
+
display: flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
gap: 8px;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.nostr-chat-recipient-name {
|
|
270
|
+
font-weight: 600;
|
|
271
|
+
font-size: 16px;
|
|
272
|
+
display: flex;
|
|
273
|
+
align-items: center;
|
|
274
|
+
height: 36px; /* Match avatar height */
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.nostr-chat-self {
|
|
278
|
+
display: flex;
|
|
279
|
+
align-items: center;
|
|
280
|
+
gap: 8px;
|
|
281
|
+
opacity: 0.85;
|
|
282
|
+
font-size: 12px;
|
|
283
|
+
}
|
|
284
|
+
.nostr-chat-self-avatar {
|
|
285
|
+
width: 24px;
|
|
286
|
+
height: 24px;
|
|
287
|
+
border-radius: 50%;
|
|
288
|
+
object-fit: cover;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.nostr-chat-content {
|
|
292
|
+
padding: 16px;
|
|
293
|
+
display: flex;
|
|
294
|
+
flex-direction: column;
|
|
295
|
+
gap: 12px;
|
|
296
|
+
flex-grow: 1;
|
|
297
|
+
overflow-y: auto;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* Scrollbar styling for dark theme */
|
|
301
|
+
.nostr-chat-content::-webkit-scrollbar,
|
|
302
|
+
.nostr-chat-history::-webkit-scrollbar {
|
|
303
|
+
width: 8px;
|
|
304
|
+
}
|
|
305
|
+
.nostr-chat-content::-webkit-scrollbar-track,
|
|
306
|
+
.nostr-chat-history::-webkit-scrollbar-track {
|
|
307
|
+
background: transparent;
|
|
308
|
+
}
|
|
309
|
+
.nostr-chat-content::-webkit-scrollbar-thumb,
|
|
310
|
+
.nostr-chat-history::-webkit-scrollbar-thumb {
|
|
311
|
+
background: rgba(255, 255, 255, 0.2);
|
|
312
|
+
border-radius: 4px;
|
|
313
|
+
}
|
|
314
|
+
.nostr-chat-content::-webkit-scrollbar-thumb:hover,
|
|
315
|
+
.nostr-chat-history::-webkit-scrollbar-thumb:hover {
|
|
316
|
+
background: rgba(255, 255, 255, 0.3);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.nostr-chat-history {
|
|
320
|
+
display: flex;
|
|
321
|
+
flex-direction: column;
|
|
322
|
+
gap: 10px;
|
|
323
|
+
flex-grow: 1;
|
|
324
|
+
overflow-y: auto;
|
|
325
|
+
padding-right: 10px; /* For scrollbar */
|
|
326
|
+
padding-bottom: 16px;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.nostr-chat-message-row {
|
|
330
|
+
display: flex;
|
|
331
|
+
width: 100%;
|
|
332
|
+
flex-direction: column;
|
|
333
|
+
align-items: flex-start;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.nostr-chat-message-me {
|
|
337
|
+
justify-content: flex-end;
|
|
338
|
+
align-items: flex-end;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.nostr-chat-message-them {
|
|
342
|
+
justify-content: flex-start;
|
|
343
|
+
align-items: flex-start;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.nostr-chat-message-bubble {
|
|
347
|
+
padding: 8px 12px;
|
|
348
|
+
border-radius: 18px;
|
|
349
|
+
max-width: 75%;
|
|
350
|
+
word-wrap: break-word;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.nostr-chat-message-me .nostr-chat-message-bubble {
|
|
354
|
+
background-color: var(--nstrc-chat-accent-color);
|
|
355
|
+
color: var(--nstrc-chat-accent-text-color);
|
|
356
|
+
border-radius: 15px 15px 0 15px;
|
|
357
|
+
opacity: 1;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.nostr-chat-message-me.sending .nostr-chat-message-bubble {
|
|
361
|
+
opacity: 0.5;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.nostr-chat-message-me.failed .nostr-chat-message-bubble {
|
|
365
|
+
opacity: 1;
|
|
366
|
+
border: 1px dashed var(--nstrc-chat-error-color);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.nostr-chat-message-them .nostr-chat-message-bubble {
|
|
370
|
+
background-color: var(--nstrc-chat-their-message-background);
|
|
371
|
+
border-bottom-left-radius: 4px;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/* Message timestamp under bubble, always visible but with opacity change on hover */
|
|
375
|
+
.nostr-chat-message-meta {
|
|
376
|
+
font-size: 10px;
|
|
377
|
+
margin-top: 4px;
|
|
378
|
+
opacity: 0.5;
|
|
379
|
+
color: var(--nstrc-chat-text-color);
|
|
380
|
+
max-width: 75%;
|
|
381
|
+
transition: opacity 0.2s ease;
|
|
382
|
+
height: 14px; /* Fixed height to prevent layout jumps */
|
|
383
|
+
}
|
|
384
|
+
.nostr-chat-message-row:hover .nostr-chat-message-meta {
|
|
385
|
+
opacity: 0.9;
|
|
386
|
+
}
|
|
387
|
+
.nostr-chat-message-me .nostr-chat-message-meta {
|
|
388
|
+
text-align: right;
|
|
389
|
+
}
|
|
390
|
+
.nostr-chat-message-them .nostr-chat-message-meta {
|
|
391
|
+
text-align: left;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/* Slightly highlight timestamp for the last message */
|
|
395
|
+
.nostr-chat-history > .nostr-chat-message-row:last-of-type .nostr-chat-message-meta {
|
|
396
|
+
opacity: 0.75;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.nostr-chat-npub-input-container {
|
|
400
|
+
display: flex;
|
|
401
|
+
gap: 8px;
|
|
402
|
+
align-items: center;
|
|
403
|
+
padding: 20px 0;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.nostr-chat-npub-input {
|
|
407
|
+
flex: 1;
|
|
408
|
+
padding: 10px;
|
|
409
|
+
box-sizing: border-box;
|
|
410
|
+
border-radius: 4px;
|
|
411
|
+
border: var(--nstrc-chat-border);
|
|
412
|
+
background-color: var(--nstrc-chat-input-background);
|
|
413
|
+
color: var(--nstrc-chat-text-color);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.nostr-chat-actions {
|
|
417
|
+
display: flex;
|
|
418
|
+
gap: 8px;
|
|
419
|
+
flex-shrink: 0;
|
|
420
|
+
border-top: var(--nstrc-chat-border);
|
|
421
|
+
padding-top: 12px;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.nostr-chat-welcome {
|
|
425
|
+
display: flex;
|
|
426
|
+
flex-direction: column;
|
|
427
|
+
gap: 12px;
|
|
428
|
+
align-items: center;
|
|
429
|
+
justify-content: center;
|
|
430
|
+
text-align: center;
|
|
431
|
+
padding: 12px 8px;
|
|
432
|
+
}
|
|
433
|
+
.nostr-chat-welcome-text {
|
|
434
|
+
opacity: 0.9;
|
|
435
|
+
}
|
|
436
|
+
.nostr-chat-start-btn {
|
|
437
|
+
padding: 10px 16px;
|
|
438
|
+
border-radius: 20px;
|
|
439
|
+
border: none;
|
|
440
|
+
background-color: var(--nstrc-chat-button-background);
|
|
441
|
+
color: var(--nstrc-chat-button-text);
|
|
442
|
+
cursor: pointer;
|
|
443
|
+
display: inline-flex;
|
|
444
|
+
align-items: center;
|
|
445
|
+
justify-content: center;
|
|
446
|
+
font-weight: 600;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.nostr-chat-textarea {
|
|
450
|
+
flex-grow: 1;
|
|
451
|
+
height: 40px;
|
|
452
|
+
box-sizing: border-box;
|
|
453
|
+
padding: 10px;
|
|
454
|
+
border-radius: 20px;
|
|
455
|
+
border: var(--nstrc-chat-border);
|
|
456
|
+
background-color: var(--nstrc-chat-input-background);
|
|
457
|
+
color: var(--nstrc-chat-text-color);
|
|
458
|
+
font-family: Inter, sans-serif;
|
|
459
|
+
resize: none;
|
|
460
|
+
overflow-y: auto;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/* Character counter */
|
|
464
|
+
.nostr-chat-char-counter {
|
|
465
|
+
align-self: center;
|
|
466
|
+
font-size: 12px;
|
|
467
|
+
opacity: 0.75;
|
|
468
|
+
color: var(--nstrc-chat-text-color);
|
|
469
|
+
white-space: nowrap;
|
|
470
|
+
min-width: max-content;
|
|
471
|
+
}
|
|
472
|
+
.nostr-chat-char-counter.warn {
|
|
473
|
+
color: #ff8c00; /* Brighter orange color for warning */
|
|
474
|
+
opacity: 1;
|
|
475
|
+
font-weight: 700;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.nostr-chat-find-btn, .nostr-chat-send-btn {
|
|
479
|
+
padding: 10px 16px;
|
|
480
|
+
border-radius: 20px;
|
|
481
|
+
border: none;
|
|
482
|
+
background-color: var(--nstrc-chat-button-background);
|
|
483
|
+
color: var(--nstrc-chat-button-text);
|
|
484
|
+
cursor: pointer;
|
|
485
|
+
display: flex;
|
|
486
|
+
align-items: center;
|
|
487
|
+
justify-content: center;
|
|
488
|
+
font-weight: 600;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.nostr-chat-error-message {
|
|
492
|
+
color: var(--nstrc-chat-error-color);
|
|
493
|
+
font-size: 14px;
|
|
494
|
+
padding: 0 16px 16px;
|
|
495
|
+
text-align: center;
|
|
496
|
+
}
|
|
497
|
+
</style>
|
|
498
|
+
`}const x=class x extends HTMLElement{constructor(){super();a(this,"rendered",!1);a(this,"nostrService",A.getInstance());a(this,"dmSubscription",null);a(this,"theme","light");a(this,"recipientNpub",null);a(this,"recipientNip05",null);a(this,"recipientName",null);a(this,"recipientPicture",null);a(this,"recipientPubkey",null);a(this,"message","");a(this,"messages",[]);a(this,"currentUserPubkey",null);a(this,"currentUserNpub",null);a(this,"currentUserName",null);a(this,"currentUserPicture",null);a(this,"displayType","embed");a(this,"isOpen",!1);a(this,"showWelcome",!1);a(this,"welcomeText",x.DEFAULT_WELCOME_TEXT);a(this,"startChatText",x.DEFAULT_START_CHAT_TEXT);a(this,"onlineText",x.DEFAULT_ONLINE_TEXT);a(this,"helpText",x.DEFAULT_HELP_TEXT);a(this,"MESSAGE_MAX_LENGTH",1e3);a(this,"isLoading",!1);a(this,"isFinding",!1);a(this,"isError",!1);a(this,"errorMessage","");a(this,"keySupplier",null);a(this,"boundHandleFind",null);a(this,"boundHandleSend",null);a(this,"boundHandleTextareaChange",null);a(this,"boundHandleLauncherClick",null);a(this,"boundHandleCloseClick",null);a(this,"boundHandleStartChat",null);a(this,"boundHandleNpubKeydown",null);a(this,"resubscribeTimer",null);a(this,"getRelays",()=>{const t=this.getAttribute("relays");return t?t.split(",").map(r=>r.trim()).filter(r=>r.length>0).filter((r,e,o)=>o.indexOf(r)===e):D});a(this,"getTheme",()=>{const t=this.getAttribute("theme"),r=(t||"").toLowerCase();r==="light"||r==="dark"?this.theme=r:(t&&console.warn(`Invalid theme '${t}'. Accepted values are 'light', 'dark'. Falling back to 'light'.`),this.theme="light")});a(this,"getRecipient",()=>{const t=this.getAttribute("pubkey");if(t)try{this.recipientPubkey=t,this.recipientNpub=v.npubEncode(t),this.lookupRecipient(this.recipientNpub);return}catch(o){const s=`Invalid recipient pubkey "${t}": ${o instanceof Error?o.message:String(o)}`;this.isError=!0,this.errorMessage=s,console.error("nostr-live-chat:",s,o),this.render();return}const r=this.getAttribute("nip05");if(r){this.recipientNip05=r,this.lookupRecipientByNip05();return}const e=this.getAttribute("npub");e&&(this.recipientNpub=e,this.lookupRecipient())});this.attachShadow({mode:"open"})}async getCurrentUserInfo(){var t,r,e,o,s,l,p,i,d,b;try{const k=this.nostrService.getNDK();let u=null;if(typeof window<"u"&&window.nostr){const n=window.nostr;console.log("Nostr extension found, checking for public key...");try{const g=!!(n.enable&&typeof n.enable=="function"&&n.getPublicKey&&typeof n.getPublicKey=="function");if(console.log("Is this nos2x extension?",g),g){console.log("Using nos2x specific flow");try{await n.enable(),console.log("nos2x extension enabled"),await new Promise(m=>setTimeout(m,100));const c=await n.getPublicKey();console.log("nos2x returned pubkey:",c),c&&typeof c=="string"&&c.length===64&&(u=c,console.log("Successfully got pubkey from nos2x:",u))}catch(c){console.error("Error with nos2x extension:",c)}}else{if(typeof n.enable=="function"){console.log("Attempting to enable generic extension...");try{await n.enable(),console.log("Extension enabled successfully")}catch(c){console.warn("Extension enable failed, continuing anyway:",c)}}if(typeof n.getPublicKey=="function"){console.log("Calling getPublicKey()...");try{u=await n.getPublicKey(),console.log("Got pubkey from extension:",u)}catch(c){console.error("Error getting public key:",c)}}else if(n.getPublicKey){console.log("Found getPublicKey property, resolving...");try{u=await Promise.resolve(n.getPublicKey),console.log("Got pubkey from extension (property):",u)}catch(c){console.error("Error resolving public key:",c)}}}}catch(g){console.error("Error in extension interaction:",g)}}if(!u){let n=null;if(this.keySupplier)try{n=await this.keySupplier()}catch{}if(n)try{const{NDKPrivateKeySigner:g}=await L(async()=>{const{NDKPrivateKeySigner:E}=await import("../assets/nostr-service-pr_crY62.js").then(T=>T.k);return{NDKPrivateKeySigner:E}},[]);let c=n;n.startsWith("nsec")&&(c=v.decode(n).data),u=(await new g(c).user()).pubkey}catch{}}if(u){this.currentUserPubkey=u,this.currentUserNpub=v.npubEncode(u),console.log("Got pubkey from extension and will use it:",u);try{const n=k.getUser({pubkey:u});console.log("Fetching profile for user:",u),await n.fetchProfile(),console.log("Fetched profile:",n.profile),this.currentUserName=((t=n.profile)==null?void 0:t.displayName)||((r=n.profile)==null?void 0:r.name)||((e=this.currentUserNpub)==null?void 0:e.substring(0,10))||null,this.currentUserPicture=((o=n.profile)==null?void 0:o.image)||null,this.currentUserName||console.warn("No username found in profile"),this.currentUserPicture||console.warn("No profile picture found"),console.log("Profile info set:",{name:this.currentUserName,picture:this.currentUserPicture,npub:this.currentUserNpub})}catch(n){console.error("Error fetching profile:",n),this.currentUserName=((s=this.currentUserNpub)==null?void 0:s.substring(0,10))||null}this.render()}else{console.log("Checking for direct nos2x logs in console...");try{if(await new Promise(n=>setTimeout(n,500)),typeof window<"u"&&window.nostr){console.log("Trying direct call to extension again...");try{const n=await window.nostr.getPublicKey();if(n&&typeof n=="string"){console.log("Got pubkey on second try:",n),this.currentUserPubkey=n,this.currentUserNpub=v.npubEncode(n);try{const g=k.getUser({pubkey:n});console.log("Fetching profile for user on second try:",n),await g.fetchProfile(),console.log("Fetched profile on second try:",g.profile),this.currentUserName=((l=g.profile)==null?void 0:l.displayName)||((p=g.profile)==null?void 0:p.name)||((i=this.currentUserNpub)==null?void 0:i.substring(0,10))||null,this.currentUserPicture=((d=g.profile)==null?void 0:d.image)||null,this.render();return}catch(g){console.error("Error fetching profile on second try:",g),this.currentUserName=((b=this.currentUserNpub)==null?void 0:b.substring(0,10))||null,this.render();return}}}catch(n){console.error("Error getting pubkey on direct second try:",n)}}}catch(n){console.error("Error in fallback pubkey detection:",n)}console.warn("No pubkey available from extension - trying fallback method")}}catch{}}getDisplayType(){const t=this.getAttribute("display-type"),r=["fab","bottom-bar","full","embed"],o=(t?String(t):"").toLowerCase(),s=r.includes(o)?o:"embed";this.displayType=s,this.displayType==="full"?this.isOpen=!0:this.displayType==="fab"||this.displayType==="bottom-bar"?(this.isOpen===void 0||this.isOpen===null)&&(this.isOpen=!1):this.isOpen=!1,this.getAttribute("display-type")!==s&&this.setAttribute("display-type",s)}connectedCallback(){if(!this.rendered){this.getTheme(),this.getDisplayType();const t=this.getAttribute("welcome-text");t&&(this.welcomeText=t);const r=this.getAttribute("start-chat-text");r&&(this.startChatText=r);const e=this.getAttribute("online-text");e&&(this.onlineText=e);const o=this.getAttribute("help-text");o&&(this.helpText=o),this.getRecipient(),this.nostrService.connectToNostr(this.getRelays()),this.getCurrentUserInfo(),this.render(),this.rendered=!0}}static get observedAttributes(){return["npub","pubkey","nip05","relays","theme","display-type","welcome-text","start-chat-text","online-text","help-text","history-days"]}unsubscribeFromDms(){if(this.dmSubscription){try{this.dmSubscription.stop()}catch{}this.dmSubscription=null}this.resubscribeTimer&&(clearTimeout(this.resubscribeTimer),this.resubscribeTimer=null)}clearRecipientAndChatState(){this.recipientPubkey=null,this.recipientNpub=null,this.recipientNip05=null,this.recipientName=null,this.recipientPicture=null,this.messages=[],this.message="",this.showWelcome=!1,this.isLoading=!1,this.isFinding=!1,this.isError=!1,this.errorMessage=""}attributeChangedCallback(t,r,e){if(this.rendered)if(t==="npub"){if(e===null){this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.render();return}e!==r&&(this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.recipientNpub=e,this.lookupRecipient());return}else if(t==="pubkey"){if(e===null){this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.render();return}if(e!==r){this.unsubscribeFromDms(),this.clearRecipientAndChatState();try{this.recipientPubkey=e,this.recipientNpub=v.npubEncode(e),this.lookupRecipient(this.recipientNpub)}catch{}}return}else if(t==="nip05"){if(e===null){this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.render();return}e!==r&&(this.unsubscribeFromDms(),this.clearRecipientAndChatState(),this.recipientNip05=e,this.lookupRecipientByNip05());return}else if(t==="relays"){if(e!==r){const o=this.getRelays();this.recipientPubkey&&!this.showWelcome?(this.resubscribeTimer&&clearTimeout(this.resubscribeTimer),this.resubscribeTimer=window.setTimeout(()=>{this.unsubscribeFromDms(),this.nostrService.connectToNostr(o),this.subscribeToDms()},300)):this.nostrService.connectToNostr(o)}}else t==="theme"?(this.getTheme(),this.render()):t==="display-type"?(this.getDisplayType(),this.render()):t==="welcome-text"?(this.welcomeText=e!==null?e:x.DEFAULT_WELCOME_TEXT,this.render()):t==="start-chat-text"?(this.startChatText=e!==null?e:x.DEFAULT_START_CHAT_TEXT,this.render()):t==="online-text"?(this.onlineText=e!==null?e:x.DEFAULT_ONLINE_TEXT,this.render()):t==="help-text"?(this.helpText=e!==null?e:x.DEFAULT_HELP_TEXT,this.render()):t==="history-days"&&e!==r&&this.recipientPubkey&&!this.showWelcome&&(this.resubscribeTimer&&clearTimeout(this.resubscribeTimer),this.resubscribeTimer=window.setTimeout(()=>{this.subscribeToDms()},250))}async lookupRecipient(t){var r,e,o;this.unsubscribeFromDms(),this.messages=[],this.showWelcome=!1,this.isFinding=!0,this.render();try{const s=t||this.recipientNpub;if(!s)return;const{type:l,data:p}=v.decode(s);if(l!=="npub")throw new Error("Invalid npub");this.recipientPubkey=p;const i=this.nostrService.getNDK().getUser({pubkey:this.recipientPubkey});await i.fetchProfile(),this.recipientName=((r=i.profile)==null?void 0:r.displayName)||((e=i.profile)==null?void 0:e.name)||s.substring(0,10),this.recipientPicture=((o=i.profile)==null?void 0:o.image)||null,this.showWelcome=!0,this.messages=[],this.isError=!1,this.errorMessage="",this.render()}catch(s){this.isError=!0,this.errorMessage=s.message}finally{this.isFinding=!1,this.render()}}async lookupRecipientByNip05(t){this.isFinding=!0,this.render();try{const r=t||this.recipientNip05;if(!r)return;const e=await U(r),o=v.npubEncode(e);this.recipientNpub=o,this.isError=!1,this.errorMessage="",await this.lookupRecipient(o)}catch(r){this.isError=!0,this.errorMessage=r.message}finally{this.isFinding=!1,this.render()}}handleFindClick(){const r=this.shadowRoot.querySelector(".nostr-chat-npub-input").value.trim();this.isError=!1,this.errorMessage="",this.render(),r&&(r.startsWith("npub")?(this.recipientNpub=r,this.lookupRecipient()):r.includes("@")?(this.recipientNip05=r,this.lookupRecipientByNip05()):(this.isError=!0,this.errorMessage="Invalid input. Please provide an npub or nip05 address.",this.render()))}async handleSendClick(){var r,e;if(!this.message.trim()||!this.recipientPubkey)return;if(this.message.length>this.MESSAGE_MAX_LENGTH){this.isError=!0,this.errorMessage=`Message is too long (max ${this.MESSAGE_MAX_LENGTH} characters).`,this.render();return}this.isLoading=!0,this.render();let t=null;try{const o=this.nostrService.getNDK();let s;if(typeof window<"u"&&window.nostr&&window.nostr.getPublicKey&&window.nostr.signEvent)try{s=new $}catch(d){console.error("Error creating NIP-07 signer:",d),this.isError=!0,this.errorMessage=`Error connecting to Nostr extension: ${d.message}`,this.isLoading=!1,this.render();return}if(!s)throw new Error("No signer available. Please install a NIP-07 extension or set a private key.");o.signer=s;const l=new M(o,{kind:S.EncryptedDirectMessage,tags:[["p",this.recipientPubkey]],created_at:Math.floor(Date.now()/1e3)});let p=!1;if(typeof((e=(r=window.nostr)==null?void 0:r.nip04)==null?void 0:e.encrypt)=="function")try{l.content=await window.nostr.nip04.encrypt(this.recipientPubkey,this.message.trim()),p=!0}catch(d){console.error("NIP-07 encryption failed, falling back to local encryption:",d)}if(!p)throw new Error("No private key available for encryption. Please use a NIP-07 extension.");t=`temp_${Date.now()}`,this.messages.push({id:t,text:this.message,sender:"me",timestamp:l.created_at,status:"sending"}),this.message="",this.render(),await l.publish();const i=this.messages.find(d=>d.id===t);i&&(this.messages.find(b=>b.id===l.id&&b.id!==t)?this.messages=this.messages.filter(b=>b.id!==t):(i.id=l.id,i.status="sent"),this.render())}catch(o){if(this.isError=!0,this.errorMessage=o.message,t){const s=this.messages.find(l=>l.id===t);s&&(s.status="failed"),this.render()}}finally{this.isLoading=!1,this.render()}}handleTextareaChange(t){var s;const r=t.target;this.message=r.value;const e=Math.max(0,this.MESSAGE_MAX_LENGTH-this.message.length),o=(s=this.shadowRoot)==null?void 0:s.querySelector(".nostr-chat-char-counter");o&&(o.textContent=`${e} chars left`,o.classList.toggle("warn",e<=10))}handleStartChat(){this.showWelcome=!1,this.subscribeToDms(),this.render()}async subscribeToDms(){if(this.dmSubscription&&this.dmSubscription.stop(),!this.recipientPubkey)return;let t=null;try{if(typeof window<"u"&&window.nostr&&window.nostr.getPublicKey)t={pubkey:await window.nostr.getPublicKey()};else{let i=null;if(this.keySupplier)try{i=await this.keySupplier()}catch{}if(i){const{NDKPrivateKeySigner:d}=await L(async()=>{const{NDKPrivateKeySigner:u}=await import("../assets/nostr-service-pr_crY62.js").then(n=>n.k);return{NDKPrivateKeySigner:u}},[]);let b=i;i.startsWith("nsec")&&(b=v.decode(i).data),t=await new d(b).user()}}}catch(i){console.error("Failed to determine current user for subscription",i)}if(!t){this.isError=!0,this.errorMessage="No signer available. Please install a NIP-07 extension or set a private key to start the chat.",this.render();return}this.messages=[];const r=this.getAttribute("history-days");let e;if(!r)e=void 0;else if(r.toLowerCase()==="all"||parseInt(r,10)<=0)e=void 0;else{const i=Math.max(1,parseInt(r,10)||30);e=Math.floor((Date.now()-i*24*60*60*1e3)/1e3)}const o={kinds:[S.EncryptedDirectMessage],"#p":[t.pubkey],authors:[this.recipientPubkey]},s={kinds:[S.EncryptedDirectMessage],"#p":[this.recipientPubkey],authors:[t.pubkey]},l=e!==void 0?{...o,since:e}:o,p=e!==void 0?{...s,since:e}:s;this.dmSubscription=this.nostrService.getNDK().subscribe([l,p],{closeOnEose:!1,groupable:!1}),this.dmSubscription.on("event",async i=>{var d;try{!this.currentUserPubkey&&t&&(this.currentUserPubkey=t.pubkey,this.currentUserNpub=v.npubEncode(t.pubkey));const b=i.pubkey===t.pubkey,k=b?(d=i.tags.find(c=>c[0]==="p"))==null?void 0:d[1]:i.pubkey;if(!k){try{console.debug("nostr-live-chat: skipping event with missing peer",i.id)}catch{}return}if(k!==this.recipientPubkey)return;if(b){const c=this.messages.find(m=>m.id===i.id);if(c){c.status==="sending"&&(c.status="sent",this.render());return}}let u="";if(!k){try{console.debug("nostr-live-chat: missing peer prior to decrypt, skipping",i.id)}catch{}return}if(!i.content||i.content.trim()===""){try{console.debug("nostr-live-chat: missing or empty content prior to decrypt, skipping",i.id)}catch{}return}if(window.nostr&&window.nostr.nip04&&typeof window.nostr.nip04.decrypt=="function")try{u=await window.nostr.nip04.decrypt(k,i.content)}catch(c){console.error("Failed to decrypt DM content:",c);return}else throw new Error("No private key available for decryption. Please use a NIP-07 extension.");if(b){const c=this.messages.find(m=>m.status==="sending"&&m.sender==="me"&&m.text===u&&Math.abs(m.timestamp-i.created_at)<2);if(c){c.id=i.id,c.status="sent",this.render();return}}const n={id:i.id,text:u,sender:b?"me":"them",timestamp:i.created_at,status:"sent"};this.messages.find(c=>c.id===n.id)||(this.messages.push(n),this.messages.sort((c,m)=>c.timestamp-m.timestamp),this.render())}catch(b){console.error("Failed to decrypt DM content:",b)}})}attachEventListeners(){const t=this.shadowRoot.querySelector(".nostr-chat-launcher");t&&(this.boundHandleLauncherClick&&t.removeEventListener("click",this.boundHandleLauncherClick),this.boundHandleLauncherClick=()=>{this.isOpen=!0,this.render()},t.addEventListener("click",this.boundHandleLauncherClick));const r=this.shadowRoot.querySelector(".nostr-chat-close-btn");r&&(this.boundHandleCloseClick&&r.removeEventListener("click",this.boundHandleCloseClick),this.boundHandleCloseClick=i=>{i==null||i.stopPropagation(),(this.displayType==="fab"||this.displayType==="bottom-bar")&&(this.isOpen=!1),this.render()},r.addEventListener("click",this.boundHandleCloseClick));const e=this.shadowRoot.querySelector(".nostr-chat-find-btn");e&&(this.boundHandleFind&&e.removeEventListener("click",this.boundHandleFind),this.boundHandleFind=this.handleFindClick.bind(this),e.addEventListener("click",this.boundHandleFind));const o=this.shadowRoot.querySelector(".nostr-chat-send-btn");o&&(this.boundHandleSend&&o.removeEventListener("click",this.boundHandleSend),this.boundHandleSend=this.handleSendClick.bind(this),o.addEventListener("click",this.boundHandleSend));const s=this.shadowRoot.querySelector(".nostr-chat-start-btn");s&&(this.boundHandleStartChat&&s.removeEventListener("click",this.boundHandleStartChat),this.boundHandleStartChat=this.handleStartChat.bind(this),s.addEventListener("click",this.boundHandleStartChat));const l=this.shadowRoot.querySelector(".nostr-chat-textarea");l&&(this.boundHandleTextareaChange&&l.removeEventListener("input",this.boundHandleTextareaChange),this.boundHandleTextareaChange=this.handleTextareaChange.bind(this),l.addEventListener("input",this.boundHandleTextareaChange));const p=this.shadowRoot.querySelector(".nostr-chat-npub-input");p&&(this.boundHandleNpubKeydown&&p.removeEventListener("keydown",this.boundHandleNpubKeydown),this.boundHandleNpubKeydown=i=>{i.key==="Enter"&&this.handleFindClick()},p.addEventListener("keydown",this.boundHandleNpubKeydown))}disconnectedCallback(){var i,d,b,k,u,n,g;this.dmSubscription&&this.dmSubscription.stop();const t=(i=this.shadowRoot)==null?void 0:i.querySelector(".nostr-chat-launcher");t&&this.boundHandleLauncherClick&&t.removeEventListener("click",this.boundHandleLauncherClick);const r=(d=this.shadowRoot)==null?void 0:d.querySelector(".nostr-chat-close-btn");r&&this.boundHandleCloseClick&&r.removeEventListener("click",this.boundHandleCloseClick);const e=(b=this.shadowRoot)==null?void 0:b.querySelector(".nostr-chat-find-btn");e&&this.boundHandleFind&&e.removeEventListener("click",this.boundHandleFind);const o=(k=this.shadowRoot)==null?void 0:k.querySelector(".nostr-chat-send-btn");o&&this.boundHandleSend&&o.removeEventListener("click",this.boundHandleSend);const s=(u=this.shadowRoot)==null?void 0:u.querySelector(".nostr-chat-start-btn");s&&this.boundHandleStartChat&&s.removeEventListener("click",this.boundHandleStartChat);const l=(n=this.shadowRoot)==null?void 0:n.querySelector(".nostr-chat-textarea");l&&this.boundHandleTextareaChange&&l.removeEventListener("input",this.boundHandleTextareaChange);const p=(g=this.shadowRoot)==null?void 0:g.querySelector(".nostr-chat-npub-input");p&&this.boundHandleNpubKeydown&&p.removeEventListener("keydown",this.boundHandleNpubKeydown),this.resubscribeTimer&&(clearTimeout(this.resubscribeTimer),this.resubscribeTimer=null)}setKeySupplier(t){this.keySupplier=t}escapeHtml(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}render(){const t={theme:this.theme,recipientNpub:this.recipientNpub,recipientName:this.recipientName,recipientPicture:this.recipientPicture,message:this.message,messages:this.messages,isLoading:this.isLoading,isFinding:this.isFinding,isError:this.isError,errorMessage:this.errorMessage,currentUserName:this.currentUserName,currentUserPicture:this.currentUserPicture,showWelcome:this.showWelcome,welcomeText:this.welcomeText,startChatText:this.startChatText,onlineText:this.onlineText,helpText:this.helpText,maxMessageLength:this.MESSAGE_MAX_LENGTH},r=z(this.theme),{onlineText:e,helpText:o,...s}=t,l=O(s);let p=r;this.displayType==="embed"?p+=l:this.displayType==="full"?p+=`
|
|
499
|
+
<div class="nostr-chat-float-panel open">${l}</div>
|
|
500
|
+
`:this.displayType==="fab"?p+=`
|
|
501
|
+
${this.isOpen?"":`
|
|
502
|
+
<div class="nostr-chat-launcher fab" role="button" aria-label="Open live chat">
|
|
503
|
+
<div class="bubble">
|
|
504
|
+
<div class="title">${this.escapeHtml(this.onlineText)}</div>
|
|
505
|
+
<div class="subtitle">${this.escapeHtml(this.helpText)}</div>
|
|
506
|
+
</div>
|
|
507
|
+
<button class="fab-btn" aria-label="Open chat">💬</button>
|
|
508
|
+
</div>
|
|
509
|
+
`}
|
|
510
|
+
<div class="nostr-chat-float-panel ${this.isOpen?"open":""}">
|
|
511
|
+
${l}
|
|
512
|
+
</div>
|
|
513
|
+
`:this.displayType==="bottom-bar"&&(p+=`
|
|
514
|
+
${this.isOpen?"":`
|
|
515
|
+
<div class="nostr-chat-launcher bottom-bar" role="button" aria-label="Open live chat">
|
|
516
|
+
<button class="bar-btn">Live chat</button>
|
|
517
|
+
</div>
|
|
518
|
+
`}
|
|
519
|
+
<div class="nostr-chat-float-panel ${this.isOpen?"open":""}">
|
|
520
|
+
${l}
|
|
521
|
+
</div>
|
|
522
|
+
`),this.shadowRoot.innerHTML=p,this.attachEventListeners(),setTimeout(()=>{var d;const i=(d=this.shadowRoot)==null?void 0:d.querySelector(".nostr-chat-history");i&&(i.scrollTop=i.scrollHeight)},0)}};a(x,"DEFAULT_WELCOME_TEXT","Welcome! How can we help you today?"),a(x,"DEFAULT_START_CHAT_TEXT","Start chat"),a(x,"DEFAULT_ONLINE_TEXT","We're Online!"),a(x,"DEFAULT_HELP_TEXT","How may I help you today?");let F=x;customElements.define("nostr-live-chat",F);
|
|
523
|
+
//# sourceMappingURL=nostr-live-chat.es.js.map
|