fix: track action targets by ID, re-resolve before each action to survive re-renders
This commit is contained in:
@@ -176,18 +176,24 @@ window.OutlookRelook.Keyboard = (function () {
|
||||
updateCountBadge();
|
||||
}
|
||||
|
||||
function getActionTargets(items) {
|
||||
var targets = [];
|
||||
// Returns an array of message IDs to act on.
|
||||
// We return IDs (not DOM elements) because OWA re-renders rows after each
|
||||
// action, invalidating direct element references.
|
||||
function getActionTargetIds(items) {
|
||||
var ids = [];
|
||||
if (selectedIds.size > 0) {
|
||||
selectedIds.forEach(function (id) {
|
||||
var idx = findItemById(items, id);
|
||||
if (idx >= 0) targets.push(items[idx]);
|
||||
});
|
||||
selectedIds.forEach(function (id) { ids.push(id); });
|
||||
} else {
|
||||
var fi = getFocusedIndex(items);
|
||||
if (fi >= 0) targets.push(items[fi]);
|
||||
if (focusedId) ids.push(focusedId);
|
||||
}
|
||||
return targets;
|
||||
return ids;
|
||||
}
|
||||
|
||||
// Re-resolve an ID to the current DOM element (or null if it's gone).
|
||||
function resolveTargetById(id) {
|
||||
var items = getMessageItems();
|
||||
var idx = findItemById(items, id);
|
||||
return idx >= 0 ? items[idx] : null;
|
||||
}
|
||||
|
||||
// --- Selection count badge ---
|
||||
@@ -255,36 +261,48 @@ window.OutlookRelook.Keyboard = (function () {
|
||||
target.dispatchEvent(overEvent);
|
||||
}
|
||||
|
||||
function performAction(targets, actionFn) {
|
||||
if (targets.length === 0) return;
|
||||
// performAction takes an array of IDs (strings), re-resolves each to a
|
||||
// fresh DOM element before acting, and processes them sequentially.
|
||||
// This handles OWA's re-renders that invalidate stale element references.
|
||||
function performAction(ids, actionFn) {
|
||||
if (!ids || ids.length === 0) return;
|
||||
var i = 0;
|
||||
function processNext() {
|
||||
if (i >= targets.length) {
|
||||
if (i >= ids.length) {
|
||||
clearSelection();
|
||||
return;
|
||||
}
|
||||
var target = targets[i];
|
||||
var id = ids[i];
|
||||
i++;
|
||||
|
||||
// First, try to find the inline button without clicking the row.
|
||||
// Hover to make OWA's inline action buttons appear.
|
||||
// Re-resolve the ID to the current DOM element each iteration
|
||||
var target = resolveTargetById(id);
|
||||
if (!target) {
|
||||
// Element no longer exists (e.g., already deleted) — skip to next
|
||||
processNext();
|
||||
return;
|
||||
}
|
||||
|
||||
// Hover to make OWA's inline action buttons appear
|
||||
triggerHover(target);
|
||||
|
||||
setTimeout(function () {
|
||||
// Try inline button first (avoids opening the email in fill-screen mode)
|
||||
var inlineHandled = actionFn(target);
|
||||
|
||||
// If inline button wasn't found, fall back to clicking the row + toolbar
|
||||
if (inlineHandled === false) {
|
||||
// Fallback: click the row + use toolbar
|
||||
target.click();
|
||||
setTimeout(function () {
|
||||
actionFn(target);
|
||||
setTimeout(processNext, 200);
|
||||
// Re-resolve once more in case clicking caused a re-render
|
||||
var freshTarget = resolveTargetById(id) || target;
|
||||
actionFn(freshTarget);
|
||||
setTimeout(processNext, 250);
|
||||
}, 150);
|
||||
} else {
|
||||
setTimeout(processNext, 200);
|
||||
// Wait long enough for OWA to finish re-rendering before next action
|
||||
setTimeout(processNext, 300);
|
||||
}
|
||||
}, 100);
|
||||
}, 120);
|
||||
}
|
||||
processNext();
|
||||
}
|
||||
@@ -316,19 +334,20 @@ window.OutlookRelook.Keyboard = (function () {
|
||||
});
|
||||
}
|
||||
|
||||
function actionMove(targets) {
|
||||
if (targets.length > 0) {
|
||||
triggerHover(targets[0]);
|
||||
function actionMove(ids) {
|
||||
if (!ids || ids.length === 0) return;
|
||||
var first = resolveTargetById(ids[0]);
|
||||
if (!first) return;
|
||||
triggerHover(first);
|
||||
setTimeout(function () {
|
||||
var btn = findButton(targets[0], 'Move to');
|
||||
var btn = findButton(first, 'Move to');
|
||||
if (btn) {
|
||||
btn.click();
|
||||
} else {
|
||||
triggerContextMenuAction(targets[0], /move to/i);
|
||||
triggerContextMenuAction(first, /move to/i);
|
||||
}
|
||||
}, 150);
|
||||
}
|
||||
}
|
||||
|
||||
function actionFlag(targets) {
|
||||
performAction(targets, function (target) {
|
||||
@@ -423,22 +442,22 @@ window.OutlookRelook.Keyboard = (function () {
|
||||
e.preventDefault();
|
||||
toggleSelect(items, currentIdx);
|
||||
} else if (matchesAction(e, preset.delete)) {
|
||||
targets = getActionTargets(items);
|
||||
targets = getActionTargetIds(items);
|
||||
actionDelete(targets);
|
||||
} else if (matchesAction(e, preset.archive)) {
|
||||
targets = getActionTargets(items);
|
||||
targets = getActionTargetIds(items);
|
||||
actionArchive(targets);
|
||||
} else if (matchesAction(e, preset.readUnread)) {
|
||||
targets = getActionTargets(items);
|
||||
targets = getActionTargetIds(items);
|
||||
actionMarkReadUnread(targets);
|
||||
} else if (matchesAction(e, preset.move)) {
|
||||
targets = getActionTargets(items);
|
||||
targets = getActionTargetIds(items);
|
||||
actionMove(targets);
|
||||
} else if (matchesAction(e, preset.flag)) {
|
||||
targets = getActionTargets(items);
|
||||
targets = getActionTargetIds(items);
|
||||
actionFlag(targets);
|
||||
} else if (matchesAction(e, preset.pin)) {
|
||||
targets = getActionTargets(items);
|
||||
targets = getActionTargetIds(items);
|
||||
actionPin(targets);
|
||||
} else if (matchesAction(e, preset.deselect)) {
|
||||
clearSelection();
|
||||
|
||||
Reference in New Issue
Block a user