Skip to content

Commit c60454e

Browse files
committed
v3.67.415
1 parent bea09b9 commit c60454e

13 files changed

Lines changed: 909 additions & 6 deletions

File tree

css/styles-components.css

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,17 @@
180180
margin-top: 5px;
181181
}
182182

183+
.form-warning {
184+
font-size: 11px;
185+
color: var(--danger);
186+
margin-top: 6px;
187+
padding: 6px 8px;
188+
border: 1px solid rgb(from var(--danger) r g b / 0.4);
189+
border-radius: 6px;
190+
background: rgb(from var(--danger) r g b / 0.08);
191+
line-height: 1.4;
192+
}
193+
183194
.form-range {
184195
-webkit-appearance: none;
185196
appearance: none;
@@ -1202,6 +1213,28 @@
12021213
stroke: currentColor;
12031214
}
12041215

1216+
.call-channel-btn {
1217+
background: transparent;
1218+
border: none;
1219+
cursor: pointer;
1220+
opacity: 0.4;
1221+
transition: opacity 0.2s, transform 0.2s;
1222+
padding: 5px;
1223+
display: flex;
1224+
align-items: center;
1225+
justify-content: center;
1226+
color: var(--primary);
1227+
}
1228+
1229+
.call-channel-btn:hover {
1230+
opacity: 1;
1231+
transform: scale(1.1);
1232+
}
1233+
1234+
.nm-call-hidden {
1235+
display: none !important;
1236+
}
1237+
12051238
.share-modal {
12061239
max-width: 500px;
12071240
}

css/styles-features.css

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3829,3 +3829,197 @@ body.chat-bubbles .message.supporter-style .read-more-btn {
38293829
background: var(--bg-secondary);
38303830
text-decoration: none;
38313831
}
3832+
3833+
.incoming-call-content {
3834+
text-align: center;
3835+
max-width: 320px;
3836+
padding: 28px 24px;
3837+
}
3838+
3839+
.incoming-call-avatar-wrap {
3840+
display: flex;
3841+
justify-content: center;
3842+
margin-bottom: 14px;
3843+
}
3844+
3845+
.incoming-call-avatar {
3846+
width: 88px;
3847+
height: 88px;
3848+
border-radius: 50%;
3849+
object-fit: cover;
3850+
border: 2px solid var(--primary);
3851+
animation: incomingCallPulse 1.6s ease-in-out infinite;
3852+
}
3853+
3854+
@keyframes incomingCallPulse {
3855+
0%, 100% { box-shadow: 0 0 0 0 rgb(from var(--primary) r g b / 0.4); }
3856+
50% { box-shadow: 0 0 0 12px rgb(from var(--primary) r g b / 0); }
3857+
}
3858+
3859+
.incoming-call-name {
3860+
font-size: 1.2rem;
3861+
font-weight: 600;
3862+
color: var(--text-bright);
3863+
margin-bottom: 4px;
3864+
word-break: break-word;
3865+
}
3866+
3867+
.incoming-call-sub {
3868+
font-size: 0.85rem;
3869+
color: var(--text-dim);
3870+
margin-bottom: 22px;
3871+
}
3872+
3873+
.incoming-call-actions {
3874+
display: flex;
3875+
justify-content: center;
3876+
gap: 36px;
3877+
}
3878+
3879+
.incoming-call-btn {
3880+
width: 58px;
3881+
height: 58px;
3882+
border-radius: 50%;
3883+
border: none;
3884+
cursor: pointer;
3885+
color: #fff;
3886+
display: flex;
3887+
align-items: center;
3888+
justify-content: center;
3889+
transition: transform 0.15s, filter 0.15s;
3890+
}
3891+
3892+
.incoming-call-btn:hover { transform: scale(1.08); filter: brightness(1.1); }
3893+
.incoming-call-btn.accept { background: #1db954; }
3894+
.incoming-call-btn.decline { background: var(--danger); }
3895+
.incoming-call-btn.decline svg { transform: rotate(135deg); }
3896+
3897+
.call-overlay {
3898+
display: none;
3899+
position: fixed;
3900+
inset: 0;
3901+
z-index: 10002;
3902+
background: rgba(5, 5, 10, 0.96);
3903+
backdrop-filter: blur(24px);
3904+
-webkit-backdrop-filter: blur(24px);
3905+
flex-direction: column;
3906+
}
3907+
3908+
.call-overlay.active { display: flex; }
3909+
3910+
.call-overlay-top {
3911+
text-align: center;
3912+
padding: 18px 16px 6px;
3913+
}
3914+
3915+
.call-title {
3916+
font-size: 1.05rem;
3917+
font-weight: 600;
3918+
color: var(--text-bright);
3919+
word-break: break-word;
3920+
}
3921+
3922+
.call-status {
3923+
font-size: 0.85rem;
3924+
color: var(--text-dim);
3925+
margin-top: 2px;
3926+
}
3927+
3928+
.call-grid {
3929+
flex: 1;
3930+
display: grid;
3931+
gap: 10px;
3932+
padding: 14px;
3933+
overflow: auto;
3934+
grid-template-columns: 1fr;
3935+
align-content: center;
3936+
}
3937+
3938+
.call-grid[data-count="2"] { grid-template-columns: 1fr; }
3939+
.call-grid[data-count="3"],
3940+
.call-grid[data-count="4"] { grid-template-columns: 1fr 1fr; }
3941+
.call-grid[data-count="5"],
3942+
.call-grid[data-count="6"],
3943+
.call-grid[data-count="7"],
3944+
.call-grid[data-count="8"],
3945+
.call-grid[data-count="9"] { grid-template-columns: 1fr 1fr 1fr; }
3946+
3947+
@media (min-width: 700px) {
3948+
.call-grid { grid-template-columns: 1fr 1fr; }
3949+
.call-grid[data-count="1"],
3950+
.call-grid[data-count="2"] { grid-template-columns: 1fr 1fr; max-width: 1100px; margin: 0 auto; }
3951+
}
3952+
3953+
.call-tile {
3954+
position: relative;
3955+
background: var(--bg-tertiary);
3956+
border: 1px solid var(--border);
3957+
border-radius: 14px;
3958+
overflow: hidden;
3959+
min-height: 160px;
3960+
display: flex;
3961+
align-items: center;
3962+
justify-content: center;
3963+
}
3964+
3965+
.call-tile video {
3966+
width: 100%;
3967+
height: 100%;
3968+
object-fit: cover;
3969+
background: #000;
3970+
}
3971+
3972+
.call-tile.no-video video { display: none; }
3973+
3974+
.call-tile-avatar {
3975+
display: none;
3976+
width: 84px;
3977+
height: 84px;
3978+
border-radius: 50%;
3979+
object-fit: cover;
3980+
border: 2px solid var(--border);
3981+
}
3982+
3983+
.call-tile.no-video .call-tile-avatar { display: block; }
3984+
3985+
.call-tile-name {
3986+
position: absolute;
3987+
left: 8px;
3988+
bottom: 8px;
3989+
padding: 2px 8px;
3990+
border-radius: 8px;
3991+
background: rgba(0, 0, 0, 0.55);
3992+
color: #fff;
3993+
font-size: 0.78rem;
3994+
max-width: calc(100% - 16px);
3995+
overflow: hidden;
3996+
text-overflow: ellipsis;
3997+
white-space: nowrap;
3998+
}
3999+
4000+
.call-controls {
4001+
display: flex;
4002+
justify-content: center;
4003+
gap: 20px;
4004+
padding: 16px;
4005+
padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
4006+
}
4007+
4008+
.call-control-btn {
4009+
width: 54px;
4010+
height: 54px;
4011+
border-radius: 50%;
4012+
border: 1px solid var(--border);
4013+
background: var(--bg-tertiary);
4014+
color: var(--text-bright);
4015+
cursor: pointer;
4016+
display: flex;
4017+
align-items: center;
4018+
justify-content: center;
4019+
transition: transform 0.15s, background 0.15s, filter 0.15s;
4020+
}
4021+
4022+
.call-control-btn:hover { transform: scale(1.08); }
4023+
.call-control-btn.active { background: var(--danger); color: #fff; border-color: var(--danger); }
4024+
.call-control-btn.hangup { background: var(--danger); color: #fff; border-color: var(--danger); }
4025+
.call-control-btn.hangup svg { transform: rotate(135deg); }

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.415";
3662+
var NYMCHAT_VERSION = "3.67.415";
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.415 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.67.415 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.415")
5132+
// Prefix match (e.g. "3.61" matches "3.67.415")
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.415", "v3.61", "version 3.60.300"
5187+
// Specific version reference like "3.67.415", "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
}

index.html

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,19 @@ <h2>Report User/Content</h2>
534534
d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z" />
535535
</svg>
536536
</button>
537+
<button class="call-channel-btn nm-call-hidden" id="audioCallBtn" data-action="initiateAudioCall"
538+
title="Start audio call">
539+
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
540+
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
541+
</svg>
542+
</button>
543+
<button class="call-channel-btn nm-call-hidden" id="videoCallBtn" data-action="initiateVideoCall"
544+
title="Start video call">
545+
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
546+
<polygon points="23 7 16 12 23 17 23 7"></polygon>
547+
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect>
548+
</svg>
549+
</button>
537550
</div>
538551
</div>
539552
<div class="channel-title-wrap">
@@ -757,6 +770,58 @@ <h2>Report User/Content</h2>
757770
</div>
758771
</div>
759772

773+
<!-- Incoming Call Modal -->
774+
<div class="modal" id="incomingCallModal">
775+
<div class="modal-content incoming-call-content">
776+
<div class="incoming-call-avatar-wrap">
777+
<img src="" id="incomingCallAvatar" class="incoming-call-avatar" alt="">
778+
</div>
779+
<div class="incoming-call-name" id="incomingCallName"></div>
780+
<div class="incoming-call-sub" id="incomingCallSub">Incoming call</div>
781+
<div class="incoming-call-actions">
782+
<button class="incoming-call-btn decline" data-action="rejectIncomingCall" title="Decline">
783+
<svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
784+
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
785+
</svg>
786+
</button>
787+
<button class="incoming-call-btn accept" data-action="acceptIncomingCall" title="Accept">
788+
<svg viewBox="0 0 24 24" width="26" height="26" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
789+
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
790+
</svg>
791+
</button>
792+
</div>
793+
</div>
794+
</div>
795+
796+
<!-- Active Call Overlay -->
797+
<div class="call-overlay" id="callOverlay">
798+
<div class="call-overlay-top">
799+
<div class="call-title" id="callTitle"></div>
800+
<div class="call-status" id="callStatus">Calling…</div>
801+
</div>
802+
<div class="call-grid" id="callGrid"></div>
803+
<div class="call-controls">
804+
<button class="call-control-btn" id="callMuteBtn" data-action="toggleCallMute" title="Mute microphone">
805+
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
806+
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
807+
<path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
808+
<line x1="12" y1="19" x2="12" y2="23"></line>
809+
</svg>
810+
</button>
811+
<button class="call-control-btn nm-call-hidden" id="callVideoBtn" data-action="toggleCallVideo" title="Turn off camera">
812+
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
813+
<polygon points="23 7 16 12 23 17 23 7"></polygon>
814+
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect>
815+
</svg>
816+
</button>
817+
<button class="call-control-btn hangup" id="callHangupBtn" data-action="hangupCall" title="End call">
818+
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
819+
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path>
820+
</svg>
821+
</button>
822+
</div>
823+
</div>
824+
760825
<!-- Developer Nsec Verification Modal -->
761826
<div class="modal" id="devNsecModal">
762827
<div class="modal-content">
@@ -1291,6 +1356,17 @@ <h2>Report User/Content</h2>
12911356
<div class="form-hint">Control who can send you PMs and group chat invites. "Friends only" filters messages from non-friends.</div>
12921357
</div>
12931358

1359+
<div class="form-group">
1360+
<label class="form-label">Accept Audio &amp; Video Calls</label>
1361+
<select class="form-select" id="acceptCallsSelect">
1362+
<option value="enabled">Enabled</option>
1363+
<option value="friends">Friends only</option>
1364+
<option value="disabled">Disabled</option>
1365+
</select>
1366+
<div class="form-hint">Control who can ring you with an audio or video call. "Friends only" silently ignores calls from non-friends.</div>
1367+
<div class="form-warning">⚠ Audio/video calls and P2P file sharing connect peers directly over WebRTC, which can reveal your true IP address to the other party. Use a VPN or Tor to help conceal it.</div>
1368+
</div>
1369+
12941370
<div class="form-group">
12951371
<label class="form-label">Disappearing PM (forward secrecy)</label>
12961372
<select class="form-select" id="dmForwardSecrecySelect">
@@ -1850,6 +1926,7 @@ <h2>Report User/Content</h2>
18501926
<script defer src="js/modules/shop.js"></script>
18511927
<script defer src="js/modules/zaps.js"></script>
18521928
<script defer src="js/modules/p2p.js"></script>
1929+
<script defer src="js/modules/calls.js"></script>
18531930
<script defer src="js/modules/translate.js"></script>
18541931
<script defer src="js/modules/sidebar-sections.js"></script>
18551932
<script defer src="js/modules/polls.js"></script>

0 commit comments

Comments
 (0)