Skip to content

List personalization: 「恢复视图默认」 clears the reader's stored setting instead of copying the default into it — today the reader stays on the old value after the view changes #28948

Closed

Description

@objectstack-fleet

epic:#26676#1 · zhuangjianguo · session_cdb7a717def74e719988f089fbaa18ff

Filed by the record-page epic seat from a review of list personalization under epic #26676. An independent reviewer read the code and tested on examples/app-crm, and the seat re-read the evidence. The maintainer: 「把「恢复默认清除偏好」、「账号偏好字段校验」、「个性化标记与统一重置」立卡,并收窄 #28912 的验收。命名个人视图暂不做。」 (2026-11-02). Code readings below are on main a36409337b. No domain:* label is set: triage routes this card.

Business reason

A reader restores the list's density, hidden columns or sort to the view's default. Later an admin changes that view's default. The reader should follow the view, and today does not: the "reset" stored the old default as the reader's own choice.

Measured

  • On the lead list, the reviewer changed the density and pressed 「恢复视图默认设置」. The list looked right, and the reader's sys_user_preference row held rowHeight: "compact" instead of nothing.
  • Because an entry remains, the header ⋯ keeps offering 「重置视图」.

Reading

  • ui/packages/plugin-list/src/ListView.tsx:5456, resetDisplayToViewDefault: it writes density and hidden fields through the controls' own doors (density.setMode, updateHiddenFields), so the host stores them as a choice.
  • ListView.tsx:5169, handleResetSort: it notifies onSortChange, so a host persists "a reset exactly as it persists a header click".
  • ui/packages/app-shell/src/context/ListPreferencesProvider.tsx:205-216: a patch key of undefined or null clears that part, and sort: [] and hiddenFields: [] are real choices. The clear already exists, and these paths do not use it.
  • ui/packages/app-shell/src/views/objectViewListRenderer.tsx:197-199, 373-376: the persist callbacks.

Target

  1. 「恢复视图默认设置」 and 「恢复视图默认排序」 clear the matching parts of the reader's preference. A view left with nothing is removed, as the provider already does.
  2. The host needs a way to tell a reset from a choice. plugin-list cannot import the provider, so this is a prop or a callback value between the two. It is not a metadata key.
  3. A deliberate choice is unchanged: sort: [] ("no sort") and hiddenFields: [] ("show every column") stay stored.
  4. Display settings that are not in the preference (row color, row numbers, inline edit, layout) behave as today.

Acceptance

  • Change the density, press restore: the view's entry has no rowHeight. Change the view's rowHeight: the reader sees the new value.
  • The same for hidden fields on a view that stores them, and for sort through the sort popover.
  • With nothing else stored, the ⋯ 「重置视图」 entry disappears after a restore.
  • Removing every sort level, or showing every column by hand, still survives a reload.
  • Tests pin each case at the host seam, not only in ListView.

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: priority:p2 · domain:ui · pm:queue · 2026-11-02T05:01Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    domain:uiDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

    Claim: PM loop round 16 · 2026-11-02T05:24Z
    Session: session_01QsR2jTivKAK8N8dfW5mn9D (card thread, os-dev); dispatched by seat session session_01QsR2jUJ19MstFvFhjgiYTu
    Account: zhuangjianguo
    Branch: claude/project-thread-gbdojf (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-28948
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: ui/packages/plugin-list/src/ListView.tsx (resetDisplayToViewDefault and the sort reset), ui/packages/app-shell/src/views/objectViewListRenderer.tsx, ui/packages/app-shell/src/context/ListPreferencesProvider.tsx, their tests, and a root .changeset (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: yes (widening)
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6569483642
    Premise: holds (at origin/main f7c545ad: ListView.tsx resetDisplayToViewDefault re-applies the view defaults through each control's door, so the host stores them as the reader's own choice instead of clearing the stored preference)
    Serial constraints cleared: none known. #28950 (seat 1) follows after this lands; #28949 edits objectViewListUrlState.ts beside ListPreferencesProvider in parallel.

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jTivKAK8N8dfW5mn9D
    os-dev-report

    {
      "issue": 28948,
      "status": "done",
      "branch": "claude/project-thread-gbdojf",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29044",
      "session": "session_01QsR2jTivKAK8N8dfW5mn9D",
      "premise_still_valid": true,
      "summary": "ListView gains host prop onRestoreViewDefaults(parts) ('sort' | 'hiddenFields' | 'rowHeight') and viewDefaults gains sort. With the prop wired, the Display control's and the sort popover's 'Reset to view default' name the parts they returned to the view's own and no longer write the view's values through onHiddenFieldsChange / schema.onDensityChange / onSortChange; sort and hidden fields are put back locally at once, density follows schema.rowHeight after the host's clear. The console object page passes viewDefaults.sort (the view's own sort) and wires restoreViewDefaults, which patches each named part to null via listPrefs.patchView (an empty view entry is removed, so the header Reset view goes) and drops sort from the URL. Deliberate sort: [] / hiddenFields: [] still stored; other Display settings unchanged; hosts without the prop unchanged. Behaviour note: the console's sort reset now returns to the view's own sort, not the sort the list opened with. Premise held at origin/main fed3a51b. File surface: ListView.tsx, objectViewListRenderer.tsx, ListPreferencesProvider.tsx (docblock), their tests (new ListView.restoreViewDefaults-28948.test.tsx; ObjectView.userListState-12418.test.tsx), .changeset/list-reset-clears-stored-preference.md (patch, Clause-② yes (widening), Metadata-protocol none) -- no breach.",
      "tests": "At eda72c06 under os-verify-lock after turbo build app-shell^... + plugin-list^... + formula/sdui-parser/lint/client (64 tasks, exit 0): ui vitest packages/plugin-list/ + 16 git-grep-selected app-shell/console/plugin-view files, --maxWorkers=2 -> Test Files 196 passed (196), Tests 1907 passed (1907) (declared narrowing for app-shell; CI Test UI runs the rest). New file 6/6; host file 32/32. type-check plugin-list and app-shell exit 0. ESLint on changed tsx exit 0, 0 errors. Ablations via scripts/ablation-replace.mjs (source-resolved, no dist), each restored blob == HEAD, git diff HEAD empty: sort reset back to emitSortChange -> 1 failed/5 passed; density leg dropped -> 2 failed/4 passed; host stores view values instead of null -> 4 failed/28 passed in the host file. First density ablation attempt refused by the tool (replacement count did not rise), rerun with a unique replacement.",
      "gates": "dispatch-gates --commands at eda72c06: 35 derived, 35 run, each exit 0 (check:type-check-debt and pnpm --dir ui exec vitest run scripts/ under the lock, the latter 169 passed / 2 skipped); check-sdui-manifest exit 0; PR-body gates re-run on the final body as GITHUB_EVENT_PATH (changeset-no-major, adr-0087-registration, closing-keyword-parity, empty-changeset) exit 0; check-partof-closing-keyword with PR_BODY exit 0; ui check:new-line-citations 0 new. --ran: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN. CI at pr_create: 17 in_progress, 3 skipped, 0 failed.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "7 — issue_read x3 (get, get_comments x2), pull_request_read x1 (get_check_runs), ToolSearch loads x3; no write tool",
      "api_writes": "5 — git push x4 (branch), fleet-write pr_create (POST /repos/objectstack-ai/objectstack/dispatches -> relay run 41399507825, PR #29044, body read back 8704/8704 identical, no assignees), this os-dev-report comment via post-stamped",
      "open_questions": [],
      "out_of_scope_findings": []
    }
  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

    Landed · 2026-11-02T07:23Z · PR #29044 merged through the merge queue as 12aad143 at 2026-11-02T07:17Z (GitHub's clock). ACCEPT 6570766659 at head eda72c06.

    probe before (12aad143~1) now (origin/main)
    onRestoreViewDefaults in plugin-list/src/ListView.tsx 0 11
    restoreViewDefaults in app-shell/src/views/objectViewListRenderer.tsx 0 2
    ListView.restoreViewDefaults-28948.test.tsx exists no yes

    Fixes #28948 closed this card. pm:dispatched comes off in the same stroke as this note.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:uiDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions