Skip to content

Commit 8bdfb78

Browse files
committed
v3.66.398
1 parent d624911 commit 8bdfb78

16 files changed

Lines changed: 138 additions & 99 deletions

css/styles-chat.css

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,11 +1135,12 @@ body.chat-bubbles .read-more-btn {
11351135

11361136
.message-scroll-flash {
11371137
animation: messageScrollFlash 1.6s ease-out;
1138+
border-radius: var(--radius-sm);
11381139
}
11391140

11401141
@keyframes messageScrollFlash {
1141-
0% { background-color: rgb(from var(--primary) r g b / 0.25); }
1142-
100% { background-color: transparent; }
1142+
0% { box-shadow: inset 0 0 0 9999px rgb(from var(--primary) r g b / 0.3); }
1143+
100% { box-shadow: inset 0 0 0 9999px transparent; }
11431144
}
11441145

11451146
.nm-mention {
@@ -1196,6 +1197,24 @@ body.chat-bubbles .read-more-btn {
11961197
font-style: italic;
11971198
}
11981199

1200+
.spam-false-positive-btn {
1201+
margin-left: 6px;
1202+
padding: 2px 10px;
1203+
border: 1px solid var(--primary);
1204+
border-radius: 12px;
1205+
background: transparent;
1206+
color: var(--primary);
1207+
cursor: pointer;
1208+
font-size: inherit;
1209+
font-family: inherit;
1210+
transition: background 0.15s, color 0.15s;
1211+
}
1212+
1213+
.spam-false-positive-btn:hover {
1214+
background: var(--primary);
1215+
color: var(--bg);
1216+
}
1217+
11991218
.system-message.me-message {
12001219
font-style: italic;
12011220
}

css/styles-features.css

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@
682682
text-shadow: none !important;
683683
}
684684

685-
.message.cosmetic-aura-gold {
685+
body:not(.chat-bubbles) .message.cosmetic-aura-gold {
686686
box-shadow: inset 0 0 0 1px rgba(255, 215, 0, 0.35), 0 0 18px rgba(255, 215, 0, 0.18);
687687
border-left: 3px solid #ffd700;
688688
background: linear-gradient(135deg, rgba(255, 215, 0, 0.05), rgba(255, 215, 0, 0.02));
@@ -2903,7 +2903,11 @@ body.chat-bubbles .message.supporter-style .message-content {
29032903
}
29042904

29052905
body.chat-bubbles .message.cosmetic-aura-gold .message-content {
2906-
background: rgba(255, 215, 0, 0.10) !important;
2906+
box-shadow: inset 0 0 0 1px rgba(255, 215, 0, 0.55), 0 0 12px rgba(255, 215, 0, 0.18);
2907+
}
2908+
2909+
body.chat-bubbles .nym-bracket {
2910+
display: none;
29072911
}
29082912

29092913
body.chat-bubbles .message.self.style-fire .message-content,

css/styles-shell.css

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -763,20 +763,18 @@ body.sidebar-reorder-mode .nav-title {
763763
}
764764

765765
.channel-header-controls {
766-
display: flex;
767-
flex-direction: column;
768-
gap: 4px;
769-
}
770-
771-
.channel-nav-buttons {
772-
display: flex;
773-
gap: 2px;
766+
display: grid;
767+
grid-template-columns: auto auto;
768+
grid-auto-rows: auto;
769+
row-gap: 4px;
770+
column-gap: 2px;
771+
justify-content: start;
772+
align-items: center;
774773
}
775774

775+
.channel-nav-buttons,
776776
.channel-action-buttons {
777-
display: flex;
778-
gap: 2px;
779-
align-items: center;
777+
display: contents;
780778
}
781779

782780
.channel-nav-btn {

css/styles-themes-responsive.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -862,12 +862,16 @@ body.light-mode .style-preview-satoshi::after {
862862
-webkit-text-fill-color: transparent;
863863
}
864864

865-
body.light-mode .message.cosmetic-aura-gold {
865+
body.light-mode:not(.chat-bubbles) .message.cosmetic-aura-gold {
866866
box-shadow: inset 0 0 0 1px rgba(180, 140, 0, 0.3), 0 0 12px rgba(180, 140, 0, 0.12);
867867
border-left: 3px solid #b8960a;
868868
background: linear-gradient(135deg, rgba(180, 140, 0, 0.06), rgba(180, 140, 0, 0.02));
869869
}
870870

871+
body.light-mode.chat-bubbles .message.cosmetic-aura-gold .message-content {
872+
box-shadow: inset 0 0 0 1px rgba(180, 140, 0, 0.5), 0 0 10px rgba(180, 140, 0, 0.15);
873+
}
874+
871875
body.light-mode .message.supporter-style {
872876
background: linear-gradient(135deg, rgba(180, 140, 0, 0.06), rgba(180, 140, 0, 0.02));
873877
border-left: 3px solid #b8960a;

functions/api/bot.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3659,7 +3659,7 @@ async function handleShopAction(context, body, botPrivkey, botPubkey) {
36593659
}
36603660

36613661
var BOT_NYM = "Nymbot";
3662-
var NYMCHAT_VERSION = "3.66.397";
3662+
var NYMCHAT_VERSION = "3.66.398";
36633663
var NYMCHAT_IOS_APP = "https://testflight.apple.com/join/k8FS8Mm3";
36643664
var NYMCHAT_ANDROID_APP = "https://play.google.com/store/apps/details?id=com.nym.bar";
36653665
var COMMAND_PREFIX = "?";
@@ -4296,7 +4296,7 @@ var NYMBOT_SYSTEM_PROMPT = [
42964296
"Games & Fun: ?trivia [category] — AI-generated trivia (general, history, science, crypto, nostr), ?joke — AI-generated joke, ?riddle — AI-generated riddle, ?wordplay [mode] — AI word game (wordle, anagram, scramble), ?flip — Coin flip, ?8ball — Magic 8-ball, ?pick <options> — Random pick.",
42974297
"Utility: ?math <expr> — Calculate, ?units <value> <from> to <to> — Convert units, ?time — UTC time, ?btc — Current Bitcoin price.",
42984298
"Channel Activity: ?who — Active nyms in channel, ?summarize — AI summary of channel discussion, ?top — Top channels by activity, ?last [N] — Recent messages, ?seen <nym> — Where was someone last seen.",
4299-
"Info: ?help — List all bot commands, ?about — About Nymchat (version, platform links), ?nostr — Nostr protocol tips, ?changelog [version] — Live Nymchat release notes pulled from GitHub (default shows the latest release; pass a tag like ?changelog v3.66.397 for a specific version).",
4299+
"Info: ?help — List all bot commands, ?about — About Nymchat (version, platform links), ?nostr — Nostr protocol tips, ?changelog [version] — Live Nymchat release notes pulled from GitHub (default shows the latest release; pass a tag like ?changelog v3.66.398 for a specific version).",
43004300
"Users can also type @Nymbot <question> to ask me directly.",
43014301
"Users can quote-reply any message and mention @Nymbot to ask about it, or reply to my responses to continue the conversation with context.",
43024302
"",
@@ -5129,7 +5129,7 @@ function findRelease(releases, query) {
51295129
var t = (releases[i].tag || "").toLowerCase().replace(/^v/, "");
51305130
if (t === normalized) return releases[i];
51315131
}
5132-
// Prefix match (e.g. "3.61" matches "3.66.397")
5132+
// Prefix match (e.g. "3.61" matches "3.66.398")
51335133
for (var j = 0; j < releases.length; j++) {
51345134
var tt = (releases[j].tag || "").toLowerCase().replace(/^v/, "");
51355135
if (tt.indexOf(normalized) === 0) return releases[j];
@@ -5184,7 +5184,7 @@ function needsChangelogContext(question) {
51845184
if (/\b(changelog|release notes?|what'?s new|whats new|patch notes?|update notes?)\b/.test(q)) return true;
51855185
if (/\b(latest|newest|recent|new|previous|last)\b.{0,30}\b(release|version|update)\b/.test(q)) return true;
51865186
if (/\b(release|version|update)\b.{0,30}\b(history|notes?|log|info)\b/.test(q)) return true;
5187-
// Specific version reference like "3.66.397", "v3.61", "version 3.60.300"
5187+
// Specific version reference like "3.66.398", "v3.61", "version 3.60.300"
51885188
if (/\bv?\d+\.\d+(?:\.\d+)?\b/.test(q) && /\b(nym|nymchat|app|version|release|update)\b/.test(q)) return true;
51895189
return false;
51905190
}

functions/api/relay-pool.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,18 +863,20 @@ export async function onRequest(context) {
863863
return;
864864
}
865865
info.eventCount++;
866+
const relayTail = ',"' + relayUrl + '"]';
866867
if (childToParent.size > 0) {
867868
const subEnd = raw.indexOf('"', 10);
868869
if (subEnd !== -1) {
869870
const childSubId = raw.substring(10, subEnd);
870871
const parent = childToParent.get(childSubId);
871872
if (parent && parent !== childSubId) {
872-
sendToClient('["EVENT","' + parent + raw.substring(subEnd));
873+
const body = raw.substring(subEnd, raw.length - 1);
874+
sendToClient('["EVENT","' + parent + body + relayTail);
873875
return;
874876
}
875877
}
876878
}
877-
sendToClient(raw);
879+
sendToClient(raw.slice(0, -1) + relayTail);
878880

879881
// OK: ["OK","eventId",bool,"msg"]
880882
} else if (raw.charCodeAt(2) === 79 && raw.startsWith('["OK"')) {

index.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,9 +1198,9 @@ <h2>Report User/Content</h2>
11981198
<div class="layout-grid" id="layoutGrid">
11991199
<div class="layout-option selected" data-layout="bubbles" data-action="selectMessageLayout">
12001200
<div class="layout-preview layout-preview-bubbles">
1201-
<div class="lp-bubble lp-bubble-other"><span class="lp-bubble-nick">&lt;alice#e45f&gt;</span><span class="lp-bubble-text">hey there!</span></div>
1202-
<div class="lp-bubble lp-bubble-self"><span class="lp-bubble-nick">&lt;you#6si9&gt;</span><span class="lp-bubble-text">hello!</span></div>
1203-
<div class="lp-bubble lp-bubble-other"><span class="lp-bubble-nick">&lt;bob#2t5g&gt;</span><span class="lp-bubble-text">what's up?</span></div>
1201+
<div class="lp-bubble lp-bubble-other"><span class="lp-bubble-nick">alice#e45f</span><span class="lp-bubble-text">hey there!</span></div>
1202+
<div class="lp-bubble lp-bubble-self"><span class="lp-bubble-nick">you#6si9</span><span class="lp-bubble-text">hello!</span></div>
1203+
<div class="lp-bubble lp-bubble-other"><span class="lp-bubble-nick">bob#2t5g</span><span class="lp-bubble-text">what's up?</span></div>
12041204
</div>
12051205
<span class="layout-label">Bubbles (Default)</span>
12061206
</div>
@@ -1767,6 +1767,7 @@ <h2>Report User/Content</h2>
17671767
<option value="Bug report">Bug report</option>
17681768
<option value="Feature request">Feature request</option>
17691769
<option value="Question">Question</option>
1770+
<option value="Spam false positive">Spam false positive</option>
17701771
</select>
17711772
</div>
17721773
<div class="form-group nm-h-30">

js/app.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3526,9 +3526,9 @@ function initWallpaperUI() {
35263526
}
35273527
}
35283528

3529-
const NYMCHAT_VERSION = 'v3.66.397';
3529+
const NYMCHAT_VERSION = 'v3.66.398';
35303530

3531-
function showAbout() {
3531+
function showAbout(prefill) {
35323532
const modal = document.getElementById('aboutModal');
35333533
if (!modal) return;
35343534

@@ -3547,7 +3547,29 @@ function showAbout() {
35473547
status.style.color = '';
35483548
}
35493549

3550+
const typeEl = document.getElementById('aboutContactType');
3551+
const msgEl = document.getElementById('aboutContactMessage');
3552+
if (prefill && typeof prefill === 'object') {
3553+
if (typeEl && prefill.topic) {
3554+
const opt = Array.from(typeEl.options).find(o => o.value === prefill.topic);
3555+
if (opt) typeEl.value = prefill.topic;
3556+
}
3557+
if (msgEl && typeof prefill.message === 'string') {
3558+
msgEl.value = prefill.message;
3559+
}
3560+
}
3561+
35503562
modal.classList.add('active');
3563+
if (prefill && msgEl) {
3564+
try { msgEl.focus(); } catch (_) { }
3565+
}
3566+
}
3567+
3568+
function reportSpamFalsePositive(content) {
3569+
const body = content
3570+
? `The following message was incorrectly flagged by the spam filter:\n\n\`\`\`\n${content}\n\`\`\``
3571+
: 'A message was incorrectly flagged by the spam filter.';
3572+
showAbout({ topic: 'Spam false positive', message: body });
35513573
}
35523574

35533575
async function sendAboutContact() {

js/modules/inline-bindings.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ window.nymHapticTap = function (ms) {
111111
'showSettings': function () { window.showSettings(); },
112112
'showAbout': function () { window.showAbout(); },
113113
'sendAboutContact': function () { window.sendAboutContact(); },
114+
'reportSpamFalsePositive': function (_e, t) { window.reportSpamFalsePositive(t.dataset.spamContent || ''); },
114115
'signOut': function () { window.signOut(); },
115116
'openNostrLogin': function () { window.openNostrLogin(); },
116117
'editNick': function () { window.editNick(); },

js/modules/messages.js

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -561,15 +561,18 @@ Object.assign(NYM.prototype, {
561561
// knows why their message disappeared (it was still sent to relays).
562562
const keywordHit = this.hasBlockedKeyword(message.content, message.author);
563563
const spamHit = this.isSpamMessage(message.content);
564-
if (this.blockedUsers.has(message.pubkey) || keywordHit || spamHit) {
565-
if (message.isOwn) {
566-
const reason = keywordHit
567-
? 'matched one of your blocked keywords'
568-
: spamHit
569-
? 'was flagged by the spam filter'
570-
: 'matched a block rule';
564+
if (message.isOwn) {
565+
if (keywordHit || this.blockedUsers.has(message.pubkey)) {
566+
const reason = keywordHit ? 'matched one of your blocked keywords' : 'matched a block rule';
571567
this.displaySystemMessage(`Your message ${reason} and was hidden locally. It was still sent.`);
568+
return;
569+
}
570+
if (spamHit) {
571+
const escContent = this.escapeHtml(message.content);
572+
const html = `Your message was flagged by the spam filter. <button class="spam-false-positive-btn" data-action="reportSpamFalsePositive" data-spam-content="${escContent}">Report false positive</button>`;
573+
this.displaySystemMessage(html, 'system', { html: true });
572574
}
575+
} else if (this.blockedUsers.has(message.pubkey) || keywordHit || spamHit) {
573576
return;
574577
}
575578

@@ -682,7 +685,7 @@ Object.assign(NYM.prototype, {
682685
const baseNym = this.parseNymFromDisplay(message.author);
683686
const avatarSrc = this.getAvatarUrl(message.pubkey);
684687
const safePk2 = this._safePubkey(message.pubkey);
685-
const displayAuthorBase = `<img src="${this.escapeHtml(avatarSrc)}" class="avatar-message" data-avatar-pubkey="${safePk2}" alt="" loading="lazy">&lt;${this.escapeHtml(baseNym)}<span class="nym-suffix">#${this.getPubkeySuffix(message.pubkey)}</span>${flairHtml}`;
688+
const displayAuthorBase = `<img src="${this.escapeHtml(avatarSrc)}" class="avatar-message" data-avatar-pubkey="${safePk2}" alt="" loading="lazy"><span class="nym-bracket">&lt;</span>${this.escapeHtml(baseNym)}<span class="nym-suffix">#${this.getPubkeySuffix(message.pubkey)}</span>${flairHtml}`;
686689
let displayAuthor = displayAuthorBase; // string used in HTML
687690
let authorExtraClass = '';
688691
if (Array.isArray(userShopItems?.cosmetics) && userShopItems.cosmetics.includes('cosmetic-redacted')) {
@@ -814,7 +817,7 @@ Object.assign(NYM.prototype, {
814817

815818
messageEl.innerHTML = `
816819
${time ? `<span class="message-time ${this.settings.timeFormat === '12hr' ? 'time-12hr' : ''}" data-full-time="${fullTimestamp}" title="${fullTimestamp}">${time}</span>` : ''}
817-
<span class="message-author ${authorClass} ${userColorClass} ${authorExtraClass}"><span class="bubble-time" data-full-time="${fullTimestamp}" title="${fullTimestamp}">${bubbleTime}</span><span class="author-clickable">${displayAuthor}${verifiedBadge}${supporterBadge}${friendBadge}</span>&gt;</span>
820+
<span class="message-author ${authorClass} ${userColorClass} ${authorExtraClass}"><span class="bubble-time" data-full-time="${fullTimestamp}" title="${fullTimestamp}">${bubbleTime}</span><span class="author-clickable">${displayAuthor}${verifiedBadge}${supporterBadge}${friendBadge}</span><span class="nym-bracket">&gt;</span></span>
818821
<span class="message-content ${userColorClass}${emojiOnlyClass}">${messageContentHtml}<span class="bubble-time-inner" data-full-time="${fullTimestamp}" title="${fullTimestamp}">${editedBubble}${bubbleTime}</span>${hoverButtons}</span>
819822
${editedIRC}
820823
${deliveryCheckmark}
@@ -2673,7 +2676,7 @@ Object.assign(NYM.prototype, {
26732676
if (score > bestScore) { bestScore = score; best = el; }
26742677
}
26752678
if (!best) {
2676-
this.displaySystemMessage('Original message is not in view');
2679+
this.displaySystemMessage('Original message is not available');
26772680
return;
26782681
}
26792682
const scroller = this._getMessagesScroller ? this._getMessagesScroller() : document.getElementById('messagesScroller');
@@ -2810,14 +2813,13 @@ Object.assign(NYM.prototype, {
28102813

28112814
return messages.filter(msg => {
28122815
if (this.deletedEventIds.has(msg.id)) return false;
2813-
// Spam gate
28142816
if (!msg.isOwn && !this.isFriend(msg.pubkey) &&
28152817
!this.nymchatPubkeys.has(msg.pubkey) && this._isPubkeyGated(msg.pubkey)) {
28162818
return false;
28172819
}
2818-
if (this.blockedUsers.has(msg.pubkey) || msg.blocked) return false;
2819-
if (this.hasBlockedKeyword(msg.content, msg.author)) return false;
2820-
if (this.isSpamMessage(msg.content)) return false;
2820+
if (!msg.isOwn && (this.blockedUsers.has(msg.pubkey) || msg.blocked)) return false;
2821+
if (!msg.isOwn && this.hasBlockedKeyword(msg.content, msg.author)) return false;
2822+
if (!msg.isOwn && this.isSpamMessage(msg.content)) return false;
28212823
return true;
28222824
}).sort((a, b) => this._compareMessages(a, b));
28232825
},

0 commit comments

Comments
 (0)