mobile: revert finger-following swipe-back to the working release-based version (interactive one had an undiagnosable-blind layout offset) (batch142)
This commit is contained in:
+14
-63
@@ -1158,7 +1158,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="/icons.js?v=6"></script>
|
<script src="/icons.js?v=6"></script>
|
||||||
<script>window.__BUILD='2026-07-19-batch141';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
<script>window.__BUILD='2026-07-20-batch142';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
||||||
// Emoji are rendered with the OS's own (colour) emoji font — instant, zero network.
|
// Emoji are rendered with the OS's own (colour) emoji font — instant, zero network.
|
||||||
//
|
//
|
||||||
// We used to run Twemoji over every emoji, which swapped each one for an <img> pulled INDIVIDUALLY from
|
// We used to run Twemoji over every emoji, which swapped each one for an <img> pulled INDIVIDUALLY from
|
||||||
@@ -4961,71 +4961,22 @@ function bzcBack(){
|
|||||||
}
|
}
|
||||||
try{ history.pushState(null,'',location.href); }catch(_){}
|
try{ history.pushState(null,'',location.href); }catch(_){}
|
||||||
window.addEventListener('popstate', ()=>{ if(bzcBack()){ try{ history.pushState(null,'',location.href); }catch(_){} } });
|
window.addEventListener('popstate', ()=>{ if(bzcBack()){ try{ history.pushState(null,'',location.href); }catch(_){} } });
|
||||||
// #4: native-style INTERACTIVE swipe-back. Drag the open conversation rightward from the left edge and it
|
// #4: left-edge SWIPE-back. A drag that begins at the very left edge and releases clearly rightward closes
|
||||||
// FOLLOWS YOUR FINGER 1:1, with the chat list parallaxing in underneath; release past ~35% of the width (or
|
// the topmost layer (popup → in-conversation search → open chat) via bzcBack() → showWelcome()'s parallax
|
||||||
// a quick flick) completes the pop, otherwise it snaps back. The old version's bug — the pane getting stuck
|
// slide. RELEASE-triggered on purpose: the finger-following version had a layout bug (the conversation pane
|
||||||
// — happened because passive listeners let iOS/scroll steal the gesture and fire touchcancel. Fix: once a
|
// sat one screen-width off, so it couldn't be dragged into view) that I could not resolve without seeing it
|
||||||
// clear horizontal drag is detected we preventDefault (passive:false) to CLAIM the gesture, and touchcancel
|
// render on-device. This version reliably runs the same push-slide close.
|
||||||
// always resolves to a clean state via end()/reset(). Arms only in the left 32px so it never clashes with
|
|
||||||
// the bubble swipe-to-reply (which starts >32px). Works in the native app, PWA and mobile browser alike.
|
|
||||||
(function(){
|
(function(){
|
||||||
const EDGE=32;
|
let sx=0, sy=0, edge=false;
|
||||||
let sx=0, sy=0, w=0, armed=false, dragging=false, content=null, chatcol=null, t0=0;
|
|
||||||
const isMobile=()=>window.matchMedia('(max-width:760px)').matches;
|
|
||||||
function canSwipe(){
|
|
||||||
if(!isMobile() || selected==null) return false;
|
|
||||||
if(!document.body.classList.contains('chat-open') || document.body.classList.contains('chat-closing')) return false;
|
|
||||||
if(document.querySelector('.modal-ov') || document.getElementById('lightbox')) return false;
|
|
||||||
const sh=document.getElementById('convoSearchHead'); if(sh && sh.style.display==='flex') return false; // let search close via its own X / the back button
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
function reset(){ if(content){ content.style.transition=''; content.style.transform=''; } if(chatcol){ chatcol.style.transition=''; chatcol.style.transform=''; } document.body.classList.remove('chat-dragging'); armed=false; dragging=false; content=null; chatcol=null; }
|
|
||||||
window.addEventListener('touchstart',(e)=>{
|
window.addEventListener('touchstart',(e)=>{
|
||||||
if(dragging) return;
|
if(e.touches.length!==1){ edge=false; return; }
|
||||||
if(e.touches.length!==1 || !canSwipe()){ armed=false; return; }
|
const t=e.touches[0]; edge = t.clientX<=24; sx=t.clientX; sy=t.clientY; // only arm when starting at the left edge
|
||||||
const t=e.touches[0];
|
}, {passive:true});
|
||||||
if(t.clientX>EDGE){ armed=false; return; }
|
window.addEventListener('touchend',(e)=>{
|
||||||
armed=true; dragging=false; sx=t.clientX; sy=t.clientY; w=window.innerWidth||360; t0=Date.now();
|
if(!edge) return; edge=false;
|
||||||
|
const t=e.changedTouches&&e.changedTouches[0]; if(!t) return;
|
||||||
|
if((t.clientX-sx)>60 && Math.abs(t.clientY-sy)<50) bzcBack(); // rightward, mostly-horizontal swipe = back
|
||||||
}, {passive:true});
|
}, {passive:true});
|
||||||
window.addEventListener('touchmove',(e)=>{
|
|
||||||
if(!armed || e.touches.length!==1) return;
|
|
||||||
const t=e.touches[0], dx=t.clientX-sx, dy=t.clientY-sy;
|
|
||||||
if(!dragging){
|
|
||||||
if(Math.abs(dy)>Math.abs(dx) && Math.abs(dy)>8){ armed=false; return; } // vertical scroll → release
|
|
||||||
if(dx>10 && dx>=Math.abs(dy)){ // confirmed rightward → claim it
|
|
||||||
dragging=true;
|
|
||||||
content=document.querySelector('.shell > .content');
|
|
||||||
chatcol=document.getElementById('chatcol');
|
|
||||||
renderChats(searchVal()); // make the list under the pane current
|
|
||||||
document.body.classList.add('chat-dragging');
|
|
||||||
if(content) content.style.transition='none';
|
|
||||||
if(chatcol) chatcol.style.transition='none';
|
|
||||||
if(window.bzDbg) window.bzDbg('swipe',{s:'confirm',hasC:content?1:0,hasL:chatcol?1:0,sx:Math.round(sx),dx:Math.round(dx),w:Math.round(w),cCls:content?String(content.className).slice(0,20):'NULL'}); // TEMP
|
|
||||||
} else return;
|
|
||||||
}
|
|
||||||
e.preventDefault(); // needs passive:false — claims the gesture
|
|
||||||
const x=Math.max(0, dx);
|
|
||||||
if(content) content.style.transform='translate3d('+x+'px,0,0)';
|
|
||||||
if(chatcol) chatcol.style.transform='translate3d('+(-22*(1-Math.min(1,x/w)))+'%,0,0)';
|
|
||||||
}, {passive:false});
|
|
||||||
function end(e){
|
|
||||||
if(!dragging){ armed=false; return; }
|
|
||||||
const t=(e.changedTouches&&e.changedTouches[0]);
|
|
||||||
const dx=t?Math.max(0,t.clientX-sx):0, dt=Math.max(1,Date.now()-t0), v=dx/dt;
|
|
||||||
const _done = dx>w*0.25 || (v>0.35 && dx>50); // easier to complete (was 35%)
|
|
||||||
if(window.bzDbg){ var _ct=content?getComputedStyle(content).transform:'x', _cl=content?Math.round(content.getBoundingClientRect().left):-1, _lt=chatcol?getComputedStyle(chatcol).transform:'x'; window.bzDbg('swipe',{s:'end',dx:Math.round(dx),done:_done?1:0,cMoved:(_ct&&_ct!=='none'&&_ct!=='x')?1:0,cLeft:_cl,lMoved:(_lt&&_lt!=='none'&&_lt!=='x')?1:0}); } // TEMP: cMoved/cLeft prove whether the conversation actually translated
|
|
||||||
if(_done){ // complete the pop
|
|
||||||
if(content){ content.style.transition='transform .17s cubic-bezier(.4,0,.7,.4)'; content.style.transform='translate3d(100%,0,0)'; }
|
|
||||||
if(chatcol){ chatcol.style.transition='transform .17s cubic-bezier(.4,0,.7,.4)'; chatcol.style.transform='translate3d(0,0,0)'; }
|
|
||||||
setTimeout(()=>{ document.body.classList.remove('chat-dragging'); showWelcome(true); if(content){ content.style.transition=''; content.style.transform=''; } if(chatcol){ chatcol.style.transition=''; chatcol.style.transform=''; } armed=false; dragging=false; content=null; chatcol=null; }, 175);
|
|
||||||
} else { // snap back — stay in the chat
|
|
||||||
if(content){ content.style.transition='transform .17s'; content.style.transform='translate3d(0,0,0)'; }
|
|
||||||
if(chatcol){ chatcol.style.transition='transform .17s'; chatcol.style.transform='translate3d(-22%,0,0)'; }
|
|
||||||
setTimeout(reset, 175);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.addEventListener('touchend', end, {passive:true});
|
|
||||||
window.addEventListener('touchcancel',(e)=>{ if(dragging) end(e); else armed=false; }, {passive:true}); // never leave the pane stuck
|
|
||||||
})();
|
})();
|
||||||
// #9: swipe a message bubble to the right to reply to it (mobile), like WhatsApp/Teams. The bubble
|
// #9: swipe a message bubble to the right to reply to it (mobile), like WhatsApp/Teams. The bubble
|
||||||
// follows the finger a little; releasing past the threshold opens the reply composer for that message.
|
// follows the finger a little; releasing past the threshold opens the reply composer for that message.
|
||||||
|
|||||||
Reference in New Issue
Block a user