From 48a0ae435aa1c054ce985f151a31533313f3d2a5 Mon Sep 17 00:00:00 2001 From: Intenzi Date: Thu, 16 Jul 2026 16:06:00 +0530 Subject: [PATCH 1/2] fix: delete post-lock payload when tab is hidden - Defer heartbeat-send listener registration to run after WP Core's handler --- includes/heartbeat.php | 48 +++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/includes/heartbeat.php b/includes/heartbeat.php index eea2b36..cd75eaf 100644 --- a/includes/heartbeat.php +++ b/includes/heartbeat.php @@ -149,32 +149,36 @@ function wp_presence_enqueue_heartbeat_ping() { // Guards against duplicate leave() invocations. let hasLeft = false; - $(document).on('heartbeat-send', function (event, data) { - // Skip while the document is hidden (background tab, minimized - // window, app switched away) so the existing entries expire via - // the default TTL. One early-return suppresses both presence-ping - // and presence-editor-ping, since the consolidated handler emits - // both. - if (document.visibilityState === 'hidden') { - return; - } - - const ping = { screen: window.pagenow || 'front' }; - if (frontContext) { - if (frontContext.title) { - ping.title = frontContext.title; + // Defer registration to document ready to ensure it runs after WP Core's post.js handler. + $(function () { + $(document).on('heartbeat-send', function (event, data) { + // Skip while the document is hidden (background tab, minimized + // window, app switched away) so the existing entries expire via + // the default TTL. One early-return suppresses both presence-ping + // and presence-editor-ping, since the consolidated handler emits + // both. + if (document.visibilityState === 'hidden') { + delete data['wp-refresh-post-lock']; + return; } - if (frontContext.post_id) { - ping.post_id = frontContext.post_id; + + const ping = { screen: window.pagenow || 'front' }; + if (frontContext) { + if (frontContext.title) { + ping.title = frontContext.title; + } + if (frontContext.post_id) { + ping.post_id = frontContext.post_id; + } } - } - data['presence-ping'] = ping; + data['presence-ping'] = ping; - if (editorPostId) { - data['presence-editor-ping'] = { post_id: editorPostId }; - } + if (editorPostId) { + data['presence-editor-ping'] = { post_id: editorPostId }; + } - hasLeft = false; + hasLeft = false; + }); }); function leave() { From 1a67dd600b70d5057dfb9edfa895f1f2dada43b2 Mon Sep 17 00:00:00 2001 From: Intenzi Date: Thu, 16 Jul 2026 20:27:00 +0530 Subject: [PATCH 2/2] test: assert wp-refresh-post-lock is deleted when editor tab is hidden --- tests/e2e/presence-visibility.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/e2e/presence-visibility.test.js b/tests/e2e/presence-visibility.test.js index af143cf..38718a8 100644 --- a/tests/e2e/presence-visibility.test.js +++ b/tests/e2e/presence-visibility.test.js @@ -89,7 +89,7 @@ test.describe( 'Presence Visibility', () => { expect( visible[ 'presence-ping' ].screen ).toBeTruthy(); } ); - test( 'heartbeat-send omits presence-editor-ping while editor tab is hidden', async ( { + test( 'heartbeat-send omits presence-editor-ping and wp-refresh-post-lock while editor tab is hidden', async ( { admin, page, requestUtils, @@ -108,6 +108,7 @@ test.describe( 'Presence Visibility', () => { await setVisibility( page, 'hidden' ); const hidden = await captureHeartbeatSend( page ); expect( hidden[ 'presence-editor-ping' ] ).toBeUndefined(); + expect( hidden[ 'wp-refresh-post-lock' ] ).toBeUndefined(); await setVisibility( page, 'visible' ); const visible = await captureHeartbeatSend( page );