fix key repeat: only create new state when previous is acked (match Dart client)
The Dart mosh client only calls sendNew() when hasPendingState is false. The Go client was calling SetPending on every tick with dirty=true, which reset diffSent and caused new sequence numbers for the same cumulative payload. Now tick() checks AckedByRemote >= SentNum before calling SetPending — at most one unacked state in flight, matching the Dart client's behavior.
This commit is contained in:
@@ -178,9 +178,15 @@ func (c *Client) Tick() {
|
||||
}
|
||||
|
||||
func (c *Client) tick() {
|
||||
// Batch: compute diff from accumulated actions.
|
||||
// Only create a new state when the server has acked the previous one.
|
||||
// This matches the Dart mosh client's behavior: at most one unacked
|
||||
// state in flight. Keystrokes accumulate until the ack arrives, then
|
||||
// the next tick sends them all as a single new state.
|
||||
// Without this check, SetPending resets diffSent, causing Tick() to
|
||||
// increment sentNum for the same cumulative payload — the server
|
||||
// applies duplicate keystrokes.
|
||||
c.actionsMu.Lock()
|
||||
if c.dirty {
|
||||
if c.dirty && c.transport.AckedByRemote() >= c.transport.SentNum() {
|
||||
c.dirty = false
|
||||
c.processAcksLocked()
|
||||
newActions := c.actions[c.ackedActionCount:]
|
||||
|
||||
+3
-13
@@ -84,19 +84,12 @@ func newSession(url, key string) (*session, error) {
|
||||
func (s *session) jsObject() js.Value {
|
||||
obj := js.Global().Get("Object").New()
|
||||
|
||||
// Tick immediately when idle (no unacked states). When busy (ack
|
||||
// pending), queue keystrokes and let the interval flush them.
|
||||
// This gives instant feel for the first key while preventing
|
||||
// cumulative state duplication during rapid typing.
|
||||
obj.Set("send", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
if len(args) < 1 {
|
||||
return nil
|
||||
}
|
||||
s.client.Send([]byte(args[0].String()))
|
||||
t := s.client.Transport()
|
||||
if t.AckedByRemote() >= t.SentNum() {
|
||||
s.client.Tick()
|
||||
}
|
||||
s.client.Tick()
|
||||
return nil
|
||||
}))
|
||||
|
||||
@@ -105,14 +98,11 @@ func (s *session) jsObject() js.Value {
|
||||
return nil
|
||||
}
|
||||
s.client.Resize(uint16(args[0].Int()), uint16(args[1].Int()))
|
||||
t := s.client.Transport()
|
||||
if t.AckedByRemote() >= t.SentNum() {
|
||||
s.client.Tick()
|
||||
}
|
||||
s.client.Tick()
|
||||
return nil
|
||||
}))
|
||||
|
||||
// tick() — send keepalive. Called by JS setInterval at a slow rate.
|
||||
// tick() — flush pending keystrokes + keepalive/retransmit.
|
||||
obj.Set("tick", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
s.client.Tick()
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user