feat: live presence, delivery-tick sync, brand rollout, call fixes, desktop 0.1.3
Live presence (fixes stale in-call/status until refresh — impossible in apps): - server broadcasts a user's status over the chat socket on connect/disconnect, call join/leave, and status change (chat.js broadcastPresence; signaling + routes hooks). - client onPresence() updates the contact dot + open-chat header live. Chat delivery ticks (#6): chat-list row now mirrors the thread (delivered→double grey, read→blue) via a new 'with' field on the delivered relay + onChatRead/onChatDelivered. Call fixes: no bogus 'host handed over' when a 1:1 call ends (leaveMeeting forced); branded call-connecting + chat-thread loaders; header subtitle tracks live call state. Notifications: web notify + sw.js use sender/group DP + brand icon (not old wordmark); desktop shell drops Web Push so only the single native toast fires (#5). Brand: master icon/splash/loaders wired everywhere (PWA/favicon/apple-touch/.ico), branded login (blue + gold CTA), branded toasts (BZToast) on all pages, Electron splash. Desktop: dev auto-targets localhost (packaged→prod); version 0.1.3 with new multi-size icon; dropped unused node-notifier; removed home-mockup.html. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
# TASK FOR CLAUDE (VS Code): Apply the Biz Connect brand — icons, splash, loaders, toasts
|
||||
|
||||
Read this whole file, then execute it. Work CONSERVATIVELY — only ADD / restyle, do NOT
|
||||
refactor unrelated code. The app is live in production. Find the right spots in the CURRENT
|
||||
code yourself (don't assume old names). Summarise all changes and STOP for my review before
|
||||
committing anything.
|
||||
|
||||
Repo root: C:\BizGaze_Support\remote-access-app
|
||||
Master brand assets are already placed in: brand-assets\
|
||||
- app-icon-1024.png (1024 full-bleed app icon master)
|
||||
- splash-2732-dark.png (2732 splash, brand blue — primary)
|
||||
- splash-2732-light.png (2732 splash, white — optional light theme)
|
||||
- loader-ring.svg (default spinner, light backgrounds)
|
||||
- loader-orbit.svg (branded spinner, light backgrounds)
|
||||
- loader-orbit-dark.svg (branded spinner, dark/overlay backgrounds)
|
||||
Brand colours: blue #1F3B73, blue-dark #16294F, yellow #FFC708, gold #E0AC00.
|
||||
|
||||
Note: brand-assets/ is only the SOURCE. Put the GENERATED / used copies where each target
|
||||
needs them — web assets under server/public/ (served over HTTP); native icons/splash into the
|
||||
platform build folders (Electron / Android / iOS) as applicable.
|
||||
|
||||
## 1. App icons (from brand-assets/app-icon-1024.png)
|
||||
Generate and place:
|
||||
- Windows .ico (multi-size 16/32/48/256) — fixes the tiny/blurry taskbar icon.
|
||||
- Favicon: server/public/favicon.ico + a 32px PNG; add to each page <head>:
|
||||
<link rel="icon" href="/favicon.ico" sizes="any">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon-180.png">
|
||||
- PWA icons 192, 512, and a maskable 512; reference them in the web manifest, and set the
|
||||
manifest "background_color" and "theme_color" to "#1F3B73".
|
||||
- Native mobile icons (Android mipmap set + adaptive, iOS AppIcon set) into their folders.
|
||||
|
||||
## 2. Splash (from brand-assets/splash-2732-dark.png)
|
||||
- Web/PWA loading + Electron splash: brand-blue background #1F3B73 with the logo centred
|
||||
(use the 2732 image, or reuse the app's splash.html if present).
|
||||
- Native launch screens: use the 2732 image (Android 12 SplashScreen background #1F3B73 + the
|
||||
app icon; iOS LaunchScreen background #1F3B73 + centred logo). Keep native launch STATIC.
|
||||
- Use splash-2732-light.png only if a light theme is supported.
|
||||
|
||||
## 3. Loaders (from brand-assets/loader-*.svg)
|
||||
Copy the three SVGs into server/public/ (e.g. server/public/loaders/). Wire them:
|
||||
- Everyday "Loading…" and in-app spinners -> loader-ring.svg
|
||||
- The hero "Connecting…" moment (session connect) -> loader-orbit.svg (light) / loader-orbit-dark.svg (on dark)
|
||||
Show one centered in the middle of the screen/panel while loading; hide when done. Always pair
|
||||
show with hide on BOTH the success and error paths so it can never get stuck.
|
||||
|
||||
## 4. Branded notification toasts
|
||||
Create server/public/bizconnect-toast.css with EXACTLY:
|
||||
|
||||
```css
|
||||
/* Biz Connect — branded notification toast. BZToast.success('…') / .error / .message / .info */
|
||||
.bzt-wrap{position:fixed;top:16px;right:16px;z-index:2147483600;display:flex;flex-direction:column;gap:10px;max-width:min(380px,92vw)}
|
||||
@supports(top:env(safe-area-inset-top)){.bzt-wrap{top:calc(16px + env(safe-area-inset-top));right:calc(16px + env(safe-area-inset-right))}}
|
||||
.bzt{display:flex;align-items:flex-start;gap:12px;background:#fff;color:#1f2430;border-radius:14px;padding:12px 14px;
|
||||
box-shadow:0 12px 30px rgba(16,26,53,.20);border-left:5px solid #1F3B73;
|
||||
transform:translateX(120%);opacity:0;transition:transform .3s cubic-bezier(.2,.7,.2,1),opacity .3s}
|
||||
.bzt.bzt-in{transform:translateX(0);opacity:1}
|
||||
.bzt.success{border-left-color:#16a34a}.bzt.error{border-left-color:#b91c1c}
|
||||
.bzt-badge{flex:none;width:34px;height:34px;border-radius:50%;display:grid;place-items:center;background:#1F3B73}
|
||||
.bzt.success .bzt-badge{background:#16a34a}.bzt.error .bzt-badge{background:#b91c1c}
|
||||
.bzt-badge svg{width:20px;height:20px}
|
||||
.bzt-body{flex:1;min-width:0;padding-top:1px}
|
||||
.bzt-title{font:700 13.5px/1.3 'Segoe UI',system-ui,sans-serif;color:#1F3B73;margin:0 0 1px}
|
||||
.bzt.success .bzt-title{color:#15803d}.bzt.error .bzt-title{color:#b91c1c}
|
||||
.bzt-msg{font:500 13px/1.4 'Segoe UI',system-ui,sans-serif;color:#3a4152;overflow-wrap:anywhere}
|
||||
.bzt-x{flex:none;background:none;border:none;color:#9aa3b2;cursor:pointer;font-size:18px;line-height:1;padding:2px 4px}
|
||||
.bzt-x:hover{color:#1f2430}
|
||||
@media(prefers-reduced-motion:reduce){.bzt{transition:opacity .2s}}
|
||||
```
|
||||
|
||||
Create server/public/bizconnect-toast.js with EXACTLY:
|
||||
|
||||
```js
|
||||
/* Biz Connect toast API. Requires bizconnect-toast.css.
|
||||
BZToast.success('Saved'); BZToast.error('Connection lost'); BZToast.message('Hi', {title:'Ravi'}); */
|
||||
window.BZToast=(function(){
|
||||
var wrap=null;
|
||||
var ICON={
|
||||
message:'<svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>',
|
||||
info:'<svg viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="9" stroke="#fff" stroke-width="2.2"/><path d="M12 11v5M12 8h.01" stroke="#fff" stroke-width="2.4" stroke-linecap="round"/></svg>',
|
||||
success:'<svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>',
|
||||
error:'<svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.6" stroke-linecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg>'
|
||||
};
|
||||
function esc(s){return String(s==null?'':s).replace(/[&<>"]/g,function(c){return{'&':'&','<':'<','>':'>','"':'"'}[c];});}
|
||||
function ensure(){ if(wrap) return wrap; wrap=document.createElement('div'); wrap.className='bzt-wrap'; document.body.appendChild(wrap); return wrap; }
|
||||
function show(message,opts){
|
||||
opts=opts||{}; var type=opts.type||'message'; var w=ensure();
|
||||
var t=document.createElement('div'); t.className='bzt '+type;
|
||||
t.innerHTML='<div class="bzt-badge">'+(ICON[type]||ICON.message)+'</div><div class="bzt-body">'
|
||||
+(opts.title?'<div class="bzt-title">'+esc(opts.title)+'</div>':'')
|
||||
+'<div class="bzt-msg">'+esc(message)+'</div></div><button class="bzt-x" aria-label="Dismiss">×</button>';
|
||||
w.appendChild(t); requestAnimationFrame(function(){ t.classList.add('bzt-in'); });
|
||||
var dur=(opts.duration==null?4000:opts.duration), timer;
|
||||
function close(){ t.classList.remove('bzt-in'); setTimeout(function(){ if(t.parentNode) t.parentNode.removeChild(t); },320); clearTimeout(timer); }
|
||||
t.querySelector('.bzt-x').onclick=close; if(dur>0) timer=setTimeout(close,dur); return close;
|
||||
}
|
||||
return { show:show,
|
||||
message:function(m,o){o=o||{};o.type='message';return show(m,o);},
|
||||
success:function(m,o){o=o||{};o.type='success';return show(m,o);},
|
||||
error:function(m,o){o=o||{};o.type='error';return show(m,o);},
|
||||
info:function(m,o){o=o||{};o.type='info';return show(m,o);} };
|
||||
})();
|
||||
```
|
||||
|
||||
Then, on every page that shows notifications (connect, share, home, dashboard, console),
|
||||
include both files near the top BEFORE the page's own inline <script>:
|
||||
<link rel="stylesheet" href="/bizconnect-toast.css">
|
||||
<script src="/bizconnect-toast.js"></script>
|
||||
(Load the JS via src only — never inline.)
|
||||
|
||||
Now REPLACE the existing toast / notification pop-ups with the branded API (keep the same
|
||||
triggers and text, just route them through BZToast so they look on-brand):
|
||||
- Incoming chat message -> BZToast.message(text, {title: senderName})
|
||||
- A success (e.g. recording/transcript saved, agent added) -> BZToast.success('…')
|
||||
- An error (connection lost, upload failed, invalid code) -> BZToast.error('…')
|
||||
- Neutral info -> BZToast.info('…')
|
||||
Remove the old inline toast markup/styles it replaces. Toasts appear top-right and auto-dismiss.
|
||||
|
||||
## 5. Verify (do not commit until I review)
|
||||
- node --check any JS you extract/touch; confirm every page still loads.
|
||||
- Confirm: taskbar/favicon icon is crisp, splash shows on launch, a loader appears centered
|
||||
during connect/report, and notifications now use the branded toast.
|
||||
- List exactly which files changed, then STOP for my review.
|
||||
Reference in New Issue
Block a user