u
This commit is contained in:
@@ -46,6 +46,44 @@ import {
|
||||
} from '../../colors';
|
||||
|
||||
const DEFAULT_DRAWER_WIDTH = 460;
|
||||
|
||||
/** Sort by updated_at desc; subagents (started_by set) directly below their parent. */
|
||||
function sortConversations(list) {
|
||||
const ts = (c) => new Date(c.updated_at || c.created_at || 0).getTime() || 0;
|
||||
const byUpdated = (a, b) => ts(b) - ts(a);
|
||||
const ids = new Set(list.map((c) => c.id));
|
||||
const children = new Map();
|
||||
const roots = [];
|
||||
for (const c of list) {
|
||||
if (c.started_by != null && ids.has(c.started_by)) {
|
||||
if (!children.has(c.started_by)) children.set(c.started_by, []);
|
||||
children.get(c.started_by).push(c);
|
||||
} else {
|
||||
roots.push(c);
|
||||
}
|
||||
}
|
||||
const out = [];
|
||||
const walk = (c, depth) => {
|
||||
out.push({ conv: c, depth });
|
||||
(children.get(c.id) || []).sort(byUpdated).forEach((k) => walk(k, depth + 1));
|
||||
};
|
||||
roots.sort(byUpdated).forEach((c) => walk(c, 0));
|
||||
return out;
|
||||
}
|
||||
|
||||
function formatUpdated(value) {
|
||||
if (!value) return '';
|
||||
const d = new Date(value);
|
||||
if (Number.isNaN(d.getTime())) return '';
|
||||
return d.toLocaleString('de-DE', {
|
||||
day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit',
|
||||
});
|
||||
}
|
||||
|
||||
function conversationTitle(c) {
|
||||
const msg = (c.first_message || '').replace(/\s+/g, ' ').trim();
|
||||
return msg || '…';
|
||||
}
|
||||
const MIN_DRAWER_WIDTH = 320;
|
||||
|
||||
export default class ChatDrawer extends PureComponent {
|
||||
@@ -1085,24 +1123,32 @@ export default class ChatDrawer extends PureComponent {
|
||||
if (!conv) return '';
|
||||
return (
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, overflow: 'hidden' }}>
|
||||
<Typography variant="body2" fontWeight={600} noWrap>
|
||||
#{conv.id}
|
||||
<Typography variant="body2" fontWeight={600} noWrap sx={{ flexGrow: 1, minWidth: 0 }}>
|
||||
{conversationTitle(conv)}
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary" noWrap>
|
||||
{conv.model || 'Standard'}
|
||||
<Typography variant="caption" color="text.secondary" noWrap sx={{ flexShrink: 0 }}>
|
||||
{formatUpdated(conv.updated_at)}
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
}}
|
||||
>
|
||||
{conversations.map((c) => (
|
||||
<MenuItem key={c.id} value={c.id}>
|
||||
{sortConversations(conversations).map(({ conv: c, depth }) => (
|
||||
<MenuItem key={c.id} value={c.id} sx={{ pl: 2 + depth * 2.5 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, width: '100%', overflow: 'hidden' }}>
|
||||
<Typography variant="body2" fontWeight={600} noWrap>
|
||||
#{c.id}
|
||||
{depth > 0 && (
|
||||
<Typography variant="caption" color="text.secondary">↳</Typography>
|
||||
)}
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={depth > 0 ? 400 : 600}
|
||||
noWrap
|
||||
sx={{ flexGrow: 1, minWidth: 0 }}
|
||||
>
|
||||
{conversationTitle(c)}
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary" noWrap sx={{ flexGrow: 1 }}>
|
||||
{c.model || 'Standard'}
|
||||
<Typography variant="caption" color="text.secondary" noWrap sx={{ flexShrink: 0 }}>
|
||||
{formatUpdated(c.updated_at)}
|
||||
</Typography>
|
||||
</Box>
|
||||
</MenuItem>
|
||||
|
||||
Reference in New Issue
Block a user