vibedate 0.8.1 → 0.8.2
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/dist/cli.js +382 -26
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -626,6 +626,187 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
626
626
|
}
|
|
627
627
|
.chat-panel .cp-send:hover{ filter: brightness(1.06); }
|
|
628
628
|
.chat-panel .cp-send:active{ transform: scale(.95); }
|
|
629
|
+
|
|
630
|
+
/* ---- you identity chip (header) ---- */
|
|
631
|
+
.you-chip{
|
|
632
|
+
display:none; align-items:center; gap:10px;
|
|
633
|
+
padding: 6px 12px 6px 7px; border-radius: 999px;
|
|
634
|
+
background: rgba(0,0,0,.28); border: 1px solid var(--border-2);
|
|
635
|
+
max-width: min(420px, 52vw); min-width: 0;
|
|
636
|
+
}
|
|
637
|
+
.you-chip.is-on{ display:inline-flex; }
|
|
638
|
+
.you-chip .yc-avatar{
|
|
639
|
+
width:30px; height:30px; border-radius:50%; overflow:hidden; flex-shrink:0;
|
|
640
|
+
border: 1px solid var(--border-2); background: var(--bg-1);
|
|
641
|
+
}
|
|
642
|
+
.you-chip .yc-avatar svg{ width:100%; height:100%; display:block; }
|
|
643
|
+
.you-chip .yc-meta{ min-width:0; display:flex; flex-direction:column; gap:1px; }
|
|
644
|
+
.you-chip .yc-handle{
|
|
645
|
+
font-size:.78rem; font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
|
|
646
|
+
}
|
|
647
|
+
.you-chip .yc-sub{
|
|
648
|
+
font-size:.68rem; color: var(--muted-2); display:flex; align-items:center; gap:6px; flex-wrap:wrap;
|
|
649
|
+
}
|
|
650
|
+
.topbar-right{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; justify-content:flex-end; }
|
|
651
|
+
|
|
652
|
+
/* ---- identity / status marks ---- */
|
|
653
|
+
.mark{
|
|
654
|
+
display:inline-flex; align-items:center; gap:3px;
|
|
655
|
+
font-size:.66rem; font-weight:700; letter-spacing:.01em;
|
|
656
|
+
padding: 2px 7px; border-radius:999px; line-height:1.3; white-space:nowrap;
|
|
657
|
+
}
|
|
658
|
+
.mark-verified{
|
|
659
|
+
color: #bff2df; background: rgba(127,227,192,.12); border: 1px solid rgba(127,227,192,.32);
|
|
660
|
+
}
|
|
661
|
+
.mark-identity{
|
|
662
|
+
color: #e8d9ff; background: rgba(203,168,255,.12); border: 1px solid rgba(203,168,255,.32);
|
|
663
|
+
}
|
|
664
|
+
.mark-demo{
|
|
665
|
+
color: var(--muted-2); background: rgba(248,239,232,.05); border: 1px solid var(--border);
|
|
666
|
+
text-transform: uppercase; letter-spacing: .06em;
|
|
667
|
+
}
|
|
668
|
+
.mark-live{
|
|
669
|
+
color: #ffd0c8; background: rgba(255,122,104,.12); border: 1px solid rgba(255,122,104,.35);
|
|
670
|
+
}
|
|
671
|
+
.lg-pill{
|
|
672
|
+
display:inline-flex; align-items:center; gap:5px;
|
|
673
|
+
font-size:.7rem; font-weight:700; padding: 3px 9px; border-radius:999px;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/* ---- people column (live + demo) ---- */
|
|
677
|
+
.people-col{ display:flex; flex-direction:column; gap: 22px; min-width: 0; }
|
|
678
|
+
.section-head{
|
|
679
|
+
display:flex; align-items:baseline; justify-content:space-between; gap:10px;
|
|
680
|
+
margin: 0 0 12px;
|
|
681
|
+
}
|
|
682
|
+
.section-head h2{
|
|
683
|
+
font-size: 1.02rem; font-weight: 700; margin:0;
|
|
684
|
+
display:flex; align-items:center; gap:8px;
|
|
685
|
+
}
|
|
686
|
+
.section-head .count{
|
|
687
|
+
font-size:.72rem; font-weight:700; color: var(--muted-2);
|
|
688
|
+
background: rgba(0,0,0,.22); border: 1px solid var(--border);
|
|
689
|
+
padding: 3px 8px; border-radius:999px;
|
|
690
|
+
}
|
|
691
|
+
.section-sub{
|
|
692
|
+
font-size:.78rem; color: var(--muted-2); margin: -6px 0 12px; line-height:1.45;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/* Live now roster cards */
|
|
696
|
+
.live-roster{ display:flex; flex-direction:column; gap:10px; }
|
|
697
|
+
.live-card{
|
|
698
|
+
display:flex; align-items:center; gap:12px;
|
|
699
|
+
background: linear-gradient(165deg, rgba(255,122,104,.08), transparent 55%),
|
|
700
|
+
linear-gradient(180deg, var(--bg-card), var(--bg-card-2));
|
|
701
|
+
border: 1px solid rgba(255,122,104,.22);
|
|
702
|
+
border-radius: 16px; padding: 14px 14px;
|
|
703
|
+
box-shadow: var(--shadow-1);
|
|
704
|
+
transition: border-color var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out);
|
|
705
|
+
}
|
|
706
|
+
.live-card:hover{ border-color: rgba(255,122,104,.4); transform: translateY(-1px); }
|
|
707
|
+
.live-card .lc-avatar{
|
|
708
|
+
width:48px; height:48px; border-radius:50%; overflow:hidden; flex-shrink:0;
|
|
709
|
+
border:1px solid var(--border-2); background:var(--bg-1);
|
|
710
|
+
}
|
|
711
|
+
.live-card .lc-avatar svg{ width:100%; height:100%; display:block; }
|
|
712
|
+
.live-card .lc-body{ flex:1; min-width:0; }
|
|
713
|
+
.live-card .lc-handle-row{
|
|
714
|
+
display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin-bottom:4px;
|
|
715
|
+
}
|
|
716
|
+
.live-card .lc-handle{ font-weight:700; font-size:.92rem; word-break:break-all; }
|
|
717
|
+
.live-card .lc-meta{
|
|
718
|
+
display:flex; align-items:center; gap:6px; flex-wrap:wrap;
|
|
719
|
+
font-size:.72rem; color: var(--muted-2);
|
|
720
|
+
}
|
|
721
|
+
.live-card .lc-actions{ display:flex; flex-direction:column; gap:6px; flex-shrink:0; }
|
|
722
|
+
.live-card .lc-actions button{
|
|
723
|
+
border:0; border-radius:10px; padding:8px 14px; font-weight:700; font-size:.76rem;
|
|
724
|
+
min-width: 72px;
|
|
725
|
+
transition: transform var(--dur-fast) var(--ease-out), filter var(--dur-fast) ease, border-color var(--dur-fast) ease, color var(--dur-fast) ease;
|
|
726
|
+
}
|
|
727
|
+
.live-card .lc-actions button:active{ transform: scale(.96); }
|
|
728
|
+
.live-card .btn-call{
|
|
729
|
+
background: linear-gradient(180deg, var(--coral), var(--coral-dim)); color: #2a1109;
|
|
730
|
+
box-shadow: 0 8px 18px -10px rgba(255,122,104,.55);
|
|
731
|
+
}
|
|
732
|
+
.live-card .btn-call:hover{ filter: brightness(1.06); }
|
|
733
|
+
.live-card .btn-call:disabled{ opacity:.4; cursor:not-allowed; filter:none; box-shadow:none; }
|
|
734
|
+
.live-card .btn-chat{
|
|
735
|
+
background: transparent; color: var(--muted); border: 1px solid var(--border-2);
|
|
736
|
+
}
|
|
737
|
+
.live-card .btn-chat:hover{ color: var(--fg); border-color: var(--muted-2); }
|
|
738
|
+
.live-card .btn-chat.has-unread{
|
|
739
|
+
color: var(--coral); border-color: rgba(255,122,104,.45);
|
|
740
|
+
background: rgba(255,122,104,.08);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
.live-empty{
|
|
744
|
+
border: 1px dashed var(--border-2); border-radius: 16px;
|
|
745
|
+
padding: 18px 16px; text-align:center;
|
|
746
|
+
background: rgba(0,0,0,.14);
|
|
747
|
+
}
|
|
748
|
+
.live-empty strong{ display:block; font-size:.9rem; margin-bottom:4px; }
|
|
749
|
+
.live-empty p{ margin:0; font-size:.8rem; color: var(--muted-2); line-height:1.45; }
|
|
750
|
+
|
|
751
|
+
.live-now-wrap.has-live .section-head h2 .pulse-live{
|
|
752
|
+
width:8px; height:8px; border-radius:50%; background: var(--coral);
|
|
753
|
+
box-shadow: 0 0 0 3px rgba(255,122,104,.2);
|
|
754
|
+
animation: pulse-dot 2s ease-in-out infinite; display:inline-block;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/* Demo badge on match cards */
|
|
758
|
+
.mc-demo-badge{
|
|
759
|
+
position:absolute; top:14px; right:14px; z-index:2;
|
|
760
|
+
}
|
|
761
|
+
.match-card{ position:absolute; /* ensure badge anchors */ }
|
|
762
|
+
.mc-handle-row{ display:flex; align-items:center; gap:7px; flex-wrap:wrap; }
|
|
763
|
+
.demo-note{
|
|
764
|
+
font-size:.74rem; color: var(--muted-2); margin: 0 0 10px; line-height:1.4;
|
|
765
|
+
}
|
|
766
|
+
.demo-note b{ color: var(--muted); font-weight:600; }
|
|
767
|
+
|
|
768
|
+
/* Stack polish when demo secondary */
|
|
769
|
+
.stack-wrap.is-secondary{ opacity: .92; }
|
|
770
|
+
.people-col .stack-wrap{ height: 430px; }
|
|
771
|
+
|
|
772
|
+
/* Video / room / chat polish */
|
|
773
|
+
.video-modal .vtile video{
|
|
774
|
+
box-shadow: 0 24px 60px -28px rgba(0,0,0,.8), 0 0 0 1px rgba(255,122,104,.12);
|
|
775
|
+
}
|
|
776
|
+
.video-modal .vlabel{
|
|
777
|
+
background: rgba(0,0,0,.35); padding: 4px 10px; border-radius:999px;
|
|
778
|
+
border: 1px solid var(--border);
|
|
779
|
+
}
|
|
780
|
+
.room-video .rv-tile video{
|
|
781
|
+
box-shadow: 0 14px 36px -20px rgba(0,0,0,.7);
|
|
782
|
+
}
|
|
783
|
+
.room-video .rv-head{
|
|
784
|
+
background: rgba(0,0,0,.28); border: 1px solid var(--border);
|
|
785
|
+
border-radius: 12px; padding: 10px 14px;
|
|
786
|
+
}
|
|
787
|
+
.chat-panel{
|
|
788
|
+
border-color: rgba(255,122,104,.18);
|
|
789
|
+
}
|
|
790
|
+
.chat-panel .cp-head{
|
|
791
|
+
background: rgba(0,0,0,.18);
|
|
792
|
+
}
|
|
793
|
+
.live-panel, .room-panel{
|
|
794
|
+
border-color: rgba(255,122,104,.18);
|
|
795
|
+
}
|
|
796
|
+
.live-panel .lp-title .lp-live-count,
|
|
797
|
+
.room-panel .rp-title .rp-count{
|
|
798
|
+
margin-left:auto; font-size:.68rem; font-weight:700; color: var(--muted-2);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
@media (max-width: 1020px){
|
|
802
|
+
.you-chip{ max-width: 100%; }
|
|
803
|
+
}
|
|
804
|
+
@media (max-width: 480px){
|
|
805
|
+
.live-card{ flex-wrap: wrap; }
|
|
806
|
+
.live-card .lc-actions{ flex-direction: row; width: 100%; }
|
|
807
|
+
.live-card .lc-actions button{ flex:1; }
|
|
808
|
+
}
|
|
809
|
+
|
|
629
810
|
</style>
|
|
630
811
|
</head>
|
|
631
812
|
<body>
|
|
@@ -635,7 +816,16 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
635
816
|
<span class="name">vibe<span>dating</span></span>
|
|
636
817
|
<span class="tag">matched by how hard you push the model</span>
|
|
637
818
|
</div>
|
|
638
|
-
<div class="
|
|
819
|
+
<div class="topbar-right">
|
|
820
|
+
<div class="you-chip" id="youChip" aria-live="polite">
|
|
821
|
+
<div class="yc-avatar" id="youChipAvatar"></div>
|
|
822
|
+
<div class="yc-meta">
|
|
823
|
+
<div class="yc-handle" id="youChipHandle">@you</div>
|
|
824
|
+
<div class="yc-sub" id="youChipSub"></div>
|
|
825
|
+
</div>
|
|
826
|
+
</div>
|
|
827
|
+
<div class="local-badge"><span class="dot" aria-hidden="true"></span> raw usage stays local · only league shared</div>
|
|
828
|
+
</div>
|
|
639
829
|
</header>
|
|
640
830
|
|
|
641
831
|
<div class="hero">
|
|
@@ -729,12 +919,27 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
729
919
|
</div>
|
|
730
920
|
</section>
|
|
731
921
|
|
|
732
|
-
<
|
|
733
|
-
<
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
922
|
+
<div class="people-col panel" aria-label="People">
|
|
923
|
+
<section class="live-now-wrap" id="liveNowWrap" aria-label="Live now">
|
|
924
|
+
<div class="section-head">
|
|
925
|
+
<h2><span class="pulse-live" aria-hidden="true"></span> Live now</h2>
|
|
926
|
+
<span class="count" id="liveNowCount">0</span>
|
|
927
|
+
</div>
|
|
928
|
+
<p class="section-sub">Real discovered peers on the wire — usage-verified and identity marks from their hello.</p>
|
|
929
|
+
<div class="live-roster" id="liveRoster"></div>
|
|
930
|
+
</section>
|
|
931
|
+
|
|
932
|
+
<section aria-label="Demo profiles">
|
|
933
|
+
<div class="section-head">
|
|
934
|
+
<h2>Demo profiles</h2>
|
|
935
|
+
<span class="mark mark-demo" title="Seeded local pool \u2014 not real people">demo</span>
|
|
936
|
+
</div>
|
|
937
|
+
<p class="demo-note">Seeded local filler from <b>CANDIDATES</b> — not live peers. Swipe to practice matching by league.</p>
|
|
938
|
+
<div class="stack-wrap" id="demoStackWrap">
|
|
939
|
+
<div class="card-stack" id="cardStack"></div>
|
|
940
|
+
</div>
|
|
941
|
+
</section>
|
|
942
|
+
</div>
|
|
738
943
|
|
|
739
944
|
<section class="panel" aria-label="League ladder">
|
|
740
945
|
<h2 class="panel-title">League ladder</h2>
|
|
@@ -770,10 +975,10 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
770
975
|
</div>
|
|
771
976
|
</div>
|
|
772
977
|
|
|
773
|
-
<aside class="live-panel" id="livePanel" aria-label="Live peers">
|
|
774
|
-
<div class="lp-title"><span class="lp-dot" aria-hidden="true"></span> Live
|
|
978
|
+
<aside class="live-panel" id="livePanel" aria-label="Live peers compact">
|
|
979
|
+
<div class="lp-title"><span class="lp-dot" aria-hidden="true"></span> Live now <span class="lp-live-count" id="lpLiveCount"></span></div>
|
|
775
980
|
<div id="liveRows"></div>
|
|
776
|
-
<div class="lp-legend">✓ usage verified · 🔑 identity verified —
|
|
981
|
+
<div class="lp-legend">✓ usage verified · 🔑 identity verified — real peers only (not demo)</div>
|
|
777
982
|
</aside>
|
|
778
983
|
|
|
779
984
|
<div class="incoming-call" id="incomingCall" role="dialog" aria-modal="true" aria-label="Incoming call">
|
|
@@ -791,7 +996,7 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
791
996
|
<div class="cp-head">
|
|
792
997
|
<div>
|
|
793
998
|
<div class="cp-title" id="chatTitle">@peer</div>
|
|
794
|
-
<div class="cp-sub" id="chatSub">live
|
|
999
|
+
<div class="cp-sub" id="chatSub">live peer · P2P text</div>
|
|
795
1000
|
</div>
|
|
796
1001
|
<button class="cp-close" id="chatClose" type="button" aria-label="Close chat">×</button>
|
|
797
1002
|
</div>
|
|
@@ -811,7 +1016,7 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
811
1016
|
</div>
|
|
812
1017
|
|
|
813
1018
|
<aside class="room-panel" id="roomPanel" aria-label="Room">
|
|
814
|
-
<div class="rp-title"><span class="lp-dot" aria-hidden="true"></span> Room
|
|
1019
|
+
<div class="rp-title"><span class="lp-dot" aria-hidden="true"></span> Room <span class="rp-count" id="rpCount"></span></div>
|
|
815
1020
|
<div class="rp-meta" id="roomMeta">not in a room</div>
|
|
816
1021
|
<div class="rp-actions">
|
|
817
1022
|
<button class="rp-btn" id="roomJoinBtn" type="button">Join video</button>
|
|
@@ -868,6 +1073,12 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
868
1073
|
function fmt(n){ return Math.round(n).toLocaleString("en-US"); }
|
|
869
1074
|
function variantFor(handle){ var h=0; for (var i=0;i<handle.length;i++){ h=(h*31+handle.charCodeAt(i))>>>0; } return h % BLOB_PATHS.length; }
|
|
870
1075
|
|
|
1076
|
+
// Shared with the live A/V script (separate IIFE) \u2014 roster cards need avatars + league colors.
|
|
1077
|
+
window.__vdAvatarSVG = avatarSVG;
|
|
1078
|
+
window.__vdVariantFor = variantFor;
|
|
1079
|
+
window.__vdLeagueById = leagueById;
|
|
1080
|
+
window.__vdLeagueColorHex = leagueColorHex;
|
|
1081
|
+
|
|
871
1082
|
var state = { connected:false };
|
|
872
1083
|
var stackIndex = 0;
|
|
873
1084
|
var provider = "claude-code";
|
|
@@ -932,17 +1143,54 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
932
1143
|
state = s || { connected:false };
|
|
933
1144
|
if (state.connected){
|
|
934
1145
|
renderReveal(state);
|
|
1146
|
+
renderYouChip(state);
|
|
935
1147
|
renderYouMarker(state.league);
|
|
936
1148
|
stackIndex = 0;
|
|
937
1149
|
renderStack();
|
|
938
1150
|
showStep("reveal");
|
|
939
1151
|
} else {
|
|
1152
|
+
renderYouChip(null);
|
|
940
1153
|
stackIndex = 0;
|
|
941
1154
|
renderStack();
|
|
942
1155
|
showStep("idle");
|
|
943
1156
|
}
|
|
944
1157
|
}
|
|
945
1158
|
|
|
1159
|
+
function renderYouChip(s){
|
|
1160
|
+
var chip = document.getElementById("youChip");
|
|
1161
|
+
if (!chip) return;
|
|
1162
|
+
if (!s || !s.connected){
|
|
1163
|
+
chip.classList.remove("is-on");
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
var lg = leagueById(s.league);
|
|
1167
|
+
var hex = lg ? lg.hex : "#ffcf6b";
|
|
1168
|
+
document.getElementById("youChipAvatar").innerHTML = avatarSVG(3, hex);
|
|
1169
|
+
document.getElementById("youChipHandle").textContent = s.handle || "@you";
|
|
1170
|
+
var sub = document.getElementById("youChipSub");
|
|
1171
|
+
sub.innerHTML = "";
|
|
1172
|
+
var pill = document.createElement("span");
|
|
1173
|
+
pill.className = "lg-pill";
|
|
1174
|
+
pill.style.background = "color-mix(in srgb, " + hex + " 16%, transparent)";
|
|
1175
|
+
pill.style.border = "1px solid color-mix(in srgb, " + hex + " 40%, transparent)";
|
|
1176
|
+
pill.style.color = hex;
|
|
1177
|
+
pill.textContent = lg ? lg.label : ((s.league || "?") + " League");
|
|
1178
|
+
sub.appendChild(pill);
|
|
1179
|
+
if (s.verified){
|
|
1180
|
+
var vm = document.createElement("span");
|
|
1181
|
+
vm.className = "mark mark-verified";
|
|
1182
|
+
vm.textContent = "\u2713 verified";
|
|
1183
|
+
sub.appendChild(vm);
|
|
1184
|
+
} else {
|
|
1185
|
+
var lm = document.createElement("span");
|
|
1186
|
+
lm.className = "mark mark-demo";
|
|
1187
|
+
lm.textContent = "local";
|
|
1188
|
+
lm.title = "Usage read locally / self-reported";
|
|
1189
|
+
sub.appendChild(lm);
|
|
1190
|
+
}
|
|
1191
|
+
chip.classList.add("is-on");
|
|
1192
|
+
}
|
|
1193
|
+
|
|
946
1194
|
function renderReveal(s){
|
|
947
1195
|
var lg = leagueById(s.league);
|
|
948
1196
|
var hex = lg ? lg.hex : "#ffcf6b";
|
|
@@ -992,6 +1240,7 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
992
1240
|
rawToggle.setAttribute("aria-expanded","false");
|
|
993
1241
|
rawToggle.textContent = "show raw usage (visible only to you)";
|
|
994
1242
|
document.querySelectorAll(".you-marker").forEach(function(m){ m.remove(); });
|
|
1243
|
+
renderYouChip(null);
|
|
995
1244
|
stackIndex = 0;
|
|
996
1245
|
renderStack();
|
|
997
1246
|
showStep("idle");
|
|
@@ -1039,8 +1288,8 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
1039
1288
|
if (!state.connected){
|
|
1040
1289
|
empty.innerHTML = "<strong>Connect to see matches.</strong><p>Read your usage to get sorted into a league and start matching.</p>";
|
|
1041
1290
|
} else {
|
|
1042
|
-
empty.innerHTML = "<strong>
|
|
1043
|
-
'<button class="btn btn-primary" id="btnRestart" type="button" style="width:auto;padding:11px 20px;">
|
|
1291
|
+
empty.innerHTML = "<strong>End of demo pool.</strong><p>These were seeded demo profiles \u2014 not live peers. Real people show up under Live now.</p>" +
|
|
1292
|
+
'<button class="btn btn-primary" id="btnRestart" type="button" style="width:auto;padding:11px 20px;">Restart demo</button>';
|
|
1044
1293
|
}
|
|
1045
1294
|
cardStackEl.appendChild(empty);
|
|
1046
1295
|
var restart = empty.querySelector("#btnRestart");
|
|
@@ -1056,12 +1305,13 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
1056
1305
|
var label = lg ? lg.label : (cand.league + " League");
|
|
1057
1306
|
var bio = cand.bio || [];
|
|
1058
1307
|
el.innerHTML =
|
|
1308
|
+
'<span class="mc-demo-badge mark mark-demo" title="Seeded demo profile \u2014 not a live peer">demo</span>' +
|
|
1059
1309
|
'<div class="mc-top">' +
|
|
1060
1310
|
'<div class="mc-avatar">' + avatarSVG(variantFor(cand.handle), hex) + '</div>' +
|
|
1061
1311
|
'<div>' +
|
|
1062
|
-
'<div class="mc-handle">' + cand.handle + '</div>' +
|
|
1312
|
+
'<div class="mc-handle-row"><div class="mc-handle">' + cand.handle + '</div></div>' +
|
|
1063
1313
|
'<span class="mc-league" style="background:color-mix(in srgb,' + hex + ' 16%, transparent);border:1px solid color-mix(in srgb,' + hex + ' 40%, transparent);color:' + hex + '">' + label + '</span>' +
|
|
1064
|
-
'<div class="mc-verified"
|
|
1314
|
+
'<div class="mc-verified" style="color:var(--muted-2)">seeded local profile</div>' +
|
|
1065
1315
|
'</div>' +
|
|
1066
1316
|
'</div>' +
|
|
1067
1317
|
'<div class="mc-bio"><p>' + (bio[0] || "") + '</p><p>' + (bio[1] || "") + '</p></div>' +
|
|
@@ -1069,7 +1319,7 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
1069
1319
|
'<div class="mc-actions">' +
|
|
1070
1320
|
'<button class="round-btn pass" type="button" title="Pass">✕</button>' +
|
|
1071
1321
|
'<button class="round-btn like" type="button" title="Like">♥</button>' +
|
|
1072
|
-
'<span class="hint"
|
|
1322
|
+
'<span class="hint">demo</span>' +
|
|
1073
1323
|
'</div>' : '');
|
|
1074
1324
|
cardStackEl.appendChild(el);
|
|
1075
1325
|
if (depth === 0){
|
|
@@ -1469,7 +1719,7 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
1469
1719
|
delete unread[handle];
|
|
1470
1720
|
chatTitle.textContent = handle;
|
|
1471
1721
|
chatSub.textContent = peerKnown(handle)
|
|
1472
|
-
? "live
|
|
1722
|
+
? "live peer \xB7 P2P text \xB7 not a demo profile"
|
|
1473
1723
|
: "peer offline \xB7 messages will not deliver";
|
|
1474
1724
|
chatPanel.classList.add("is-open");
|
|
1475
1725
|
renderChat();
|
|
@@ -1531,14 +1781,117 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
1531
1781
|
// Render the live-peers rows: one per connected peer with its verification
|
|
1532
1782
|
// marks, a Chat button (opens the conversation), and a Call button that
|
|
1533
1783
|
// rings THAT peer specifically.
|
|
1784
|
+
// Marks from the peer's hello: \u2713 usage verified (real logs), \u{1F511} identity (signed).
|
|
1785
|
+
function peerMarksHtml(p){
|
|
1786
|
+
var html = "";
|
|
1787
|
+
if (p.verified === true) html += '<span class="mark mark-verified" title="Usage verified from real local logs">\u2713 verified</span>';
|
|
1788
|
+
if (p.identityVerified === true) html += '<span class="mark mark-identity" title="Identity signature verified">\u{1F511} identity</span>';
|
|
1789
|
+
return html;
|
|
1790
|
+
}
|
|
1791
|
+
|
|
1792
|
+
function leaguePillHtml(leagueId){
|
|
1793
|
+
var FALLBACK = { "1M":"#d69a6e","5M":"#cfd8e6","10M":"#ffcf6b","100M":"#f0839c","1B+":"#cba8ff" };
|
|
1794
|
+
var LABELS = { "1M":"1M League","5M":"5M League","10M":"10M League","100M":"100M League","1B+":"1B+ League" };
|
|
1795
|
+
var lg = typeof window.__vdLeagueById === "function" ? window.__vdLeagueById(leagueId) : null;
|
|
1796
|
+
var hex = lg ? lg.hex : (FALLBACK[leagueId] || "#ffcf6b");
|
|
1797
|
+
var label = lg ? lg.label : (LABELS[leagueId] || ((leagueId || "?") + " League"));
|
|
1798
|
+
return '<span class="lg-pill" style="background:color-mix(in srgb,' + hex + ' 16%, transparent);border:1px solid color-mix(in srgb,' + hex + ' 40%, transparent);color:' + hex + '">' + label + '</span>';
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
function avatarForPeer(handle, leagueId){
|
|
1802
|
+
var FALLBACK = { "1M":"#d69a6e","5M":"#cfd8e6","10M":"#ffcf6b","100M":"#f0839c","1B+":"#cba8ff" };
|
|
1803
|
+
var hex = (typeof window.__vdLeagueColorHex === "function")
|
|
1804
|
+
? window.__vdLeagueColorHex(leagueId)
|
|
1805
|
+
: (FALLBACK[leagueId] || "#ffcf6b");
|
|
1806
|
+
if (typeof window.__vdAvatarSVG === "function" && typeof window.__vdVariantFor === "function") {
|
|
1807
|
+
return window.__vdAvatarSVG(window.__vdVariantFor(handle), hex);
|
|
1808
|
+
}
|
|
1809
|
+
return "";
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
// Compact dock rows (floating panel) + full Live now roster cards (main column).
|
|
1534
1813
|
function renderLiveRows(peers){
|
|
1535
1814
|
liveRows.innerHTML = "";
|
|
1815
|
+
var roster = document.getElementById("liveRoster");
|
|
1816
|
+
var wrap = document.getElementById("liveNowWrap");
|
|
1817
|
+
var countEl = document.getElementById("liveNowCount");
|
|
1818
|
+
var lpCount = document.getElementById("lpLiveCount");
|
|
1819
|
+
var demoWrap = document.getElementById("demoStackWrap");
|
|
1820
|
+
|
|
1821
|
+
if (countEl) countEl.textContent = String(peers.length);
|
|
1822
|
+
if (lpCount) lpCount.textContent = peers.length ? (peers.length + " online") : "";
|
|
1823
|
+
if (wrap) wrap.classList.toggle("has-live", peers.length > 0);
|
|
1824
|
+
if (demoWrap) demoWrap.classList.toggle("is-secondary", peers.length > 0);
|
|
1825
|
+
|
|
1826
|
+
if (roster) {
|
|
1827
|
+
roster.innerHTML = "";
|
|
1828
|
+
if (peers.length === 0) {
|
|
1829
|
+
var empty = document.createElement("div");
|
|
1830
|
+
empty.className = "live-empty";
|
|
1831
|
+
empty.innerHTML = "<strong>No live peers right now</strong><p>When someone on your league topic connects, they show up here \u2014 clearly separate from the demo pool below.</p>";
|
|
1832
|
+
roster.appendChild(empty);
|
|
1833
|
+
} else {
|
|
1834
|
+
peers.forEach(function(p){
|
|
1835
|
+
var card = document.createElement("article");
|
|
1836
|
+
card.className = "live-card";
|
|
1837
|
+
|
|
1838
|
+
var av = document.createElement("div");
|
|
1839
|
+
av.className = "lc-avatar";
|
|
1840
|
+
av.innerHTML = avatarForPeer(p.handle, p.league);
|
|
1841
|
+
|
|
1842
|
+
var body = document.createElement("div");
|
|
1843
|
+
body.className = "lc-body";
|
|
1844
|
+
var handleRow = document.createElement("div");
|
|
1845
|
+
handleRow.className = "lc-handle-row";
|
|
1846
|
+
var handleEl = document.createElement("div");
|
|
1847
|
+
handleEl.className = "lc-handle";
|
|
1848
|
+
handleEl.textContent = p.handle;
|
|
1849
|
+
handleRow.appendChild(handleEl);
|
|
1850
|
+
var liveMark = document.createElement("span");
|
|
1851
|
+
liveMark.className = "mark mark-live";
|
|
1852
|
+
liveMark.textContent = "live";
|
|
1853
|
+
handleRow.appendChild(liveMark);
|
|
1854
|
+
body.appendChild(handleRow);
|
|
1855
|
+
|
|
1856
|
+
var meta = document.createElement("div");
|
|
1857
|
+
meta.className = "lc-meta";
|
|
1858
|
+
meta.innerHTML = leaguePillHtml(p.league) + peerMarksHtml(p) +
|
|
1859
|
+
'<span style="opacity:.75">' + (p.harness || "") + "</span>";
|
|
1860
|
+
body.appendChild(meta);
|
|
1861
|
+
|
|
1862
|
+
var actions = document.createElement("div");
|
|
1863
|
+
actions.className = "lc-actions";
|
|
1864
|
+
var chatBtn = document.createElement("button");
|
|
1865
|
+
chatBtn.className = "btn-chat" + (unread[p.handle] ? " has-unread" : "");
|
|
1866
|
+
chatBtn.type = "button";
|
|
1867
|
+
chatBtn.textContent = "Chat" + (unread[p.handle] ? " (" + unread[p.handle] + ")" : "");
|
|
1868
|
+
chatBtn.addEventListener("click", function(){ openChat(p.handle); });
|
|
1869
|
+
var callBtn = document.createElement("button");
|
|
1870
|
+
callBtn.className = "btn-call";
|
|
1871
|
+
callBtn.type = "button";
|
|
1872
|
+
callBtn.textContent = "Call";
|
|
1873
|
+
callBtn.disabled = !!(rtc.remoteHandle || pendingOffer);
|
|
1874
|
+
callBtn.addEventListener("click", function(){
|
|
1875
|
+
if (rtc.remoteHandle || pendingOffer) return;
|
|
1876
|
+
callBtn.disabled = true;
|
|
1877
|
+
startCallAsOfferer(p.handle).catch(function(){ hangup(); });
|
|
1878
|
+
});
|
|
1879
|
+
actions.appendChild(chatBtn);
|
|
1880
|
+
actions.appendChild(callBtn);
|
|
1881
|
+
|
|
1882
|
+
card.appendChild(av);
|
|
1883
|
+
card.appendChild(body);
|
|
1884
|
+
card.appendChild(actions);
|
|
1885
|
+
roster.appendChild(card);
|
|
1886
|
+
});
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
// Compact floating dock \u2014 still handy when scrolled away from the roster.
|
|
1536
1891
|
peers.forEach(function(p){
|
|
1537
1892
|
var row = document.createElement("div");
|
|
1538
1893
|
row.className = "live-row";
|
|
1539
1894
|
var who = document.createElement("div");
|
|
1540
|
-
// Marks from the peer's hello, shown only when present: \u2713 usage
|
|
1541
|
-
// verified (real local logs), \u{1F511} identity-verified (signed hello).
|
|
1542
1895
|
var marks = (p.verified === true ? " \u2713" : "") + (p.identityVerified === true ? " \u{1F511}" : "");
|
|
1543
1896
|
var h = document.createElement("div"); h.className = "h"; h.textContent = p.handle + marks;
|
|
1544
1897
|
var s = document.createElement("div"); s.className = "s"; s.textContent = p.league + " \xB7 " + p.harness;
|
|
@@ -1553,9 +1906,8 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
1553
1906
|
var btn = document.createElement("button");
|
|
1554
1907
|
btn.className = "vbtn"; btn.type = "button"; btn.textContent = "Call";
|
|
1555
1908
|
btn.addEventListener("click", function(){
|
|
1556
|
-
if (rtc.remoteHandle || pendingOffer) return;
|
|
1909
|
+
if (rtc.remoteHandle || pendingOffer) return;
|
|
1557
1910
|
btn.disabled = true;
|
|
1558
|
-
// DIRECTED call: the rtc-offer is relayed only to this peer's handle.
|
|
1559
1911
|
startCallAsOfferer(p.handle).catch(function(){ hangup(); });
|
|
1560
1912
|
});
|
|
1561
1913
|
actions.appendChild(chatBtn);
|
|
@@ -1576,14 +1928,16 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
1576
1928
|
peers.forEach(function(p){ ensureChatLoop(p.handle); });
|
|
1577
1929
|
if (chatWith) {
|
|
1578
1930
|
chatSub.textContent = peerKnown(chatWith)
|
|
1579
|
-
? "live
|
|
1931
|
+
? "live peer \xB7 P2P text"
|
|
1580
1932
|
: "peer offline \xB7 messages will not deliver";
|
|
1581
1933
|
}
|
|
1582
|
-
if (peers.length === 0) { livePanel.classList.remove("is-open"); return; }
|
|
1583
|
-
livePanel.classList.add("is-open");
|
|
1584
1934
|
renderLiveRows(peers);
|
|
1935
|
+
if (peers.length === 0) { livePanel.classList.remove("is-open"); }
|
|
1936
|
+
else { livePanel.classList.add("is-open"); }
|
|
1585
1937
|
} catch(e){}
|
|
1586
1938
|
}
|
|
1939
|
+
// Initial empty state for the main Live now section, then poll.
|
|
1940
|
+
renderLiveRows([]);
|
|
1587
1941
|
refreshPeers();
|
|
1588
1942
|
setInterval(refreshPeers, 4000);
|
|
1589
1943
|
|
|
@@ -1824,6 +2178,8 @@ var webAppHtml = `<!DOCTYPE html>
|
|
|
1824
2178
|
roomMeta.textContent = roomName +
|
|
1825
2179
|
(roomVid.self ? " \xB7 you " + roomVid.self : "") +
|
|
1826
2180
|
" \xB7 " + n + " other" + (n === 1 ? "" : "s");
|
|
2181
|
+
var rpCount = document.getElementById("rpCount");
|
|
2182
|
+
if (rpCount) rpCount.textContent = n ? (n + " other" + (n === 1 ? "" : "s")) : "empty";
|
|
1827
2183
|
roomPanel.classList.add("is-open");
|
|
1828
2184
|
roomJoinBtn.disabled = roomVid.joined || !roomVid.self;
|
|
1829
2185
|
roomLeaveBtn.disabled = !roomVid.joined;
|
|
@@ -2428,7 +2784,7 @@ async function handle(req, res, opts) {
|
|
|
2428
2784
|
}
|
|
2429
2785
|
|
|
2430
2786
|
// src/cli.ts
|
|
2431
|
-
var VERSION = "0.8.
|
|
2787
|
+
var VERSION = "0.8.2";
|
|
2432
2788
|
function parsePort(raw) {
|
|
2433
2789
|
const n = Number(raw);
|
|
2434
2790
|
if (!Number.isInteger(n) || n < 1 || n > 65535) return void 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vibedate",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Dating by tokens — matched by usage league across agentic CLIs. Raw usage stays local; only your league is shared. CLI + local web app + MCP. Local-first.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|