Head 61843a4e3b4ca9cf087c1d2fcc9bac57002a8691 Target hotfix/release-0.0.23/wls-21-priority at c7ea08dfbd18ffc31ec8261a249e27d46bbd0df1 Merge base 91dd0ed2c5487d0740707e676f79f90e3d432eb7
Should I merge it now? Yes.
I would merge 61843a4e3b4 within the agreed scope.
The search and live-history repairs still pass. The new tab changes preserve creator badge updates and tab selection, while removing the tabset entirely for fans. Stable keys also keep the shared delegation tabs intact when their options are cloned.
Socket tab movement remains deferred as agreed in the PR 10896 review. The fan count example depends on an unverified backend response shape and is not a confirmed merge blocker. Neither concern becomes a new blocker just because this PR carries the same code to another branch.
GitHub reports the PR open, ready for review, and mergeable with a clean merge state. It lists no status checks or submitted reviews. The yes recommendation comes from the source review and focused checks below.
What this PR carries
The PR changes eight files relative to its merge base. The target branch has separate changes, so a direct comparison between the two branch tips also lists unrelated work. I used the merge-base comparison and GitHub's changed-file list for the review scope.
The inbox requests the server's tab, counts, and cursor. History requests validation with the first direct-message page and prepends older pages. Live entries survive the first history response. Presence polling and paged New Message recipients are also included.
Compared with the approved 425977eec067 head from PR 10896, the new implementation changes only three files, with 23 additions and 16 deletions. Those files are the shared tab template and the message container's template and TypeScript file. The five other files match the previously reviewed implementation.
The template now creates app-tab-view only when isCreator is true. Hiding the element previously left its tabset alive, with selection callbacks still attached. Fans now have no tabset to recreate.
The selection handler also ignores fan callbacks and repeated selections. The fan profile setup retains General by key, rather than leaving the first Priority option behind.
The Angular fixture rendered zero fan tabs through 25 repeated field updates. It emitted no extra selection events and no NG0955 or NG0956 warnings. The component-method fixture also confirmed that a fan callback leaves the active tab at General without starting an inbox refresh.
The shared loop tracks each option's key instead of its object identity. A deep clone of the field therefore keeps the existing ngx-bootstrap tabs. I checked both callers, Messages and Delegation. Both provide distinct keys.
Messages also stops cloning its field for badge and active-tab updates. The component uses normal Angular change detection, and the real-template fixture confirmed that changing counts in place paints Priority 7 and General 2. Selecting General emitted once and retained the same tab instances.
The delegation fixture used its two existing keys. Cloning the options retained both tab instances. Removing Delegated Access left the original My Delegates instance in place.
The message loop calls trackThreadMessage. It keeps the existing sk and optimistic uinqueId choices, then uses message_id when those identifiers are absent. Timestamp and object identity are the remaining fallbacks.
The extracted-method check returned distinct keys for two rows with only message_id. It also confirmed the legacy identifier precedence and object fallback. This fixes the case where the old expression returned an absent key for both rows.
Checks and limits
Check on 61843a4e3b4
Result
Creator tabs, badge updates, and General selection
Passed. Three tabs, updated counts, one selection event.
Cloned keyed options and delegation option removal
Passed. Existing tab instances retained.
Fan tab rendering through 25 updates
Passed. No tabset and no NG0955 or NG0956 warnings in the fixture.
Actual badge, tab-selection, and message-tracking methods
Passed. Stable field references, guarded fan callbacks, correct key fallbacks.
Return to the previous search within the debounce window
Passed. Loader stays false and the next-page cursor remains.
Live entry arrives before the first history response
Passed. The entry remains visible after the response.
History duplicate ID, request error, and conversation switch
Passed under the fixture inputs. Live entries survive and unrelated entries are excluded.
Ordinary same-tab live preview and unread increment
Passed.
Cursor containing plus, slash, and equals
Encoded without changing the value.
Whitespace check for the full PR diff
git diff --check passed.
Local merge calculation against the recorded target
git merge-tree completed without conflicts.
Full application builds and main or generated-tenant SSR
Not run for this review.
Signed-in staging creator and fan flows
Not run for this review. The PR checklist remains unchecked.
The tab checks use Angular TestBed, the real shared template, and real ngx-bootstrap tab directives with a domino DOM. A small decorated component shell supplies the inputs and output, and a minimal host reproduces the source template's creator condition. The fixture uses zone-based change detection, matching the application configuration. It is not a browser session running the complete Messages page.
The method checks extract the current methods verbatim with the TypeScript parser. They use the repository's TypeScript and RxJS packages, with network and unrelated Angular effects stubbed. Search uses real RxJS operators with virtual time.
The history duplicate check uses matching stable IDs in the socket entry and response. These tests do not establish every backend identifier format, presence response, or recipient pagination path. The successful merge calculation establishes conflict resolution only. It does not replace a build.
Follow-up work stays outside this merge decision
Socket tab movement still leaves a loaded row in its old tab under the recorded test event. The user deferred that investigation during the PR 10896 review.
The synthetic split-count fan example still produces the earlier discrepancy. A live fan response has not established that count shape. Verify the backend contract before treating it as a product defect.
I have kept both points visible without turning them into merge blockers. This review found no new blocker in the changes since the approved PR 10896 head.