From b2c2e40737a333874c27f77e8675fc2d71e299ff Mon Sep 17 00:00:00 2001 From: frank Date: Fri, 28 Jul 2023 10:49:02 +0800 Subject: [PATCH] fix_: add callTime for `OnChangeText` --- protocol/messenger_mention.go | 26 ++++++++-------- protocol/messenger_mention_test.go | 49 +++++++++++++++++------------- services/ext/api.go | 4 +-- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/protocol/messenger_mention.go b/protocol/messenger_mention.go index d624d044876..83a690e3aed 100644 --- a/protocol/messenger_mention.go +++ b/protocol/messenger_mention.go @@ -170,6 +170,7 @@ type ChatMentionContext struct { NewText string CallID uint64 + CallTime int64 mu *sync.Mutex LatestCallID uint64 } @@ -301,19 +302,20 @@ func (m *MentionManager) ReplaceWithPublicKey(chatID, text string) (string, erro return newText, nil } -func withCallID(ctx *ChatMentionContext, callID uint64) *ChatMentionContext { +func withCallID(ctx *ChatMentionContext, callID uint64, callTime int64) *ChatMentionContext { result := *ctx result.CallID = callID + result.CallTime = callTime return &result } -func (m *MentionManager) OnChangeText(chatID, fullText string, callID uint64) (*ChatMentionContext, error) { +func (m *MentionManager) OnChangeText(chatID, fullText string, callID uint64, callTime int64) (*ChatMentionContext, error) { ctx := m.getChatMentionContext(chatID) if callID > 0 { ctx.mu.Lock() if callID <= ctx.LatestCallID { ctx.mu.Unlock() - return withCallID(ctx, callID), fmt.Errorf("callID is less than or equal to latestCallID, callID: %d, maxCallID: %d", callID, ctx.LatestCallID) + return withCallID(ctx, callID, callTime), fmt.Errorf("callID is less than or equal to latestCallID, callID: %d, maxCallID: %d", callID, ctx.LatestCallID) } ctx.LatestCallID = callID ctx.mu.Unlock() @@ -321,7 +323,7 @@ func (m *MentionManager) OnChangeText(chatID, fullText string, callID uint64) (* diff := diffText(ctx.PreviousText, fullText) if diff == nil { - return withCallID(ctx, callID), nil + return withCallID(ctx, callID, callTime), nil } ctx.PreviousText = fullText if ctx.MentionState == nil { @@ -335,12 +337,12 @@ func (m *MentionManager) OnChangeText(chatID, fullText string, callID uint64) (* atIndexes, err := calculateAtIndexEntries(ctx.MentionState) if err != nil { - return withCallID(ctx, callID), err + return withCallID(ctx, callID, callTime), err } ctx.MentionState.AtIdxs = atIndexes m.logger.Debug("OnChangeText", zap.String("chatID", chatID), zap.Any("state", ctx.MentionState)) ctx, err = m.calculateSuggestions(chatID, fullText) - return withCallID(ctx, callID), err + return withCallID(ctx, callID, callTime), err } func (m *MentionManager) calculateSuggestions(chatID, fullText string) (*ChatMentionContext, error) { @@ -372,8 +374,8 @@ func (m *MentionManager) calculateSuggestionsWithMentionableUsers(chatID string, } newAtIndexEntries := checkIdxForMentions(fullText, state.AtIdxs, mentionableUsers) - calculatedInput, success := calculateInput(fullText, newAtIndexEntries) - if !success { + calculatedInput, inputSegmentString := calculateInput(fullText, newAtIndexEntries) + if fullText != inputSegmentString { m.logger.Warn("calculateSuggestionsWithMentionableUsers: calculateInput failed", zap.String("chatID", chatID), zap.String("fullText", fullText), zap.Any("state", state)) } @@ -426,7 +428,7 @@ func (m *MentionManager) SelectMention(chatID, text, primaryName, publicKey stri ctx.NewText = string(tr[:atSignIdx+1]) + primaryName + space + string(tr[mentionEnd:]) - _, err := m.OnChangeText(chatID, ctx.NewText, 0) + _, err := m.OnChangeText(chatID, ctx.NewText, 0, 0) if err != nil { return nil, err } @@ -1013,9 +1015,9 @@ func appendInputSegment(result *[]InputSegment, typ SegmentType, value string, f } } -func calculateInput(text string, atIndexEntries []*AtIndexEntry) ([]InputSegment, bool) { +func calculateInput(text string, atIndexEntries []*AtIndexEntry) ([]InputSegment, string) { if len(atIndexEntries) == 0 { - return []InputSegment{{Type: Text, Value: text}}, true + return []InputSegment{{Type: Text, Value: text}}, text } idxCount := len(atIndexEntries) lastFrom := atIndexEntries[idxCount-1].From @@ -1051,7 +1053,7 @@ func calculateInput(text string, atIndexEntries []*AtIndexEntry) ([]InputSegment } } - return result, fullText == text + return result, fullText } func subs(s string, start int, end ...int) string { diff --git a/protocol/messenger_mention_test.go b/protocol/messenger_mention_test.go index 6ce89a8cb63..aa222dcfaea 100644 --- a/protocol/messenger_mention_test.go +++ b/protocol/messenger_mention_test.go @@ -5,6 +5,7 @@ import ( "reflect" "strings" "testing" + "time" "github.com/stretchr/testify/require" @@ -794,7 +795,7 @@ func TestMentionSuggestionCases(t *testing.T) { for i, tc := range testCases { t.Run(fmt.Sprintf("%d", i+1), func(t *testing.T) { - ctx, err := mentionManager.OnChangeText(chatID, tc.inputText, uint64(i+1)) + ctx, err := mentionManager.OnChangeText(chatID, tc.inputText, uint64(i+1), now()) require.NoError(t, err) t.Logf("Input: %+v, MentionState:%+v, InputSegments:%+v\n", tc.inputText, ctx.MentionState, ctx.InputSegments) require.Equal(t, tc.expectedSize, len(ctx.MentionSuggestions)) @@ -806,7 +807,7 @@ func TestMentionSuggestionAfterToInputField(t *testing.T) { mentionableUserMap, chatID, mentionManager := setupMentionSuggestionTest(t, nil) _, err := mentionManager.ToInputField(chatID, "abc") require.NoError(t, err) - ctx, err := mentionManager.OnChangeText(chatID, "@", 1) + ctx, err := mentionManager.OnChangeText(chatID, "@", 1, now()) require.NoError(t, err) require.Equal(t, len(mentionableUserMap), len(ctx.MentionSuggestions)) } @@ -826,7 +827,7 @@ func TestMentionSuggestionSpecialInputModeForAndroid(t *testing.T) { for i, tc := range testCases { t.Run(fmt.Sprintf("%d", i+1), func(t *testing.T) { - ctx, err := mentionManager.OnChangeText(chatID, tc.inputText, uint64(i+1)) + ctx, err := mentionManager.OnChangeText(chatID, tc.inputText, uint64(i+1), now()) require.NoError(t, err) require.Equal(t, tc.expectedSize, len(ctx.MentionSuggestions)) t.Logf("Input: %+v, MentionState:%+v, InputSegments:%+v\n", tc.inputText, ctx.MentionState, ctx.InputSegments) @@ -849,7 +850,7 @@ func TestMentionSuggestionSpecialChars(t *testing.T) { for i, tc := range testCases { t.Run(fmt.Sprintf("%d", i+1), func(t *testing.T) { - ctx, err := mentionManager.OnChangeText(chatID, tc.inputText, uint64(i+1)) + ctx, err := mentionManager.OnChangeText(chatID, tc.inputText, uint64(i+1), now()) require.NoError(t, err) t.Logf("Input: %+v, MentionState:%+v, InputSegments:%+v\n", tc.inputText, ctx.MentionState, ctx.InputSegments) require.Equal(t, tc.expectedSize, len(ctx.MentionSuggestions)) @@ -879,7 +880,7 @@ func TestMentionSuggestionAtSignSpaceCases(t *testing.T) { var ctx *ChatMentionContext var err error for i, tc := range testCases { - ctx, err = mentionManager.OnChangeText(chatID, tc.inputText, uint64(i+1)) + ctx, err = mentionManager.OnChangeText(chatID, tc.inputText, uint64(i+1), now()) require.NoError(t, err) t.Logf("After OnChangeText, Input: %+v, MentionState:%+v, InputSegments:%+v\n", tc.inputText, ctx.MentionState, ctx.InputSegments) require.Equal(t, tc.expectedSize, len(ctx.MentionSuggestions)) @@ -896,12 +897,12 @@ func TestSelectMention(t *testing.T) { var callID uint64 = 1 text := "@u2 abc" - ctx, err := mentionManager.OnChangeText(chatID, text, callID) + ctx, err := mentionManager.OnChangeText(chatID, text, callID, now()) require.NoError(t, err) require.Equal(t, 0, len(ctx.MentionSuggestions)) callID++ - ctx, err = mentionManager.OnChangeText(chatID, "@u abc", callID) + ctx, err = mentionManager.OnChangeText(chatID, "@u abc", callID, now()) require.NoError(t, err) require.Equal(t, len(mentionableUsers), len(ctx.MentionSuggestions)) @@ -912,22 +913,26 @@ func TestSelectMention(t *testing.T) { require.Equal(t, text, ctx.PreviousText) callID++ - ctx, err = mentionManager.OnChangeText(chatID, text, callID) + ctx, err = mentionManager.OnChangeText(chatID, text, callID, now()) require.NoError(t, err) require.Equal(t, 0, len(ctx.MentionSuggestions)) } +func now() int64 { + return time.Now().UnixMilli() +} + func TestInputSegments(t *testing.T) { _, chatID, mentionManager := setupMentionSuggestionTest(t, nil) var callID uint64 = 1 - ctx, err := mentionManager.OnChangeText(chatID, "@u1", callID) + ctx, err := mentionManager.OnChangeText(chatID, "@u1", callID, now()) require.NoError(t, err) require.Equal(t, 1, len(ctx.InputSegments)) require.Equal(t, Text, ctx.InputSegments[0].Type) require.Equal(t, "@u1", ctx.InputSegments[0].Value) callID++ - ctx, err = mentionManager.OnChangeText(chatID, "@u1 @User Number One", callID) + ctx, err = mentionManager.OnChangeText(chatID, "@u1 @User Number One", callID, now()) require.NoError(t, err) require.Equal(t, 2, len(ctx.InputSegments)) require.Equal(t, Text, ctx.InputSegments[0].Type) @@ -936,14 +941,14 @@ func TestInputSegments(t *testing.T) { require.Equal(t, "@User Number One", ctx.InputSegments[1].Value) callID++ - ctx, err = mentionManager.OnChangeText(chatID, "@u1 @User Number O", callID) + ctx, err = mentionManager.OnChangeText(chatID, "@u1 @User Number O", callID, now()) require.NoError(t, err) require.Equal(t, 2, len(ctx.InputSegments)) require.Equal(t, Text, ctx.InputSegments[1].Type) require.Equal(t, "@User Number O", ctx.InputSegments[1].Value) callID++ - ctx, err = mentionManager.OnChangeText(chatID, "@u2 @User Number One", callID) + ctx, err = mentionManager.OnChangeText(chatID, "@u2 @User Number One", callID, now()) require.NoError(t, err) require.Equal(t, 3, len(ctx.InputSegments)) require.Equal(t, Mention, ctx.InputSegments[0].Type) @@ -954,7 +959,7 @@ func TestInputSegments(t *testing.T) { require.Equal(t, "@User Number One", ctx.InputSegments[2].Value) callID++ - ctx, err = mentionManager.OnChangeText(chatID, "@u2 @User Number One a ", callID) + ctx, err = mentionManager.OnChangeText(chatID, "@u2 @User Number One a ", callID, now()) require.NoError(t, err) require.Equal(t, 4, len(ctx.InputSegments)) require.Equal(t, Mention, ctx.InputSegments[2].Type) @@ -963,7 +968,7 @@ func TestInputSegments(t *testing.T) { require.Equal(t, " a ", ctx.InputSegments[3].Value) callID++ - ctx, err = mentionManager.OnChangeText(chatID, "@u2 @User Numbed One a ", callID) + ctx, err = mentionManager.OnChangeText(chatID, "@u2 @User Numbed One a ", callID, now()) require.NoError(t, err) require.Equal(t, 3, len(ctx.InputSegments)) require.Equal(t, Mention, ctx.InputSegments[0].Type) @@ -972,7 +977,7 @@ func TestInputSegments(t *testing.T) { require.Equal(t, "@User Numbed One a ", ctx.InputSegments[2].Value) callID++ - ctx, err = mentionManager.OnChangeText(chatID, "@ @ ", callID) + ctx, err = mentionManager.OnChangeText(chatID, "@ @ ", callID, now()) require.NoError(t, err) require.Equal(t, 2, len(ctx.InputSegments)) require.Equal(t, Text, ctx.InputSegments[0].Type) @@ -981,7 +986,7 @@ func TestInputSegments(t *testing.T) { require.Equal(t, "@ ", ctx.InputSegments[1].Value) callID++ - ctx, err = mentionManager.OnChangeText(chatID, "@u3 @ ", callID) + ctx, err = mentionManager.OnChangeText(chatID, "@u3 @ ", callID, now()) require.NoError(t, err) require.Equal(t, 3, len(ctx.InputSegments)) require.Equal(t, Mention, ctx.InputSegments[0].Type) @@ -992,24 +997,26 @@ func TestInputSegments(t *testing.T) { require.Equal(t, "@ ", ctx.InputSegments[2].Value) callID++ - _, err = mentionManager.OnChangeText(chatID, " @ @User Number Three ", callID) + _, err = mentionManager.OnChangeText(chatID, " @ @User Number Three ", callID, now()) require.NoError(t, err) callID++ - _, err = mentionManager.OnChangeText(chatID, "@U @ @User Number Three ", callID) + _, err = mentionManager.OnChangeText(chatID, "@U @ @User Number Three ", callID, now()) require.NoError(t, err) ctx, err = mentionManager.SelectMention(chatID, "@U @ @User Number Three ", "User Number Three", "0xpk3") require.NoError(t, err) require.Equal(t, 2, mentionTypeNum(ctx.InputSegments)) callID++ - ctx, _ = mentionManager.OnChangeText(chatID, "@User Number Threea", callID) + ctx, _ = mentionManager.OnChangeText(chatID, "@User Number Threea", callID, now()) require.Equal(t, 0, mentionTypeNum(ctx.InputSegments)) callID++ - ctx, _ = mentionManager.OnChangeText(chatID, "@User Number Threea\n@u2\nabc@u3 asa", callID) + ctx, err = mentionManager.OnChangeText(chatID, "@User Number Threea\n@u2\nabc@u3 asa", callID, now()) + require.NoError(t, err) require.Equal(t, 2, mentionTypeNum(ctx.InputSegments)) callID++ - ctx, _ = mentionManager.OnChangeText(chatID, "@User Number Thre\n@u2\nabc@u3 asa", callID) + ctx, err = mentionManager.OnChangeText(chatID, "@User Number Thre\n@u2\nabc@u3 asa", callID, now()) + require.NoError(t, err) require.Equal(t, 2, mentionTypeNum(ctx.InputSegments)) require.Equal(t, "@u2", ctx.InputSegments[1].Value) require.Equal(t, "@u3", ctx.InputSegments[3].Value) diff --git a/services/ext/api.go b/services/ext/api.go index 054053fcbf4..1941505fc97 100644 --- a/services/ext/api.go +++ b/services/ext/api.go @@ -1705,8 +1705,8 @@ func (api *PublicAPI) ChatMentionReplaceWithPublicKey(chatID, text string) (stri // 2. user input "c", call this function with text "abc" // whatever, we should ensure ChatMentionOnChangeText know(invoked) the latest full text. // ChatMentionOnChangeText will maintain state of fulltext and diff between previous/latest full text internally. -func (api *PublicAPI) ChatMentionOnChangeText(chatID, text string, callID uint64) (*protocol.ChatMentionContext, error) { - return api.service.messenger.GetMentionsManager().OnChangeText(chatID, text, callID) +func (api *PublicAPI) ChatMentionOnChangeText(chatID, text string, callID uint64, callTime int64) (*protocol.ChatMentionContext, error) { + return api.service.messenger.GetMentionsManager().OnChangeText(chatID, text, callID, callTime) } // ChatMentionSelectMention select mention from mention suggestion list