V0.7.0 avatar and user to user name update

This commit is contained in:
2026-03-10 23:52:42 -04:00
parent 34d834944b
commit fd041ea95a
9 changed files with 47 additions and 12 deletions

View File

@@ -7,7 +7,7 @@ TZ=UTC
# Copy this file to .env and customize # Copy this file to .env and customize
# Image version to run (set by build.sh, or use 'latest') # Image version to run (set by build.sh, or use 'latest')
JAMA_VERSION=0.6.9 JAMA_VERSION=0.7.0
# Default admin credentials (used on FIRST RUN only) # Default admin credentials (used on FIRST RUN only)
ADMIN_NAME=Admin User ADMIN_NAME=Admin User

View File

@@ -1,6 +1,6 @@
{ {
"name": "jama-backend", "name": "jama-backend",
"version": "0.6.9", "version": "0.7.0",
"description": "TeamChat backend server", "description": "TeamChat backend server",
"main": "src/index.js", "main": "src/index.js",
"scripts": { "scripts": {

View File

@@ -92,6 +92,7 @@ router.get('/', authMiddleware, (req, res) => {
const other = db.prepare('SELECT display_name, name, avatar FROM users WHERE id = ?').get(otherUserId); const other = db.prepare('SELECT display_name, name, avatar FROM users WHERE id = ?').get(otherUserId);
if (other) { if (other) {
g.peer_real_name = other.name; g.peer_real_name = other.name;
g.peer_display_name = other.display_name || null; // null if no custom display name set
g.peer_avatar = other.avatar || null; g.peer_avatar = other.avatar || null;
g.name = other.display_name || other.name; g.name = other.display_name || other.name;
} }

View File

@@ -13,7 +13,7 @@
# ───────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────
set -euo pipefail set -euo pipefail
VERSION="${1:-0.6.9}" VERSION="${1:-0.7.0}"
ACTION="${2:-}" ACTION="${2:-}"
REGISTRY="${REGISTRY:-}" REGISTRY="${REGISTRY:-}"
IMAGE_NAME="jama" IMAGE_NAME="jama"

View File

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

View File

@@ -69,6 +69,13 @@
color: var(--text-secondary); color: var(--text-secondary);
} }
/* Real name in brackets in DM header */
.chat-header-real-name {
font-size: 12px;
font-weight: 400;
color: var(--text-tertiary);
}
.readonly-badge { .readonly-badge {
font-size: 11px; font-size: 11px;
padding: 2px 8px; padding: 2px 8px;

View File

@@ -183,15 +183,31 @@ export default function ChatWindow({ group, onBack, onGroupUpdated, onDirectMess
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="15 18 9 12 15 6"/></svg> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="15 18 9 12 15 6"/></svg>
</button> </button>
)} )}
<div {group.is_direct && group.peer_avatar ? (
className="group-icon-sm" <img
style={{ background: group.type === 'public' ? '#1a73e8' : '#a142f4' }} src={group.peer_avatar}
> alt={group.name}
{group.type === 'public' ? '#' : group.name[0]?.toUpperCase()} className="group-icon-sm"
</div> style={{ objectFit: 'cover', padding: 0 }}
/>
) : (
<div
className="group-icon-sm"
style={{ background: group.type === 'public' ? '#1a73e8' : '#a142f4' }}
>
{group.type === 'public' ? '#' : group.is_direct ? (group.peer_real_name || group.name)[0]?.toUpperCase() : group.name[0]?.toUpperCase()}
</div>
)}
<div className="flex-col flex-1 overflow-hidden"> <div className="flex-col flex-1 overflow-hidden">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="chat-header-name">{group.name}</span> {group.is_direct && group.peer_display_name ? (
<span className="chat-header-name">
{group.peer_display_name}
<span className="chat-header-real-name"> ({group.peer_real_name})</span>
</span>
) : (
<span className="chat-header-name">{group.is_direct && group.peer_real_name ? group.peer_real_name : group.name}</span>
)}
{group.is_readonly ? ( {group.is_readonly ? (
<span className="readonly-badge">Read-only</span> <span className="readonly-badge">Read-only</span>
) : null} ) : null}

View File

@@ -223,3 +223,10 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
/* DM real name in brackets — smaller, muted */
.dm-real-name {
font-size: 11px;
font-weight: 400;
color: var(--text-tertiary);
}

View File

@@ -110,7 +110,11 @@ export default function Sidebar({ groups, activeGroupId, onSelectGroup, notifica
)} )}
<div className="group-info flex-1 overflow-hidden"> <div className="group-info flex-1 overflow-hidden">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className={`group-name truncate ${hasUnread ? 'unread-name' : ''}`}>{group.is_direct && group.peer_real_name ? group.peer_real_name : group.name}</span> <span className={`group-name truncate ${hasUnread ? 'unread-name' : ''}`}>
{group.is_direct && group.peer_display_name
? <>{group.peer_display_name}<span className="dm-real-name"> ({group.peer_real_name})</span></>
: group.is_direct && group.peer_real_name ? group.peer_real_name : group.name}
</span>
{group.last_message_at && ( {group.last_message_at && (
<span className="group-time">{formatTime(group.last_message_at)}</span> <span className="group-time">{formatTime(group.last_message_at)}</span>
)} )}