fix(dashboard): parse Codex reset_at as epoch ms or seconds
Codex returns weekly window reset_at in milliseconds in some cases, which was being multiplied by 1000 and producing nonsensical reset countdowns and pace calculations. Route through _parseResetTimestamp so both formats work, and add a regression test. Also tightens comments in useMobileKeyboard / ChatView around why visualViewport scroll events skip offsetTop updates. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1106,9 +1106,10 @@
|
||||
.chat-thread--keyboard-active {
|
||||
height: calc(var(--vv-height, calc(100dvh - var(--keyboard-overlap, 0px))) - var(--header-height));
|
||||
max-height: calc(var(--vv-height, calc(100dvh - var(--keyboard-overlap, 0px))) - var(--header-height));
|
||||
/* useMobileKeyboard pins --vv-offset-top across pan-time scroll
|
||||
events (only resize/focus update it), so this transform anchors
|
||||
the thread on initial focus without juddering during swipes. */
|
||||
/* Re-anchored: useMobileKeyboard now only updates --vv-offset-top
|
||||
on resize/focus transitions (not on every visualViewport scroll
|
||||
during a pan), so the transform tracks the keyboard open/close
|
||||
without jittering during a swipe. */
|
||||
transform: translateY(var(--vv-offset-top, 0px));
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
@@ -540,7 +540,6 @@ export function ListView({
|
||||
return sortDirection === "asc" ? comparison : -comparison;
|
||||
});
|
||||
}
|
||||
|
||||
return groups;
|
||||
}, [tasks, searchQuery, sortField, sortDirection, hideDoneTasks, selectedColumn]);
|
||||
|
||||
|
||||
@@ -133,8 +133,9 @@ export function useMobileKeyboard(
|
||||
return;
|
||||
}
|
||||
|
||||
// Full update for resize + focus transitions (real keyboard
|
||||
// open/close events).
|
||||
// Full update — used on resize and focus transitions. These are the
|
||||
// events that signal an actual keyboard open/close, so we want to
|
||||
// re-snapshot offsetTop/height/overlap.
|
||||
const update = () => {
|
||||
const metrics = getKeyboardMetrics();
|
||||
setKeyboardOverlap(metrics.overlap);
|
||||
@@ -143,13 +144,13 @@ export function useMobileKeyboard(
|
||||
setKeyboardOpen(metrics.open);
|
||||
};
|
||||
|
||||
// Scroll-only update: visualViewport.scroll fires at 60fps during
|
||||
// an iOS pan with the keyboard up. Routing offsetTop through React
|
||||
// state on every event amplifies the pan into a visible judder via
|
||||
// the .chat-thread translateY(--vv-offset-top) transform. We skip
|
||||
// offsetTop here; it stays pinned to whatever resize/focus last
|
||||
// captured. Other metrics still update so a true viewport shrink
|
||||
// is reflected.
|
||||
// Scroll-only update — fires on every visualViewport pan (60fps on
|
||||
// iOS during a swipe with the keyboard up). Updating offsetTop on
|
||||
// each event amplifies jitter into the .chat-thread transform that
|
||||
// tracks --vv-offset-top, visibly judders the thread, and can shift
|
||||
// it hundreds of px. We deliberately skip offsetTop here and only
|
||||
// update height/keyboardOpen if those changed; offsetTop stays
|
||||
// pinned to whatever resize/focus last set it.
|
||||
const updateScrollOnly = () => {
|
||||
const metrics = getKeyboardMetrics();
|
||||
setKeyboardOverlap(metrics.overlap);
|
||||
|
||||
Reference in New Issue
Block a user