Skip to content

Feat/3.0.0 beta1 - #2345

Merged
zgqgit merged 10 commits into
releasefrom
feat/3.0.0-beta1
Aug 21, 2026
Merged

Feat/3.0.0 beta1#2345
zgqgit merged 10 commits into
releasefrom
feat/3.0.0-beta1

Conversation

@zgqgit

@zgqgit zgqgit commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

What

简要描述做了什么改动。

Why

为什么需要这个改动?

How

实现方式、设计决策(如有)。

Test

  • 本地测试通过
  • 114 测试服务器验证通过

Related

  • Issue/ticket:

zgqgit and others added 10 commits August 20, 2026 19:36
The previous fix only covered plain-text values. A value carrying a
heading, table or image still takes the split-the-paragraph path, and that
path rebuilt every piece from `paragraph.text` — so any paragraph holding
such a value came out flattened: the substituted text lost its formatting,
all surviving text was re-stamped with the FIRST run's format, and the
paragraph style went back to Normal. In a template whose lines start with
plain text, that reads as "only the first underline survived".

The split now rebuilds from the XML instead of from plain text:

- each new paragraph clones the source paragraph's pPr, so style,
  numbering, borders and tab leaders come along
- surviving text is emitted per source run, cloning that run's rPr, so a
  mid-paragraph underline or bold no longer collapses onto run[0]'s format
- the substituted text clones the run the placeholder sat in, matching the
  inline path

Falls back to the old flat-text behaviour only when the placeholders cannot
be located in the run text (a hyperlink or field), where run fidelity is
not available anyway.
…book

Previewing an .xlsx in either app hammered object storage with the same
signed URL over and over. Two mechanisms in ExcelPreview could do that,
and both are removed:

- the parse effect listed `t` in its dependencies. react-i18next hands
  back a new `t` whenever the namespace or language settles, so that
  identity change alone re-downloaded and re-parsed the file. `t` now
  lives in a ref; only the URL and extension drive the effect.
- `useTranslation` defaulted to `useSuspense: true`, so before the shared
  namespace resolved the viewer suspended, and the boundary tore it down
  and remounted it — every remount being a fresh download. The labels are
  error text, so the viewer no longer suspends for them.

Downloads are also de-duplicated while in flight, so any remaining source
of remounts costs one request rather than one per mount.

Only ExcelPreview took a translation inside the fetching component, which
is why the other viewers never showed this.
A video staged in the composer sat as a bare icon until the message was
sent, because the poster is only extracted server-side when the turn is
submitted and parsed. The chip now shows the first decoded frame, captured
locally from the picked file — no upload, no storage, no wait.

`captureVideoPosterFromFile` already existed but was never called. It is
wired into the upload staging beside the duration probe, and hardened with
a 5s timeout so a container that never fires an event cannot hang the
promise and leak its object URL.

Best effort by design: a codec the browser cannot decode leaves today's
icon in place, and the server poster replaces the local blob as soon as it
lands. The chip also falls back to the icon if a poster fails to load,
since the composer blob is revoked once the message is sent.
Adding the local first-frame poster broke the thumbnail in the sent
bubble: the composer's blob URL travelled into the message payload, and
`resolveMediaCoverUrl` prefers `mediaCoverUrl` over `cover_filepath`. The
blob is revoked on send, so the bubble held a dead URL that also outranked
the server cover once parsing produced it — the video came out iconless
where it used to get a poster.

The blob now stops at the composer: both completed-file payloads drop a
`blob:` cover, leaving `cover_filepath` to drive the message exactly as
before. The composer chip still shows it, since it reads the staged file
rather than the payload.
The previous fix stripped the local poster one step too early. The
composer bar renders uploading files and completed files from two
different lists, and the completed list doubles as the send payload — so
dropping the blob there made the thumbnail vanish the moment the upload
finished, leaving the icon until the message was sent and parsed.

The blob now stops at the send boundary instead: the completed list keeps
it for display, and `handleSend` hands the parent a copy without it.
@zgqgit
zgqgit merged commit 59819a9 into release Aug 21, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant