import { useState, useEffect } from 'react'; import { api } from '../utils/api.js'; const CLAUDE_URL = 'https://claude.ai'; // Render "Built With" value — separator trails its token so it never starts a new line function BuiltWithValue({ value }) { if (!value) return null; const parts = value.split('·').map(s => s.trim()); return ( {parts.map((part, i) => ( {part === 'Claude.ai' ? {part} : part} {i < parts.length - 1 && ·} ))} ); } export default function AboutModal({ onClose }) { const [settings, setSettings] = useState({ app_name: 'jama', app_version: '' }); const [about, setAbout] = useState(null); useEffect(() => { api.getSettings().then(({ settings }) => setSettings(settings)).catch(() => {}); fetch('/api/about') .then(r => r.json()) .then(({ about }) => setAbout(about)) .catch(() => {}); }, []); const appName = settings.app_name || 'jama'; // Version always mirrors Settings window — from settings API (env var) const version = settings.app_version || about?.version || ''; const a = about || {}; const rows = [ { label: 'Version', value: version }, { label: 'Built With', value: a.built_with, builtWith: true }, { label: 'Developer', value: a.developer }, { label: 'License', value: a.license, link: a.license_url }, ].filter(r => r.value); return (
e.target === e.currentTarget && onClose()}>
jama

{appName}

just another messaging app

{about ? ( <>
{rows.map(({ label, value, builtWith, link }) => (
{label} {builtWith ? : link ? {value} : value}
))}
{a.description &&

{a.description}

} ) : (
)}
); }