Skip to content

Commit d44961c

Browse files
authored
Support reacting literally with non-Emojis (#320)
1 parent 6d80b51 commit d44961c

File tree

3 files changed

+54
-30
lines changed

3 files changed

+54
-30
lines changed

src/base.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ pub enum MessageAction {
152152
Edit,
153153

154154
/// React to a message with an Emoji.
155-
React(String),
155+
///
156+
/// `:react` will by default try to convert the [String] argument to an Emoji, and error when
157+
/// it doesn't recognize it. The second [bool] argument forces it to be interpreted literally
158+
/// when it is `true`.
159+
React(String, bool),
156160

157161
/// Redact a message, with an optional reason.
158162
///
@@ -166,7 +170,11 @@ pub enum MessageAction {
166170
///
167171
/// If no specific Emoji to remove to is specified, then all reactions from the user on the
168172
/// message are removed.
169-
Unreact(Option<String>),
173+
///
174+
/// Like `:react`, `:unreact` will by default try to convert the [String] argument to an Emoji,
175+
/// and error when it doesn't recognize it. The second [bool] argument forces it to be
176+
/// interpreted literally when it is `true`.
177+
Unreact(Option<String>, bool),
170178
}
171179

172180
/// The type of room being created.

src/commands.rs

+7-26
Original file line numberDiff line numberDiff line change
@@ -221,24 +221,17 @@ fn iamb_edit(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
221221
}
222222

223223
fn iamb_react(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
224-
let args = desc.arg.strings()?;
224+
let mut args = desc.arg.strings()?;
225225

226226
if args.len() != 1 {
227227
return Result::Err(CommandError::InvalidArgument);
228228
}
229229

230-
let k = args[0].as_str();
231-
232-
if let Some(emoji) = emojis::get(k).or_else(|| emojis::get_by_shortcode(k)) {
233-
let mact = IambAction::from(MessageAction::React(emoji.to_string()));
234-
let step = CommandStep::Continue(mact.into(), ctx.context.clone());
235-
236-
return Ok(step);
237-
} else {
238-
let msg = format!("Invalid Emoji or shortcode: {k}");
230+
let react = args.remove(0);
231+
let mact = IambAction::from(MessageAction::React(react, desc.bang));
232+
let step = CommandStep::Continue(mact.into(), ctx.context.clone());
239233

240-
return Result::Err(CommandError::Error(msg));
241-
}
234+
return Ok(step);
242235
}
243236

244237
fn iamb_unreact(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
@@ -248,20 +241,8 @@ fn iamb_unreact(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
248241
return Result::Err(CommandError::InvalidArgument);
249242
}
250243

251-
let mact = if let Some(k) = args.pop() {
252-
let k = k.as_str();
253-
254-
if let Some(emoji) = emojis::get(k).or_else(|| emojis::get_by_shortcode(k)) {
255-
IambAction::from(MessageAction::Unreact(Some(emoji.to_string())))
256-
} else {
257-
let msg = format!("Invalid Emoji or shortcode: {k}");
258-
259-
return Result::Err(CommandError::Error(msg));
260-
}
261-
} else {
262-
IambAction::from(MessageAction::Unreact(None))
263-
};
264-
244+
let reaction = args.pop();
245+
let mact = IambAction::from(MessageAction::Unreact(reaction, desc.bang));
265246
let step = CommandStep::Continue(mact.into(), ctx.context.clone());
266247

267248
return Ok(step);

src/windows/room/chat.rs

+37-2
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,22 @@ impl ChatState {
358358

359359
Ok(None)
360360
},
361-
MessageAction::React(emoji) => {
361+
MessageAction::React(reaction, literal) => {
362+
let emoji = if literal {
363+
reaction
364+
} else if let Some(emoji) =
365+
emojis::get(&reaction).or_else(|| emojis::get_by_shortcode(&reaction))
366+
{
367+
emoji.to_string()
368+
} else {
369+
let msg = format!("{reaction:?} is not a known Emoji shortcode; do you want to react with exactly {reaction:?}?");
370+
let act = IambAction::Message(MessageAction::React(reaction, true));
371+
let prompt = PromptYesNo::new(msg, vec![Action::from(act)]);
372+
let prompt = Box::new(prompt);
373+
374+
return Err(UIError::NeedConfirm(prompt));
375+
};
376+
362377
let room = self.get_joined(&store.application.worker)?;
363378
let event_id = match &msg.event {
364379
MessageEvent::EncryptedOriginal(ev) => ev.event_id.clone(),
@@ -422,7 +437,27 @@ impl ChatState {
422437

423438
Ok(None)
424439
},
425-
MessageAction::Unreact(emoji) => {
440+
MessageAction::Unreact(reaction, literal) => {
441+
let emoji = match reaction {
442+
reaction if literal => reaction,
443+
Some(reaction) => {
444+
if let Some(emoji) =
445+
emojis::get(&reaction).or_else(|| emojis::get_by_shortcode(&reaction))
446+
{
447+
Some(emoji.to_string())
448+
} else {
449+
let msg = format!("{reaction:?} is not a known Emoji shortcode; do you want to remove exactly {reaction:?}?");
450+
let act =
451+
IambAction::Message(MessageAction::Unreact(Some(reaction), true));
452+
let prompt = PromptYesNo::new(msg, vec![Action::from(act)]);
453+
let prompt = Box::new(prompt);
454+
455+
return Err(UIError::NeedConfirm(prompt));
456+
}
457+
},
458+
None => None,
459+
};
460+
426461
let room = self.get_joined(&store.application.worker)?;
427462
let event_id = match &msg.event {
428463
MessageEvent::EncryptedOriginal(ev) => ev.event_id.clone(),

0 commit comments

Comments
 (0)