perf(renderer): narrow activity approval subscriptions
This commit is contained in:
parent
b6308ccb42
commit
a491cd6c1c
1 changed files with 30 additions and 20 deletions
|
|
@ -87,6 +87,30 @@ import type { InboxMessage } from '@shared/types';
|
||||||
|
|
||||||
type StructuredMessage = Record<string, unknown>;
|
type StructuredMessage = Record<string, unknown>;
|
||||||
|
|
||||||
|
interface PermissionStatusIconProps {
|
||||||
|
requestId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PermissionStatusIcon = memo(function PermissionStatusIcon({
|
||||||
|
requestId,
|
||||||
|
}: PermissionStatusIconProps): React.JSX.Element {
|
||||||
|
const pendingApprovals = useStore(useShallow((s) => s.pendingApprovals));
|
||||||
|
const resolvedApprovals = useStore(useShallow((s) => s.resolvedApprovals));
|
||||||
|
|
||||||
|
const resolved = resolvedApprovals.get(requestId);
|
||||||
|
if (resolved === true) {
|
||||||
|
return <Check size={12} className="text-emerald-400" />;
|
||||||
|
}
|
||||||
|
if (resolved === false) {
|
||||||
|
return <X size={12} className="text-red-400" />;
|
||||||
|
}
|
||||||
|
const isPending = pendingApprovals.some((a) => a.requestId === requestId);
|
||||||
|
if (isPending) {
|
||||||
|
return <Clock size={12} className="animate-pulse text-amber-400" />;
|
||||||
|
}
|
||||||
|
return <Check size={12} className="text-emerald-400/50" />;
|
||||||
|
});
|
||||||
|
|
||||||
function parseQualifiedRecipient(
|
function parseQualifiedRecipient(
|
||||||
value: string | undefined
|
value: string | undefined
|
||||||
): { teamName: string; memberName: string } | null {
|
): { teamName: string; memberName: string } | null {
|
||||||
|
|
@ -1034,30 +1058,16 @@ export const ActivityItem = memo(
|
||||||
commentTaskRef?.displayId ??
|
commentTaskRef?.displayId ??
|
||||||
(commentTaskRef?.taskId ? `#${commentTaskRef.taskId.slice(0, 6)}` : null);
|
(commentTaskRef?.taskId ? `#${commentTaskRef.taskId.slice(0, 6)}` : null);
|
||||||
|
|
||||||
// Permission request status icon (check/x/clock)
|
const permissionRequestId = useMemo(() => {
|
||||||
const pendingApprovals = useStore(useShallow((s) => s.pendingApprovals));
|
|
||||||
const resolvedApprovals = useStore(useShallow((s) => s.resolvedApprovals));
|
|
||||||
const permissionIcon = useMemo(() => {
|
|
||||||
if (!structured) return null;
|
if (!structured) return null;
|
||||||
const type = typeof structured.type === 'string' ? structured.type : null;
|
const type = typeof structured.type === 'string' ? structured.type : null;
|
||||||
if (type !== 'permission_request') return null;
|
if (type !== 'permission_request') return null;
|
||||||
const requestId = typeof structured.request_id === 'string' ? structured.request_id : null;
|
const requestId = typeof structured.request_id === 'string' ? structured.request_id : null;
|
||||||
if (!requestId) return null;
|
return requestId || null;
|
||||||
|
}, [structured]);
|
||||||
const resolved = resolvedApprovals.get(requestId);
|
const permissionIcon = permissionRequestId ? (
|
||||||
if (resolved === true) {
|
<PermissionStatusIcon requestId={permissionRequestId} />
|
||||||
return <Check size={12} className="text-emerald-400" />;
|
) : null;
|
||||||
}
|
|
||||||
if (resolved === false) {
|
|
||||||
return <X size={12} className="text-red-400" />;
|
|
||||||
}
|
|
||||||
const isPending = pendingApprovals.some((a) => a.requestId === requestId);
|
|
||||||
if (isPending) {
|
|
||||||
return <Clock size={12} className="animate-pulse text-amber-400" />;
|
|
||||||
}
|
|
||||||
// Not in pending and not resolved — already handled before we started tracking
|
|
||||||
return <Check size={12} className="text-emerald-400/50" />;
|
|
||||||
}, [structured, pendingApprovals, resolvedApprovals]);
|
|
||||||
|
|
||||||
// Noise messages: minimal inline row
|
// Noise messages: minimal inline row
|
||||||
if (noiseLabel) {
|
if (noiseLabel) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue