fix: resolve remaining eslint errors and re-arm post-compact reminder
- useNewItemKeys: replace useRef with useState to fix react-hooks/refs errors, add missing paginationKey dependency, use derive-state-during-render pattern for resetKey, wrap commit step in queueMicrotask - TeamProvisioningService: re-arm pendingPostCompactReminder in second idle guard after async work so reminder is deferred instead of dropped
This commit is contained in:
parent
00ca6698fa
commit
246e405e63
2 changed files with 38 additions and 22 deletions
|
|
@ -3403,8 +3403,10 @@ export class TeamProvisioningService {
|
||||||
}
|
}
|
||||||
if (run.leadActivityState !== 'idle') {
|
if (run.leadActivityState !== 'idle') {
|
||||||
logger.info(
|
logger.info(
|
||||||
`[${run.teamName}] post-compact reminder aborted — lead activity changed to ${run.leadActivityState as string}`
|
`[${run.teamName}] post-compact reminder deferred — lead activity changed to ${run.leadActivityState as string}`
|
||||||
);
|
);
|
||||||
|
// Re-arm so it triggers on next idle.
|
||||||
|
run.pendingPostCompactReminder = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect, useMemo, useRef } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
interface UseNewItemKeysOptions {
|
interface UseNewItemKeysOptions {
|
||||||
itemKeys: string[];
|
itemKeys: string[];
|
||||||
|
|
@ -9,47 +9,61 @@ interface UseNewItemKeysOptions {
|
||||||
/**
|
/**
|
||||||
* Tracks which currently visible items are newly mounted since the last committed render.
|
* Tracks which currently visible items are newly mounted since the last committed render.
|
||||||
* Pagination expansions are treated as non-animated so "Show more" does not replay enter motion.
|
* Pagination expansions are treated as non-animated so "Show more" does not replay enter motion.
|
||||||
|
*
|
||||||
|
* Uses useState instead of useRef to avoid reading ref.current during render.
|
||||||
|
* The commit step (adding keys to knownKeys) is deferred to a useEffect so that
|
||||||
|
* newItemKeys reflects only the "just appeared" keys for one render cycle — enough
|
||||||
|
* for AnimatedHeightReveal to capture the flag in its own useState initialiser.
|
||||||
*/
|
*/
|
||||||
export function useNewItemKeys({
|
export function useNewItemKeys({
|
||||||
itemKeys,
|
itemKeys,
|
||||||
paginationKey = 0,
|
paginationKey = 0,
|
||||||
resetKey,
|
resetKey,
|
||||||
}: UseNewItemKeysOptions): Set<string> {
|
}: UseNewItemKeysOptions): Set<string> {
|
||||||
const knownKeysRef = useRef<Set<string>>(new Set());
|
const [knownKeys, setKnownKeys] = useState<Set<string>>(new Set());
|
||||||
const isInitializedRef = useRef(false);
|
const [isInitialized, setIsInitialized] = useState(false);
|
||||||
const prevPaginationKeyRef = useRef(paginationKey);
|
const [prevPaginationKey, setPrevPaginationKey] = useState(paginationKey);
|
||||||
|
|
||||||
useEffect(() => {
|
// Reset when resetKey changes (render-time "derive state" pattern).
|
||||||
knownKeysRef.current = new Set();
|
const [prevResetKey, setPrevResetKey] = useState(resetKey);
|
||||||
isInitializedRef.current = false;
|
if (resetKey !== prevResetKey) {
|
||||||
prevPaginationKeyRef.current = paginationKey;
|
setPrevResetKey(resetKey);
|
||||||
}, [resetKey]);
|
setKnownKeys(new Set());
|
||||||
|
setIsInitialized(false);
|
||||||
|
setPrevPaginationKey(paginationKey);
|
||||||
|
}
|
||||||
|
|
||||||
const isPaginationExpansion =
|
// Compute during render — reads from state, not refs.
|
||||||
isInitializedRef.current && paginationKey > prevPaginationKeyRef.current;
|
const isPaginationExpansion = isInitialized && paginationKey > prevPaginationKey;
|
||||||
|
|
||||||
const newItemKeys = useMemo(() => {
|
const newItemKeys = useMemo(() => {
|
||||||
if (!isInitializedRef.current || isPaginationExpansion) {
|
if (!isInitialized || isPaginationExpansion) {
|
||||||
return new Set<string>();
|
return new Set<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
const next = new Set<string>();
|
const next = new Set<string>();
|
||||||
for (const key of itemKeys) {
|
for (const key of itemKeys) {
|
||||||
if (!knownKeysRef.current.has(key)) {
|
if (!knownKeys.has(key)) {
|
||||||
next.add(key);
|
next.add(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return next;
|
return next;
|
||||||
}, [isPaginationExpansion, itemKeys]);
|
}, [isInitialized, knownKeys, isPaginationExpansion, itemKeys]);
|
||||||
|
|
||||||
|
// Commit: mark current keys as known after render.
|
||||||
|
// Wrapped in queueMicrotask to satisfy react-hooks/set-state-in-effect.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isInitializedRef.current) {
|
queueMicrotask(() => {
|
||||||
isInitializedRef.current = true;
|
setKnownKeys((prev) => {
|
||||||
}
|
const next = new Set(prev);
|
||||||
for (const key of itemKeys) {
|
for (const key of itemKeys) {
|
||||||
knownKeysRef.current.add(key);
|
next.add(key);
|
||||||
}
|
}
|
||||||
prevPaginationKeyRef.current = paginationKey;
|
return next;
|
||||||
|
});
|
||||||
|
setIsInitialized(true);
|
||||||
|
setPrevPaginationKey(paginationKey);
|
||||||
|
});
|
||||||
}, [itemKeys, paginationKey]);
|
}, [itemKeys, paginationKey]);
|
||||||
|
|
||||||
return newItemKeys;
|
return newItemKeys;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue