跳至主要内容

使用歷史紀錄 (useHistory)

Lexical 的 useHistory 增加了對撤銷和重做功能的支援。部分撤銷和重做功能需要支援某些動態操作的合併,例如連續輸入的合併。以下將提供有關連續輸入撤銷合併功能的背景資訊。

輸入文字的撤銷合併

簡短說明

在使用文字編輯器時,使用者期待有良好的撤銷體驗。其關鍵部分是當撤銷連續輸入事件時,應有順暢且經過深思熟慮的工作流程。對於本文,嚴格定義的輸入事件可能限於輸入字符、按下 Backspace 鍵刪除字元以及按下 Delete 鍵進行向前刪除。使用者通常期望連續輸入應該能通過單次撤銷操作完全撤銷,而不是每個字符都需要單獨的撤銷操作。涵蓋此功能的演算法是「輸入文字的撤銷合併」,這裡涉及到一定程度的細微差異。本文將涵蓋這些細微差異,同時儘量避免具體的實作細節。

哪些編輯需要合併?

如上所述,連續輸入應該合併為單個撤銷操作。連續輸入是一個具有多重含義的詞語,接下來我們將深入探討一些細節。

還有其他需要撤銷合併的編輯類型,例如快速調整圖片大小或快速更改選定文字的字體大小。這些後兩個例子屬於「動態操作」,它們的實作可能與輸入合併相差甚遠。

什麼構成連續輸入?

為了撤銷合併的目的,連續輸入事件可以安全地限定在以下三種操作:

  1. 向前輸入字符(稍後將討論組合字符輸入)。
  2. 向後刪除,例如按下 Backspace 鍵的刪除動作。
  3. 向前刪除,例如按下 Delete 鍵的刪除動作。

任何對上述操作的中斷都會破壞連續輸入的概念。請注意,在這三種操作之間切換本身可能會被視為中斷連續輸入,或者也可能不會。這最終是一個可用性決策。在我看來,當檢視各種文字處理器時,在這三種操作之間切換應保持連續性,因為使用者在輸入過程中經常會出現錯別字或進行更正,因此會傾向於將整個輸入、回刪和刪除的過程視為單一可撤銷的操作序列。

請注意,Google 文件和 Quip 將在輸入、回刪和刪除之間切換視為連續輸入會話的中斷。

以選取文字開始並繼續輸入

讓我們從一些選取的文字開始。使用者可能已直接選取了文字,或者是由於粘貼文字或其他操作步驟所導致的選取。當隨後進行連續輸入時,初始選取應與後續的輸入事件一起,作為單一合併撤銷會話的一部分。

超時

文字編輯通常是一種無模式的使用者體驗,因此除上述輸入操作外的任何事件都可能會中斷連續輸入。首當其衝的就是超時。

Quip 似乎要求連續輸入在 1 秒內發生,而 Google 文件則大約為 2 秒。在我看來,超時時間可能會延長到 3 到 5 秒。輸入事件之間的時間越長,使用者就越有機會有意地輸入一段文字、一個想法或概念。

使用超時並非必須,具體的時間長度也有待討論。在協作共編時,超時也會被用來分組來自不同用戶端的文字。更長的超時時間往往會使協作變得更順暢,且不易打斷,因為在表達想法時接收其他用戶端的輸入通常並不有用。

實作者應根據客戶的期望以及可能共享此超時時間的相關協作功能來考慮合適的超時時間。

硬換行與軟換行

按下 Return 鍵產生的硬換行通常會中斷並重設連續輸入。

對於 Google 文件和 Quip 而言,按下 shift+Return 鍵產生的軟換行不會終止連續輸入。這是合理的,因為軟換行結束了文本換行,但並未結束段落。

選取變更和鍵盤焦點變更

使用者對選取的任何更改應終止合併,這包括:

  • 使用箭頭鍵進行的導航。
  • 選取單詞、句子或段落的手勢。
  • 其他不會通過上述輸入事件將閃爍光標移動到下一個或前一個字符的選取變更。

此外,結束編輯視窗的鍵盤焦點,包括將焦點移至另一個編輯視窗或同一視窗內的不同視圖,也應終止合併。這也包括將焦點設置到模式彈出窗口,例如超連結屬性編輯器。

組合字符

在輸入附加符號、CJK(中日韓字符)甚至表情符號時會發生字符組合。這個過程通常涉及至少以下三個階段:

  • 開始組合。
  • 使用其他文字替換組合文字並保持組合狀態。此步驟可能在單次組合會話中發生多次。
  • 停止組合,無論是接受該文字還是取消最近的輸入。

合併應在組合開始時終止。組合文字的替換通常應該被合併。根據實作,停止組合可能會或可能不會重設合併。Quip 似乎嘗試將多個組合字符合併,但在組合字符與非組合字符之間切換時會中斷合併。Google 文件似乎更頻繁地中斷合併。兩者都合併了文字替換。

自動更正、拼寫更正和文字替換

文字替換的行為類似於組合字符。當文字被轉換時,合併應終止,且轉換後的文字將成為下一次撤銷會話中合併的首個條目。

複製與貼上

像複製和貼上這樣的操作通常會觸發不屬於上述 3 種連續輸入操作的事件。因此,複製和貼上也會終止合併。

結論

文字撤銷合併大大提高了撤銷的可用性,因為它允許使用者跳過所有用於形成或重新形成段落內文本的中間事件。鑑於文字編輯的無模式特性,將連續輸入嚴格限制在三個事件中允許實現一個穩健且乾淨的實作。實作者將需要緊密的瓶頸來捕捉選取變更、鍵盤焦點變更以及來自協作用戶端的變更。儘管上述內容尚不完全,但我希望讀者會覺得這些內容有所幫助。