dsh-quick-toc 0.7.1 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.en.md CHANGED
@@ -1,235 +1,239 @@
1
- # Changelog
2
-
3
- All notable changes to **dsh-quick-toc** are documented here. Chinese version: [CHANGELOG.md](CHANGELOG.md).
4
-
5
- ## [0.7.1] - 2026-09-19
6
-
7
- ### Added
8
- - **A "back to where I scrolled to" button**: the outline already carried a "back to the newest row" button in the list's lower-right corner whenever it was not at the bottom; there is now a matching round button in the upper-right corner, arrow pointing up, that takes you back to **the row you were looking at when you left that surface**. The place is recorded **at close time**, and the docked panel and the curtain **keep their own** — neither overwrites the other. Reopening the surface is what lights the button up, and it returns that row to **where it sat** — if it was clipped by the viewport's top edge (which is what happens when the list is parked at the bottom), it goes home clipped by the same amount instead of being forced to the very top. Using the button once — or scrolling back there yourself — fades it out and forgets that record until the next close. It is placed from the list's measured start inside the surface, so neither the docked panel's grip bar and header row nor the curtain's own toolbar can sit on top of it, and it grows to 34px with the curtain.
9
-
10
- ### Changed
11
- - **Opening the panel or the curtain now lands on the row being read**: only the curtain did this before, while the panel simply showed wherever the list had last been left, so the two surfaces disagreed. One rule now: the turn currently being read is aligned to the top of the list, instantly. When that turn is one of the newest few the list is already at its end, so the row lands at the bottom — no clamping is involved.
12
- - **The panel's collapse and expand animation now uses `transform`**: it used to transition `left` (a layout property, so the whole panel — grip bar, header and every rendered outline row — was re-laid out on each frame) together with `clip-path`. On a long session the main thread could not keep up with the compositor, so collapsing turned into "a line sweeps across and the content it passes disappears" instead of the panel sliding away. The box now always sits parked at its collapsed spot and the open state is a transform on top of it: the visual geometry is unchanged, and the animation no longer slows down with the size of the list.
13
- - **Toolbar icon geometry calibrated**: the curtain button is a 12×9 landscape rectangle (centred on both axes) instead of a portrait slab, with its arrow pointing down and its tail landing on the rectangle's top edge; the level filter's three lines are heavier (2.2); the questions-only bubble keeps the same 2.2 outline and is slightly larger and a touch lower (the bubble is the visual body and the tail hangs off its lower left, so geometric centring reads as top-heavy); the ✕ and the magnifier drop their old 1px translate nudge in favour of geometry drawn exactly on centre — a nudge is half a pixel off at any other size.
14
- - The "remember reading position" and "auto-load history" rows in the settings card no longer carry a description.
15
-
16
- ### Fixed
17
- - **Paging through history "never caught up"**: once the reader reached the unloaded region, the auto-loader kept crawling at 50 messages per page every 130ms, so in a deep gap they were already there while the rows were still being filled in. There are now two paths: when a "not loaded" placeholder is actually in view, that turn's seq is paged in one hop (carrying an extra 8 rows of margin towards older history); only while merely approaching the prefetch band does it pull one page at a time. The same area held a misreading — the host's "load earlier" button is disabled while a page is in flight, and the plugin read "loading" as "reached the beginning", announcing "this is the oldest message" hundreds of turns early.
18
- - **The view being pushed away while loading, and "turning auto-load off still bounced"**: a placeholder row grows taller when it loads, pushing everything below it down. The compensation used to run inside `requestAnimationFrame` (one or two frames after the DOM change — the "jumps and springs back" the reader saw) and only covered loads the plugin itself started, so a page the host paged in had none at all. It now runs in a layout effect (same frame as the DOM change, before the browser paints), anchors on the **first real row** in view (the placeholders are exactly what grows, so anchoring below them is what lets new content grow upward out of the viewport), and the list carries `overflow-anchor: none` — the browser's own scroll anchoring also rewrites `scrollTop` for the same growth, and the two together push the content up.
19
- - **"It janks every so often / the longer it runs the slower it gets"**: the auto-follow read `getBoundingClientRect` for **every** message in the session on each pass — thousands of them, a dozen times a second — so the work grew with the length of the session. The node list is now cached and only re-scanned when the container or its end keys change, and the scan interval widens while the panel is collapsed.
20
- - **Auto-loading nudged the middle conversation upward**: before each page it lifted the conversation 26px out of the host's stick-to-bottom zone (0.5.1 added that so the host would not re-pin history paged in from the outline), but it did so on every page — the reader only touched the outline and saw the conversation move. The host side now relies on the outline's own quiet window, and the lift is gone entirely.
21
- - **One upward scroll could pull several pages**: the prefetch test measured the "loaded / not loaded" boundary row, which by definition sits against the viewport's top edge, so the condition was always true. It now measures from the nearest placeholder in view, with hysteresis.
22
- - **Opening the curtain left the list a little above the end and then walked it down; upward jumps landed inaccurately; opening scrolled down from above**: the follow **centred** the row being read, and for the newest turn the centred position lies past the end of the list, so it stopped half a viewport short; `revealGroupInOutline` used `scrollIntoView({ block: "nearest" })`, which scrolls the minimum distance (so the landing point was arbitrary) and animates. Both now share one rule — **that row goes to the top of the list, instantly**.
23
- - **The droplet stayed a little thick when pressed flat and then vanished a beat later**: the press ended at `scaleY(0.12)`, leaving about 2px of a 17px dome sitting on the strip, while the handle was not removed for another 220ms and its fade-out was deliberately delayed by 0.2s — so those 2px sat motionless for a beat and then the whole thing disappeared. Both ends are `scaleY(0)` now: pressed flush into the strip, and growing from zero on the way back.
24
-
25
- ## [0.7.0] - 2026-09-19
26
-
27
- ### Added
28
- - **A full-width "curtain" outline**: the view-tab strip along the top of the conversation now carries a droplet handle (half-transparent at rest, solid under the pointer, its base resting on the strip's lower line) — click it and the outline drops down across the full width of the conversation area. Its height is 82% of what is left of the conversation (at least 240px, at most 760px), its top edge meets the tab strip and its lower corners are rounded; there is no scrim and nothing underneath is dimmed, so the newest message and the composer stay reachable below it. Closing: click any row, press Esc, or use the ✕ in the upper-right corner; the "curtain" round button in the panel's header is the other way in. **It is not a second list** — the curtain is the panel itself moved into that container, so paging, search results, hover previews, the keyboard cursor and the reading position are all the same ones; switching from the panel to the curtain loses no state.
29
- - **Wide typography inside the curtain**: each row becomes three parts — the `H1–H6` level badge on the left, a larger heading in the middle, and the opening of that section in small type on the right; the level filter lays itself out on one line. The magnifier pushes the search column in from the right (360px), the outline column gives way to the left, and results land in that right column.
30
- - **A "jump to the end of this section" button on every row**: with the pointer on a heading row, a group header, a search result or a curtain row, a round button fades in at that row's right end (always mounted, only its opacity changes, so nothing is pushed around or reflowed) — clicking it jumps to the end of that section's content: a heading row lands just before the next heading of the same or a higher level, and a group header lands at the very bottom of the whole turn (the end of the model's last reply). Every hover highlight stops 32px short of the row's right edge, leaving a constant 8px to the round button, so a long heading never runs into it.
31
- - **Cross-session search**: the search-scope button now has three steps: title → full text → sessions. The third uses the host's session full-text index to search the message bodies of **other sessions** (bodies only; the fuzzy switch does not apply to it, and the host returns at most 20 hits); clicking a result switches to that session and keeps looking for the same keyword there. Only sessions that can be opened right now are listed — archived ones, subagent sessions and sessions no longer in the list are skipped, with the number of skipped hits reported underneath, and a host without the full-text index enabled says so instead of failing silently.
32
- - **A remembered reading position per session** (on by default in the settings card): reopening a session returns to the turn you were last reading. The position is stored in this browser only, and only resumes within half an hour (anything older opens at the newest turn). The record carries its seq, so that turn is paged back in even when it is no longer in the conversation window; when it genuinely cannot be reached (the host says there is no older history) the record is dropped silently, with no banner.
33
- - **Keyboard navigation**: ↑/↓ move a visible keyboard cursor through the outline (an inset outline plus a light fill, deliberately distinct from the reading position's blue box), Enter activates the current row (jump / load an unloaded turn / switch session), Home / End go to either end, and Esc collapses the panel (Esc inside the search box closes the search first). After clicking anywhere in the panel (an input excepted) ↑/↓ work straight away — no need to Tab in first — and the cursor's position is announced to screen readers.
34
- - **Questions only**: a speech-bubble button in the header folds the outline down to each turn's time and the first line of your own prompt, which makes "what did I actually ask" easy to find among long replies. The switch cross-fades, and while it is on the level filter is disabled (there are no heading rows); turning it off restores the previous level selection.
35
-
36
- ### Changed
37
- - **The collapsed edge handle now slides into the edge**: expanding it fades the handle out first and slides the panel in afterwards (no longer both at once), and collapsing slides the handle back behind the edge line, clipped by it, instead of vanishing out of nowhere.
38
-
39
- ### Fixed
40
- - **No longer covering other plugins' overlays**: the panel and the handles used to lift themselves above almost everything with a flat `z-index: 500`, which measurably covered community plugins' own popovers (the context plugin's cards sit at 200, for instance). They now move into the one gap in the application's stacking order — edge handle 12, docked panel 14, curtain 16, hover preview 18: above the conversation content (and it has to be above the transcript width grip at 8, or that 40px-wide transparent grab column steals the pointer along the panel's edge), but below everything that calls itself an overlay in the host or in a plugin (layout overlays at 20, better-sidebar at 25, cordis at 30, host popovers from 100 up).
41
-
42
- ## [0.6.3] - 2026-09-15
43
-
44
- ### Fixed
45
- - **The configuration card's expand/collapse chevron did not match the host's arrows**: it was a text character (⌄), thinner than the host's 14×14 SVG chevron icon, and the glyph's ink is not centred inside its 20px line box — the rotation turned around the box centre, so the glyph swung aside instead of flipping in place. It is now the host's own 14×14 SVG chevron (an inline SVG whose path is byte-identical to the icon the host uses, with the class on the `<svg>` itself — the same structure as the host's plugin card), so expanding and collapsing flip it around the icon's own centre.
46
-
47
- ## [0.6.2] - 2026-09-15
48
-
49
- ### Added
50
- - **A vertical position for the collapsed handle**: the card gains a "Handle position" row — a **0%–100% slider in 1% steps** that decides where the edge handle sits vertically once the panel is collapsed: `0%` at the bottom, `100%` at the top, and `50%` (the previously fixed centred spot) by default. The handle follows that height on whichever edge the panel is docked to.
51
-
52
- ### Changed
53
- - **Writing a default value back means "not customized"**: as soon as a card field is back at its default (a slider returned to the default step, a switch returned to its default state, the level set back to the default selection), the entry leaves the document's user layer — the "customized" badge and that field's "Reset" go with it, exactly as if it had never been changed. 0.6.1 and earlier pinned the default into the settings document and kept the badge.
54
-
55
- ### Fixed
56
- - **A panel size could fail to reach storage**: the size write is debounced by 0.4s, and the "already published" record was advanced the moment a write was scheduled — so a second adjustment inside that window (dragging the height, dragging the top bar, toggling a level or the fuzzy switch) cancelled the pending write while the record already counted it as published, and that size was never written again. Measured: drag the width 200 → 150 and then drag the height, and the stored width stayed 200 — the next load brought the panel back 200px wide. The record now advances only when the write really happens, and a cancelled write is issued again on the next pass.
57
- - **A narrow or short panel's size was stored in vain**: the limits used when reading a size back disagreed with the drag limits — dragging allows 120px wide and 60px high, but anything under 180px wide / 160px high was discarded as invalid on the next load, dropping the panel back to the default width. Both sides now share the same floors (120px / 60px).
58
- - **The first height drag jumped while the height was "auto"**: the drag started from a fixed 400px guess, so a panel that was in fact taller or shorter jumped to a wrong height on the very first move. It now starts from the panel's measured height (the visual height after the panel scale — the unit that gets stored), falling back to 400px only when nothing can be measured.
59
-
60
- ## [0.6.1] - 2026-09-15
61
-
62
- ### Added
63
- - **A panel-scale slider**: the card gains a "Panel scale" row — a **50%–200% slider in 5% steps** (the same control shape as the font-tune plugin's slider) that scales the panel's **content** (text, icons, buttons and their spacing). The scale does **not** change the panel's own size: a width and height dragged to some size stay exactly that size at 50% and at 200%, so magnifying simply shows less on screen at once. Dragging only moves the readout and the settings document is written **once the pointer is released** (no rewrite per notch); the readout keeps the dragged value until the host confirms it, so it never flashes back to the old number.
64
- - **A narrow panel's header**: the four buttons stay on one line — the empty middle gives way first, and once the buttons would touch, the row becomes sideways-scrollable (the wheel over the header reaches the buttons behind the edge) while the grey grab bar above fades out.
65
-
66
- ### Changed
67
- - **The jump animation goes back to the browser's own smooth scrolling**: the motion is handed to the container's `scrollTo({behavior:"smooth"})` — advanced on the wall clock, so it takes the same time on a 60Hz and a 240Hz panel, and it coasts to a stop. Three guards remain: step out of DSH's stick-to-bottom zone before jumping; re-aim once when the target's live offset drifts by more than 40px (the host re-paging moves it); and re-issue the call when the animation was cut short by the host's own compensation scroll (more than 400ms with less than a pixel of movement). Only a browser that carries the call out as an instant jump falls back to the plugin's frame-by-frame glide (also timed in milliseconds, quick off the mark and coasting to a stop).
68
- - **Panel size limits removed**: the width used to be clamped to 180–560px and the height had a 160px floor. Only a "still draggable back" floor of 120px wide / 60px high remains; how large or small it gets is the reader's call.
69
- - **The panel scale acts on the content only** (see above): the factor applies inside the panel, so the panel's own width, height, position, collapse clip and collapse animation are untouched.
70
-
71
- ### Fixed
72
- - **Long jumps were an instant jump on a 240Hz panel**: 0.6.0's frame-by-frame glide was timed in **frames** (22–46 of them), and 46 frames is only about 190ms on a 240Hz display (measured: 5078px in 188ms, roughly four times too fast), which reads as a teleport or a uniform blur; the same frame count is about 770ms at 60Hz, which is why neither the offline tests nor a headless browser could see it. The animation is now timed in real milliseconds, independent of the refresh rate.
73
- - **A dragged panel size sprang back to its old size**: the panel kept "what I published" and "what I adopted from outside" in one ledger. Any settings write or host snapshot refresh during a drag then compared the **not-yet-persisted** old value against that ledger and pulled the panel back to its previous size, cancelling the pending write — the drag was silently undone. The two directions are now kept apart: a value is adopted only when it differs from both the panel's live state and the value the panel itself just sent, and size/position are never read back from the settings at all (this panel is their only writer, so a read could only ever return a stale copy).
74
-
75
- ## [0.6.0] - 2026-09-14
76
-
77
- ### Added
78
- - **A bilingual interface**: a new language setting — `follow the host` (default; uses whatever language DSH currently runs in), `中文` or `English`. Every interface string comes from one table, falling back to Chinese when an English entry is missing. Chinese stamps keep the relative words `昨天` / `前天`; English reads yesterday as the word (`yesterday`) and carries the numeric `YY-MM-DD HH:MM` date for anything older (no "2 days ago").
79
- - **A plugin-configuration card**: a "Conversation Outline" card under **Settings → Plugins → Plugin configuration** (the same place DSH's own configurable plugins live), holding the language, the default docked edge (left by default), the heading levels shown, fuzzy search, the hover preview card and the console diagnostic switch. A changed field is marked "customized" and gets its own reset control back to the default.
80
- - **The panel and the card are live in both directions**: they read and write one shared store. Dragging or toggling in the panel shows up in the card, and a change made in the card takes effect on the panel's next render — no page reload either way.
81
- - **Preferences move into DSH's settings**: the preferences above no longer live only in the browser; they are written to the Host settings document, for which the plugin now ships a host half (it registers the `dsh-quick-toc` settings namespace with range validation). A local mirror stays in the browser: on a page that may not write settings (DSH keeps them read-only off a loopback address) the panel keeps working off the mirror, exactly as 0.5.x did. Values left behind by a 0.5.x install are imported into the host layer once, the first time it answers — and only while the user layer is still empty, so nothing already configured gets stomped.
82
-
83
- ### Changed
84
- - **Long jumps glide again**: 0.5.1 stopped animating long jumps to fix the "lands halfway" bug; 0.6.0 brings the animation back as a glide **drawn frame by frame by the plugin** (ease-in-out, ~0.37–0.77s by distance), not via the browser's smooth scrolling — some setups carry that call out as an instant jump, and drawing it guarantees a visible scroll on any setup. Every frame re-aims at the target's live offset (so a host re-page mid-flight is followed), and the landing is briefly re-checked afterwards (~0.6s), so a cross-page jump never stops halfway.
85
- - **The outline fills a taller panel**: when the panel is opened or dragged taller and the latest page is shorter than the list viewport (blank space below the newest group), the window grows until the content fills the height or every turn is shown.
86
- - **The "currently reading" highlight fades over 0.4s** (opacity, blue fill and border transition together, with the pinned header's blue layer in sync) — the colour change between groups is now clearly visible and calmer.
87
- - **Top offset, width and height left the settings**: they describe this screen, so they are drag-only now and keep being saved per browser; the card no longer offers numeric inputs for them.
88
- - **Preferences are read and written in one place**: the panel no longer writes `localStorage` on every pointer move; changes are merged and persisted after a short delay, while the live position during a drag stays in the panel's own state. The position/size keys are unchanged (`panelY.v1` / `panelW.v1` / `panelH.v1`); the other keys become the mirror of the host settings (same names, fallback layer).
89
- - **The diagnostic switch moved into the card**: tick it there and the mount line prints on the spot — no more hand-editing `localStorage` and reloading.
90
-
91
- ### Fixed
92
- - **The panel crashed on some conversations (React #310)**: the number of hooks it called could differ between two renders — both the bail-out when `useChat` is missing and the early return for "this conversation has no displayable turn yet" sat below part of the hook list, so those hooks reappeared on a later render and React threw `Rendered more hooks than during the previous render`, taking the panel and its slot down with it (present in 0.5.0 and 0.5.1). The panel is now split into a hook-free outer guard and an inner component, so every render calls exactly the same hooks.
93
-
94
- ## [0.5.1] - 2026-09-13
95
-
96
- ### Added
97
- - **"Back to the newest row" button**: a round button in the outline list's lower-right corner. It fades in whenever the list is not at its bottom and fades out once it is; clicking scrolls the outline back to the newest entry (smooth for a short distance, instant when the list is far up).
98
- - **Turn stamps carry the day**: the time shown in group headers, search result rows and hover cards is no longer a bare `HH:MM` — yesterday reads `昨天 15:04`, the day before `前天 15:04`, anything older `25-09-11 15:04` (two-digit year; decided by calendar day, not a 24-hour difference).
99
- - **Failures are reported**: a turn that produced no reply at all (request timeout, upstream error) now shows a `请求失败` row under its group header with the host's own error text; clicking it jumps to that error in the conversation, and the error text is searchable in full-text scope (its result row is tagged 请求失败).
100
-
101
- ### Changed
102
- - **The header now holds two buttons per side**: the heading-level filter and the dock toggle on the left, search and collapse on the right, with a spacer pinning the pairs to the two ends; the three-bar identity mark on the left is gone.
103
- - **The level filter popup is left-aligned with its button** (it used to be right-aligned).
104
- - **The mount diagnostic is silent by default**: the console no longer prints `[dsh-quick-toc] panel mounted …`. To diagnose, run `localStorage.setItem("dsh-quick-toc.debug", "1")` and reload — the line then reports `turnOutline` and the jump loader's stage-by-stage state, while normal use stays quiet.
105
- - **Long jumps land instantly**: a jump across a long history no longer "stops halfway" (short jumps still glide smoothly); after landing it re-checks for ~0.6s, which corrects a target that moved while content was mounting.
106
-
107
- ### Fixed
108
- - **Failed or aborted turns were mislabelled 未加载**: those turns have no model reply, so they carried neither a time nor headings and were re-listed as unloaded turns. A loaded user message now counts as "this turn is loaded", failures additionally show their error row, and a user-aborted turn simply shows as a heading-less turn.
109
- - **Scrolling the outline up to load older messages bounced the transcript back to the newest turn**, so paging up never got anywhere: the host force-scrolls to the bottom whenever a scroll is not attributed to the reader while it still believes the reader sits at the bottom, and a page-in triggered from the outline matches exactly that condition. The plugin now lifts the transcript just off the bottom stick zone before clicking the host's "load earlier", so the page-in keeps its place.
110
- - **A heading-less turn's group header was formatted unlike every other header**: it used to be enlarged (12px / 600 / primary colour), which made it read as a different kind of entry. All group headers now share one style (11px, secondary colour, one row box); a heading-less turn is simply a group with no rows under its header.
111
-
112
- ## [0.5.0] - 2026-09-12
113
-
114
- ### Added
115
- - **Whole-session turn index**: with the host's `turnOutline` projection the outline now covers **every turn of the session**, including turns the paged event window has not loaded. Unloaded turns appear as entries tagged 未加载 with the host's prompt/response previews (host-side budgets: 50 / 120 characters); clicking one pages that turn in through the host's turn-jump loader and scrolls to it. On a host without the projection the panel degrades to loaded turns only.
116
- - **Row subtitles**: under each heading the panel shows the first sentence of that section's body (skipping blank lines, fenced code, table rules and bare bullet markers), so identically-titled headings can be told apart at a glance.
117
- - **Hover previews**: hovering a heading or result row opens a card after ~0.26s with the title, turn time, heading path and the section's opening (up to 260 characters); docked right, the card opens to the left; leaving the row fades it out.
118
- - **Search normalization (always on)**: letter case, full-width/half-width forms and runs of whitespace count as the same match, and the highlight lands on the real characters of the original text.
119
- - **"Fuzzy" switch**: an independent toggle next to the title/full-text pill. When on, a query also matches text with a little material wedged in between (subsequence matching with a bounded gap); the setting is remembered.
120
- - **Unloaded turns are searchable too**: full-text scope also searches the previews of unloaded turns, and clicking such a hit loads the turn first, then locates and highlights.
121
- - **Edge hints**: under the search results, "scroll up to load earlier messages" — dismissed by the first upward scroll. In the outline, reaching the first turn (or scrolling down while already at the last) flashes "已经是最早的消息" / "已经到底了" at the bottom of the panel: fade in, ~2.6s hold, fade out.
122
-
123
- ### Changed
124
- - **Auto-follow tracks more tightly**: the artificial delay is gone, the outline positions itself instantly instead of animating after the conversation, and the highlight transition dropped from 0.3s to 0.15s. Following no longer depends on the one scroll container captured at mount — it listens on the document in the capture phase and re-queries the container on every run, with a slow poll as a backstop, so it also keeps working after programmatic jumps (the native turn rail).
125
- - **The turn being read is marked by a closed blue box** (light fill + outline + left accent bar) that fades in and out; other turns are no longer dimmed into grey (0.6 → 0.85) and the panel's idle opacity went 0.45 → 0.72, which makes the whole list far more readable.
126
- - **Heading-less turns** promote their time row to body-level size and weight (12px / 600 / primary colour) instead of a grey caption, and they now look the same as headed turns when they are the one being read.
127
- - Active-state colour collapsed onto a single source: the search button, the level-filter button (including while it animates shut), the title/full-text pill, the fuzzy switch, the level chips and the current result row all use the same tint.
128
- - The click on the host's "load earlier" is throttled to 900ms while scrolling the outline (one continuous scroll cannot hammer the pager); scrolling the outline still both expands the index and loads older conversation, as in 0.4.x.
129
- - Every UI string now comes from one table, preparing the zh/en split (the 0.5.0 interface is still Chinese).
130
-
131
- ### Fixed
132
- - After jumping with the native turn rail (the tick bar on the right of the conversation), the outline stopped following and no longer lit up the turn being read: the follow listener was bound to the scroll container captured **at mount**, and a jump that repages the window replaces that container, so the listener sat on a discarded node and never saw another scroll event. It now listens on the document in the capture phase and re-queries the current container on every run.
133
- - A turn without Markdown headings could never become the turn being read (no highlight, no follow): the node→turn map used by the follow only registered messages that carry headings. Every node of the turn (the user message and each model reply) is registered now.
134
-
135
- ## [0.4.0] - 2026-09-11
136
-
137
- ### Added
138
- - **Search result list**: while a query is present the outline becomes a result list — one row per match, showing the matched heading or message with the keyword highlighted, its heading path, the turn time and a repeat count (plus a context snippet in full-text scope). Rows are chronological with the **newest hit at the bottom**, a fresh search starts at the newest hit and you scroll up to reach earlier ones; **clicking a row** makes that hit current, i.e. the same path as Enter stepping — it highlights the keyword in the conversation and scrolls there. `n/N` Enter-stepping is kept.
139
- - **Sticky group headers**: while scrolling the outline, the header of the turn you are inside stays pinned to the top of the panel, flush against the toolbar above it.
140
- - **Collapsible level-filter row**: the **层级 (levels)** button at the left of the magnifier hides/shows the `1`–`6` row (the choice is remembered; the filter keeps applying while it is hidden).
141
- - **Position breadcrumb**: the top of the panel shows the path of the section you are reading; click it to jump there. The rule is "the deepest heading above the viewport's middle line" — the section that fills most of the screen — and since a jump also lands above that line, the breadcrumb still shows the same heading after you click it.
142
- - **Heading level filter**: the `1`–`6` chips at the top of the panel are independent switches, so any combination works (e.g. H1 and H3 with H2 hidden) and the choice is remembered; switching off the last remaining level restores all six.
143
-
144
- ### Changed
145
- - **Performance**: heading parsing and text extraction are now cached per node, so a streaming update only re-processes the node that changed instead of the whole history; the cache drops nodes that left the conversation, keeping it bounded.
146
- - The turn header (the time row) now jumps to the **start of that turn's model reply** (it used to jump to the user message).
147
- - **Compatibility**: verified against and declared for DSH **0.1.5-rc.1 and 0.1.5-rc.2** (`engines.dsh` keeps its floor of `>=0.1.5-rc.1`). The host interface is identical in both — the session-scoped slot `conversation.input.overlay`, the `useChat` hook from `dsh-client-ui-chat` and the client-module seed table were all checked against the installed bundles.
148
- - `countOccurrences` now guards an empty needle (an empty query made `indexOf` spin in place — an infinite loop; every current call site is guarded, so this is hardening).
149
-
150
- ### Fixed
151
- - The outline did not jump to the newest turn when content first appeared: that effect's dependency array was written above the `groups` declaration, so it always evaluated to `0` during render and the effect only ever ran on mount. The effect now sits below `groups` and depends on `groups.length`.
152
- - Dragging the top bar to move the panel persisted the position from **before** the drag (the closure kept the value captured at pointer-down), so the panel jumped back to its old spot after a reload. It now stores the position the drag ended at.
153
- - When the same keyword occurred more than once inside one text node, the in-chat highlight wrapped only the FIRST occurrence there, so the later one was neither tinted nor eligible to be marked as the current hit — stepping to it found no current mark and degraded to a plain scroll with no distinct highlight. Every occurrence inside each text node is now wrapped in order, so the in-conversation hit order lines up with `n/N`.
154
- - `# comment` / `## example` lines inside a ``` fenced code block were treated as headings and leaked into the outline: they have no element to jump to, and they shifted the index of the real headings after them so those jumped to the wrong place. Heading parsing now skips fenced blocks (``` and ~~~, info strings, longer closing fences, up to 3 spaces of indentation).
155
-
156
- ## [0.4.1] - 2026-09-12
157
-
158
- ### Changed
159
- - **Heading levels are now a popup**: a round icon button in the header (three lines of decreasing width, hover feedback matching the magnifier) scales the H1–H6 picker out of the **button's center**, right-aligned with an outer shadow; closing shrinks it back into the button with a fade. The picker no longer occupies its own row, the chips are labelled H1–H6, and their selected tint matches the title / full-text toggle.
160
- - Removed the "you are here" breadcrumb row introduced in 0.4.0 (it felt unnecessary in use).
161
-
162
- ## [0.3.3] - 2026-09-10
163
-
164
- ### Added
165
- - The panel and its collapsed edge handle fade out while the center column shows another view (trajectory, context, plugin views) and fade back in on the chat view. The check polls lightly (120 ms) and falls back to visible whenever the active view cannot be determined.
166
-
167
- ### Changed
168
- - Compatibility is declared for DSH `0.1.5-rc.1` only (`engines.dsh`, `dsh.compatibility.dshReleases` and `peerDependencies`), which is the version this plugin is verified against.
169
- - READMEs updated: the feature list and the usage section now cover search, search-scope switching, in-chat highlighting and turn jumping, and the compatibility table lists the supported DSH version of the last two releases.
170
- - GitHub release bodies now default to the Chinese CHANGELOG section with the English section folded below it, and the changelog is split into `CHANGELOG.md` (Chinese, default) and `CHANGELOG.en.md` (English).
171
-
172
- ## [0.3.2] - 2026-09-08
173
-
174
- ### Changed
175
- - Documentation pass: the compatibility matrix and feature list in the READMEs are refreshed, and the npm package description now mentions keyword search and in-chat highlighting.
176
-
177
- ## [0.3.1] - 2026-09-08
178
-
179
- ### Fixed
180
- - Panel and collapsed edge handle no longer float above DSH modals: the base z-index is now 500 (above app popovers at z 100 and the transcript width handles at z 8, but below DSH's modal layer at z 1000), so opening Settings covers the outline instead of the outline sitting on top of it.
181
- - Circular controls are true circles again on DSH 0.1.5-rc.1: the theme applies `corner-shape: superellipse(1.5)` to every element, which turned `border-radius: 50%` into a squircle. The icon buttons, search-scope toggle, top drag bar and edge handle now declare `corner-shape: round`.
182
-
183
- ### Changed
184
- - Compatibility declaration also lists DSH `0.1.5-rc.1` (verified compatible; `engines.dsh` stays `>=0.1.2-rc.1`).
185
-
186
- ## [0.3.0] - 2026-08-24
187
-
188
- ### Fixed
189
- - Compatibility with the then-current DSH 0.1.2-rc.1: the removed `@deepseek-ai/dsh-client-runtime` package no longer breaks plugin loading (externals drift). Runtime hooks now arrive as session-scope slot props.
190
- - Conversation data access moved from `useSession(s => s.chat.*)` to the session-scope `useChat` hook (`ChatSnapshot.order` + `nodes` map, contributed by `dsh-client-ui-chat`). Node shape unchanged (`kind: user/assistant-step`, `location.turn`, `data.blocks`), so grouping / search / highlight / jump logic is untouched.
191
- - Panel mount moved into the session-scoped `conversation.input.overlay` slot. In that DSH version session-scoped hooks only reach a declared *session* slot; a frame-floating `shell.overlay` occupant's `SessionProvider` binds to the root binding (no session id) and rendered the panel slot empty. The panel still draws its own fixed, frame-floating dock (position: fixed), so the overlay seat is only the hook source.
192
-
193
- ### Changed
194
- - `dsh.client.inject` now lists `dsh-client-ui-chat` / `dsh-client-ui-conversation` / `dsh-client-ui-layout` instead of the removed runtime package.
195
- - Dropped the unused `sessions` service from the client inject list.
196
-
197
- ### Added
198
- - Version guard: `dsh.compatibility.dshReleases` declares `0.1.2-rc.1: compatible` and `engines.dsh: ">=0.1.2-rc.1"` (dshmarket install-time host-compat preflight); peerDependencies pin `dsh-client-ui-chat` / `dsh-client-ui-conversation` `>=0.1.2-rc.1`. The panel degrades gracefully with a console warning when the `chat` hook is unavailable (older hosts).
199
-
200
- ## [0.2.2] - 2026-08-24
201
-
202
- ### Added
203
- - Keyword search: header magnifier button opens a search box; Enter cycles through matches (n/N counter); Escape or the magnifier toggles it closed
204
- - Search scope toggle: 标题 (heading titles only) or 全文 (also user messages and AI reply texts)
205
- - In-chat match highlighting: matched keywords are highlighted in the conversation; the current match gets a distinct highlight and is scrolled to the upper-middle of the viewport
206
- - Every occurrence counts toward n/N (multiple hits in one message = multiple matches)
207
- - Heading-less turns get a standalone time entry; all group headers show the turn's first-line preview next to the time (click to jump)
208
-
209
- ### Changed
210
- - Panel collapse animation unified for both docks: clip-path hides the panel at the sidebar/screen edge (shadow removed to avoid clipping artifacts)
211
- - Inactive outline groups dimmed to 0.6 opacity
212
-
213
- ## [0.1.1] - 2026-08-17
214
-
215
- ### Changed
216
- - Release workflow also uploads a stable-named tarball (`dsh-quick-toc.tgz`) so `/releases/latest/download/` always resolves to the newest release
217
-
218
- ## [0.1.0] - 2026-08-17
219
-
220
- ### Added
221
- - Turn-grouped outline: each user message + its AI replies form one group, with the group's end time as the header
222
- - Auto-follow highlight: turns visible in the conversation viewport light up in the outline (multiple at once); the outline auto-loads and scrolls to keep them visible
223
- - Smooth jump: clicking a heading glides to the exact heading position in the conversation (with a small top offset)
224
- - Dock left/right with a draggable top bar, resizable from the edges/corner, collapsible into an edge handle (click it to expand)
225
- - Scrollbar follows the dock side (left when docked left, right when docked right)
226
- - Paged rendering: latest groups first; scrolling the outline to the top loads older groups
227
- - Auto "load older": when the outline reaches the top with everything loaded, it clicks the conversation's own load-more button
228
- - Header time jump: clicking a group's time label jumps to that turn's start
229
- - Markdown-aware titles: `**bold**`, `*italic*`, `` `code` ``, `[links](url)`, `~~strike~~` stripped from heading text
230
- - Persisted panel state (dock side, position, size) with automatic migration from older key names
231
- - Auto-hides when the conversation has no headings; light/dark theme support
232
-
233
- ### Published
234
- - npm: `dsh-quick-toc@0.1.0`
235
- - GitHub: `LyaxZ/dsh-quick-toc` with auto-release workflow (tag push -> npm pack -> release asset)
1
+ # Changelog
2
+
3
+ All notable changes to **dsh-quick-toc** are documented here. Chinese version: [CHANGELOG.md](CHANGELOG.md).
4
+
5
+ ## [0.7.2] - 2026-09-22
6
+
7
+ ### Added
8
+ - **Curtain scale**: the settings card gains a "Curtain scale" slider (50%-200%, 5% steps) that scales the text, icons and buttons inside the curtain while the curtain's own size stays as it is; it is independent of the panel scale. The curtain's content starts one notch smaller than before — 100% on the slider is 90% of the previous size.
9
+ - **DSH 0.1.7-alpha.1 support**: one installed package now works on both 0.1.5-rc.x and 0.1.7-alpha.x, using whichever settings interface, configuration-card slot and session-switch call the running host actually offers; tested on both 0.1.5-rc.2 and 0.1.7-alpha.1.
10
+
11
+ ## [0.7.1] - 2026-09-19
12
+
13
+ ### Added
14
+ - **A "back to where I scrolled to" floating button**: closing the panel or the curtain records the row at the top of the list, and opening that surface again shows an upward button in the upper-right corner that returns to it. The two surfaces record separately, and the button disappears after one use or once the list is scrolled back there.
15
+
16
+ ### Changed
17
+ - **Opening the panel or the curtain puts the row being read at the top of the list** (previously only the curtain did this, and the panel showed the position last left in it).
18
+ - **The panel's collapse and expand animate a position offset** instead of reflowing the whole panel frame by frame, so the collapse animation no longer distorts in long sessions.
19
+ - **The top icons' geometry and line weight are adjusted**: the curtain button is a horizontal rectangle with a downward arrow, the level filter and "questions only" lines are heavier, and the ✕ and magnifier no longer shift their icon to compensate.
20
+ - The "remember reading position" and "auto-load history" rows in the settings card no longer show a description.
21
+
22
+ ### Fixed
23
+ - **Loading older history is slow**: an unloaded placeholder row in view now loads that turn in one step, and pages are pulled one at a time only near the prefetch range; a loading state is no longer misreported as the earliest message.
24
+ - **The view is pulled back when older history loads while scrolling up**: height compensation completes in the same frame as the content change, anchors on the first loaded row in view, and also covers pages the host loads itself.
25
+ - **The panel becomes sluggish after a while**: auto-follow no longer measures every message in the session.
26
+ - **Loading older history moves the middle conversation upward**: the conversation area is no longer lifted before paging.
27
+ - **One upward scroll can load several pages in a row**: the prefetch test now starts from the nearest placeholder row in view and includes hysteresis.
28
+ - **The curtain opened with the list slightly above the end, upward jumps landed inaccurately, and opening scrolled down from the top**: these now follow one rule, with the row being read aligned to the top of the list instantly.
29
+ - **The top droplet kept a visible sliver when pressed fully down and then disappeared at once**: pressing it fully down now sinks it into the divider line.
30
+
31
+ ## [0.7.0] - 2026-09-19
32
+
33
+ ### Added
34
+ - **A full-width "curtain" outline**: a droplet handle in the tab strip at the top of the conversation expands the outline across the full width below the tab strip, at the remaining height of the conversation area, with rounded lower corners and without covering or dimming the conversation. Clicking any row, pressing Esc or using the ✕ at the upper right collapses it, and the "curtain" round button in the panel header is another entry point. It moves the panel itself into the container, so paging, search, hover previews, the keyboard cursor and the reading position are all the same set.
35
+ - **Wide typography in the curtain**: a row has three parts, a level badge, a larger heading and the opening of that section's body, and the level filter lays out on one line. Clicking the magnifier expands the search column from the right.
36
+ - **A "jump to the end of this section" button on each row**: with the pointer on a heading row, a group header or a search result, a round button appears at the right end and jumps to the end of that section (a heading row stops before the next heading of the same or higher level, a group header at the end of the turn).
37
+ - **Cross-session search**: a third search scope, "sessions", searches other sessions' bodies through the host's full-text index (bodies only, at most 20 hits at a time); clicking a result switches to that session and continues the search there. Sessions that cannot be opened are skipped and counted, and a host without the index says so.
38
+ - **A remembered reading position per session** (on by default): reopening a session returns to the turn read last, and the record carries a seq so the turn is loaded automatically when it is outside the conversation window. The position is stored on this machine only and is not restored after half an hour.
39
+ - **Keyboard navigation**: ↑/↓ move the cursor through the outline, Enter activates the current row, Home / End go to the first and last rows and Esc collapses the panel; it works right after clicking anywhere in the panel, with no Tab needed.
40
+ - **Questions only**: a speech-bubble button in the header folds the outline down to each turn's time and the first line of the prompt; the switch cross-fades, and the level filter is unavailable while it is on.
41
+
42
+ ### Changed
43
+ - **The collapsed edge handle slides in along the edge**: expanding fades the handle out first and then slides the panel in, and collapsing slides the handle back clipped by the edge.
44
+
45
+ ### Fixed
46
+ - **The panel no longer covers other plugins' overlays**: the layers sit in a gap in the application's stacking order (handle 12, panel 14, curtain 16, hover preview 18), above the conversation content but below host and plugin overlays.
47
+
48
+ ## [0.6.3] - 2026-09-15
49
+
50
+ ### Fixed
51
+ - **The configuration card's expand arrow does not match the host's**: the text character `⌄` used before is thinner than the host's 14×14 icon and shifts position when rotated; it is now the host's inline SVG arrow, flipping around its own centre.
52
+
53
+ ## [0.6.2] - 2026-09-15
54
+
55
+ ### Added
56
+ - **A vertical position for the collapsed handle**: the settings card gains a slider (0%–100%, 1% per step) that decides the handle's height in the conversation area once the panel is collapsed: 0% at the bottom, 100% at the top, 50% by default.
57
+
58
+ ### Changed
59
+ - **Writing a default value counts as "not customized"**: a field returned to its default leaves the settings user layer, and its "customized" and reset marks disappear.
60
+
61
+ ### Fixed
62
+ - **A panel size sometimes cannot be saved**: the size write is debounced by 0.4 seconds while the ledger was marked when the write started, so a second adjustment within 0.4 seconds cancelled the pending write and that size was never saved again. The ledger is now marked only when the write happens.
63
+ - **A small panel size cannot be saved**: the read-back floor (180×160) did not match the drag floor (120×60); both are now 120×60.
64
+ - **The first height drag jumps while the height is "auto"**: the drag starts from the panel's measured height.
65
+
66
+ ## [0.6.1] - 2026-09-15
67
+
68
+ ### Added
69
+ - **A panel scale slider**: the settings card gains "Panel scale" (50%–200%, 5% per step), scaling the panel's content while the panel's own size stays as dragged. Dragging updates the readout only, and the setting is written when the pointer is released.
70
+ - **A header for narrow panels**: the four buttons stay on one line, the empty middle gives way first, and once the row is full it scrolls sideways while the grey grab bar above fades out.
71
+
72
+ ### Changed
73
+ - **The jump animation goes back to the browser's own smooth scrolling**, advanced on real time so its duration is the same on 60Hz and 240Hz screens; the target is re-aimed when it moves mid-flight or the animation is interrupted, and frame-by-frame drawing remains only for a browser that executes the call as an instant jump.
74
+ - **Panel size limits are removed**: only the floor of 120px wide / 60px high, still enough to drag the panel back, remains.
75
+
76
+ ### Fixed
77
+ - **Long jumps are too fast on a 240Hz screen**: the old animation was timed in frames, only about 190ms at 240Hz; it is now timed on real time and independent of the refresh rate.
78
+ - **The panel returns to its original size after being dragged**: changes sent out and changes adopted from outside shared one ledger, so a settings write during a drag pulled the panel back with a not-yet-saved value. The two paths are now accounted separately.
79
+
80
+ ## [0.6.0] - 2026-09-14
81
+
82
+ ### Added
83
+ - **A bilingual interface**: the language setting offers "follow the host" (default), `中文` and `English`; Chinese timestamps keep the Chinese forms (昨天 / 前天), and English uses `yesterday` and a date form.
84
+ - **A plugin configuration card**: the "Conversation Outline" card under **Settings → Plugins → Plugin configuration** manages the language, default docked edge, heading levels shown, fuzzy search, hover preview and diagnostic switch in one place; changed fields are marked "customized" with an individual reset.
85
+ - **The panel and the card stay in sync in real time**: both read and write the same preferences, so a change on either side takes effect on the other without a reload.
86
+ - **Preferences are saved to DSH settings**: they are written to the host settings document, with a local mirror for pages that cannot write settings; local values from 0.5.x are imported once when the host layer first answers.
87
+
88
+ ### Changed
89
+ - **Long jumps have their animation back**: drawn frame by frame by the plugin and timed by duration rather than frames, re-aiming at the target every frame and re-checking the landing briefly, so a cross-page jump no longer stops halfway.
90
+ - **The outline fills a taller panel**, leaving no blank space below the newest group.
91
+ - **The "currently reading" blue box fades in and out over 0.4 seconds.**
92
+ - **Top offset, width and height leave the settings** and can only be adjusted by dragging.
93
+ - **Preference writes are merged**: instead of writing on every pointer move, changes are merged and saved after a short delay; the diagnostic switch moves into the settings card and prints as soon as it is on.
94
+
95
+ ### Fixed
96
+ - **The panel crashes in some conversations (React #310)**: the number of hooks differed between renders, taking the panel and its slot down; it is now split into a hook-free outer guard and an inner component.
97
+
98
+ ## [0.5.1] - 2026-09-13
99
+
100
+ ### Added
101
+ - **A "back to the bottom" floating button**: it appears while the list is not at the bottom, returns to the newest row when clicked and hides once the bottom is reached.
102
+ - **Turn times carry a date**: yesterday and the day before are labelled as such together with the time, and anything older shows `YY-MM-DD HH:MM`, decided by calendar day.
103
+ - **Errors from failed turns are shown**: turns such as request timeouts or upstream errors show a `Request failed` row with the host's error text under the group header; clicking it jumps there, and the error text is searchable.
104
+
105
+ ### Changed
106
+ - **The header now has two buttons per side** (left: level filter and dock toggle; right: search and collapse), and the three-bar mark on the left is gone.
107
+ - **The level filter popup is left-aligned with its button.**
108
+ - **The mount diagnostic log is silent by default**; set `dsh-quick-toc.debug` to `1` and reload to print it.
109
+ - **Long jumps land instantly**, with a brief check after landing.
110
+
111
+ ### Fixed
112
+ - **Failed or aborted turns are mislabelled as "Not loaded"**: these turns now count as loaded, and a failed turn also shows its error row.
113
+ - **Loading earlier messages from the outline brings the conversation back to the newest turn**: the conversation is moved out of the stick-to-bottom zone before paging.
114
+ - **A heading-less turn's group header is formatted unlike the other group headers**: all group headers now share one style.
115
+
116
+ ## [0.5.0] - 2026-09-12
117
+
118
+ ### Added
119
+ - **A whole-session turn index**: with the host projection the outline covers the entire session, unloaded turns carry a "Not loaded" mark and the host's preview, and clicking one loads that turn and scrolls to it.
120
+ - **Row subtitles**: the first sentence of each section's body is shown under the heading, so headings with the same title can be told apart.
121
+ - **Hover previews**: with the pointer on a heading row for about 0.26 seconds a card appears with the title, time, heading path and the section's opening, on the left when the panel is docked right.
122
+ - **Search normalization (always on)**: differences in letter case, full-width and half-width forms and whitespace count as the same match.
123
+ - **A "fuzzy" switch**: a query also matches keywords with a little other text in between, and the state is remembered.
124
+ - **Unloaded turns are searchable too**: full-text search also covers their preview text.
125
+ - **Edge hints**: the search results say that earlier messages can be loaded, and scrolling past the oldest or newest point flashes a hint at the bottom of the panel for about 2.6 seconds.
126
+
127
+ ### Changed
128
+ - **Auto-follow tracks more promptly**: the artificial delay is gone, positioning is instant and the highlight transition is shorter; following no longer depends on the scroll container captured at mount, listening on the document in the capture phase and re-querying on every run.
129
+ - **The turn being read is marked with a closed blue box**, the other turns are dimmed less, and the panel's idle opacity is raised to 0.72.
130
+ - **A heading-less turn's time row is promoted to body-level font size and weight.**
131
+ - **Active-state colours are unified into a single colour source.**
132
+ - **The "load earlier" trigger on upward scrolling is throttled**, avoiding repeated paging.
133
+ - **Interface strings are unified into one string table**, preparing for the later bilingual interface.
134
+
135
+ ### Fixed
136
+ - **After jumping with the turn rail beside the conversation, the outline no longer follows or lights up** (the scroll listener was bound to a container that had been replaced): it now listens on the document in the capture phase and re-queries the container.
137
+ - **A turn with no Markdown headings is not marked as "currently reading"** (the map only registered messages that carry headings): every node of the turn is now registered.
138
+
139
+ ## [0.4.0] - 2026-09-11
140
+
141
+ ### Added
142
+ - **A search result list**: with a query present the outline switches to a result list (highlighted heading, heading path, turn time, repeat count, plus a snippet in full-text scope) with the newest hit at the bottom, and clicking a row makes that hit current, highlighting and scrolling to it in the conversation; Enter stepping through `n/N` remains.
143
+ - **Sticky group headers**: the current turn's group header is pinned to the top of the panel.
144
+ - **A collapsible level-filter row**: the "levels" button in the header hides and shows the `1`–`6` row.
145
+ - **A position breadcrumb**: the top of the panel shows the path of the section being read, and clicking it jumps there.
146
+ - **A heading level filter**: the `1`–`6` chips are independent and can be combined freely; switching all of them off restores all six levels.
147
+
148
+ ### Changed
149
+ - **Performance**: heading parsing and text extraction are cached per node, so a streaming update recomputes only the nodes that changed.
150
+ - The group header (time row) click now jumps to the start of that turn's model answer.
151
+ - Compatibility with DSH `0.1.5-rc.1` and `0.1.5-rc.2` is declared.
152
+ - `countOccurrences` gains an empty-query guard.
153
+
154
+ ### Fixed
155
+ - **The first load does not locate the newest turn**: the effect's dependencies were written before its declaration, so it ran only once.
156
+ - **The position recorded after dragging the top bar is the one from before the drag**, and the panel returns to its old place after a reload.
157
+ - **A second hit inside the same text node is not highlighted**, and jumping to it scrolls without highlighting.
158
+ - **`#` lines inside fenced code blocks are treated as headings**, shifting the numbering of the real headings after them.
159
+
160
+ ## [0.4.1] - 2026-09-12
161
+
162
+ ### Changed
163
+ - **The level filter becomes a popup**: a round button in the header opens an H1–H6 picker from the button's centre that shrinks back and fades when closed, so it no longer occupies a row of its own.
164
+ - The position breadcrumb row at the top of the panel (added in 0.4.0) is removed.
165
+
166
+ ## [0.3.3] - 2026-09-10
167
+
168
+ ### Added
169
+ - When the middle column switches to another view, the outline panel and the edge handle fade out, and they fade back in on the conversation view.
170
+
171
+ ### Changed
172
+ - Compatibility is declared for DSH `0.1.5-rc.1` only.
173
+ - The README adds notes on search and jumping, and the compatibility table lists the supported DSH version of the last two releases.
174
+ - The changelog is split into Chinese and English files, and release descriptions take the Chinese section by default with the English one folded below.
175
+
176
+ ## [0.3.2] - 2026-09-08
177
+
178
+ ### Changed
179
+ - Documentation pass: the README's compatibility table and feature list are updated, and the npm description mentions keyword search and in-chat highlighting.
180
+
181
+ ## [0.3.1] - 2026-09-08
182
+
183
+ ### Fixed
184
+ - The panel and the collapsed handle no longer float above DSH overlays (z-index set to 500).
185
+ - Circular controls are true circles again on DSH 0.1.5-rc.1, whose theme's `corner-shape` turns a 50% radius into a rounded square corner.
186
+
187
+ ### Changed
188
+ - Compatibility declarations now include DSH `0.1.5-rc.1`.
189
+
190
+ ## [0.3.0] - 2026-08-24
191
+
192
+ ### Fixed
193
+ - Compatibility with DSH 0.1.2-rc.1: loading no longer fails because `dsh-client-runtime` was removed, and runtime hooks are injected through the props of the session-scope slot.
194
+ - Conversation data access moves from `useSession` to the session-scoped `useChat`.
195
+ - The panel mounts into the session-scoped `conversation.input.overlay` slot, fixing a child slot that always rendered empty.
196
+
197
+ ### Changed
198
+ - `dsh.client.inject` now lists `dsh-client-ui-chat` / `-conversation` / `-layout` instead of the removed runtime package.
199
+ - The unused `sessions` service is removed from the client inject list.
200
+
201
+ ### Added
202
+ - Version guard: `dsh.compatibility.dshReleases` and `engines.dsh` are declared for the market's install-time compatibility preflight, the related DSH packages are constrained with peerDependencies, and the panel degrades gracefully when the `chat` hook is unavailable.
203
+
204
+ ## [0.2.2] - 2026-08-24
205
+
206
+ ### Added
207
+ - Keyword search: the magnifier opens a search box, Enter steps through matches with an `n/N` counter, and Esc or a second click on the magnifier closes it.
208
+ - A search scope switch: headings only, or user messages and AI reply text as well.
209
+ - In-chat highlighting: matched keywords are highlighted in the conversation, and the current match is marked separately and scrolled to the upper middle of the viewport.
210
+ - Every occurrence within one message counts towards `n/N`.
211
+ - A heading-less turn also gets its own time entry, and all group headers show that turn's first-line preview.
212
+
213
+ ### Changed
214
+ - The collapse animation is the same for both docks (clipped along the sidebar or screen edge, shadow removed).
215
+ - Inactive outline groups are dimmed to 0.6 opacity.
216
+
217
+ ## [0.1.1] - 2026-08-17
218
+
219
+ ### Changed
220
+ - The release process also uploads a stably named tarball (`dsh-quick-toc.tgz`), so that `/releases/latest/download/` always points to the newest version.
221
+
222
+ ## [0.1.0] - 2026-08-17
223
+
224
+ ### Added
225
+ - A turn-grouped outline: each user message and the AI replies that follow it form one group, and the group header shows the group's end time.
226
+ - Auto-follow highlighting: turns inside the conversation viewport light up in the outline, and the outline scrolls to keep them visible.
227
+ - Smooth jumps: clicking a heading scrolls smoothly to that heading's place in the conversation.
228
+ - Dock left or right, drag to resize, and collapse into an edge handle.
229
+ - The scrollbar follows the dock side, left when docked left and right when docked right.
230
+ - Paged rendering: the newest groups are shown by default, and scrolling up loads older groups.
231
+ - Automatic "load earlier": at the top with everything loaded, the outline clicks the conversation's own load button.
232
+ - Group header time jump: clicking the time label jumps to the start of that turn.
233
+ - Markdown-aware headings: `**bold**`, `*italic*`, `` `code` ``, `[links](url)` and `~~strikethrough~~` are stripped.
234
+ - Panel state (dock side, position, size) is persisted, with automatic migration from older key names.
235
+ - The panel hides itself when the conversation has no headings, and light and dark themes are supported.
236
+
237
+ ### Published
238
+ - npm: `dsh-quick-toc@0.1.0`
239
+ - GitHub: `LyaxZ/dsh-quick-toc`, with an automatic release workflow (push a tag, npm pack, release asset).