Skip to content

Commit

Permalink
Support for removeReaction of custom emoji
Browse files Browse the repository at this point in the history
  • Loading branch information
singpolyma committed Nov 14, 2024
1 parent 05d7379 commit 71f1dea
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 46 deletions.
35 changes: 28 additions & 7 deletions snikket/Chat.hx
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ abstract class Chat {
**/
public function addReaction(m:ChatMessage, reaction:Reaction) {
final toSend = m.reply();
toSend.localId = ID.long();
reaction.render(
(text) -> {
toSend.text = text.replace("\u{fe0f}", "");
Expand All @@ -214,7 +215,7 @@ abstract class Chat {
@param m ChatMessage to remove the reaction from
@param reaction the emoji to remove
**/
abstract public function removeReaction(m:ChatMessage, reaction:String):Void;
abstract public function removeReaction(m:ChatMessage, reaction:Reaction):Void;

abstract private function sendChatState(state: String, threadId: Null<String>):Void;

Expand Down Expand Up @@ -725,7 +726,7 @@ class DirectChat extends Chat {
message.versions = [toSend]; // This is a correction
message.localId = localId;
client.storeMessage(message, (corrected) -> {
toSend.versions = corrected.versions;
toSend.versions = corrected.localId == localId ? corrected.versions : [message];
for (recipient in message.recipients) {
message.to = recipient;
client.sendStanza(toSend.asStanza());
Expand Down Expand Up @@ -776,11 +777,21 @@ class DirectChat extends Chat {
}

@HaxeCBridge.noemit // on superclass as abstract
public function removeReaction(m:ChatMessage, reaction:String) {
public function removeReaction(m:ChatMessage, reaction:Reaction) {
if (Std.is(reaction, CustomEmojiReaction)) {
if (reaction.envelopeId == null) throw "Cannot remove custom emoji reaction without envelopeId";
final correct = m.reply();
correct.localId = ID.long();
correct.setHtml("");
correct.text = null;
correctMessage(reaction.envelopeId, correct);
return;
}

// NOTE: doing it this way means no fallback behaviour
final reactions = [];
for (areaction => reacts in m.reactions) {
if (areaction != reaction) {
if (areaction != reaction.key) {
final react = reacts.find(r -> r.senderId == client.accountId());
if (react != null && !Std.is(react, CustomEmojiReaction)) {
reactions.push(react);
Expand Down Expand Up @@ -1162,7 +1173,7 @@ class Channel extends Chat {
message.versions = [toSend]; // This is a correction
message.localId = localId;
client.storeMessage(message, (corrected) -> {
toSend.versions = corrected.versions;
toSend.versions = corrected.localId == localId ? corrected.versions : [message];
client.sendStanza(toSend.asStanza());
if (localId == lastMessage?.localId) {
setLastMessage(corrected);
Expand Down Expand Up @@ -1207,11 +1218,21 @@ class Channel extends Chat {
}

@HaxeCBridge.noemit // on superclass as abstract
public function removeReaction(m:ChatMessage, reaction:String) {
public function removeReaction(m:ChatMessage, reaction:Reaction) {
if (Std.is(reaction, CustomEmojiReaction)) {
if (reaction.envelopeId == null) throw "Cannot remove custom emoji reaction without envelopeId";
final correct = m.reply();
correct.localId = ID.long();
correct.setHtml("");
correct.text = null;
correctMessage(reaction.envelopeId, correct);
return;
}

// NOTE: doing it this way means no fallback behaviour
final reactions = [];
for (areaction => reacts in m.reactions) {
if (areaction != reaction) {
if (areaction != reaction.key) {
final react = reacts.find(r -> r.senderId == getFullJid().asString());
if (react != null && !Std.is(react, CustomEmojiReaction)) reactions.push(react);
}
Expand Down
63 changes: 32 additions & 31 deletions snikket/ChatMessage.hx
Original file line number Diff line number Diff line change
Expand Up @@ -412,43 +412,44 @@ class ChatMessage {

final replyToM = replyToMessage;
if (replyToM != null) {
if (body == null) body = "";
final lines = replyToM.text?.split("\n") ?? [];
var quoteText = "";
for (line in lines) {
if (!~/^(?:> ?){3,}/.match(line)) {
if (line.charAt(0) == ">") {
quoteText += ">" + line + "\n";
} else {
quoteText += "> " + line + "\n";
final replyId = replyToM.getReplyId();
if (body != null) {
final lines = replyToM.text?.split("\n") ?? [];
var quoteText = "";
for (line in lines) {
if (!~/^(?:> ?){3,}/.match(line)) {
if (line.charAt(0) == ">") {
quoteText += ">" + line + "\n";
} else {
quoteText += "> " + line + "\n";
}
}
}
}
final reaction = EmojiUtil.isEmoji(StringTools.trim(body)) ? StringTools.trim(body) : null;
body = quoteText + body;
final replyId = replyToM.getReplyId();
if (replyId != null) {
final codepoints = StringUtil.codepointArray(quoteText);
if (reaction != null) {
final addedReactions: Map<String, Bool> = [];
stanza.tag("reactions", { xmlns: "urn:xmpp:reactions:0", id: replyId });
stanza.textTag("reaction", reaction);
addedReactions[reaction] = true;

for (areaction => reactions in replyToM.reactions) {
if (!(addedReactions[areaction] ?? false) && reactions.find(r -> r.senderId == senderId()) != null) {
addedReactions[areaction] = true;
stanza.textTag("reaction", areaction);
final reaction = EmojiUtil.isEmoji(StringTools.trim(body)) ? StringTools.trim(body) : null;
body = quoteText + body;
if (replyId != null) {
final codepoints = StringUtil.codepointArray(quoteText);
if (reaction != null) {
final addedReactions: Map<String, Bool> = [];
stanza.tag("reactions", { xmlns: "urn:xmpp:reactions:0", id: replyId });
stanza.textTag("reaction", reaction);
addedReactions[reaction] = true;

for (areaction => reactions in replyToM.reactions) {
if (!(addedReactions[areaction] ?? false) && reactions.find(r -> r.senderId == senderId()) != null) {
addedReactions[areaction] = true;
stanza.textTag("reaction", areaction);
}
}
stanza.up();
stanza.tag("fallback", { xmlns: "urn:xmpp:fallback:0", "for": "urn:xmpp:reactions:0" })
.tag("body").up().up();
}
stanza.up();
stanza.tag("fallback", { xmlns: "urn:xmpp:fallback:0", "for": "urn:xmpp:reactions:0" })
.tag("body").up().up();
stanza.tag("fallback", { xmlns: "urn:xmpp:fallback:0", "for": "urn:xmpp:reply:0" })
.tag("body", { start: "0", end: Std.string(codepoints.length) }).up().up();
}
stanza.tag("fallback", { xmlns: "urn:xmpp:fallback:0", "for": "urn:xmpp:reply:0" })
.tag("body", { start: "0", end: Std.string(codepoints.length) }).up().up();
stanza.tag("reply", { xmlns: "urn:xmpp:reply:0", to: replyToM.from?.asString(), id: replyId }).up();
}
if (replyId != null) stanza.tag("reply", { xmlns: "urn:xmpp:reply:0", to: replyToM.from?.asString(), id: replyId }).up();
}

for (attachment in attachments) {
Expand Down
6 changes: 3 additions & 3 deletions snikket/Message.hx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ class Message {
msg.chatId(),
msg.senderId(),
timestamp,
reactions.map(text -> new Reaction(msg.senderId(), timestamp, text)),
reactions.map(text -> new Reaction(msg.senderId(), timestamp, text, msg.localId)),
EmojiReactions
)));
}
Expand Down Expand Up @@ -229,7 +229,7 @@ class Message {
msg.chatId(),
msg.senderId(),
timestamp,
[new Reaction(msg.senderId(), timestamp, text.trim())],
[new Reaction(msg.senderId(), timestamp, text.trim(), msg.localId)],
AppendReactions
)));
}
Expand All @@ -249,7 +249,7 @@ class Message {
msg.chatId(),
msg.senderId(),
timestamp,
[new CustomEmojiReaction(msg.senderId(), timestamp, els[0].attr.get("alt") ?? "", hash.serializeUri())],
[new CustomEmojiReaction(msg.senderId(), timestamp, els[0].attr.get("alt") ?? "", hash.serializeUri(), msg.localId)],
AppendReactions
)));
}
Expand Down
8 changes: 5 additions & 3 deletions snikket/Reaction.hx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ class Reaction {
public final timestamp: String;
public final text: String;
public final key: String;
public final envelopeId: Null<String>;

public function new(senderId: String, timestamp: String, text: String, key: Null<String> = null) {
public function new(senderId: String, timestamp: String, text: String, envelopeId: Null<String> = null, key: Null<String> = null) {
this.senderId = senderId;
this.timestamp = timestamp;
this.text = text.replace("\u{fe0f}", "");
this.envelopeId = envelopeId;
this.key = key ?? this.text;
}

Expand All @@ -26,8 +28,8 @@ class Reaction {
class CustomEmojiReaction extends Reaction {
public final uri: String;

public function new(senderId: String, timestamp: String, text: String, uri: String) {
super(senderId, timestamp, text, uri);
public function new(senderId: String, timestamp: String, text: String, uri: String, envelopeId: Null<String> = null) {
super(senderId, timestamp, text, envelopeId, uri);
this.uri = uri;
}

Expand Down
4 changes: 2 additions & 2 deletions snikket/persistence/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ const browser = (dbname, tokenize, stemmer) => {

function hydrateObjectReaction(r) {
if (r.uri) {
return new snikket.CustomEmojiReaction(r.senderId, r.timestamp, r.text, r.uri);
return new snikket.CustomEmojiReaction(r.senderId, r.timestamp, r.text, r.uri, r.envelopeId);
} else {
return new snikket.Reaction(r.senderId, r.timestamp, r.text, r.key);
return new snikket.Reaction(r.senderId, r.timestamp, r.text, r.envelopeId, r.key);
}
}

Expand Down

0 comments on commit 71f1dea

Please sign in to comment.