fix(chat): restore history on Turnstile verification

Turnstile callback unconditionally showed the greeting message, wiping
session history for returning visitors who hadn't verified yet.

Callback now uses the same restoreOrGreet pattern as neuronDemoToggle:
replays prior messages if session.messages is non-empty, else shows the
greeting once and marks session.greeted.

Also extracts the gallery voting inline script (a49ca0a129e8.js) as a
side effect of re-running extract-js.py. Chat JS rebuilds to de72b8b61d75.js.
This commit is contained in:
Will Anderson
2026-05-03 19:51:59 -05:00
parent 047be5ae02
commit 4c5d4b3c84
7 changed files with 32 additions and 120 deletions
+13 -2
View File
@@ -261,7 +261,18 @@ CHAT_HTML_AND_JS = r"""
if (gate) gate.style.display = 'none';
if (msgs) msgs.style.display = 'flex';
if (inputRow) inputRow.style.display = 'flex';
addMsg('ai', 'Hey. What is on your mind?', true);
if (session.messages && session.messages.length > 0) {
session.messages.forEach(function(m) { addMsg(m.role, m.text, true); });
var remaining = MAX - msgCount;
if (remaining <= 0) {
var input = document.getElementById('neuron-demo-text');
if (input) { input.disabled = true; input.placeholder = 'Interaction limit reached'; }
}
} else if (!session.greeted) {
addMsg('ai', 'Hey. What is on your mind?', true);
session.greeted = true;
try { localStorage.setItem('neuron_demo_session', JSON.stringify(session)); } catch(e) {}
}
updateCountdown();
var inp = document.getElementById('neuron-demo-text');
if (inp) inp.focus();
@@ -435,7 +446,7 @@ CHAT_HTML_AND_JS = r"""
# with our new inline content + script. extract-js will then re-extract this
# fresh inline block to a content-hashed asset on the next build.
OLD_LINE = '<script src=\\"/assets/js/fc247ef45b1d.js\\" defer></script>'
OLD_LINE = '<script src=\\"/assets/js/de72b8b61d75.js\\" defer></script>'
def main():
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+15 -9
View File
@@ -1,6 +1,6 @@
{
"generated_by": "scripts/extract-js.py",
"count": 12,
"count": 13,
"entries": [
{
"file": "account.el",
@@ -50,6 +50,13 @@
"interpolated": [],
"note": "carried from prior run"
},
{
"file": "gallery.el",
"hash": "a49ca0a129e8",
"asset": "/assets/js/a49ca0a129e8.js",
"size": 8793,
"interpolated": []
},
{
"file": "gallery.el",
"hash": "cd30551e3c3b",
@@ -82,14 +89,6 @@
"interpolated": [],
"note": "carried from prior run"
},
{
"file": "styles.el",
"hash": "37b5ead0d425",
"asset": "/assets/js/37b5ead0d425.js",
"size": 23539,
"interpolated": [],
"note": "carried from prior run"
},
{
"file": "styles.el",
"hash": "407e72cd7182",
@@ -97,6 +96,13 @@
"size": 6430,
"interpolated": [],
"note": "carried from prior run"
},
{
"file": "styles.el",
"hash": "de72b8b61d75",
"asset": "/assets/js/de72b8b61d75.js",
"size": 24583,
"interpolated": []
}
]
}
+1 -107
View File
@@ -270,113 +270,7 @@ window.NEURON_CFG=window.NEURON_CFG||{};
window.NEURON_CFG.supabase_url=\"" + supabase_url + "\";
window.NEURON_CFG.supabase_anon_key=\"" + supabase_anon_key + "\";
</script>
<script>
(function(){
var cfg=window.NEURON_CFG||{};
var sbUrl=cfg.supabase_url,sbKey=cfg.supabase_anon_key;
if(!sbUrl||!sbKey)return;
var sb=window.supabase.createClient(sbUrl,sbKey);
var token=null;
var votes={};
function getCtrl(sid){
var found=null;
document.querySelectorAll('.vote-controls').forEach(function(c){
if(c.getAttribute('data-share-id')===sid)found=c;
});
return found;
}
function applyState(ctrl,state){
var sid=ctrl.getAttribute('data-share-id');
votes[sid]=state.user_vote||'none';
var scoreEl=ctrl.querySelector('.vote-score');
if(scoreEl&&state.score!=null)scoreEl.textContent=state.score;
var upBtn=ctrl.querySelector('.vote-btn.vote-up');
var dnBtn=ctrl.querySelector('.vote-btn.vote-down');
if(upBtn){upBtn.disabled=false;upBtn.classList.toggle('is-active',state.user_vote==='up');}
if(dnBtn){dnBtn.disabled=false;dnBtn.classList.toggle('is-active',state.user_vote==='down');}
}
function loadVoteState(sid){
var url='/api/vote-state/'+sid;
if(token)url+='?access_token='+encodeURIComponent(token);
fetch(url).then(function(r){return r.json();}).then(function(d){
var ctrl=getCtrl(sid);
if(ctrl)applyState(ctrl,d);
}).catch(function(){});
}
function loadAll(){
document.querySelectorAll('.vote-controls').forEach(function(ctrl){
var id=ctrl.getAttribute('data-share-id');
if(id)loadVoteState(id);
});
}
function castVote(sid,direction){
if(!token){showSignIn();return;}
var ctrl=getCtrl(sid);
var btns=ctrl?ctrl.querySelectorAll('.vote-btn'):[];
btns.forEach(function(b){b.disabled=true;b.classList.add('is-loading');});
fetch('/api/vote',{
method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({access_token:token,id:sid,direction:direction})
}).then(function(r){return r.json();}).then(function(d){
if(ctrl&&d.ok)applyState(ctrl,d);
btns.forEach(function(b){b.disabled=false;b.classList.remove('is-loading');});
}).catch(function(){
btns.forEach(function(b){b.disabled=false;b.classList.remove('is-loading');});
});
}
document.querySelectorAll('.vote-controls').forEach(function(ctrl){
ctrl.querySelectorAll('.vote-btn').forEach(function(btn){
btn.addEventListener('click',function(){
var sid=ctrl.getAttribute('data-share-id');
if(!token){showSignIn();return;}
var dir=btn.getAttribute('data-direction');
var cur=votes[sid]||'none';
castVote(sid,cur===dir?'none':dir);
});
});
});
var modal=document.getElementById('signin-modal');
var cancelEl=document.getElementById('signin-cancel');
var sendEl=document.getElementById('signin-send');
var emailEl=document.getElementById('signin-email');
var msgEl=document.getElementById('signin-msg');
function showSignIn(){if(modal)modal.classList.add('open');if(emailEl)emailEl.focus();}
if(cancelEl)cancelEl.addEventListener('click',function(){modal.classList.remove('open');});
if(modal)modal.addEventListener('click',function(e){if(e.target===modal)modal.classList.remove('open');});
if(sendEl)sendEl.addEventListener('click',function(){
var email=emailEl?emailEl.value.trim():'';
if(!email){if(msgEl)msgEl.textContent='Please enter your email.';return;}
sendEl.disabled=true;
if(msgEl)msgEl.textContent='Sending...';
sb.auth.signInWithOtp({email:email,options:{emailRedirectTo:window.location.href}}).then(function(r){
sendEl.disabled=false;
if(msgEl)msgEl.textContent=r.error?(r.error.message||'Error. Try again.'):'Check your email for a sign-in link.';
});
});
if(emailEl)emailEl.addEventListener('keydown',function(e){if(e.key==='Enter'&&sendEl)sendEl.click();});
sb.auth.onAuthStateChange(function(event,session){
token=session?session.access_token:null;
if(token&&modal)modal.classList.remove('open');
loadAll();
});
sb.auth.getSession().then(function(r){
token=r.data&&r.data.session?r.data.session.access_token:null;
loadAll();
});
})();
</script>
<script src=\"/assets/js/a49ca0a129e8.js\" defer></script>
<script src=\"/assets/js/cd30551e3c3b.js\" defer></script>
</body>
</html>"
+1 -1
View File
@@ -2023,7 +2023,7 @@ fn page_close() -> String {
</div>
</div>
<script src=\"/assets/js/37b5ead0d425.js\" defer></script>
<script src=\"/assets/js/de72b8b61d75.js\" defer></script>
</body>
</html>
"