v0.11.20 UI updates

This commit is contained in:
2026-03-22 14:30:06 -04:00
parent 7d6b28b4a3
commit 8116b307f7
6 changed files with 22 additions and 6 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "jama-frontend",
"version": "0.11.19",
"version": "0.11.20",
"private": true,
"scripts": {
"dev": "vite",

View File

@@ -8,6 +8,12 @@ import { useSocket } from '../contexts/SocketContext.jsx';
import './ChatWindow.css';
import GroupInfoModal from './GroupInfoModal.jsx';
// Must match Avatar.jsx and Sidebar.jsx exactly so header colours are consistent with message avatars
const AVATAR_COLORS = ['#1a73e8','#ea4335','#34a853','#fa7b17','#a142f4','#00897b','#e91e8c','#0097a7'];
function nameToColor(name) {
return AVATAR_COLORS[(name || '').charCodeAt(0) % AVATAR_COLORS.length];
}
export default function ChatWindow({ group, onBack, onGroupUpdated, onDirectMessage, onMessageDeleted, onlineUserIds = new Set() }) {
const { user: currentUser } = useAuth();
const { socket } = useSocket();
@@ -237,13 +243,21 @@ export default function ChatWindow({ group, onBack, onGroupUpdated, onDirectMess
<img src={group.peer_avatar} alt={group.name} className="group-icon-sm" style={{ objectFit: 'cover', padding: 0 }} />
{isOnline && <span className="online-dot" style={{ position: 'absolute', bottom: 1, right: 1 }} />}
</div>
) : isDirect && !group.is_managed ? (
// No custom avatar — use same per-user colour as Avatar.jsx and Sidebar.jsx
<div style={{ position: 'relative', flexShrink: 0 }}>
<div className="group-icon-sm" style={{ background: nameToColor(group.peer_real_name || group.name), flexShrink: 0 }}>
{(group.peer_real_name || group.name)[0]?.toUpperCase()}
</div>
{isOnline && <span className="online-dot" style={{ position: 'absolute', bottom: 1, right: 1 }} />}
</div>
) : group.is_managed ? (
<div className="group-icon-sm" style={{ background: avatarColors.dm, borderRadius: 8, flexShrink: 0, fontSize: 11, fontWeight: 700 }}>
{group.is_multi_group ? 'MG' : 'UG'}
</div>
) : (
<div className="group-icon-sm" style={{ background: group.type === 'public' ? avatarColors.public : avatarColors.dm, flexShrink: 0 }}>
{group.type === 'public' ? '#' : isDirect ? (group.peer_real_name || group.name)[0]?.toUpperCase() : group.name[0]?.toUpperCase()}
{group.type === 'public' ? '#' : group.name[0]?.toUpperCase()}
</div>
)}

View File

@@ -139,7 +139,7 @@ export default function Sidebar({ groups, activeGroupId, onSelectGroup, notifica
return (
<div className="sidebar">
<div className="sidebar-newchat-bar">
{!isMobile && !groupMessagesMode && (
{!isMobile && (
<button className="newchat-btn" onClick={onNewChat}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" width="18" height="18">
<path strokeLinecap="round" strokeLinejoin="round" d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 0 1 .865-.501 48.172 48.172 0 0 0 3.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z" />
@@ -180,7 +180,7 @@ export default function Sidebar({ groups, activeGroupId, onSelectGroup, notifica
)}
</div>
{isMobile && !groupMessagesMode && (
{isMobile && (
<button className="newchat-fab" onClick={onNewChat} title="New Chat">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" width="24" height="24">
<path strokeLinecap="round" strokeLinejoin="round" d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 0 1 .865-.501 48.172 48.172 0 0 0 3.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z" />

View File

@@ -433,6 +433,7 @@ export default function Chat() {
onSelectGroup={selectGroup}
notifications={notifications}
unreadGroups={unreadGroups}
onNewChat={() => setModal('newchat')}
onProfile={() => setModal('profile')}
onUsers={() => setPage('users')}
onSettings={() => setModal('settings')}
@@ -472,6 +473,7 @@ export default function Chat() {
{modal === 'branding' && <BrandingModal onClose={() => setModal(null)} />}
{modal === 'help' && <HelpModal onClose={() => setModal(null)} dismissed={helpDismissed} />}
{modal === 'about' && <AboutModal onClose={() => setModal(null)} />}
{modal === 'newchat' && <NewChatModal onClose={() => setModal(null)} onCreated={(g) => { loadGroups(); setModal(null); setActiveGroupId(g.id); setPage('chat'); }} />}
</div>
);
}