From f53fe992547f92471704f877ee0ce5f0cf67d09c Mon Sep 17 00:00:00 2001 From: Mike Maxim Date: Thu, 9 Apr 2020 11:19:55 -0400 Subject: [PATCH] add quick reaction input (#23602) --- go/chat/server.go | 69 +++++++++++++++++++ .../conversation/input-area/normal/index.tsx | 6 +- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/go/chat/server.go b/go/chat/server.go index fc889ad5a1e1..ecbeb3d3d8c4 100644 --- a/go/chat/server.go +++ b/go/chat/server.go @@ -877,9 +877,78 @@ func (h *Server) runStellarSendUI(ctx context.Context, sessionID int, uid gregor return chat1.NewMessageBodyWithText(newBody), nil } +var quickReactionPattern = regexp.MustCompile(`(?:^\+:)([^\s]+)(?::)$`) + +func (h *Server) isQuickReaction(ctx context.Context, uid gregor1.UID, convID chat1.ConversationID, + body string) (reaction string, msgID chat1.MessageID, ok bool) { + body = strings.TrimSpace(body) + if !(strings.HasPrefix(body, "+:") && strings.HasSuffix(body, ":")) { + return "", 0, false + } + hits := quickReactionPattern.FindStringSubmatch(body) + if len(hits) < 2 { + return "", 0, false + } + tryStock := func() (string, bool) { + if h.G().EmojiSource.IsStockEmoji(hits[1]) { + return ":" + hits[1] + ":", true + } + return "", false + } + tryCustom := func() (string, bool) { + emojis, err := h.G().EmojiSource.Harvest(ctx, body, uid, convID, types.EmojiHarvestModeFast) + if err != nil { + h.Debug(ctx, "isQuickReaction: failed to harvest: %s", err) + return "", false + } + if len(emojis) != 1 { + return "", false + } + return ":" + emojis[0].Alias + ":", true + } + var hit *string + if reaction, ok = tryStock(); ok { + hit = new(string) + *hit = reaction + } + if hit == nil { + if reaction, ok = tryCustom(); ok { + hit = new(string) + *hit = reaction + } + } + if hit == nil { + return "", 0, false + } + conv, err := utils.GetUnverifiedConv(ctx, h.G(), uid, convID, types.InboxSourceDataSourceLocalOnly) + if err != nil { + h.Debug(ctx, "isQuickReaction: failed to get conv: %s", err) + return "", 0, false + } + return *hit, conv.MaxVisibleMsgID(), true +} + func (h *Server) PostTextNonblock(ctx context.Context, arg chat1.PostTextNonblockArg) (res chat1.PostLocalNonblockRes, err error) { ctx = globals.ChatCtx(ctx, h.G(), arg.IdentifyBehavior, nil, h.identNotifier) defer h.Trace(ctx, func() error { return err }, "PostTextNonblock")() + uid, err := utils.AssertLoggedInUID(ctx, h.G()) + if err != nil { + return res, err + } + reaction, msgID, ok := h.isQuickReaction(ctx, uid, arg.ConversationID, arg.Body) + if ok { + h.Debug(ctx, "PostTextNonblock: detected quick reaction") + return h.PostReactionNonblock(ctx, chat1.PostReactionNonblockArg{ + ConversationID: arg.ConversationID, + TlfName: arg.TlfName, + TlfPublic: arg.TlfPublic, + Supersedes: msgID, + Body: reaction, + OutboxID: arg.OutboxID, + ClientPrev: arg.ClientPrev, + IdentifyBehavior: arg.IdentifyBehavior, + }) + } var parg chat1.PostLocalNonblockArg parg.SessionID = arg.SessionID diff --git a/shared/chat/conversation/input-area/normal/index.tsx b/shared/chat/conversation/input-area/normal/index.tsx index 657fb84a8c23..4a97fabe5d5c 100644 --- a/shared/chat/conversation/input-area/normal/index.tsx +++ b/shared/chat/conversation/input-area/normal/index.tsx @@ -94,7 +94,7 @@ const searchUsersAndTeamsAndTeamChannels = memoize( const suggestorToMarker = { channels: '#', commands: /(!|\/)/, - emoji: ':', + emoji: /(\+?):/, // 'users' is for @user, @team, and @team#channel users: /((\+\d+(\.\d+)?[a-zA-Z]{3,12}@)|@)/, // match normal mentions and ones in a stellar send } @@ -138,8 +138,8 @@ const emojiRenderer = (item: EmojiData, selected: boolean) => { ) } -const emojiTransformer = (emoji: EmojiData, _: unknown, tData: TransformerData, preview: boolean) => { - return standardTransformer(`:${emoji.short_name}:`, tData, preview) +const emojiTransformer = (emoji: EmojiData, marker: string, tData: TransformerData, preview: boolean) => { + return standardTransformer(`${marker}${emoji.short_name}:`, tData, preview) } type InputState = {