zudo-text

検索したい単語を入力

いつでも検索バーを開ける

Instant New note — 番号を待たずに書き始める

New note(Mod+N、ネイティブメニュー、Command Palette、Note Tray toolbar の「+」)は、ネットワークを一切待たずにタブを追加・選択し、書き込めるエディタにフォーカスを渡します。番号(inbox/N.md の N)はあとから割り当てられ、同じタブがその場で番号に変わります。採用デザインは「A — Indicator only」です。

このページは、その契約と、変更するときに守るべき不変条件をまとめたものです。番号の割り当て自体の安全性(サーバープローブ、tombstone の回避)は Cross-device divergence と #7507 の文脈にあります。

なぜ待たせないのか

createFreshNumberedNote は、候補番号ごとにサーバーの head をプローブします(1 回あたり FRESH_NOTE_PROBE_TIMEOUT_MS = 4,000 ms)。この安全策は削らずに、待ち時間だけをユーザーの操作から外すのがこの設計です。プローブ、タイムアウト、create-only の createAt はそのまま残し、max + 1 を事前に計算して番号として扱うこともしません。

3 つの事実を分けて持つ

事実どこにあるか表示
ローカルに保存できたかpending note の封印済みジャーナル(journaledRevision)と、番号付きパスへの通常の書き込み(writtenRevision)失敗すると local-error(「!」の三角)
番号が割り当てられたかPendingNote.number未割り当ての間はスピナーだけのタブ
リモートが受け取ったか既存の syncMetadata.pendingItems(パスごと)受け取るまで番号の横に小さなマーク。完了で消える

成功のバッジやトーストは出しません。最後の状態は「番号だけ」です。作成したパスがアップロード待ちの一覧に見当たらないだけでは「完了」とみなしません。一度その一覧に載ったあとで消えたか、作成後にサーバーの受領(lastCloudAcknowledgmentAt)があったときに限り、マークを消します。

構成

  • tauri-app/renderer/services/pending-new-notes.ts — pending note のレジストリとジャーナル。モジュールスコープで、どのペインにも属しません。ビューを閉じても note は破棄されません。

  • tauri-app/renderer/services/create-fresh-numbered-note.ts — onCandidate / resumeCandidate / ensureFloor を追加。onCandidate を渡すと常に create-only の経路を通ります。

  • tauri-app/renderer/hooks/use-pending-note-tray.ts — Note Tray の 1 リーフと registry の結線。選択、エディタの識別子、番号付き store への受け渡し(hand-off)、タブの状態を持ちます。

  • tauri-app/renderer/view-providers/inbox-provider.tsx — 上記を使うオーバーレイ。pending note の選択中は、エディタの内容を registry から読み、編集を registry に書きます。番号付きの共有バッファには触れません。

  • tauri-app/renderer/data/instant-new-note.ts — write-page が inbox リーフの New note をプロバイダへ回すためのイベント。これで全エントリポイントが同じ経路を通ります。

  • packages/ui-components/src/note-tab-status.tsx と draft-bar.tsx — スピナー(Spinner の scaled)と状態グリフ。--display-scale に追従し、prefers-reduced-motion で回転を止めます。

流れ

  1. beginPendingNote() は同期的にレコードを作り、一覧に載せて返します。ここまでに await はありません。cloud ワークスペースが armed でなければ null を返し、呼び出し側は従来の経路を使います。

  2. 割り当ては「workspace + directory」ごとに直列化されます。作成順がそのまま番号順になります。編集は直列化しません。

  3. 割り当ての前にレコードを封印し、各候補番号は createAt の 前 にジャーナルへ書きます。

  4. 番号が付くと subscribePendingNoteAllocations で store に通知します(draftCount を同期的に引き上げ)。続いて最新の本文を番号付きパスへ通常の書き込みで送ります。書き込み中の編集は最大 3 回まで追いかけます。

  5. リーフがその note を表示している場合は hand-off します。flushPendingNoteForHandOff で最新を書き、handleDraftChange(n) で store を切り替え、まだ差分があれば setContentForPane で渡し、completePendingHandOff で registry の書き込みを止めます。エディタの識別子(負の合成値)は hand-off をまたいで同じなので、CodeMirror は作り直されず、選択・スクロール・undo・IME は保たれます。

  6. 束縛のないレコードは、最新の本文が番号付きパスに書けた時点で registry 側で完了します。

再起動と再試行

  • ジャーナルは note ごとに 1 エントリ、アカウントとワークスペースで鍵付けし、ワークスペース鍵で暗号化して localStorage に置きます(removed-notes と同じ前例)。テストと dev:mock ではメモリ版を使います。平文の production localStorage、ローカルのワークスペースミラー、2 つ目のアップロードエンジンは作りません。

  • サインアウトで消去し、暗号化の再 arm(ロック、鍵の変更、ワークスペース切り替え)で揮発状態を捨てます。封印済みエントリはそのワークスペースが正しく再 arm されたときに戻ります。

  • ウィンドウ(ポップアウト、ブラウザのタブ)は localStorage を共有するので、動いているレコードはそれを動かしているウィンドウがリースします(id と時刻だけの平文キー、5 秒ごとに更新、150 秒で失効。ウィンドウを閉じると即座に手放し、バックグラウンドから戻ったときにも更新)。復元は、別の生きたウィンドウがリースしているレコードを飛ばし、残りをリースしたうえで少し待って取り直し、自分のリースが残ったものだけを再開します。同時に復元した 2 つのウィンドウが同じ操作を動かすことはありません。

  • 未割り当てのレコードは同じ操作 id と同じ候補番号で再開します。再開する候補番号もサーバープローブを通します。候補番号がすでに存在していても 採用しません(別の書き手かもしれないため)。次の番号へ進み、不確かな番号には触れません。

  • ジャーナルは、番号付きパスに届いたリビジョン(writtenRevision)も記録します。再起動時、最新のリビジョンが届いていればそのまま完了します(スロットにあるのはそれ以降の編集です)。届いていなければ、スロットが作成直後の空本文なら書き込み、同じ本文なら完了します。別の本文があるときは順序を判断できないので上書きせず、kept として本文を保ちます。スロットが無いときも同じです。kept のレコードは書き込みも hand-off もせず、コピーと書き出しのあとで「Dismiss kept text」で手放せます。

  • 再試行は同じレコードと同じ操作で行い、2 つ目の作成は始めません。

既知の残り

  • createAt が成功してから番号が封印されるまでの間にプロセスが落ちると、空の note が 1 つ余分に残る可能性があります。採用も削除もしないので、本文が失われることはありません。

  • 別のウィンドウのリースを理由に飛ばしたレコードは、そのウィンドウが落ちたあと、次の復元(再起動か再 arm)まで再開されません。本文は封印済みのジャーナルに残っています。

ガード

番号が付くまでは、番号やパスに依存する操作(アーカイブ、移動、公開、削除、並べ替え、整理)を止め、PENDING_NOTE_ACTION_REFUSAL の説明を返します。並べ替えと整理は store 側でも assertNoPendingNotesIn で拒否します。編集、切り替え、再試行、コピー、テキストの書き出しはいつでも行えます。ワークスペース境界では pending-new-notes が editor-buffer フェーズの flush として登録され、未封印の本文を封印し、番号付きの本文を書き出します。

対象外

  • 時系列・格子レイアウトと single-document モードは従来の経路のままです(text-editor レイアウトのみ)。

  • 読み取り専用のフレームは従来の経路のままです。

  • macOS ネイティブ(WebKit)での実機確認は、リポジトリの方針どおり T3 / pnpm exam に委ねています。