v0.6.5 various updates

This commit is contained in:
2026-03-10 18:16:05 -04:00
parent 09e6a75a9b
commit 2d21aac35f
11 changed files with 33 additions and 9 deletions

View File

@@ -22,7 +22,6 @@ export default function HelpModal({ onClose, dismissed: initialDismissed }) {
setDismissed(val);
try {
await api.dismissHelp(val);
if (val) onClose(); // immediately close when "do not show again" checked
} catch (_) {}
};

View File

@@ -32,7 +32,9 @@ function useAppSettings() {
useEffect(() => {
const name = settings.app_name || 'jama';
document.title = name;
// Preserve any unread badge prefix already set by Chat.jsx
const prefix = document.title.match(/^(\(\d+\)\s*)/)?.[1] || '';
document.title = prefix + name;
const logoUrl = settings.logo_url;
const faviconUrl = logoUrl || '/icons/jama.png';
let link = document.querySelector("link[rel~='icon']");

View File

@@ -91,7 +91,12 @@ function UserRow({ u, onUpdated }) {
{u.status !== 'active' && <span className="role-badge status-suspended">{u.status}</span>}
{!!u.is_default_admin && <span className="text-xs" style={{ color: 'var(--text-tertiary)' }}>Default Admin</span>}
</div>
<div style={{ fontSize: 12, color: 'var(--text-secondary)', marginTop: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{u.email}</div>
<div style={{ fontSize: 12, color: 'var(--text-secondary)', marginTop: 1, display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{u.email}</span>
<span style={{ color: 'var(--text-tertiary)', whiteSpace: 'nowrap', flexShrink: 0 }}>
Last login: {u.last_login ? new Date(u.last_login + 'Z').toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' }) : 'Never'}
</span>
</div>
{!!u.must_change_password && <div className="text-xs" style={{ color: 'var(--warning)' }}> Must change password</div>}
</div>
<svg

View File

@@ -190,11 +190,20 @@ export default function Chat() {
setUnreadGroups(prev => { const next = new Map(prev); next.delete(id); return next; });
};
// Update page title with total unread badge count
// Update page title AND PWA app badge with total unread count
useEffect(() => {
const totalUnread = [...unreadGroups.values()].reduce((a, b) => a + b, 0);
// Strip any existing badge prefix to get the clean base title
const base = document.title.replace(/^\(\d+\)\s*/, '');
document.title = totalUnread > 0 ? `(${totalUnread}) ${base}` : base;
// PWA app icon badge (Chrome/Edge desktop + Android, Safari 16.4+)
if ('setAppBadge' in navigator) {
if (totalUnread > 0) {
navigator.setAppBadge(totalUnread).catch(() => {});
} else {
navigator.clearAppBadge().catch(() => {});
}
}
}, [unreadGroups]);
const activeGroup = [