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();
|
updateCountBadge();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getActionTargets(items) {
|
// Returns an array of message IDs to act on.
|
||||||
var targets = [];
|
// 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) {
|
if (selectedIds.size > 0) {
|
||||||
selectedIds.forEach(function (id) {
|
selectedIds.forEach(function (id) { ids.push(id); });
|
||||||
var idx = findItemById(items, id);
|
|
||||||
if (idx >= 0) targets.push(items[idx]);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
var fi = getFocusedIndex(items);
|
if (focusedId) ids.push(focusedId);
|
||||||
if (fi >= 0) targets.push(items[fi]);
|
|
||||||
}
|
}
|
||||||
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 ---
|
// --- Selection count badge ---
|
||||||
@@ -255,36 +261,48 @@ window.OutlookRelook.Keyboard = (function () {
|
|||||||
target.dispatchEvent(overEvent);
|
target.dispatchEvent(overEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
function performAction(targets, actionFn) {
|
// performAction takes an array of IDs (strings), re-resolves each to a
|
||||||
if (targets.length === 0) return;
|
// 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;
|
var i = 0;
|
||||||
function processNext() {
|
function processNext() {
|
||||||
if (i >= targets.length) {
|
if (i >= ids.length) {
|
||||||
clearSelection();
|
clearSelection();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var target = targets[i];
|
var id = ids[i];
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
// First, try to find the inline button without clicking the row.
|
// Re-resolve the ID to the current DOM element each iteration
|
||||||
// Hover to make OWA's inline action buttons appear.
|
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);
|
triggerHover(target);
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
// Try inline button first (avoids opening the email in fill-screen mode)
|
|
||||||
var inlineHandled = actionFn(target);
|
var inlineHandled = actionFn(target);
|
||||||
|
|
||||||
// If inline button wasn't found, fall back to clicking the row + toolbar
|
|
||||||
if (inlineHandled === false) {
|
if (inlineHandled === false) {
|
||||||
|
// Fallback: click the row + use toolbar
|
||||||
target.click();
|
target.click();
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
actionFn(target);
|
// Re-resolve once more in case clicking caused a re-render
|
||||||
setTimeout(processNext, 200);
|
var freshTarget = resolveTargetById(id) || target;
|
||||||
|
actionFn(freshTarget);
|
||||||
|
setTimeout(processNext, 250);
|
||||||
}, 150);
|
}, 150);
|
||||||
} else {
|
} else {
|
||||||
setTimeout(processNext, 200);
|
// Wait long enough for OWA to finish re-rendering before next action
|
||||||
|
setTimeout(processNext, 300);
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 120);
|
||||||
}
|
}
|
||||||
processNext();
|
processNext();
|
||||||
}
|
}
|
||||||
@@ -316,18 +334,19 @@ window.OutlookRelook.Keyboard = (function () {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function actionMove(targets) {
|
function actionMove(ids) {
|
||||||
if (targets.length > 0) {
|
if (!ids || ids.length === 0) return;
|
||||||
triggerHover(targets[0]);
|
var first = resolveTargetById(ids[0]);
|
||||||
setTimeout(function () {
|
if (!first) return;
|
||||||
var btn = findButton(targets[0], 'Move to');
|
triggerHover(first);
|
||||||
if (btn) {
|
setTimeout(function () {
|
||||||
btn.click();
|
var btn = findButton(first, 'Move to');
|
||||||
} else {
|
if (btn) {
|
||||||
triggerContextMenuAction(targets[0], /move to/i);
|
btn.click();
|
||||||
}
|
} else {
|
||||||
}, 150);
|
triggerContextMenuAction(first, /move to/i);
|
||||||
}
|
}
|
||||||
|
}, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
function actionFlag(targets) {
|
function actionFlag(targets) {
|
||||||
@@ -423,22 +442,22 @@ window.OutlookRelook.Keyboard = (function () {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
toggleSelect(items, currentIdx);
|
toggleSelect(items, currentIdx);
|
||||||
} else if (matchesAction(e, preset.delete)) {
|
} else if (matchesAction(e, preset.delete)) {
|
||||||
targets = getActionTargets(items);
|
targets = getActionTargetIds(items);
|
||||||
actionDelete(targets);
|
actionDelete(targets);
|
||||||
} else if (matchesAction(e, preset.archive)) {
|
} else if (matchesAction(e, preset.archive)) {
|
||||||
targets = getActionTargets(items);
|
targets = getActionTargetIds(items);
|
||||||
actionArchive(targets);
|
actionArchive(targets);
|
||||||
} else if (matchesAction(e, preset.readUnread)) {
|
} else if (matchesAction(e, preset.readUnread)) {
|
||||||
targets = getActionTargets(items);
|
targets = getActionTargetIds(items);
|
||||||
actionMarkReadUnread(targets);
|
actionMarkReadUnread(targets);
|
||||||
} else if (matchesAction(e, preset.move)) {
|
} else if (matchesAction(e, preset.move)) {
|
||||||
targets = getActionTargets(items);
|
targets = getActionTargetIds(items);
|
||||||
actionMove(targets);
|
actionMove(targets);
|
||||||
} else if (matchesAction(e, preset.flag)) {
|
} else if (matchesAction(e, preset.flag)) {
|
||||||
targets = getActionTargets(items);
|
targets = getActionTargetIds(items);
|
||||||
actionFlag(targets);
|
actionFlag(targets);
|
||||||
} else if (matchesAction(e, preset.pin)) {
|
} else if (matchesAction(e, preset.pin)) {
|
||||||
targets = getActionTargets(items);
|
targets = getActionTargetIds(items);
|
||||||
actionPin(targets);
|
actionPin(targets);
|
||||||
} else if (matchesAction(e, preset.deselect)) {
|
} else if (matchesAction(e, preset.deselect)) {
|
||||||
clearSelection();
|
clearSelection();
|
||||||
|
|||||||
Reference in New Issue
Block a user